I'm trying to play around with OS development, and I started with a boot loader, where phase 0 loads phase 1 from a file (specified by inode) on an ext4 partition (specified by first LBA). Of course, I need something to boot from, so I grabbed QEMU. Now what?

What has worked fine so far is this:

truncate -s64M /tmp/SomeVolume
/sbin/mke2fs -t ext4 -F /tmp/SomeVolume
yasm phase0.asm
dd if=phase0 of=/tmp/SomeVolume conv=notrunc

I make a volume of about 64 MB, format it as ext4, and overwrite the first 1024 octets with phase0 (which is always 1024 bytes in size). This works fine.

But now I want to make a properly partitioned file, to test it for more realistic scenarios. I know I could /sbin/cfdisk my volume file, but mke2fs doesn't have a parameter that lets me choose a span within the file.

Now I'm aware of solutions using loop, but unfortunately, it doesn't seem to work for me (it seems I'm not able to change max_part in Debian jessie). There seems to be another module called nbd, but I don't have the server and client for that module installed. And it's getting a little ridiculous that I need root privileges for something that could clearly be done in userland.

How can I do this as a user? Or should I just build the MBR/GPT-partitioned volume around the ext4-formatted file I created?


4 Answers 4


The long way around. But for the fun of it:

1. Create a temporary image:

    $ truncate -s64MiB tmp.img

2. Create two partitions using fdisk:

Rather detailed, but OK.

$ fdisk tmp.img

First partition:

: n <Enter>
: <Enter> (p)
: <Enter> (1)
: <Enter> (2048)
: +40M <Enter>

Second partition:

: n <Enter>
: <Enter> (p)
: <Enter> (2)
: <Enter> (83968)
: <Enter> (131071)

Print what we are about to write:

: x
: p
Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 00  32  33    0  57  52    5       2048      81920 83
 2 00  57  53    5  40  32    8      83968      47104 83

Write and exit:

:w (Dont! forget ;-) )

We have two partitions of 40 and 23 MiB:

81920 * 512 / 1024 / 1024 = 40MiB
47104 * 512 / 1024 / 1024 = 23MiB

3. Create two file systems:

truncate -s40MiB ext4.img
truncate -s23MiB ext3.img
mke2fs -t ext4 -F -L part_ext4 ext4.img
mke2fs -t ext3 -F -L part_ext3 ext3.img

4. Stitch it all together:

Extract first 2048*512 bytes from temporary image:

dd if=tmp.img of=disk.img bs=512 count=2048

Combine them:

cat ext4.img ext3.img >> disk.img


  • I'm starting to think there is no easy way to do this otherwise. Thanks for the effort :)
    – Rhymoid
    Oct 8, 2013 at 17:09
  • @Rhymoid this indeed seems rather overcomplicated and error-prone. Please read my answer and go for option 4 - the least painful and most "natural".
    – peterph
    Oct 8, 2013 at 22:16

I'm not really sure I inderstand your question correctly. If you are trying to partition VM image, you have several options:

  1. use loops or device mapper in linear mode for each partition. You don't need to have these set-up in parallel for formatting;

  2. partx/kpartx to tell kernel what partitions it should consider on a loop/device mapper devices or even a regular file:

    kpartx -av /path/to/file


    losetup /dev/loopX /path/to/file
    kpartx -av /dev/loopX

    The devices are device mapper devices (i.e. linked to from /dev/mapper by default).

  3. using partprobe

    losetup /dev/loopX /path/to/file
    partprobe /dev/loopX

    which will instruct the kernel to check the partitioning, hence creating /dev/loopXpY.

  4. boot live CD/USB image (can be an installer) in the VM and do the partitioning from within. This has the obvious advantage of being able to partition the virtual drive even for VM images stored in special formats (like QEMU's qcow2 for example).

  • The problem is that my disk image is regular file, and not mounted as a block device. partx doesn't work, probably for that reason (man page says that the parameter needs to be a block device, and partx dies with "failed to read partition table"; ). For some reason, I can't seem to configure loop to support partitions, as explained. I could try the third option, but it seems like a round-about method. I just want to expose a span within a regular file to mke2fs as if it were a partition.
    – Rhymoid
    Oct 8, 2013 at 15:30
  • Loop devices do not support partitions. You need either to create the partition devices with (k)partx or by hand. Or boot the VM and do it from the inside.
    – peterph
    Oct 8, 2013 at 16:08
  • Loop devices sure do support partitions, which is why partx, parted, and partprobe can activate them. kpartx is for activating partitions on device-mapper devices ( by creating another dm device ), since they don't natively support partitions.
    – psusi
    Oct 8, 2013 at 17:49
  • @psusi Indeed, you're right with kernel being able to handle partitions on loop devices itself (when being told by partprobe to do so). However, kpartx actually works for loop devices as well (and actually for regular files as well).
    – peterph
    Oct 8, 2013 at 22:12
  • @peterph, it works, but it's (slightly) less efficient since it creates a linear device-mapper device stacked on top of the loop device. Better to rely on the kernel's native partitioning support via partx, partprobe, or parted's native handling.
    – psusi
    Oct 9, 2013 at 4:22


Seems to have some info on this. It looks like you can mount the raw disk as a loopback device:

Mount your raw disk image as a loopback device: losetup /dev/loop0 [path to image]

Run kpartx and: kpartx -va /dev/loop0

This will add your partitions to /dev/mapper/loop0pX where each X is a different partition

You can now mount each partition: mount /dev/mapper/loop0pX /media/partition

If you want to make sure you do not write anything to your backup simply mount it as read-only: mount -o ro /dev/mapper/loop0pX /media/partition

Once you are finished you will need to do your clean up.

Unmount: umount /media/partition Remove the mapper devices: kpartx -d /dev/loop0 Remove the loopback device: losetup -d /dev/loop0

These commands may all need to be run as root. If loop0 reports that it is busy just pick another loop device (/dev/loop1, ect).

-edit: I see you want to do this non-root, so the above may not be useful to you.


You don't need to mess with max_part. Use parted to create the partitions on the loop device, or partprobe to activate them if they already exist. You may need to upgrade to the version of parted in testing/unstable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.