Using kpartx/losetup With Disk Image (.img) Files and Partitions
By: Tony Tannous
Tags: Kpartx, Disk Img, Mount, Loopback, Virtualization

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.img system_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: 3232759808B Sector 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: 6313984s Sector 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 for offsets 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 start sector . 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 a block/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.img loop7p1 : 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.img add 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

, we can use the mappings, established by the above command, at location to access the partitions, i.e. & 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 DESCRIPTION This 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 partition When 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.