Please enable Javascript to view the contents

loop device 生命周期管理

 ·  ☕ 3 分钟

1. 创建镜像文件

1.1 loop存储适用场景

把普通文件当成 /dev/loopN 块设备来用,读写走块设备接口,backing file 仍是宿主机上的一个文件

  • 挂载 ISO 与磁盘镜像
  • 本地练手与压测
  • 加密卷与密文镜像
  • 模拟云盘或 CSI 块卷
  • 只读暴露文件
  • 临时挂载

和真实磁盘相比,loop 设备性能受 backing file 所在文件系统影响,关联默认不持久化,重启后一般要重新 losetup 或写进 /etc/fstab

1.2 创建镜像

在宿主机上准备 backing file

  • 稀疏文件,按需分配空间
1
truncate -s 10G /data/tmp/disk.img
  • 预分配全量空间,适合压测
1
dd if=/dev/zero of=/data/tmp/disk.img bs=1M count=10240
  • 预分配全量空间,比 dd 更快
1
fallocate -l 10G /data/tmp/disk.img
  • 指定块大小,与目标文件系统块对齐
1
dd if=/dev/zero of=/data/tmp/disk.img bs=4k count=2621440

2. 关联 loop 设备

把镜像文件挂到 /dev/loopN

  • 自动分配空闲 loop 设备并关联
1
losetup -f --show /data/tmp/disk.img
  • 指定 loop 设备关联
1
losetup /dev/loop0 /data/tmp/disk.img
  • 关联时指定扇区大小与只读模式
1
2
3
losetup /dev/loop0 /data/tmp/disk.img \
  --sector-size 4096 \
  --read-only
  • 查看所有已关联的 loop 设备
1
losetup -a
  • 查看某个 loop 设备详情
1
losetup -l /dev/loop0
  • 反查镜像文件对应的 loop 设备
1
losetup -j /data/tmp/disk.img
  • 按列查看 loop 设备信息
1
losetup -O NAME,BACK-FILE,STATE,MAJ:MIN /dev/loop0

3. 分区与格式化

在 loop 设备上建分区表或直接格式化

  • 创建 GPT 分区表与分区
1
2
parted -s /dev/loop0 mklabel gpt
parted -s /dev/loop0 mkpart primary 0% 100%
  • 用 kpartx 加载分区映射
1
kpartx -av /dev/loop0

会生成 /dev/mapper/loop0p1,避免分区设备未自动创建。

  • 直接在整盘创建文件系统
1
2
3
mkfs.xfs /dev/loop0
mkfs.ext4 /dev/loop0
mkfs.btrfs /dev/loop0
  • 对分区格式化
1
mkfs.xfs /dev/mapper/loop0p1
  • xfs 只读检查
1
xfs_repair -n /dev/loop0
  • ext4 只读检查
1
e2fsck -fn /dev/loop0

4. 挂载与使用

挂载 loop 设备或镜像文件

  • 创建挂载点
1
mkdir -p /mnt/looptest
  • 普通挂载
1
mount /dev/loop0 /mnt/looptest
  • 只读挂载
1
mount -o ro /dev/loop0 /mnt/looptest
  • 指定文件系统类型挂载
1
mount -t xfs /dev/loop0 /mnt/looptest
  • 挂载分区设备
1
mount /dev/mapper/loop0p1 /mnt/looptest
  • 直接挂载镜像文件
1
mount -o loop /data/tmp/disk.img /mnt/looptest

mount 会自动寻找空闲 loop 设备。

  • 验证挂载
1
2
findmnt /mnt/looptest
mount | grep loop0

5. 扩容

镜像扩容后需同步更新 loop 设备与文件系统

  • 扩容镜像文件到 20G
1
fallocate -l 20G /data/tmp/disk.img
  • 仅修改镜像大小元数据
1
truncate -s 20G /data/tmp/disk.img
  • 通知 loop 设备重读容量
1
losetup -c /dev/loop0
  • xfs 在线扩容
1
xfs_growfs /mnt/looptest
  • ext4 在线扩容
1
resize2fs /dev/loop0
  • ext4 扩容到指定大小
1
resize2fs /dev/loop0 20G
  • 扩容分区表中的第 1 个分区
1
growpart /dev/loop0 1
  • 通知内核重读分区表
1
partprobe /dev/loop0

6. 卸载与解除关联

按挂载 → 分区映射 → loop 关联的顺序释放

  • 卸载文件系统
1
umount /mnt/looptest
  • lazy 卸载
1
umount -l /mnt/looptest
  • 杀掉占用挂载点的进程
1
fuser -km /mnt/looptest
  • 移除 kpartx 分区映射
1
kpartx -d /dev/loop0
  • 解除 loop 设备关联
1
losetup -d /dev/loop0
  • 解除所有 loop 设备关联
1
losetup -D

慎用,会影响所有 loop 设备。

7. 清理

删除镜像并确认无残留设备

  • 删除镜像文件
1
rm -f /data/tmp/disk.img
  • 确认无残留 loop 设备
1
2
losetup -a
ls /dev/loop* 2>/dev/null
  • 查看 mapper 设备
1
dmsetup ls | grep loop
  • 移除 mapper 设备
1
dmsetup remove loop0p1

8. 批量生命周期示例

循环创建与批量清理

  • 批量创建 5 个 loop 设备
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
for i in $(seq 0 4); do
  IMG=/data/tmp/disk_${i}.img
  MNT=/mnt/loop_${i}
  truncate -s 5G $IMG
  LOOP=$(losetup -f --show $IMG)
  mkfs.xfs -f $LOOP
  mkdir -p $MNT
  mount $LOOP $MNT
  echo "$LOOP -> $MNT ($IMG)"
done
  • 批量卸载并清理
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
for i in $(seq 0 4); do
  MNT=/mnt/loop_${i}
  IMG=/data/tmp/disk_${i}.img
  LOOP=$(losetup -j $IMG | awk -F: '{print $1}')
  [ -n "$LOOP" ] && {
    umount $MNT 2>/dev/null
    losetup -d $LOOP
  }
  rm -f $IMG
  rmdir $MNT 2>/dev/null
done

9. 状态查看速查

loop 设备与内核模块排查

  • 所有 loop 设备一览
1
losetup -l
  • 简明列表
1
losetup -a
  • 查找某文件对应的 loop 设备
1
losetup -j /data/tmp/disk.img
  • 查看 loop 内核模块
1
2
lsmod | grep loop
modinfo loop
  • 查看 loop 设备最大数量
1
cat /sys/module/loop/parameters/max_loop
  • 临时调整最大数量
1
modprobe loop max_loop=32

重启后失效。

  • 永久调整最大数量
1
echo "options loop max_loop=32" > /etc/modprobe.d/loop.conf

10. 常见问题

  • losetup: /dev/loop0: Device or resource busy:先查占用再释放
1
2
3
losetup -a
lsof /dev/loop0
fuser -m /mnt/xxx
  • losetup -f 找不到空闲设备:检查并调大 max_loop
1
2
cat /sys/module/loop/parameters/max_loop
modprobe loop max_loop=32
  • mount: /dev/loop0 is already in use:先解除关联再重建
1
2
losetup -a
losetup -d /dev/loop0
  • 分区设备 /dev/loop0p1 未生成:用 kpartx 创建 mapper
1
kpartx -av /dev/loop0
  • 扩容后文件系统未识别新大小:先重读 loop 容量再扩文件系统
1
2
3
losetup -c /dev/loop0
xfs_growfs /mnt/looptest
resize2fs /dev/loop0
  • losetup -c 报错:先 umount,再 losetup -c,再重新 mount
1
2
3
umount /mnt/looptest
losetup -c /dev/loop0
mount /dev/loop0 /mnt/looptest
  • 重启后 loop 关联丢失:关联非持久化,需写入 fstab 或 systemd unit 开机自动 setup

  • fallocate 在 ext3 等文件系统上失败:改用 dd 预分配

1
dd if=/dev/zero of=/data/tmp/disk.img bs=1M count=10240

微信公众号
作者
微信公众号