aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-04-23 01:58:32 -0400
committerBen Myers <bpm@sgi.com>2012-05-14 17:20:25 -0400
commit32ce90a4b79155a155de2b284d8b69023e5e8fea (patch)
tree1280a85dea9061a8089a39fccc8a5ce0fc222e62
parentdea9609527a55b65638a6323894269334dfe6ec5 (diff)
xfs: remove log item from AIL in xfs_iflush after a shutdown
If a filesystem has been forced shutdown we are never going to write inodes to disk, which means the inode items will stay in the AIL until we free the inode. Currently that is not a problem, but a pending change requires us to empty the AIL before shutting down the filesystem. In that case leaving the inode in the AIL is lethal. Make sure to remove the log item from the AIL to allow emptying the AIL on shutdown filesystems. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_dquot.c3
-rw-r--r--fs/xfs/xfs_iget.c18
-rw-r--r--fs/xfs/xfs_inode.c17
-rw-r--r--fs/xfs/xfs_sync.c1
4 files changed, 12 insertions, 27 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index e2f6f7c877db..786a61e1cccd 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -915,8 +915,7 @@ xfs_qm_dqflush(
915 915
916 spin_lock(&mp->m_ail->xa_lock); 916 spin_lock(&mp->m_ail->xa_lock);
917 if (lip->li_flags & XFS_LI_IN_AIL) 917 if (lip->li_flags & XFS_LI_IN_AIL)
918 xfs_trans_ail_delete(mp->m_ail, lip, 918 xfs_trans_ail_delete(mp->m_ail, lip);
919 SHUTDOWN_CORRUPT_INCORE);
920 else 919 else
921 spin_unlock(&mp->m_ail->xa_lock); 920 spin_unlock(&mp->m_ail->xa_lock);
922 921
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index bcc6c249b2c7..ab89ca7fdb95 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -123,23 +123,7 @@ xfs_inode_free(
123 xfs_idestroy_fork(ip, XFS_ATTR_FORK); 123 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
124 124
125 if (ip->i_itemp) { 125 if (ip->i_itemp) {
126 /* 126 ASSERT(!(ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL));
127 * Only if we are shutting down the fs will we see an
128 * inode still in the AIL. If it is there, we should remove
129 * it to prevent a use-after-free from occurring.
130 */
131 xfs_log_item_t *lip = &ip->i_itemp->ili_item;
132 struct xfs_ail *ailp = lip->li_ailp;
133
134 ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
135 XFS_FORCED_SHUTDOWN(ip->i_mount));
136 if (lip->li_flags & XFS_LI_IN_AIL) {
137 spin_lock(&ailp->xa_lock);
138 if (lip->li_flags & XFS_LI_IN_AIL)
139 xfs_trans_ail_delete(ailp, lip);
140 else
141 spin_unlock(&ailp->xa_lock);
142 }
143 xfs_inode_item_destroy(ip); 127 xfs_inode_item_destroy(ip);
144 ip->i_itemp = NULL; 128 ip->i_itemp = NULL;
145 } 129 }
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index bc46c0a133d3..00f9c2f34e1f 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2397,7 +2397,6 @@ xfs_iflush(
2397 xfs_inode_t *ip, 2397 xfs_inode_t *ip,
2398 uint flags) 2398 uint flags)
2399{ 2399{
2400 xfs_inode_log_item_t *iip;
2401 xfs_buf_t *bp; 2400 xfs_buf_t *bp;
2402 xfs_dinode_t *dip; 2401 xfs_dinode_t *dip;
2403 xfs_mount_t *mp; 2402 xfs_mount_t *mp;
@@ -2410,7 +2409,6 @@ xfs_iflush(
2410 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || 2409 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
2411 ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK)); 2410 ip->i_d.di_nextents > XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK));
2412 2411
2413 iip = ip->i_itemp;
2414 mp = ip->i_mount; 2412 mp = ip->i_mount;
2415 2413
2416 /* 2414 /*
@@ -2447,13 +2445,14 @@ xfs_iflush(
2447 /* 2445 /*
2448 * This may have been unpinned because the filesystem is shutting 2446 * This may have been unpinned because the filesystem is shutting
2449 * down forcibly. If that's the case we must not write this inode 2447 * down forcibly. If that's the case we must not write this inode
2450 * to disk, because the log record didn't make it to disk! 2448 * to disk, because the log record didn't make it to disk.
2449 *
2450 * We also have to remove the log item from the AIL in this case,
2451 * as we wait for an empty AIL as part of the unmount process.
2451 */ 2452 */
2452 if (XFS_FORCED_SHUTDOWN(mp)) { 2453 if (XFS_FORCED_SHUTDOWN(mp)) {
2453 if (iip) 2454 error = XFS_ERROR(EIO);
2454 iip->ili_fields = 0; 2455 goto abort_out;
2455 xfs_ifunlock(ip);
2456 return XFS_ERROR(EIO);
2457 } 2456 }
2458 2457
2459 /* 2458 /*
@@ -2500,11 +2499,13 @@ corrupt_out:
2500 xfs_buf_relse(bp); 2499 xfs_buf_relse(bp);
2501 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 2500 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
2502cluster_corrupt_out: 2501cluster_corrupt_out:
2502 error = XFS_ERROR(EFSCORRUPTED);
2503abort_out:
2503 /* 2504 /*
2504 * Unlocks the flush lock 2505 * Unlocks the flush lock
2505 */ 2506 */
2506 xfs_iflush_abort(ip); 2507 xfs_iflush_abort(ip);
2507 return XFS_ERROR(EFSCORRUPTED); 2508 return error;
2508} 2509}
2509 2510
2510 2511
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c
index c318d8a4a631..7648776e0a9e 100644
--- a/fs/xfs/xfs_sync.c
+++ b/fs/xfs/xfs_sync.c
@@ -782,6 +782,7 @@ restart:
782 goto reclaim; 782 goto reclaim;
783 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { 783 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
784 xfs_iunpin_wait(ip); 784 xfs_iunpin_wait(ip);
785 xfs_iflush_abort(ip);
785 goto reclaim; 786 goto reclaim;
786 } 787 }
787 if (xfs_ipincount(ip)) { 788 if (xfs_ipincount(ip)) {