From: Josef Bacik btrfs/330 uncovered a problem where we were accidentally turning off the free space tree when we do the transition from ro->rw. This happens because we don't update Signed-off-by: Josef Bacik Signed-off-by: Daniel Vacek --- v5: https://lore.kernel.org/linux-btrfs/325598eeb1d23f9ae04f675b4ee218f7e98e3ff0.1706116485.git.josef@toxicpanda.com/ * Re-wrapped comments. * Fixed argument type. mount_opt is now ull. --- fs/btrfs/disk-io.c | 2 +- fs/btrfs/super.c | 28 +++++++++++++++------------- fs/btrfs/super.h | 3 ++- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index f47a20976b53..993d2080fcbf 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3416,7 +3416,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device * Handle the space caching options appropriately now that we have the * super block loaded and validated. */ - btrfs_set_free_space_cache_settings(fs_info); + btrfs_set_free_space_cache_settings(fs_info, &fs_info->mount_opt); if (!btrfs_check_options(fs_info, &fs_info->mount_opt, sb->s_flags)) { ret = -EINVAL; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 06788b27a870..4a2887147ead 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -745,10 +745,10 @@ bool btrfs_check_options(const struct btrfs_fs_info *info, } /* - * This is subtle, we only call this during open_ctree(). We need to pre-load - * the mount options with the on-disk settings. Before the new mount API took - * effect we would do this on mount and remount. With the new mount API we'll - * only do this on the initial mount. + * Because we have an odd set of behavior with turning on and off the space cache + * and free space tree we have to call this before we start the mount operation + * after we load the super, or before we start remount. This is to make sure we + * have the proper free space settings in place if the user didn't specify any. * * This isn't a change in behavior, because we're using the current state of the * file system to set the current mount options. If you mounted with special @@ -756,21 +756,22 @@ bool btrfs_check_options(const struct btrfs_fs_info *info, * settings, because mounting without these features cleared the on-disk * settings, so this being called on re-mount is not needed. */ -void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info) +void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info, + unsigned long long *mount_opt) { - if (fs_info->sectorsize != PAGE_SIZE && btrfs_test_opt(fs_info, SPACE_CACHE)) { + if (fs_info->sectorsize != PAGE_SIZE && btrfs_raw_test_opt(*mount_opt, SPACE_CACHE)) { btrfs_info(fs_info, "forcing free space tree for sector size %u with page size %lu", fs_info->sectorsize, PAGE_SIZE); - btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE); - btrfs_set_opt(fs_info->mount_opt, FREE_SPACE_TREE); + btrfs_clear_opt(*mount_opt, SPACE_CACHE); + btrfs_set_opt(*mount_opt, FREE_SPACE_TREE); } /* * At this point our mount options are populated, so we only mess with * these settings if we don't have any settings already. */ - if (btrfs_test_opt(fs_info, FREE_SPACE_TREE)) + if (btrfs_raw_test_opt(*mount_opt, FREE_SPACE_TREE)) return; if (btrfs_is_zoned(fs_info) && @@ -780,10 +781,10 @@ void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info) return; } - if (btrfs_test_opt(fs_info, SPACE_CACHE)) + if (btrfs_raw_test_opt(*mount_opt, SPACE_CACHE)) return; - if (btrfs_test_opt(fs_info, NOSPACECACHE)) + if (btrfs_raw_test_opt(*mount_opt, NOSPACECACHE)) return; /* @@ -791,9 +792,9 @@ void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info) * them ourselves based on the state of the file system. */ if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) - btrfs_set_opt(fs_info->mount_opt, FREE_SPACE_TREE); + btrfs_set_opt(*mount_opt, FREE_SPACE_TREE); else if (btrfs_free_space_cache_v1_active(fs_info)) - btrfs_set_opt(fs_info->mount_opt, SPACE_CACHE); + btrfs_set_opt(*mount_opt, SPACE_CACHE); } static void set_device_specific_options(struct btrfs_fs_info *fs_info) @@ -1573,6 +1574,7 @@ static int btrfs_reconfigure(struct fs_context *fc) sync_filesystem(sb); set_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state); + btrfs_set_free_space_cache_settings(fs_info, &ctx->mount_opt); if (!btrfs_check_options(fs_info, &ctx->mount_opt, fc->sb_flags)) return -EINVAL; diff --git a/fs/btrfs/super.h b/fs/btrfs/super.h index d80a86acfbbe..584f428d36e2 100644 --- a/fs/btrfs/super.h +++ b/fs/btrfs/super.h @@ -16,7 +16,8 @@ bool btrfs_check_options(const struct btrfs_fs_info *info, int btrfs_sync_fs(struct super_block *sb, int wait); char *btrfs_get_subvol_name_from_objectid(struct btrfs_fs_info *fs_info, u64 subvol_objectid); -void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info); +void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info, + unsigned long long *mount_opt); static inline struct btrfs_fs_info *btrfs_sb(struct super_block *sb) { -- 2.51.0