diff options
author | Brian Foster <bfoster@redhat.com> | 2019-04-12 10:39:20 -0400 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-04-14 21:15:56 -0400 |
commit | 22fedd80b652213e694b788e9389892b67b86286 (patch) | |
tree | 27b55edfa42f89ee8da517ef18edd673b26c5f0f | |
parent | 545aa41f5cba935d595a95cda650ffbdf87575ee (diff) |
xfs: shutdown after buf release in iflush cluster abort path
If xfs_iflush_cluster() fails due to corruption, the error path
issues a shutdown and simulates an I/O completion to release the
buffer. This code has a couple small problems. First, the shutdown
sequence can issue a synchronous log force, which is unsafe to do
with buffer locks held. Second, the simulated I/O completion does not
guarantee the buffer is async and thus is unlocked and released.
For example, if the last operation on the buffer was a read off disk
prior to the corruption event, XBF_ASYNC is not set and the buffer
is left locked and held upon return. This results in a memory leak
as shown by the following message on module unload:
BUG xfs_buf (...): Objects remaining in xfs_buf on __kmem_cache_shutdown()
Fix both of these problems by setting XBF_ASYNC on the buffer prior
to the simulated I/O error and performing the shutdown immediately
after ioend processing when the buffer has been released.
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r-- | fs/xfs/xfs_inode.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f643a9295179..4591598ca04d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -3614,7 +3614,6 @@ cluster_corrupt_out: | |||
3614 | * inode buffer and shut down the filesystem. | 3614 | * inode buffer and shut down the filesystem. |
3615 | */ | 3615 | */ |
3616 | rcu_read_unlock(); | 3616 | rcu_read_unlock(); |
3617 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
3618 | 3617 | ||
3619 | /* | 3618 | /* |
3620 | * We'll always have an inode attached to the buffer for completion | 3619 | * We'll always have an inode attached to the buffer for completion |
@@ -3624,11 +3623,14 @@ cluster_corrupt_out: | |||
3624 | * xfs_buf_submit(). | 3623 | * xfs_buf_submit(). |
3625 | */ | 3624 | */ |
3626 | ASSERT(bp->b_iodone); | 3625 | ASSERT(bp->b_iodone); |
3626 | bp->b_flags |= XBF_ASYNC; | ||
3627 | bp->b_flags &= ~XBF_DONE; | 3627 | bp->b_flags &= ~XBF_DONE; |
3628 | xfs_buf_stale(bp); | 3628 | xfs_buf_stale(bp); |
3629 | xfs_buf_ioerror(bp, -EIO); | 3629 | xfs_buf_ioerror(bp, -EIO); |
3630 | xfs_buf_ioend(bp); | 3630 | xfs_buf_ioend(bp); |
3631 | 3631 | ||
3632 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
3633 | |||
3632 | /* abort the corrupt inode, as it was not attached to the buffer */ | 3634 | /* abort the corrupt inode, as it was not attached to the buffer */ |
3633 | xfs_iflush_abort(cip, false); | 3635 | xfs_iflush_abort(cip, false); |
3634 | kmem_free(cilist); | 3636 | kmem_free(cilist); |