Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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                                 cmn_err(CE_DEBUG, "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 }
540 
  This page was automatically generated by the LXR engine.