有许多帖子losetup -d /dev/loop0
说不移除回溯设备,即使它返回了成功的返回代码。我相信这些帖子的根本原因是块设备autoclear
设置了标志,因此losetup
只能调用,LOOP_CLR_FD
而不能调用LOOP_CTL_REMOVE
。其他进程必须仍持有文件描述符,因此循环设备不会被分离或移除。这可以通过以下方式确认strace
:
$ sudo losetup -J -l | jq '.'
{
"loopdevices": [
{
"name": "/dev/loop0",
"sizelimit": 0,
"offset": 0,
"autoclear": true,
"ro": false,
"back-file": "/example/backing_file",
"dio": false,
"log-sec": 512
}
]
}
$ sudo strace -ff losetup -d /dev/loop0
...
newfstatat(AT_FDCWD, "/dev/loop-control", {st_mode=S_IFCHR|0660, st_rdev=makedev(0xa, 0xed), ...}, 0) = 0
openat(AT_FDCWD, "/dev/loop0", O_RDONLY|O_CLOEXEC) = 3
ioctl(3, LOOP_CLR_FD) = 0
close(3) = 0
...
常见的答案是 (a) 查找从循环设备挂载的任何文件系统上打开的所有文件,然后 (b) 卸载循环设备。通常建议使用lsof
和。/proc/**/fd
我的问题是,我遇到了从未安装过的块设备的问题。我无论如何也找不到哪个进程持有这个循环设备的文件描述符,因此无法关闭它。
一个快速测试 C 程序表明我可以从块设备中删除自动清除标志:
$ sudo strace -ff --verbose=ioctl /tmp/remove-autoclear
...
openat(AT_FDCWD, "/dev/loop0", O_RDONLY|O_CLOEXEC) = 3
ioctl(3, LOOP_CLR_FD) = 0
close(3) = 0
write(1, "INFO: Result of sending LOOP_CLR"..., 57) = 57
INFO: Result of sending LOOP_CLR_FD to /dev/loop0 was: 0
openat(AT_FDCWD, "/dev/loop-control", O_RDONLY|O_CLOEXEC) = 3
ioctl(3, LOOP_CTL_REMOVE, 0) = -1 EBUSY (Device or resource busy)
write(2, "ERROR(16): Sending LOOP_CTL_REMO"..., 94) = 94
ERROR(16): Sending LOOP_CTL_REMOVE to /dev/loop-control for device 0: Device or resource busy
openat(AT_FDCWD, "/dev/loop0", O_RDONLY|O_CLOEXEC) = 4
ioctl(4, LOOP_GET_STATUS, {lo_number=0, lo_offset=0, lo_flags=LO_FLAGS_AUTOCLEAR, lo_name="/example/backing_file", ...}) = 0
write(1, "INFO: Autoclear bit for /dev/loo"..., 40) = 40
INFO: Autoclear bit for /dev/loop0 is 1
ioctl(4, LOOP_SET_STATUS, {lo_number=0, lo_offset=0, lo_flags=0, lo_name="/example/backing_file", ...}) = 0
ioctl(4, LOOP_GET_STATUS, {lo_number=0, lo_offset=0, lo_flags=0, lo_name="/example/backing_file", ...}) = 0
write(1, "INFO: Successfully removed autoc"..., 56) = 56
INFO: Successfully removed autoclear bit for /dev/loop0
close(4) = 0
ioctl(3, LOOP_CTL_REMOVE, 0) = -1 EBUSY (Device or resource busy)
write(2, "ERROR(16): Sending LOOP_CTL_REMO"..., 94) = 94
ERROR(16): Sending LOOP_CTL_REMOVE to /dev/loop-control for device 0: Device or resource busy
exit_group(16) = ?
+++ exited with 16 +++
INFO: Result of sending LOOP_CLR_FD to /dev/loop0 was: 0
ERROR(16): Sending LOOP_CTL_REMOVE to /dev/loop-control for device 0: Device or resource busy
INFO: Autoclear bit for /dev/loop0 is 1
INFO: Successfully removed autoclear bit for /dev/loop0
ERROR(16): Sending LOOP_CTL_REMOVE to /dev/loop-control for device 0: Device or resource busy
$ sudo cat /sys/dev/block/7:0/loop/autoclear
0
但有趣的是,这不会losetup -d /dev/loop0
因硬错误而失败。这似乎是因为LOOP_CLR_FD
再次设置了自动清除标志。这与查找持有打开文件描述符的进程无关,我只是注意到了这一点,因为它是“远距离的幽灵行动”,它解释了为什么losetup
从不尝试调用LOOP_CTL_REMOVE
。
关于如何查找持有文件描述符的进程,/dev/loop0
以便我可以在不重新启动的情况下正确清理它,有什么建议吗?
$ sudo ls -l /proc/**/fd | grep loop0
$ sudo ls -l /proc/**/fd | grep backing_file
$ sudo lsof | grep loop0
$ sudo lsof | grep backing_file
$ sudo mount | grep loop