我正在通过环回设备(例如)处理一些磁盘映像/dev/loop0
。在磁盘(磁盘工具)应用程序中查看时,有一个标记为“自动清除”的设置,当前设置为关闭。
此设置有何作用?它特定于环回设备吗?
(我怎么才能自己找到答案呢?试过“磁盘”>“帮助”,但它似乎不支持以合理的方式搜索,而且我不知道该选择哪个顶级选项(..有人要目录吗?))
答案1
是的,它特定于循环设备。这意味着当循环设备被卸载时,它将自动与备份文件解除关联。
答案2
最小可运行示例
首先我们创建一个测试文件系统正如这里解释的那样:
mkdir sysroot
dd if=/dev/urandom of=sysroot/myfile bs=1024 count=1024
virt-make-fs --format=raw --type=ext2 sysroot sysroot.ext2
现在:
$ mkdir mnt
$ # mount can deduce "-o loop -t ext2" nowadays.
$ sudo mount sysroot.ext2 mnt
$ # Mount worked fine.
$ cmp mnt/myfile sysroot/myfile
$ losetup
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop0 0 0 1 0 /home/ciro/sysroot.ext2 0 512
$ # I don't trust userland.
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
1
$ sudo umount
$ losetp
$
因此我们看到mount
:
- 创建循环设备
- 默认设置 AUTOCLEAR -o loop -t ext2
然后当umount
看到设置了 AUTOCLEAR 时,它会自动销毁该文件。
最小反例
通过使用 手动创建循环设备losetup
,我们可以看到当未设置 AUTOCLEAR 时会发生什么:
$ sudo losetup /dev/loop0 sysroot.ext2
losetup: sysroot.ext2: Warning: file does not fit into a 512-byte sector; the end of the file will be ignored.
$ losetup
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop0 0 0 0 0 /home/ciro/sysroot.ext2 0 512
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
0
$ sudo mount /dev/loop0 mnt
$ cmp mnt/myfile sysroot/myfile
$ sudo umount mnt
$ losetup
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop0 0 0 0 0 /home/ciro/sysroot.ext2 0 512
$ sudo mount /dev/loop0 mnt
$ sudo umount -d mnt
$ losetup
因此我们看到:
umount
没有选项没有为我们清除循环设备umount -d
确实清除了
或者,我们也可以使用以下方法分离循环设备:
sudo mount /dev/loop0 mnt
sudo umount mnt
sudo losetup -d /dev/loop0
在使用的文件系统上自动丢失
man losetup
说:
-d
分离与指定循环设备关联的文件或设备。请注意,由于 Linux v3.7 内核使用“延迟设备销毁”。如果设备被系统主动使用,则分离操作不再返回 EBUSY 错误,但它会被标记为自动清除标志并在稍后销毁。
并通过以下方式验证:
$ sudo losetup /dev/loop0 sysroot.ext2
$ sudo mount /dev/loop0 mnt
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
0
$ sudo losetup -d /dev/loop0
$ cat /sys/devices/virtual/block/loop0/loop/autoclear
1
$ # Still mounted.
$ cmp mnt/myfile sysroot/myfile
$ sudo umount mnt
$ losetup
$
所以我们看到,如果你losetup -d
之前做过umount
,它会autoclear
自动设置。
低级视图
快速:
sudo strace mount sysroot.ext2 mnt
显示主要的系统调用有:
openat(AT_FDCWD, "/dev/loop0", O_RDWR|O_CLOEXEC) = 4
ioctl(4, LOOP_SET_STATUS64, {lo_offset=0, lo_number=0, lo_flags=LO_FLAGS_AUTOCLEAR, lo_file_name="/home/ciro/sysroot.ext2", ...}) = 0
mount("/dev/loop0", "/home/ciro/test/libguestfs/mnt", "ext2", MS_MGC_VAL, NULL) = 0
所以我们看到losetup
操作基本上都是通过完成的ioctl
。
感兴趣的内核源代码 v4.17 是:
include/uapi/linux/loop.h
:包含用户空间可见的API,包括放置ioctl
结构体struct loop_info64
LO_FLAGS_AUTOCLEAR
drivers/block/loop.h
包含实际实现
如果您不熟悉,请看一下这个最小的例子ioctl
:https://stackoverflow.com/questions/2264384/how-do-i-use-ioctl-to-manipulate-my-kernel-module/44613896#44613896
在 Ubuntu 18.04 上测试。
答案3
我不是循环设备方面的专家,但我可以向您介绍我所做的事情,以找出一些问题。
在一个知名搜索引擎上搜索“自动清除循环”后,我发现——除了这个问题——修补为 gnome-disk-utility 添加了该功能。
我确实看不懂代码,但我认为关键部分可能涉及函数udisks_loop_call_set_autoclear
。
我搜索了这一点,找到了 UDisks 参考手册,发现它调用了一个名为设置自动清除,结果设置了“自动清除”属性。这显然意味着:
如果为 TRUE,则当最后一个关闭器关闭设备时,内核将自动清除循环设备。这通常发生在循环设备卸载时。
搜索“清除循环设备”(或搜索man losetup
‘清除’)并没有太多帮助,所以此时我猜测“清除”只是“分离”的同义词。
我在手册页中找不到有关自动分离循环的任何内容,因此认为也许它发生在安装级别。
查看man mount
并搜索“循环”,我发现了这句话:
自 Linux 2.6.25 起,支持循环设备自动销毁,这意味着任何由 mount 分配的循环设备都将由 umount 独立于 /etc/mtab 释放。
我猜测“自动毁灭”基本上是“自动清除”的另一个同义词。
因此,自 2008 年内核版本起,mount
卸载时会自动清除自动创建的任何循环。但显然,您可以通过在 Gnome 磁盘实用程序中拨动开关来绕过该循环。
我假设也有一种方法可以从命令行控制它,这就是我想要给你的答案,但我无法轻易找到它。
我可能需要仔细阅读更多的代码(也许寻找调用类似函数的其他项目),或者了解有关循环设备或内核的更多信息。