aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorAlex Elder <aelder@sgi.com>2011-07-22 12:04:41 -0400
committerAlex Elder <aelder@sgi.com>2011-08-09 16:30:43 -0400
commite44f4112a46ca817fe2758aac7bf7893a64a8c0e (patch)
tree5482bffa17b6c335a1140d9a51857fe809772739 /fs/xfs
parent2ddb4e94065470828e131351566102274ea9e83f (diff)
xfs: set cursor in xfs_ail_splice() even when AIL was empty
In xfs_ail_splice(), if a cursor is provided it is updated to point to the last item on the list being spliced into the AIL. But if the AIL was found to be empty, the cursor (if provided) is just initialized instead. There is no reason the empty AIL case needs to be treated any differently. And treating it the same way allows this code to be rearranged a bit, with a somewhat tidier result. Signed-off-by: Alex Elder <aelder@sgi.com> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_trans_ail.c67
1 files changed, 29 insertions, 38 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 43233e92f0f6..c15aa29fa169 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -299,7 +299,7 @@ xfs_trans_ail_cursor_last(
299 * Splice the log item list into the AIL at the given LSN. We splice to the 299 * Splice the log item list into the AIL at the given LSN. We splice to the
300 * tail of the given LSN to maintain insert order for push traversals. The 300 * tail of the given LSN to maintain insert order for push traversals. The
301 * cursor is optional, allowing repeated updates to the same LSN to avoid 301 * cursor is optional, allowing repeated updates to the same LSN to avoid
302 * repeated traversals. 302 * repeated traversals. This should not be called with an empty list.
303 */ 303 */
304static void 304static void
305xfs_ail_splice( 305xfs_ail_splice(
@@ -308,50 +308,39 @@ xfs_ail_splice(
308 struct list_head *list, 308 struct list_head *list,
309 xfs_lsn_t lsn) 309 xfs_lsn_t lsn)
310{ 310{
311 struct xfs_log_item *lip = cur ? cur->item : NULL; 311 struct xfs_log_item *lip;
312 struct xfs_log_item *next_lip; 312
313 ASSERT(!list_empty(list));
313 314
314 /* 315 /*
315 * Get a new cursor if we don't have a placeholder or the existing one 316 * Use the cursor to determine the insertion point if one is
316 * has been invalidated. 317 * provided. If not, or if the one we got is not valid,
318 * find the place in the AIL where the items belong.
317 */ 319 */
318 if (!lip || (__psint_t)lip & 1) { 320 lip = cur ? cur->item : NULL;
321 if (!lip || (__psint_t) lip & 1)
319 lip = __xfs_trans_ail_cursor_last(ailp, lsn); 322 lip = __xfs_trans_ail_cursor_last(ailp, lsn);
320 323
321 if (!lip) { 324 /*
322 /* The list is empty, so just splice and return. */ 325 * If a cursor is provided, we know we're processing the AIL
323 if (cur) 326 * in lsn order, and future items to be spliced in will
324 cur->item = NULL; 327 * follow the last one being inserted now. Update the
325 list_splice(list, &ailp->xa_ail); 328 * cursor to point to that last item, now while we have a
326 return; 329 * reliable pointer to it.
327 } 330 */
328 } 331 if (cur)
332 cur->item = list_entry(list->prev, struct xfs_log_item, li_ail);
329 333
330 /* 334 /*
331 * Our cursor points to the item we want to insert _after_, so we have 335 * Finally perform the splice. Unless the AIL was empty,
332 * to update the cursor to point to the end of the list we are splicing 336 * lip points to the item in the AIL _after_ which the new
333 * in so that it points to the correct location for the next splice. 337 * items should go. If lip is null the AIL was empty, so
334 * i.e. before the splice 338 * the new items go at the head of the AIL.
335 *
336 * lsn -> lsn -> lsn + x -> lsn + x ...
337 * ^
338 * | cursor points here
339 *
340 * After the splice we have:
341 *
342 * lsn -> lsn -> lsn -> lsn -> .... -> lsn -> lsn + x -> lsn + x ...
343 * ^ ^
344 * | cursor points here | needs to move here
345 *
346 * So we set the cursor to the last item in the list to be spliced
347 * before we execute the splice, resulting in the cursor pointing to
348 * the correct item after the splice occurs.
349 */ 339 */
350 if (cur) { 340 if (lip)
351 next_lip = list_entry(list->prev, struct xfs_log_item, li_ail); 341 list_splice(list, &lip->li_ail);
352 cur->item = next_lip; 342 else
353 } 343 list_splice(list, &ailp->xa_ail);
354 list_splice(list, &lip->li_ail);
355} 344}
356 345
357/* 346/*
@@ -682,6 +671,7 @@ xfs_trans_ail_update_bulk(
682 int i; 671 int i;
683 LIST_HEAD(tmp); 672 LIST_HEAD(tmp);
684 673
674 ASSERT(nr_items > 0); /* Not required, but true. */
685 mlip = xfs_ail_min(ailp); 675 mlip = xfs_ail_min(ailp);
686 676
687 for (i = 0; i < nr_items; i++) { 677 for (i = 0; i < nr_items; i++) {
@@ -701,7 +691,8 @@ xfs_trans_ail_update_bulk(
701 list_add(&lip->li_ail, &tmp); 691 list_add(&lip->li_ail, &tmp);
702 } 692 }
703 693
704 xfs_ail_splice(ailp, cur, &tmp, lsn); 694 if (!list_empty(&tmp))
695 xfs_ail_splice(ailp, cur, &tmp, lsn);
705 696
706 if (!mlip_changed) { 697 if (!mlip_changed) {
707 spin_unlock(&ailp->xa_lock); 698 spin_unlock(&ailp->xa_lock);