Using kpartx/losetup With Disk Image (.img) Files and Partitions

Tony Tannous
The Startup
Published in
6 min readJun 12, 2020

--

Amongst the different types of virtual disk images, we occasionally bump into the .img type.

There are various methods that can be used when analyzing or working with these virtual disks, and/or their respective partitions.

This article describes some of these alternative options using a combination of mount, losetup, kpartx and loop devices.

Packages Required

Installing kpartx for mapping partitions. Using apt on Ubuntu, kpartx can installed as follows:

sudo apt install kpartx

Virtual Disk Image Demo Details

For examples used throughout the article, we’ll be using the .img file, as listed below, consisting of 2 partitions. Our primary focus will be on manipulating/mounting the data partition (i.e. partition number 2).

Name of Image: system_built_ext4.img

> ls system_built_ext4.imgsystem_built_ext4.img

Partition Details

Using parted, lets find partition detail info along with their respective offsets. These offsets will come in handy later on.

  • Run the command sudo parted system_built_ext4.img UNIT b print, as shown below. This tells parted to print out partition details, including start and end offsets in bytes,
> sudo parted system_built_ext4.img UNIT b print

which produces the following output:

Model:  (file)Disk /mnt/hgfs/vm-disks/system_built_ext4.img: 3232759808BSector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: Number Start End Size File system
1 1048576B 2097151B 1048576B
2 2097152B 3231711231B 3229614080B ext4
  • If your preference is to work in sectors, substitute UNIT b (bytes) with UNIT s(sectors) in the above command, i.e.
> sudo parted system_built_ext4.img UNIT s print

which generates the following output:

Model:  (file)Disk /mnt/hgfs/vm-disks/system_built_ext4.img: 6313984sSector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: Number Start End Size File system
1 2048s 4095s 2048s
2 4096s 6311935s 6307840s ext4

Partition Offset Calculations

Since offset calculations need to be accurate for mounts to work, we’ll start out by the outlining the different methods foroffsets calculations.

Method 1

From the output details of the first parted command above, our second partition (Number 2) is our data partition, and its starting point is at byte number 2097152. That's all there is to it. If you're using parted or any other partitioning tool that supports options for specifying your data units, then all you need to do is set output Units to bytes, and record the start offset of the partition.

Method 2

You will on some occasions see references to calculating start offset using the partition’s startsector. From the output of the second parted command above, we can see that partition Number 2 starts at sector 4096. You will also notice the output tells us that each sector is made up of 512 Bytes:

Sector size (logical/physical): 512B/512B

So, to calculate the offset in bytes using sectors and sector sizes

Partition 2, starts at sector : 4096
Number of bytes per sector : 512
Offset converted to bytes = 4096 * 512 = 2097152

Option 1: Mount using losetup

We’re going to mount our data partition (i.e. Number 2) to ablock/loop device, but lets do some exploration before we start.

Status of loop Devices

To get a status of all loop devices, we run:

> losetup -a

, which produces the output:

/dev/loop1: []: (/var/lib/snapd/snaps/core18_1754.snap)
/dev/loop6: []: (/var/lib/snapd/snaps/software-boutique_54.snap)
/dev/loop4: []: (/var/lib/snapd/snaps/core_9289.snap)
/dev/loop2: []: (/var/lib/snapd/snaps/software-boutique_39.snap)
/dev/loop0: []: (/var/lib/snapd/snaps/ubuntu-mate-welcome_539.snap)
/dev/loop5: []: (/var/lib/snapd/snaps/ubuntu-mate-welcome_420.snap)
/dev/loop3: []: (/var/lib/snapd/snaps/core_9066.snap)

From reading the notes listed in doco, man losetup, we can use the following commands:

  • to get the details of the first unused loop device, run losetup -f
> losetup -f/dev/loop7
  • setup a loop device and associate it with our virtual disk image (system_built_ext4.img), specifying the offset to where our data partition (Number 2) begins
> sudo losetup -f /mnt/hgfs/vm-disks/system_built_ext4.img -o 2097152
  • in the above losetup command, we pass the virtual disk image path/name as an argument to-f, followed by the offset -o in bytes of the partition's start location. This automatically "maps" the second partition within our virtual disk image with the first available loop device. Below has been taken from a man losetup
-f, --find [file] Find the first unused loop device. If a file argument is present, use the found device as loop device. Otherwise, just print its name.-o, --offset offset The data start is moved offset bytes into the specified file or device. The offset may be followed by the multiplicative suffixes
  • To confirm the the image is now associated with a loop device we run a losetup -a :
> sudo losetup -a/dev/loop7: [0050]:32 (/mnt/hgfs/vm-disks/system_built_ext4.img)
,offset 2097152
  • Now we can mount loop device onto a mount point and access the data/filesystem
> sudo mkdir /mnt/p2> sudo mount /dev/loop7 /mnt/p2
  • To confirm we have a valid mount
> df | grep loop7/dev/loop7       3055092      4616   2876396   1% /mnt/p2
  • To unmount /mnt/p2
> sudo umount /mnt/p2
  • To detach/free our loop device
> sudo losetup -d /dev/loop7

Option 2: One-Liner Mount Command

The mount command allows us to perform a mount with the option loop. Here are the details from man mount:

THE LOOP DEVICE
One further possible type is a mount via the loop device.
For example, the command
mount /tmp/disk.img /mnt -t vfat -o loop=/dev/loop3
will set up the loop device /dev/loop3
to correspond to the file /tmp/disk.img,
and then mount this device on /mnt.
If no explicit loop device is mentioned
(but just an option '-o loop'; is given),
then mount will try to find some

unused loop device and use that, for example
....
....
This type of mount knows about three options,
namely loop, offset and sizelimit....
  • So, translation of the above, we get our one-liner
> sudo mount /mnt/hgfs/vm-disks/system_built_ext4.img /mnt/p2 \
-o loop,offset=2097152
  • To confirm loop device to .img mapping
> sudo losetup -a /dev/loop7 [0050]:32 (/mnt/hgfs/vm-disks/system_built_ext4.img)
, offset 2097152
> df | grep loop7/dev/loop7 3055092 4616 2876396 1% /mnt/p2
  • To unmount filesystem and detach loop device
> sudo umount /mnt/p2

Option 3: Using kpartx

With kpartx, we get the benefit of not having to worry about partition offsets. kpartx handles the partition device mappings automatically. Refer to the extracts from parts of man kpartx, which are attached at the end of this section.

  • List partitions by specifying -l as an option
> sudo kpartx -l /mnt/hgfs/vm-disks/system_built_ext4.imgloop7p1 : 0 2048 /dev/loop7 2048
loop7p2 : 0 6307840 /dev/loop7 4096
  • To setup the partition mappings
> sudo kpartx -a -v /mnt/hgfs/vm-disks/system_built_ext4.imgadd map loop7p1 (253:0): 0 2048 linear 7:7 2048
add map loop7p2 (253:1): 0 6307840 linear 7:7 4096
  • According to the output of man, we can use the mappings, established by the above command, at location /dev/mapper to access the partitions, i.e. /dev/mapper/loop7p1 & /dev/mapper/loop7p2
  • To mount our Number 2 partition,
> sudo mount /dev/mapper/loop7p2 /mnt/p2
  • and to confirm the the mount has occurred
> df | grep loop7p2/dev/mapper/loop7p2   3055092      4616   2876396   1% /mnt/p2
  • Once you’re done, remove devices as follows
> sudo umount /mnt/p2> sudo kpartx -d /mnt/hgfs/vm-disks/system_built_ext4.img

kpartx man Excerpts

NAME: kpartx - Create device maps from partition tables.
SYNOPSIS
kpartx [-a|-d|-u|-l] [-r] [-p] [-f] [-g] [-s] [-v] wholedisk
DESCRIPTIONThis tool, derived from util-linux's; partx,
reads partition tables on specified device
and create device maps over partitions segments
detected.
OPTIONS
-a Add partition mappings.
-d Delete partition mappings.
-u Update partition mappings.
-l List partition mappings that would be added -a.
-r Read-only partition mappings.
-p Set device name-partition number delimiter.
-f Force creation of mappings;
overrides 'no_partitions' feature.
-g Force GUID partition table (GPT).
-s Sync mode. Don't return until the partitions are created.
-v Operate verbosely.
EXAMPLE
To mount all the partitions in a raw disk image:
kpartx -av disk.img
This will output lines such as:
add map loop1p1 (254:4): 0 409597 linear 7:1 3
The loop1p1 is the name of a device file under /dev/mapper which you can use to access the partitionWhen you're done, you need to remove the devices:
kpartx -d disk.img

Logging Out of this Article

There is nothing new about the techniques used in this article, i.e. you will find several online examples of the methods that were described. My main aim was to take an independent approach and use the official man documentation as a reference to gain an understanding of the commands themselves, rather than copying and pasting from existing blogs/websites.

I’ve also covered the use of libguestfs-tools, via a custom docker, in one of my previous articles for working with virtual disk images, which is, yet again, another approach you could look into for working with virtual .img images.

--

--

Tony Tannous
The Startup

Learner. Interests include Cloud and Devops technologies.