Disk images are a common way to copy existing drives for forensic analysis, backup or migration between machines. With the help of loop devices, they can also be mounted directly as virtual block devices, behaving just like any other disk.
Supported disk image types
There are two types of image formats we will cover in this article:
Raw disk copies. Typically use the
.imgfile extension and contain a literal copy of all bytes of a physical disk with either a single filesystem, or a complete partition layout with partition table.ISO 9660 images using the
.isoextension. Initially used as read-only media for CDs, they are now mostly used as boot files, often with a hybrid layout containing both a partition table with an EFI partition and a legacy ISO9660 filesystem.
Other formats used as virtual machine disks, like vdi, vmdk or qcow2 are not directly mountable using loop devices alone, as they require specific drivers and software dependencies.
Loop devices
A loop device is a virtual device file in linux systems that allows treating a file like a raw block device. A block device is the linux term for "anything that can store data", like disks, thumb drives, dvd writers etc.
Typically, mounting a block device like a disk involves three steps:
Find the device (eg /dev/sda)
Find the target partition on the device
Mount the filesystem in that partition
A loop device repeats these steps twice, first for the raw physical device, then within the disk image file:
Find the device (eg (/dev/sda
Find the target partition on the device
Find the disk image file on the filesystem on the partition
Find the target partition inside the image file
Mount the filesystem in that partition
Effectively, it loops through the normal mounting process twice, thus the name "loop device".
Creating sample disk images
Let's create two disk images to use in sample commands.
The first is a plain disk without partitions:
fallocate -l 1GiB simple.img
sudo mkfs.ext4 simple.imgThe second is a multi-partition disk image with a GPT partition table, a 300MB partition and a larger one covering the remaining space.
fallocate -l 1GiB partitioned.img
sudo parted -s partitioned.img \
mklabel gpt \
mkpart primary ext4 1MiB 301MiB \
mkpart primary ext4 301MiB 100%
LOOP_DEV=$(sudo losetup -Pf --show partitioned.img)
sudo mkfs.ext4 "${LOOP_DEV}p1"
sudo mkfs.ext4 "${LOOP_DEV}p2"
sudo losetup -d "$LOOP_DEV"Both image types are perfectly supported by loop devices and mount. You can use an existing .iso file instead, the commands for mounting and setting up loop devices are the same for both.
Mounting plain images
If you have a .imgor .iso file that does not contain a partition table, the mount has a shortcut:
mount -o loop simple.img /mntYou should prefer this version for simple images and iso files, as it automatically manages loop devices and lifetimes for you, reusing or creating a new one during mount and detaching it when unmounting.
Mounting partitioned images
Loop devices are accessible as files in /dev/loopX, where X is either a number (e.g. loop1) or a number plus partition identifier (e.g. loop1p1). Modern linux systems automatically create, reuse and remove loop devices as needed, through the /dev/loop-control interface.
You will likely only ever interact with the loop device controller through the losetup command.
To mount a partitioned disk image file, first a new loop device needs to be attached:
sudo losetup -Pf --show partitioned.imgThe command will print the name of the loop device attached to the image file, for example loop1.
Partitions within the disk image are made available through devices with partition identifiers. You can run lsblk to see more information about partitions available through the loop device:
loop1 7:1 0 1G 0 loop
├─loop1p1 259:4 0 300M 0 part
└─loop1p2 259:5 0 722M 0 part The image contains two partitions, available as loop1p1 and loop1p2 (your loop device names may be different).
You can now mount the partitions like you would any other with mount:
mount /dev/loop1p1 /mntAfter unmounting, you will need to detach the loop device from the image file again:
sudo losetup -d loop1Remember to always unmount any partitions before detaching loop devices and use the loop device name (e.g. loop4) instead of the partition identifier ((e.g. loop4p2) when detaching.
Resolving out of device errors
When running losetup commands, you may see errors like:
losetup: cannot find an unused loop deviceThis can be caused by two separate issues. Loop devices are managed dynamically and created on the fly as needed - within limits. The most likely problem is that you are using all available loop devices. You can check all loop devices in use with:
sudo losetup -aOutput may look like:
/dev/loop1: [0042]:410560 (/tmp/disk/partitioned.img)You can then use sudo losetup -d <name> to detach one, or sudo losetup -D to detach them all (careful, may break services like incus!).
If you do not want to detach any of your existing loop devices, the only way forward is to increase the limit of total available loop devices.
Check the current limit with:
cat /sys/module/loop/parameters/max_loopTo increase it, write the new setting for the loop kernel module:
echo "options loop max_loop=128" > /etc/modprobe.d/loop.confRestart your machine to apply the changes.
You could also increase the limit at runtime, but that would require detaching all existing loop devices and would vanish after a reboot, so it is not reliable to use.
If you absolutely cannot reboot and need a higher limit, detach all loop devices, then unload the loop kernel module and load it with a higher limit:
sudo losetup -D
sudo modprobe -r loop
sudo modprobe loop max_loop=128This approach is really only useful for ephemeral systems like CI runners and should not be used on long-running servers.