aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2016-05-17 23:53:42 -0400
committerDave Chinner <david@fromorbit.com>2016-05-17 23:53:42 -0400
commitb1438f477934f5a4d5a44df26f3079a7575d5946 (patch)
tree5eab8bfb381b7a9b20b95a099ebb9fbde917a65e /fs/xfs
parent8179c03629de67f515d3ab825b5a9428687d4b85 (diff)
xfs: xfs_iflush_cluster fails to abort on error
When a failure due to an inode buffer occurs, the error handling fails to abort the inode writeback correctly. This can result in the inode being reclaimed whilst still in the AIL, leading to use-after-free situations as well as filesystems that cannot be unmounted as the inode log items left in the AIL never get removed. Fix this by ensuring fatal errors from xfs_imap_to_bp() result in the inode flush being aborted correctly. cc: <stable@vger.kernel.org> # 3.10.x- Reported-by: Shyam Kaushik <shyam@zadarastorage.com> Diagnosed-by: Shyam Kaushik <shyam@zadarastorage.com> Tested-by: Shyam Kaushik <shyam@zadarastorage.com> Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_inode.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 96f606deee31..696936cad0fa 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3327,7 +3327,7 @@ xfs_iflush(
3327 struct xfs_buf **bpp) 3327 struct xfs_buf **bpp)
3328{ 3328{
3329 struct xfs_mount *mp = ip->i_mount; 3329 struct xfs_mount *mp = ip->i_mount;
3330 struct xfs_buf *bp; 3330 struct xfs_buf *bp = NULL;
3331 struct xfs_dinode *dip; 3331 struct xfs_dinode *dip;
3332 int error; 3332 int error;
3333 3333
@@ -3369,14 +3369,22 @@ xfs_iflush(
3369 } 3369 }
3370 3370
3371 /* 3371 /*
3372 * Get the buffer containing the on-disk inode. 3372 * Get the buffer containing the on-disk inode. We are doing a try-lock
3373 * operation here, so we may get an EAGAIN error. In that case, we
3374 * simply want to return with the inode still dirty.
3375 *
3376 * If we get any other error, we effectively have a corruption situation
3377 * and we cannot flush the inode, so we treat it the same as failing
3378 * xfs_iflush_int().
3373 */ 3379 */
3374 error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK, 3380 error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
3375 0); 3381 0);
3376 if (error || !bp) { 3382 if (error == -EAGAIN) {
3377 xfs_ifunlock(ip); 3383 xfs_ifunlock(ip);
3378 return error; 3384 return error;
3379 } 3385 }
3386 if (error)
3387 goto corrupt_out;
3380 3388
3381 /* 3389 /*
3382 * First flush out the inode that xfs_iflush was called with. 3390 * First flush out the inode that xfs_iflush was called with.
@@ -3404,7 +3412,8 @@ xfs_iflush(
3404 return 0; 3412 return 0;
3405 3413
3406corrupt_out: 3414corrupt_out:
3407 xfs_buf_relse(bp); 3415 if (bp)
3416 xfs_buf_relse(bp);
3408 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 3417 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
3409cluster_corrupt_out: 3418cluster_corrupt_out:
3410 error = -EFSCORRUPTED; 3419 error = -EFSCORRUPTED;