Thursday, November 6, 2008

Mouting partitions with losetup

References (previous posts):
Virtual Drives on Linux
Playing with mount and loopback devices
Encrypted Filesystems

One issue I faced with using loopback devices to mount hard disk images was that everything works fine as long as you have the disk image as one single filesystem. But if you use fdisk on the loop back device and created partitions, then I could not quite figure out a way to mount these.

One intuitive way to do this would be as described in http://vytautas.jakutis.lt/node/26 . In brief, what they do is:
# rmmod loop
# modprobe loop max_part=63
# losetup -f /path/to/your/disk/image.raw
# mount /dev/loop0p1 /mnt/path
Unfortunately, that doesn't work for me. The max_part=63 parameter is rejected by modprobe for me. Guess something else needs to be enabled/compiled-into my kernel for me to support this. (My kernel qualifies by the version info they give there, though)

But then, there's a simpler option. One can specify an offset in the file where the loop back device should begin. From what I've gathered, the first sector, sector 0 in a disk contains the partition table I guess. And then, the first partition starts at sector 1, and ends at sector n. The next from n+1 to n+m and so on.

So if we specify the start sector's byte offset (start_sector * 512 normally) as the offset for the loop back device, we can access the particular partition.
Reference: http://www.docunext.com/blog/2007/07/08/losetup-working-with-raw-disk-images/

So say if we have a disk image data.raw, ( say we used qemu_img to create this from a vmware vmdk disk) then we can attach the whole disk to a loop device and run fdisk to get the start sector of the partition
vmathew:/data/vmathew/vmware/dsl # losetup /dev/loop0 data.raw
vmathew:/data/vmathew/vmware/dsl # fdisk /dev/loop0

Command (m for help): p

Disk /dev/loop0: 1073 MB, 1073741824 bytes
255 heads, 63 sectors/track, 130 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xb96bb154

Device Boot Start End Blocks Id System
/dev/loop0p1 1 63 506016 83 Linux
/dev/loop0p2 64 130 538177+ 83 Linux

Command (m for help):
But note here that the units displayed is cylinders. Our second partition starts at cylinder 64, but we don't know the exact sector. To find this information
Command (m for help): u
Changing display/entry units to sectors

Command (m for help): p

Disk /dev/loop0: 1073 MB, 1073741824 bytes
255 heads, 63 sectors/track, 130 cylinders, total 2097152 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0xb96bb154

Device Boot Start End Blocks Id System
/dev/loop0p1 63 1012094 506016 83 Linux
/dev/loop0p2 1012095 2088449 538177+ 83 Linux

Command (m for help):
Now we quit the fdisk tool. We have our start sector = 1012095. So our start offset = 1012095*512 = 518192640. Thus to mount this file, we first detach the loopback and create it at this offset, and then just mount it.
Command (m for help): q

vmathew:/data/vmathew/vmware/dsl # losetup -d /dev/loop0
vmathew:/data/vmathew/vmware/dsl # losetup --offset 518192640 /dev/loop0 data.raw
vmathew:/data/vmathew/vmware/dsl # mount -t ext3 /dev/loop0 temp/
vmathew:/data/vmathew/vmware/dsl # ls temp/
jklh.txt lost+found
vmathew:/data/vmathew/vmware/dsl #
Additionally, checkout the manpage on qemu-img (you need qemu installed) to learn to use this gorgeous converter which can convert between some standard disk image types.

.

4 comments:

Unknown said...

Hello, there's a much simpler method of doing this than guessing offsets:

# losetup /dev/loop<N> <myimage>

# mdadm --build --force <somename> --level linear --raid-devices 1 /dev/loop<N>

And this will read the partition table from your image file. You will then see the partitions in the /dev/md*p* files.

Matt | Varghese Mathew said...

Thanks andrej, that's really good to know !

Thanassis said...

Even better:

losetup -fP /dev/yourDevice

Thanassis said...

Even better solution:

losetup -fP /dev/someDevice

This will auto-scan for partition information, and create proper devices (/dev/loop0p1, etc).