btrfs:为什么安装选项不应用于子卷?

btrfs:为什么安装选项不应用于子卷?

我正在运行 openSUSE Tumbleweed,并在安装 btrfs 子卷时发现奇怪的行为。我在 btrfs 文件系统上有两个子卷:@media@migration。我的/etc/fstab设置是这样的:

UUID=<UUID>       /mnt/media      btrfs   subvol=/@media,noatime,noexec,nodev,nosuid      0       0
UUID=<UUID>       /mnt/migration  btrfs   subvol=/@migration,noatime,noexec,nodev,nosuid  0       0

但是,当我运行时mount -a,我得到以下信息:

/dev/sdb1 on /mnt/media type btrfs (rw,nosuid,nodev,noexec,noatime,space_cache=v2,subvolid=278,subvol=/@media)
/dev/sdb1 on /mnt/migration type btrfs (rw,relatime,space_cache=v2,subvolid=279,subvol=/@migration)

如您所见,安装选项nosuid,nodev,noexec,noatime似乎仅应用于安装的第一个子卷。第二个只有relatime.

当我尝试重新安装第二个子卷,它显示正确:

:~> sudo mount -o remount,noatime /dev/sdb1 /mnt/migration
:~> mount | tail -n 2
/dev/sdb1 on /mnt/media type btrfs (rw,nosuid,nodev,noexec,noatime,space_cache=v2,subvolid=278,subvol=/@media)
/dev/sdb1 on /mnt/migration type btrfs (rw,noatime,space_cache=v2,subvolid=279,subvol=/@migration)

所以我的问题是:

  1. 后续子卷上的挂载选项重要吗? (也就是说,这只是一个视觉错误吗?)
  2. 有什么方法可以验证挂载选项是否真正生效?

答案1

子卷挂载实际上遵循 noatime。这是在新的 btrfs 文档中明确指出的(尽管不清楚)。https://btrfs.readthedocs.io/en/latest/btrfs-subvolume.html#mount-options

(他们还支持 noexec,这就是我的目的。)

$ sudo mount -o subvolid=257,noatime /dev/sdd1 test
$ touch -a -t 9001010101 test/foo
$ stat test/foo
Access: 1990-01-01 01:01:00.000000000 -0700
$ cat test/foo # noatime: atime unchanged
$ stat test/foo
Access: 1990-01-01 01:01:00.000000000 -0700
$ sudo umount test
$ sudo mount -o subvolid=257 /dev/sdd1 test
$ cat test/foo # default (relatime): atime changed
$ stat test/foo
Access: 2023-09-20 03:50:37.919732794 -0600

(为了简洁起见,已剪掉 stat 的其他输出行)

答案2

我的声望还不到50,所以我无法评论squircle的自我回答。但测试是有缺陷的。touch -a无论安装点选项如何,都会更新 atime。

/tmp
 32% ❯ sudo mount -t tmpfs -o noatime none noatime

/tmp
 32% ❯ cd noatime/

/tmp/noatime
 32% ❯ touch banana

/tmp/noatime
 32% ❯ stat banana
  File: banana
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 0,116   Inode: 2           Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/vytautas)   Gid: (  100/   users)
Access: 2022-04-14 00:03:14.714042647 +0300
Modify: 2022-04-14 00:03:14.714042647 +0300
Change: 2022-04-14 00:03:14.714042647 +0300
 Birth: -

/tmp/noatime
 32% ❯ cat banana

/tmp/noatime
 32% ❯ stat banana
  File: banana
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 0,116   Inode: 2           Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/vytautas)   Gid: (  100/   users)
Access: 2022-04-14 00:03:14.714042647 +0300
Modify: 2022-04-14 00:03:14.714042647 +0300
Change: 2022-04-14 00:03:14.714042647 +0300
 Birth: -

/tmp/noatime
 32% ❯ touch -a -t 1212121212 banana

/tmp/noatime
 32% ❯ stat banana
  File: banana
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 0,116   Inode: 2           Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/vytautas)   Gid: (  100/   users)
Access: 2012-12-12 12:12:00.000000000 +0200
Modify: 2022-04-14 00:03:14.714042647 +0300
Change: 2022-04-14 00:03:39.030547903 +0300
 Birth: -

答案3

我设法使用 btrfs wiki 和一些简单的实验来回答我的问题。

后续子卷上的挂载选项重要吗?

不。根据维基百科

笔记:大多数挂载选项适用于整个文件系统,并且只有第一个挂载的子卷中的选项才会生效。这是由于缺乏实施造成的,并且将来可能会发生变化。这意味着(例如)您无法使用安装选项设置每个子卷的 nodatacow、nodatasum 或压缩。这个问题最终应该得到解决,但事实证明很难在 Linux VFS 框架内正确实现。

有什么方法可以验证挂载选项是否真正生效?

是的。我用atime/noatime参数做到了这一点:

  1. atime使用选项挂载子卷 1
  2. noatime使用选项挂载子卷 2
  3. 在子卷 2 上创建测试文件
  4. 用于touch将 atime 设置为任意值(例如touch -a -t 12121212 test_file
  5. 验证 atime 是否设置为测试值ls -lu

此实验将显示,尽管子卷 2 是使用该选项挂载的,但其 atime 已在子卷 2 上更新noatime。这是因为子卷 1 是首先使用该atime选项挂载的。

相关内容