Skip to content

Commit 7dc8f21

Browse files
dgchinnergregkh
authored andcommitted
xfs: xfs_iflush_cluster fails to abort on error
commit b1438f477934f5a4d5a44df26f3079a7575d5946 upstream. 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. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent d7d92ca commit 7dc8f21

1 file changed

Lines changed: 13 additions & 4 deletions

File tree

fs/xfs/xfs_inode.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3342,7 +3342,7 @@ xfs_iflush(
33423342
struct xfs_buf **bpp)
33433343
{
33443344
struct xfs_mount *mp = ip->i_mount;
3345-
struct xfs_buf *bp;
3345+
struct xfs_buf *bp = NULL;
33463346
struct xfs_dinode *dip;
33473347
int error;
33483348

@@ -3384,14 +3384,22 @@ xfs_iflush(
33843384
}
33853385

33863386
/*
3387-
* Get the buffer containing the on-disk inode.
3387+
* Get the buffer containing the on-disk inode. We are doing a try-lock
3388+
* operation here, so we may get an EAGAIN error. In that case, we
3389+
* simply want to return with the inode still dirty.
3390+
*
3391+
* If we get any other error, we effectively have a corruption situation
3392+
* and we cannot flush the inode, so we treat it the same as failing
3393+
* xfs_iflush_int().
33883394
*/
33893395
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
33903396
0);
3391-
if (error || !bp) {
3397+
if (error == -EAGAIN) {
33923398
xfs_ifunlock(ip);
33933399
return error;
33943400
}
3401+
if (error)
3402+
goto corrupt_out;
33953403

33963404
/*
33973405
* First flush out the inode that xfs_iflush was called with.
@@ -3419,7 +3427,8 @@ xfs_iflush(
34193427
return 0;
34203428

34213429
corrupt_out:
3422-
xfs_buf_relse(bp);
3430+
if (bp)
3431+
xfs_buf_relse(bp);
34233432
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
34243433
cluster_corrupt_out:
34253434
error = -EFSCORRUPTED;

0 commit comments

Comments
 (0)