Commit b1438f47 authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner

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: default avatarShyam Kaushik <shyam@zadarastorage.com>
Diagnosed-by: default avatarShyam Kaushik <shyam@zadarastorage.com>
Tested-by: default avatarShyam Kaushik <shyam@zadarastorage.com>
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 8179c036
...@@ -3327,7 +3327,7 @@ xfs_iflush( ...@@ -3327,7 +3327,7 @@ xfs_iflush(
struct xfs_buf **bpp) struct xfs_buf **bpp)
{ {
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = ip->i_mount;
struct xfs_buf *bp; struct xfs_buf *bp = NULL;
struct xfs_dinode *dip; struct xfs_dinode *dip;
int error; int error;
...@@ -3369,14 +3369,22 @@ xfs_iflush( ...@@ -3369,14 +3369,22 @@ xfs_iflush(
} }
/* /*
* Get the buffer containing the on-disk inode. * Get the buffer containing the on-disk inode. We are doing a try-lock
* operation here, so we may get an EAGAIN error. In that case, we
* simply want to return with the inode still dirty.
*
* If we get any other error, we effectively have a corruption situation
* and we cannot flush the inode, so we treat it the same as failing
* xfs_iflush_int().
*/ */
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK, error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
0); 0);
if (error || !bp) { if (error == -EAGAIN) {
xfs_ifunlock(ip); xfs_ifunlock(ip);
return error; return error;
} }
if (error)
goto corrupt_out;
/* /*
* First flush out the inode that xfs_iflush was called with. * First flush out the inode that xfs_iflush was called with.
...@@ -3404,7 +3412,8 @@ xfs_iflush( ...@@ -3404,7 +3412,8 @@ xfs_iflush(
return 0; return 0;
corrupt_out: corrupt_out:
xfs_buf_relse(bp); if (bp)
xfs_buf_relse(bp);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
cluster_corrupt_out: cluster_corrupt_out:
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment