aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-09-03 07:47:37 -0400
committerBen Myers <bpm@sgi.com>2013-09-10 14:58:07 -0400
commit46f9d2eb37849a328011b182729990d2db3f4d52 (patch)
tree0a471bd1ca18c7579679474f3f539cd4367db00d /fs/xfs
parentfdd3cceef46f2c18c618669cfae5c0f47d6982f9 (diff)
xfs: aborted buf items can be in the AIL.
Saw this on generic/270 after a DQALLOC transaction overrun shutdown: XFS: Assertion failed: !(bip->bli_item.li_flags & XFS_LI_IN_AIL), file: fs/xfs/xfs_buf_item.c, line: 952 ..... xfs_buf_item_relse+0x4f/0xd0 xfs_buf_item_unlock+0x1b4/0x1e0 xfs_trans_free_items+0x7d/0xb0 xfs_trans_cancel+0x13c/0x1b0 xfs_symlink+0x37e/0xa60 .... When a transaction abort occured. If we are aborting a transaction and trigger this code path, then the item may be dirty. If the item is dirty, then it may be in the AIL. Hence if we are aborting, we need to check if the item is in the AIL and remove it before freeing it. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_buf_item.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 3a944b198e35..88c5ea75ebf6 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -613,13 +613,27 @@ xfs_buf_item_unlock(
613 } 613 }
614 } 614 }
615 } 615 }
616 if (clean || aborted) { 616
617 if (atomic_dec_and_test(&bip->bli_refcount)) { 617 /*
618 ASSERT(!aborted || XFS_FORCED_SHUTDOWN(lip->li_mountp)); 618 * Clean buffers, by definition, cannot be in the AIL. However, aborted
619 * buffers may be dirty and hence in the AIL. Therefore if we are
620 * aborting a buffer and we've just taken the last refernce away, we
621 * have to check if it is in the AIL before freeing it. We need to free
622 * it in this case, because an aborted transaction has already shut the
623 * filesystem down and this is the last chance we will have to do so.
624 */
625 if (atomic_dec_and_test(&bip->bli_refcount)) {
626 if (clean)
627 xfs_buf_item_relse(bp);
628 else if (aborted) {
629 ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
630 if (lip->li_flags & XFS_LI_IN_AIL) {
631 xfs_trans_ail_delete(lip->li_ailp, lip,
632 SHUTDOWN_LOG_IO_ERROR);
633 }
619 xfs_buf_item_relse(bp); 634 xfs_buf_item_relse(bp);
620 } 635 }
621 } else 636 }
622 atomic_dec(&bip->bli_refcount);
623 637
624 if (!(flags & XFS_BLI_HOLD)) 638 if (!(flags & XFS_BLI_HOLD))
625 xfs_buf_relse(bp); 639 xfs_buf_relse(bp);