]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/gnu/fs/xfs/xfs_trans_item.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / gnu / fs / xfs / xfs_trans_item.c
1 /*
2  * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_log.h"
22 #include "xfs_inum.h"
23 #include "xfs_trans.h"
24 #include "xfs_trans_priv.h"
25
26 STATIC int      xfs_trans_unlock_chunk(xfs_log_item_chunk_t *,
27                                         int, int, xfs_lsn_t);
28
29 /*
30  * This is called to add the given log item to the transaction's
31  * list of log items.  It must find a free log item descriptor
32  * or allocate a new one and add the item to that descriptor.
33  * The function returns a pointer to item descriptor used to point
34  * to the new item.  The log item will now point to its new descriptor
35  * with its li_desc field.
36  */
37 xfs_log_item_desc_t *
38 xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
39 {
40         xfs_log_item_desc_t     *lidp;
41         xfs_log_item_chunk_t    *licp;
42         int                     i=0;
43
44         /*
45          * If there are no free descriptors, allocate a new chunk
46          * of them and put it at the front of the chunk list.
47          */
48         if (tp->t_items_free == 0) {
49                 licp = (xfs_log_item_chunk_t*)
50                        kmem_alloc(sizeof(xfs_log_item_chunk_t), KM_SLEEP);
51                 ASSERT(licp != NULL);
52                 /*
53                  * Initialize the chunk, and then
54                  * claim the first slot in the newly allocated chunk.
55                  */
56                 XFS_LIC_INIT(licp);
57                 XFS_LIC_CLAIM(licp, 0);
58                 licp->lic_unused = 1;
59                 XFS_LIC_INIT_SLOT(licp, 0);
60                 lidp = XFS_LIC_SLOT(licp, 0);
61
62                 /*
63                  * Link in the new chunk and update the free count.
64                  */
65                 licp->lic_next = tp->t_items.lic_next;
66                 tp->t_items.lic_next = licp;
67                 tp->t_items_free = XFS_LIC_NUM_SLOTS - 1;
68
69                 /*
70                  * Initialize the descriptor and the generic portion
71                  * of the log item.
72                  *
73                  * Point the new slot at this item and return it.
74                  * Also point the log item at its currently active
75                  * descriptor and set the item's mount pointer.
76                  */
77                 lidp->lid_item = lip;
78                 lidp->lid_flags = 0;
79                 lidp->lid_size = 0;
80                 lip->li_desc = lidp;
81                 lip->li_mountp = tp->t_mountp;
82                 return lidp;
83         }
84
85         /*
86          * Find the free descriptor. It is somewhere in the chunklist
87          * of descriptors.
88          */
89         licp = &tp->t_items;
90         while (licp != NULL) {
91                 if (XFS_LIC_VACANCY(licp)) {
92                         if (licp->lic_unused <= XFS_LIC_MAX_SLOT) {
93                                 i = licp->lic_unused;
94                                 ASSERT(XFS_LIC_ISFREE(licp, i));
95                                 break;
96                         }
97                         for (i = 0; i <= XFS_LIC_MAX_SLOT; i++) {
98                                 if (XFS_LIC_ISFREE(licp, i))
99                                         break;
100                         }
101                         ASSERT(i <= XFS_LIC_MAX_SLOT);
102                         break;
103                 }
104                 licp = licp->lic_next;
105         }
106         ASSERT(licp != NULL);
107         /*
108          * If we find a free descriptor, claim it,
109          * initialize it, and return it.
110          */
111         XFS_LIC_CLAIM(licp, i);
112         if (licp->lic_unused <= i) {
113                 licp->lic_unused = i + 1;
114                 XFS_LIC_INIT_SLOT(licp, i);
115         }
116         lidp = XFS_LIC_SLOT(licp, i);
117         tp->t_items_free--;
118         lidp->lid_item = lip;
119         lidp->lid_flags = 0;
120         lidp->lid_size = 0;
121         lip->li_desc = lidp;
122         lip->li_mountp = tp->t_mountp;
123         return lidp;
124 }
125
126 /*
127  * Free the given descriptor.
128  *
129  * This requires setting the bit in the chunk's free mask corresponding
130  * to the given slot.
131  */
132 void
133 xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
134 {
135         uint                    slot;
136         xfs_log_item_chunk_t    *licp;
137         xfs_log_item_chunk_t    **licpp;
138
139         slot = XFS_LIC_DESC_TO_SLOT(lidp);
140         licp = XFS_LIC_DESC_TO_CHUNK(lidp);
141         XFS_LIC_RELSE(licp, slot);
142         lidp->lid_item->li_desc = NULL;
143         tp->t_items_free++;
144
145         /*
146          * If there are no more used items in the chunk and this is not
147          * the chunk embedded in the transaction structure, then free
148          * the chunk. First pull it from the chunk list and then
149          * free it back to the heap.  We didn't bother with a doubly
150          * linked list here because the lists should be very short
151          * and this is not a performance path.  It's better to save
152          * the memory of the extra pointer.
153          *
154          * Also decrement the transaction structure's count of free items
155          * by the number in a chunk since we are freeing an empty chunk.
156          */
157         if (XFS_LIC_ARE_ALL_FREE(licp) && (licp != &(tp->t_items))) {
158                 licpp = &(tp->t_items.lic_next);
159                 while (*licpp != licp) {
160                         ASSERT(*licpp != NULL);
161                         licpp = &((*licpp)->lic_next);
162                 }
163                 *licpp = licp->lic_next;
164                 kmem_free(licp, sizeof(xfs_log_item_chunk_t));
165                 tp->t_items_free -= XFS_LIC_NUM_SLOTS;
166         }
167 }
168
169 /*
170  * This is called to find the descriptor corresponding to the given
171  * log item.  It returns a pointer to the descriptor.
172  * The log item MUST have a corresponding descriptor in the given
173  * transaction.  This routine does not return NULL, it panics.
174  *
175  * The descriptor pointer is kept in the log item's li_desc field.
176  * Just return it.
177  */
178 /*ARGSUSED*/
179 xfs_log_item_desc_t *
180 xfs_trans_find_item(xfs_trans_t *tp, xfs_log_item_t *lip)
181 {
182         ASSERT(lip->li_desc != NULL);
183
184         return lip->li_desc;
185 }
186
187
188 /*
189  * Return a pointer to the first descriptor in the chunk list.
190  * This does not return NULL if there are none, it panics.
191  *
192  * The first descriptor must be in either the first or second chunk.
193  * This is because the only chunk allowed to be empty is the first.
194  * All others are freed when they become empty.
195  *
196  * At some point this and xfs_trans_next_item() should be optimized
197  * to quickly look at the mask to determine if there is anything to
198  * look at.
199  */
200 xfs_log_item_desc_t *
201 xfs_trans_first_item(xfs_trans_t *tp)
202 {
203         xfs_log_item_chunk_t    *licp;
204         int                     i;
205
206         licp = &tp->t_items;
207         /*
208          * If it's not in the first chunk, skip to the second.
209          */
210         if (XFS_LIC_ARE_ALL_FREE(licp)) {
211                 licp = licp->lic_next;
212         }
213
214         /*
215          * Return the first non-free descriptor in the chunk.
216          */
217         ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
218         for (i = 0; i < licp->lic_unused; i++) {
219                 if (XFS_LIC_ISFREE(licp, i)) {
220                         continue;
221                 }
222
223                 return XFS_LIC_SLOT(licp, i);
224         }
225         cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item");
226         return NULL;
227 }
228
229
230 /*
231  * Given a descriptor, return the next descriptor in the chunk list.
232  * This returns NULL if there are no more used descriptors in the list.
233  *
234  * We do this by first locating the chunk in which the descriptor resides,
235  * and then scanning forward in the chunk and the list for the next
236  * used descriptor.
237  */
238 /*ARGSUSED*/
239 xfs_log_item_desc_t *
240 xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
241 {
242         xfs_log_item_chunk_t    *licp;
243         int                     i;
244
245         licp = XFS_LIC_DESC_TO_CHUNK(lidp);
246
247         /*
248          * First search the rest of the chunk. The for loop keeps us
249          * from referencing things beyond the end of the chunk.
250          */
251         for (i = (int)XFS_LIC_DESC_TO_SLOT(lidp) + 1; i < licp->lic_unused; i++) {
252                 if (XFS_LIC_ISFREE(licp, i)) {
253                         continue;
254                 }
255
256                 return XFS_LIC_SLOT(licp, i);
257         }
258
259         /*
260          * Now search the next chunk.  It must be there, because the
261          * next chunk would have been freed if it were empty.
262          * If there is no next chunk, return NULL.
263          */
264         if (licp->lic_next == NULL) {
265                 return NULL;
266         }
267
268         licp = licp->lic_next;
269         ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
270         for (i = 0; i < licp->lic_unused; i++) {
271                 if (XFS_LIC_ISFREE(licp, i)) {
272                         continue;
273                 }
274
275                 return XFS_LIC_SLOT(licp, i);
276         }
277         ASSERT(0);
278         /* NOTREACHED */
279         return NULL; /* keep gcc quite */
280 }
281
282 /*
283  * This is called to unlock all of the items of a transaction and to free
284  * all the descriptors of that transaction.
285  *
286  * It walks the list of descriptors and unlocks each item.  It frees
287  * each chunk except that embedded in the transaction as it goes along.
288  */
289 void
290 xfs_trans_free_items(
291         xfs_trans_t     *tp,
292         int             flags)
293 {
294         xfs_log_item_chunk_t    *licp;
295         xfs_log_item_chunk_t    *next_licp;
296         int                     abort;
297
298         abort = flags & XFS_TRANS_ABORT;
299         licp = &tp->t_items;
300         /*
301          * Special case the embedded chunk so we don't free it below.
302          */
303         if (!XFS_LIC_ARE_ALL_FREE(licp)) {
304                 (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN);
305                 XFS_LIC_ALL_FREE(licp);
306                 licp->lic_unused = 0;
307         }
308         licp = licp->lic_next;
309
310         /*
311          * Unlock each item in each chunk and free the chunks.
312          */
313         while (licp != NULL) {
314                 ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
315                 (void) xfs_trans_unlock_chunk(licp, 1, abort, NULLCOMMITLSN);
316                 next_licp = licp->lic_next;
317                 kmem_free(licp, sizeof(xfs_log_item_chunk_t));
318                 licp = next_licp;
319         }
320
321         /*
322          * Reset the transaction structure's free item count.
323          */
324         tp->t_items_free = XFS_LIC_NUM_SLOTS;
325         tp->t_items.lic_next = NULL;
326 }
327
328
329
330 /*
331  * This is called to unlock the items associated with a transaction.
332  * Items which were not logged should be freed.
333  * Those which were logged must still be tracked so they can be unpinned
334  * when the transaction commits.
335  */
336 void
337 xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn)
338 {
339         xfs_log_item_chunk_t    *licp;
340         xfs_log_item_chunk_t    *next_licp;
341         xfs_log_item_chunk_t    **licpp;
342         int                     freed;
343
344         freed = 0;
345         licp = &tp->t_items;
346
347         /*
348          * Special case the embedded chunk so we don't free.
349          */
350         if (!XFS_LIC_ARE_ALL_FREE(licp)) {
351                 freed = xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
352         }
353         licpp = &(tp->t_items.lic_next);
354         licp = licp->lic_next;
355
356         /*
357          * Unlock each item in each chunk, free non-dirty descriptors,
358          * and free empty chunks.
359          */
360         while (licp != NULL) {
361                 ASSERT(!XFS_LIC_ARE_ALL_FREE(licp));
362                 freed += xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn);
363                 next_licp = licp->lic_next;
364                 if (XFS_LIC_ARE_ALL_FREE(licp)) {
365                         *licpp = next_licp;
366                         kmem_free(licp, sizeof(xfs_log_item_chunk_t));
367                         freed -= XFS_LIC_NUM_SLOTS;
368                 } else {
369                         licpp = &(licp->lic_next);
370                 }
371                 ASSERT(*licpp == next_licp);
372                 licp = next_licp;
373         }
374
375         /*
376          * Fix the free descriptor count in the transaction.
377          */
378         tp->t_items_free += freed;
379 }
380
381 /*
382  * Unlock each item pointed to by a descriptor in the given chunk.
383  * Stamp the commit lsn into each item if necessary.
384  * Free descriptors pointing to items which are not dirty if freeing_chunk
385  * is zero. If freeing_chunk is non-zero, then we need to unlock all
386  * items in the chunk.
387  * 
388  * Return the number of descriptors freed.
389  */
390 STATIC int
391 xfs_trans_unlock_chunk(
392         xfs_log_item_chunk_t    *licp,
393         int                     freeing_chunk,
394         int                     abort,
395         xfs_lsn_t               commit_lsn)
396 {
397         xfs_log_item_desc_t     *lidp;
398         xfs_log_item_t          *lip;
399         int                     i;
400         int                     freed;
401
402         freed = 0;
403         lidp = licp->lic_descs;
404         for (i = 0; i < licp->lic_unused; i++, lidp++) {
405                 if (XFS_LIC_ISFREE(licp, i)) {
406                         continue;
407                 }
408                 lip = lidp->lid_item;
409                 lip->li_desc = NULL;
410
411                 if (commit_lsn != NULLCOMMITLSN)
412                         IOP_COMMITTING(lip, commit_lsn);
413                 if (abort)
414                         lip->li_flags |= XFS_LI_ABORTED;
415                 IOP_UNLOCK(lip);
416
417                 /*
418                  * Free the descriptor if the item is not dirty
419                  * within this transaction and the caller is not
420                  * going to just free the entire thing regardless.
421                  */
422                 if (!(freeing_chunk) &&
423                     (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) {
424                         XFS_LIC_RELSE(licp, i);
425                         freed++;
426                 }
427         }
428
429         return freed;
430 }
431
432
433 /*
434  * This is called to add the given busy item to the transaction's
435  * list of busy items.  It must find a free busy item descriptor
436  * or allocate a new one and add the item to that descriptor.
437  * The function returns a pointer to busy descriptor used to point
438  * to the new busy entry.  The log busy entry will now point to its new
439  * descriptor with its ???? field.
440  */
441 xfs_log_busy_slot_t *
442 xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx)
443 {
444         xfs_log_busy_chunk_t    *lbcp;
445         xfs_log_busy_slot_t     *lbsp;
446         int                     i=0;
447
448         /*
449          * If there are no free descriptors, allocate a new chunk
450          * of them and put it at the front of the chunk list.
451          */
452         if (tp->t_busy_free == 0) {
453                 lbcp = (xfs_log_busy_chunk_t*)
454                        kmem_alloc(sizeof(xfs_log_busy_chunk_t), KM_SLEEP);
455                 ASSERT(lbcp != NULL);
456                 /*
457                  * Initialize the chunk, and then
458                  * claim the first slot in the newly allocated chunk.
459                  */
460                 XFS_LBC_INIT(lbcp);
461                 XFS_LBC_CLAIM(lbcp, 0);
462                 lbcp->lbc_unused = 1;
463                 lbsp = XFS_LBC_SLOT(lbcp, 0);
464
465                 /*
466                  * Link in the new chunk and update the free count.
467                  */
468                 lbcp->lbc_next = tp->t_busy.lbc_next;
469                 tp->t_busy.lbc_next = lbcp;
470                 tp->t_busy_free = XFS_LIC_NUM_SLOTS - 1;
471
472                 /*
473                  * Initialize the descriptor and the generic portion
474                  * of the log item.
475                  *
476                  * Point the new slot at this item and return it.
477                  * Also point the log item at its currently active
478                  * descriptor and set the item's mount pointer.
479                  */
480                 lbsp->lbc_ag = ag;
481                 lbsp->lbc_idx = idx;
482                 return lbsp;
483         }
484
485         /*
486          * Find the free descriptor. It is somewhere in the chunklist
487          * of descriptors.
488          */
489         lbcp = &tp->t_busy;
490         while (lbcp != NULL) {
491                 if (XFS_LBC_VACANCY(lbcp)) {
492                         if (lbcp->lbc_unused <= XFS_LBC_MAX_SLOT) {
493                                 i = lbcp->lbc_unused;
494                                 break;
495                         } else {
496                                 /* out-of-order vacancy */
497                                 printk("OOO vacancy lbcp 0x%p\n", lbcp);
498                                 ASSERT(0);
499                         }
500                 }
501                 lbcp = lbcp->lbc_next;
502         }
503         ASSERT(lbcp != NULL);
504         /*
505          * If we find a free descriptor, claim it,
506          * initialize it, and return it.
507          */
508         XFS_LBC_CLAIM(lbcp, i);
509         if (lbcp->lbc_unused <= i) {
510                 lbcp->lbc_unused = i + 1;
511         }
512         lbsp = XFS_LBC_SLOT(lbcp, i);
513         tp->t_busy_free--;
514         lbsp->lbc_ag = ag;
515         lbsp->lbc_idx = idx;
516         return lbsp;
517 }
518
519
520 /*
521  * xfs_trans_free_busy
522  * Free all of the busy lists from a transaction
523  */
524 void
525 xfs_trans_free_busy(xfs_trans_t *tp)
526 {
527         xfs_log_busy_chunk_t    *lbcp;
528         xfs_log_busy_chunk_t    *lbcq;
529
530         lbcp = tp->t_busy.lbc_next;
531         while (lbcp != NULL) {
532                 lbcq = lbcp->lbc_next;
533                 kmem_free(lbcp, sizeof(xfs_log_busy_chunk_t));
534                 lbcp = lbcq;
535         }
536
537         XFS_LBC_INIT(&tp->t_busy);
538         tp->t_busy.lbc_unused = 0;
539 }