Commit b7fdfd29 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: only set the device specific options after devices are opened



[BUG]
With v6.17-rc kernels, btrfs will always set 'ssd' mount option even if
the block device is not a rotating one:

  # cat /sys/block/sdd/queue/rotational
  1
  # cat /etc/fstab:
  LABEL=DATA2     /data2  btrfs rw,relatime,space_cache=v2,subvolid=5,subvol=/,nofail,nosuid,nodev      0 0

  # mount
  [...]
  /dev/sdd on /data2 type btrfs (rw,nosuid,nodev,relatime,ssd,space_cache=v2,subvolid=5,subvol=/)

[CAUSE]
The 'ssd' mount option is set by set_device_specific_options(), and it
expects that if there is any rotating device in the btrfs, it will set
fs_devices::rotating.

However after commit bddf57a7 ("btrfs: delay btrfs_open_devices()
until super block is created"), the device opening is delayed until the
super block is created.

But the timing of set_device_specific_options() is still left as is,
this makes the function be called without any device opened.

Since no device is opened, thus fs_devices::rotating will never be set,
making btrfs incorrectly set 'ssd' mount option.

[FIX]
Only call set_device_specific_options() after btrfs_open_devices().

Also only call set_device_specific_options() after a new mount, if we're
mounting a mounted btrfs, there is no need to set the device specific
mount options again.

Reported-by: default avatarHAN Yuwei <hrx@bupt.moe>
Link: https://lore.kernel.org/linux-btrfs/C8FF75669DFFC3C5+5f93bf8a-80a0-48a6-81bf-4ec890abc99a@bupt.moe/


Fixes: bddf57a7 ("btrfs: delay btrfs_open_devices() until super block is created")
CC: stable@vger.kernel.org # 6.17
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 53a4acbf
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -1900,8 +1900,6 @@ static int btrfs_get_tree_super(struct fs_context *fc)
		return PTR_ERR(sb);
	}

	set_device_specific_options(fs_info);

	if (sb->s_root) {
		/*
		 * Not the first mount of the fs thus got an existing super block.
@@ -1946,6 +1944,7 @@ static int btrfs_get_tree_super(struct fs_context *fc)
			deactivate_locked_super(sb);
			return -EACCES;
		}
		set_device_specific_options(fs_info);
		bdev = fs_devices->latest_dev->bdev;
		snprintf(sb->s_id, sizeof(sb->s_id), "%pg", bdev);
		shrinker_debugfs_rename(sb->s_shrink, "sb-btrfs:%s", sb->s_id);