diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-13 07:43:01 +0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-13 07:43:01 +0400 | 
| commit | e68ff9cd15552e46e0f993eace25af0947b1222d (patch) | |
| tree | 28873106aa1c88963a13b34a4bc209875763a4e4 /fs/xfs/xfs_trans_ail.c | |
| parent | c44efbaa0ef3cf53fbf6bb57c33d4f199b15f2da (diff) | |
| parent | e570280521290c27621d60cffea2400bdf1f2c88 (diff) | |
| download | linux-e68ff9cd15552e46e0f993eace25af0947b1222d.tar.xz | |
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs:
  xfs: replace xfs_buf_geterror() with bp->b_error
  xfs: Check the return value of xfs_buf_read() for NULL
  "xfs: fix error handling for synchronous writes" revisited
  xfs: set cursor in xfs_ail_splice() even when AIL was empty
  xfs: Remove the macro XFS_BUFTARG_NAME
  xfs: Remove the macro XFS_BUF_TARGET
  xfs: Remove the macro XFS_BUF_SET_TARGET
  Replace the macro XFS_BUF_ISPINNED with helper xfs_buf_ispinned
  xfs: Remove the macro XFS_BUF_SET_PTR
  xfs: Remove the macro XFS_BUF_PTR
  xfs: Remove macro XFS_BUF_SET_START
  xfs: Remove macro XFS_BUF_HOLD
  xfs: Remove macro XFS_BUF_BUSY and family
  xfs: Remove the macro XFS_BUF_ERROR and family
  xfs: Remove the macro XFS_BUF_BFLAGS
Diffstat (limited to 'fs/xfs/xfs_trans_ail.c')
| -rw-r--r-- | fs/xfs/xfs_trans_ail.c | 67 | 
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(   * Splice the log item list into the AIL at the given LSN. We splice to the   * tail of the given LSN to maintain insert order for push traversals. The   * cursor is optional, allowing repeated updates to the same LSN to avoid - * repeated traversals. + * repeated traversals.  This should not be called with an empty list.   */  static void  xfs_ail_splice( @@ -308,50 +308,39 @@ xfs_ail_splice(  	struct list_head	*list,  	xfs_lsn_t		lsn)  { -	struct xfs_log_item	*lip = cur ? cur->item : NULL; -	struct xfs_log_item	*next_lip; +	struct xfs_log_item	*lip; + +	ASSERT(!list_empty(list));  	/* -	 * Get a new cursor if we don't have a placeholder or the existing one -	 * has been invalidated. +	 * Use the cursor to determine the insertion point if one is +	 * provided.  If not, or if the one we got is not valid, +	 * find the place in the AIL where the items belong.  	 */ -	if (!lip || (__psint_t)lip & 1) { +	lip = cur ? cur->item : NULL; +	if (!lip || (__psint_t) lip & 1)  		lip = __xfs_trans_ail_cursor_last(ailp, lsn); -		if (!lip) { -			/* The list is empty, so just splice and return.  */ -			if (cur) -				cur->item = NULL; -			list_splice(list, &ailp->xa_ail); -			return; -		} -	} +	/* +	 * If a cursor is provided, we know we're processing the AIL +	 * in lsn order, and future items to be spliced in will +	 * follow the last one being inserted now.  Update the +	 * cursor to point to that last item, now while we have a +	 * reliable pointer to it. +	 */ +	if (cur) +		cur->item = list_entry(list->prev, struct xfs_log_item, li_ail);  	/* -	 * Our cursor points to the item we want to insert _after_, so we have -	 * to update the cursor to point to the end of the list we are splicing -	 * in so that it points to the correct location for the next splice. -	 * i.e. before the splice -	 * -	 *  lsn -> lsn -> lsn + x -> lsn + x ... -	 *          ^ -	 *          | cursor points here -	 * -	 * After the splice we have: -	 * -	 *  lsn -> lsn -> lsn -> lsn -> .... -> lsn -> lsn + x -> lsn + x ... -	 *          ^                            ^ -	 *          | cursor points here         | needs to move here -	 * -	 * So we set the cursor to the last item in the list to be spliced -	 * before we execute the splice, resulting in the cursor pointing to -	 * the correct item after the splice occurs. +	 * Finally perform the splice.  Unless the AIL was empty, +	 * lip points to the item in the AIL _after_ which the new +	 * items should go.  If lip is null the AIL was empty, so +	 * the new items go at the head of the AIL.  	 */ -	if (cur) { -		next_lip = list_entry(list->prev, struct xfs_log_item, li_ail); -		cur->item = next_lip; -	} -	list_splice(list, &lip->li_ail); +	if (lip) +		list_splice(list, &lip->li_ail); +	else +		list_splice(list, &ailp->xa_ail);  }  /* @@ -682,6 +671,7 @@ xfs_trans_ail_update_bulk(  	int			i;  	LIST_HEAD(tmp); +	ASSERT(nr_items > 0);		/* Not required, but true. */  	mlip = xfs_ail_min(ailp);  	for (i = 0; i < nr_items; i++) { @@ -701,7 +691,8 @@ xfs_trans_ail_update_bulk(  		list_add(&lip->li_ail, &tmp);  	} -	xfs_ail_splice(ailp, cur, &tmp, lsn); +	if (!list_empty(&tmp)) +		xfs_ail_splice(ailp, cur, &tmp, lsn);  	if (!mlip_changed) {  		spin_unlock(&ailp->xa_lock);  | 
