blog · git · desktop · images · contact & privacy · gopher


Handling full disk images in modern Linux

The internet is full with questions on how to mount single partitions from full disk images. To clarify: A “full” disk image is an image of an entire hard drive – including its boot record, partition table and, thus, individual partitions. Most of these answers state that you have to calculate offsets manually: Where does a particular partition begin inside the image? Where does it end? This is what I used to do all the time, too.

Turns out, in modern Linux, this is not needed anymore. Things are much easier now. Almost a no-brainer.

Full disk images

Let’s walk through the creation of an empty disk image from scratch.

First, you create an empty file (100MB):

$ dd if=/dev/zero of=disk.img bs=1M count=100

Then, you create some partitions inside of that image. That’s as simple as running fdisk on it:

$ fdisk disk.img

Now it’s time to create loop devices for this image and its partitions:

# losetup -Pf --show disk.img
/dev/loop0

What happens here?

  1. -f searches for the next free loop device and --show tells you which device has actually been used. You don’t have to care about that anymore.
  2. -P issues a “partition scan” on the loop device after its creation.

This means that you will now have not only /dev/loop0 but also additional device nodes for the partitions. In my example, I created two partitions:

$ ls -al /dev/loop0*
brw-rw---- 1 root disk   7, 0 Feb 18 19:17 /dev/loop0
brw-rw---- 1 root disk 259, 0 Feb 18 19:17 /dev/loop0p1
brw-rw---- 1 root disk 259, 1 Feb 18 19:17 /dev/loop0p2

$ cat /proc/partitions
major minor  #blocks  name

...

   7        0     102400 loop0
 259        0      20480 loop0p1
 259        1      80896 loop0p2

The partition scan takes care of finding where a partition starts and ends.

Note that, by default, the device nodes /dev/loop0 through /dev/loop7 are created on system boot. But – and that’s pretty awesome, too – once those eight nodes are exhausted, new nodes are created on the fly. I successfully created several thousand loop devices without any problems. In the dark ages, you had to tweak kernel module parameters to get more than eight nodes. Now, everything just works.

You can now use /dev/loop0p1 and /dev/loop0p2 as regular block devices. For example, you can create file systems:

# mkfs.ext4 /dev/loop0p1

And mount it:

# mount /dev/loop0p1 /mnt

That’s it! Dead simple.

When you’re done, unmount and detach the loop device:

# umount /mnt
# losetup -d /dev/loop0

All of this works since the introduction of /dev/loop-control. That’s about Linux 3.1 and util-linux 2.21, so all of this has been around for 3-4 years now.

Images of one single file system

If you have to deal with an image of just one file system (i.e., no partition table), then it’s even simpler:

# mount -o loop disk.img /mnt

That’s it.