[PATCH 11/12] xfs: drop s_umount over opening the log and RT devices

Christoph Hellwig
2023-08-02T15:43:32Z

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>
---
fs/xfs/xfs_super.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 8185102431301d..d5042419ed9997 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -448,17 +448,21 @@ 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;

+ /* see get_tree_bdev why this is needed and safe */
+ 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_unlock;
}

if (mp->m_rtname) {
@@ -496,7 +500,10 @@ xfs_open_devices(
mp->m_logdev_targp = mp->m_ddev_targp;
}

- return 0;
+ error = 0;
+out_unlock:
+ down_write(&sb->s_umount);
+ return error;

out_free_rtdev_targ:
if (mp->m_rtdev_targp)
@@ -508,7 +515,7 @@ xfs_open_devices(
out_close_logdev:
if (logdev && logdev != ddev)
xfs_blkdev_put(mp, logdev);
- return error;
+ goto out_unlock;
}

/*
--
2.39.2