AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 963740
Accepted
NickSoft
NickSoft
Asked: 2019-04-19 12:53:39 +0800 CST2019-04-19 12:53:39 +0800 CST 2019-04-19 12:53:39 +0800 CST

循环设备不会在卸载时自动分离

  • 772

我有一个备份脚本,我在其中卸载了一个 squashfs 文件,我进行备份然后再次将其安装回去。脚本的简化版本是:

umount /home/backup/auto/mnt/os
mksquashfs /src-dir /home/backup/auto/os.sqfs.img
mount -t squashfs -o loop /home/backup/auto/os.sqfs.img /home/backup/auto/mnt/os

这个想法是随时可以访问备份数据。

这工作了很长时间。但是,我收到一个错误,即没有足够的环回设备,并且我看到 umount 不再分离安装有 mount 的循环设备。

最近我有两个主要变化:

  1. 我将内核更新为 2.6.32-754.11.1.el6.i686
  2. 我将操作系统移至 SSD。

我刚刚注意到有新的内核更新 2.6.32-754.12.1.el6,所以我更新了,但它并没有解决问题。

操作系统:CentOS 6.10 i686

更新: 这是在故障系统上:

# strace -e trace=ioctl,mount mount -t squashfs -o loop os.sqfs.img mnt/os
ioctl(3, LOOP_GET_STATUS, {number=0, offset=0, flags=0, name="/home/squash/web.img", ...}) = 0
ioctl(3, LOOP_GET_STATUS, {number=0, offset=0, flags=0, name="/home/squash/web.img", ...}) = -1 ENXIO (No such device or address)
ioctl(4, LOOP_SET_FD, 0x3)              = 0
ioctl(4, LOOP_SET_STATUS64, {offset=0, number=0, flags=0, file_name="/home/backup/auto/os.sqfs.img", ...}) = 0
mount("/dev/loop1", "mnt/os", "squashfs", MS_MGC_VAL, NULL) = 0
+++ exited with 0 +++

# cat /etc/mtab|grep 'mnt/os'
/dev/loop1 /home/backup/auto/mnt/os squashfs ro,relatime 0 0

# ls -la /etc/mtab
lrwxrwxrwx. 1 root root 12 Apr 17 02:53 /etc/mtab -> /proc/mounts

# notice that here there is no even the umount call. Am I missing something?
# strace -e trace=ioctl,umount,mount umount mnt/os
+++ exited with 0 +++

这是在另一个具有相同版本的所有系统上,但它是 64 位的:

# strace -e trace=ioctl,mount mount -t squashfs -o loop os.sqfs.img mnt/os
ioctl(3, LOOP_GET_STATUS, {number=0, offset=0, flags=0, name="/storage/backup/auto/home.sqfs.img", ...}) = 0
ioctl(3, LOOP_GET_STATUS, {number=1, offset=0, flags=0, name="/storage/backup/auto/mail.sqfs.img", ...}) = 0
ioctl(3, LOOP_GET_STATUS, {number=1, offset=0, flags=0, name="/storage/backup/auto/mail.sqfs.img", ...}) = -1 ENXIO (No such device or address)
ioctl(4, LOOP_SET_FD, 0x3)              = 0
ioctl(4, LOOP_SET_STATUS64, {offset=0, number=0, flags=0, file_name="/storage/backup/auto/os.sqfs.img", ...}) = 0
mount("/dev/loop2", "mnt/os", "squashfs", MS_MGC_VAL, NULL) = 0
+++ exited with 0 +++

# strace -e trace=ioctl,umount,mount umount mnt/os
umount("/storage/backup/auto/mnt/os", 0) = 0
ioctl(3, LOOP_CLR_FD)                   = 0
+++ exited with 0 +++

# losetup -a
/dev/loop0: [0904]:35656625 (/storage/backup/auto/home.sqfs.img)
/dev/loop1: [0904]:35656626 (/storage/backup/auto/mail.sqfs.img)

我也没有在好的系统上看到 LO_FLAGS_AUTOCLEAR。但我确实看到了 umount 的不同。

我重新安装util-linux-ng了 - 它没有帮助。此软件包没有更新,也从未更新过。也许它与内核有关。我想知道为什么它在 64 位操作系统上运行良好。我可能会安装一个 32 位 VM 来测试它是否会这样做。

- 使固定 -

问题是我在系统复制期间使用 CentOS 7 的实时 CD 将 /etc/mtab 链接到 /proc/mounts 并且我忘记了它。我不得不重新安装 grub,所以我 chroot 到操作系统并建立了链接,因为 grub-install 不起作用。我忘了恢复它。我通过以下方式解决了这个问题:

rm -f /etc/mtab && cat /proc/mounts |grep -v rootfs > /etc/mtab

所以它现在有效:

root@home auto# smount os.sqfs.img mnt/os
root@home auto# losetup -a
/dev/loop0: [0816]:7090072 (/home/squash/web.img)
/dev/loop1: [0816]:7864675 (/home/backup/auto/os.sqfs.img)
/dev/loop4: [0816]:7864569 (/home/backup/auto/web.sqfs.img)
root@home auto# umount mnt/os
root@home auto# losetup -a
/dev/loop0: [0816]:7090072 (/home/squash/web.img)
/dev/loop4: [0816]:7864569 (/home/backup/auto/web.sqfs.img)
centos
  • 2 2 个回答
  • 1365 Views

2 个回答

  • Voted
  1. Best Answer
    Michael Hampton
    2019-04-23T20:53:23+08:002019-04-23T20:53:23+08:00

    这是我在 CentOS 6 中包含的 util-linux-ng 2.17.2 的源代码中收集到的:

    在小于 2.6.37 的内核上,Linux 要求/etc/mtab为循环挂载的文件系统写入一个条目,以便稍后自动清除循环设备。如果/etc/mtab在挂载时不可写或条目已从中删除,/etc/mtab则不会自动清除循环设备。在内核 >= 2.6.37 上,内核会记住循环设备后备存储路径,并且不需要在/etc/mtab.

    我能够在 CentOS 6.10 上通过/etc/mtab将chattr +i /etc/mtab. 仅仅删除它是不够的;它将至少使用部分安装表重新创建。这不是正常操作中应该发生的事情,因此如果您发现此文件已被设置为不可变,您应该寻找管理员错误或安全漏洞。

    如果/etc/mtab在您的旧 Linux 系统上不存在或不完整,您可以从/proc/mounts. 但是不要在现代 Linux 系统上执行此操作,/etc/mtab取而代之的是一个符号链接,/proc/self/mounts用于与期望在该位置安装表的古代代码向后兼容。

    • 4
  2. A.B
    2019-04-23T18:24:36+08:002019-04-23T18:24:36+08:00

    TL;DR:这似乎不是内核问题,但mount由于未设置循环设备的LO_FLAGS_AUTOCLEAR标志,该命令的行为不符合预期。使用更新的分发外挂载命令应该可以解决它。


    跟踪(最近系统的)命令挂载,导致我到loop(4)的标志LO_FLAGS_AUTOCLEAR:

    LO_FLAGS_AUTOCLEAR (since Linux 2.6.25)
        The loopback device will autodestruct on last close.
    

    所以我的“现代”安装命令成功地发出了这个 ioctl,如下所示:

    # strace -e trace=ioctl,mount mount -o loop /tmp/block.img /mnt/
    ioctl(3, LOOP_CTL_GET_FREE)             = 0
    ioctl(4, LOOP_SET_FD, 3)                = 0
    ioctl(4, LOOP_SET_STATUS64, {lo_offset=0, lo_number=0, lo_flags=LO_FLAGS_AUTOCLEAR, lo_file_name="/tmp/block.img", ...}) = 0
    ioctl(3, BLKGETSIZE64, [1073741824])    = 0
    ioctl(3, CDROM_GET_CAPABILITY, 0)       = -1 EINVAL (Invalid argument)
    ioctl(3, BLKSSZGET, [512])              = 0
    mount("/dev/loop0", "/mnt", "ext4", MS_MGC_VAL, NULL) = 0
    +++ exited with 0 +++
    # umount /mnt
    # losetup -l
    #
    

    (这里的 losttup 语法与 CentOS6 不同)。

    我想如果问题不在内核中(因为 OP 的 2.6.32 > 2.6.25),它可能来自 mount 命令。为了检查,我安装了一个 centos6-i686 LXC 容器,安装了 strace,创建了丢失的 /dev/loop* 文件并在内部运行了一个完全特权的 shell(使用lxc-attach's-e选项)允许执行挂载操作:

    # lxc-attach -e -n centos6-i686
    [root@centos6-i686 ~]# cat /etc/centos-release 
    CentOS release 6.10 (Final)
    # dd if=/dev/zero of=/tmp/block.img bs=1 count=1 seek=$((2**30-1))
    [...]
    # ls -lh /tmp/block.img 
    -rw-r--r--. 1 root root 1.0G Apr 22 19:06 /tmp/block.img
    # mkfs.ext4 /tmp/block.img 
    [...]
    # strace -e trace=ioctl,mount mount -o loop /tmp/block.img /mnt/
    ioctl(3, LOOP_GET_STATUS, {number=0, offset=0, flags=0, name="", ...}) = -1 ENXIO (No such device or address)
    ioctl(4, LOOP_SET_FD, 0x3)              = 0
    ioctl(4, LOOP_SET_STATUS64, {offset=0, number=0, flags=0, file_name="/tmp/block.img", ...}) = 0
    ioctl(3, BLKGETSIZE64, 1073741824)      = 0
    ioctl(3, CDROM_GET_CAPABILITY or SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, 0) = -1 EINVAL (Invalid argument)
    mount("/dev/loop0", "/mnt/", "ext4", MS_MGC_VAL, NULL) = 0
    +++ exited with 0 +++
    # umount /mnt
    # losetup --show /dev/loop0
    /dev/loop0: [003f]:1756539 (/tmp/block.img)
    # losetup -d /dev/loop0
    #
    

    显然 ioctl 没有发出 clear 标志,这导致了循环设备泄漏。查看源代码,这个功能似乎已经存在了很长时间,并且存在于 util-linux 2.17.2(CentOS6 的版本)中。CentOS6man mount甚至告诉我们:

    由于 Linux 2.6.25 支持循环设备的自动销毁,因此任何由 mount 分配的循环设备都将由 /etc/mtab 上的 umount 独立释放。

    所以我不知道为什么它不起作用,它似乎是一个错误(或者这可能与我的环境有关:64 位内核 5.0.x 等)。

    • 3

相关问题

  • 如何在 Linux 机器上找到有关硬件的详细信息?

  • 使用 crontab 和 /etc/cron.hourly,daily,weekly 的区别

  • 持续监控许多服务器运行状况的简单方法?

  • Hudson 无法在 tomcat5 中启动

  • CentOS 的依赖挑战

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve