summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_super.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2023-08-02 17:41:30 +0200
committerChristian Brauner <brauner@kernel.org>2023-08-11 13:15:04 +0200
commit8d945b595ed07db13fef1f3311ad456c97941930 (patch)
tree081d94cc85e1d7f48b68876c5f3c1679e8dd94ee /fs/xfs/xfs_super.c
parent8bed1783751fc8d0a5a263dcf87838a2fa570953 (diff)
xfs: drop s_umount over opening the log and RT devices
Just like get_tree_bdev needs to drop s_umount when opening the main device, we need to do the same for the xfs log and RT devices to avoid a potential lock order reversal with s_unmount for the mark_dead path. It might be preferable to just drop s_umount over ->fill_super entirely, but that will require a fairly massive audit first, so we'll do the easy version here first. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Message-Id: <20230802154131.2221419-12-hch@lst.de> Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/xfs/xfs_super.c')
-rw-r--r--fs/xfs/xfs_super.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 46d0cbe2b5f8..97ef41acb03d 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -462,17 +462,24 @@ STATIC int
xfs_open_devices(
struct xfs_mount *mp)
{
- struct block_device *ddev = mp->m_super->s_bdev;
+ struct super_block *sb = mp->m_super;
+ struct block_device *ddev = sb->s_bdev;
struct block_device *logdev = NULL, *rtdev = NULL;
int error;
/*
+ * blkdev_put() can't be called under s_umount, see the comment
+ * in get_tree_bdev() for more details
+ */
+ up_write(&sb->s_umount);
+
+ /*
* Open real time and log devices - order is important.
*/
if (mp->m_logname) {
error = xfs_blkdev_get(mp, mp->m_logname, &logdev);
if (error)
- return error;
+ goto out_relock;
}
if (mp->m_rtname) {
@@ -510,7 +517,10 @@ xfs_open_devices(
mp->m_logdev_targp = mp->m_ddev_targp;
}
- return 0;
+ error = 0;
+out_relock:
+ down_write(&sb->s_umount);
+ return error;
out_free_rtdev_targ:
if (mp->m_rtdev_targp)
@@ -523,7 +533,7 @@ xfs_open_devices(
out_close_logdev:
if (logdev && logdev != ddev)
blkdev_put(logdev, mp);
- return error;
+ goto out_relock;
}
/*