Friday, September 9, 2011

mounting images with kpartx or losetup + fdisk

Loop-mounting partitions from a disk image
    Update: it seems that kpartx pretty much does all of the below. Thanks to Faidon Liambotis for the pointer.

    Every now and then, I have a disk image (as produced by cat, pv, or dd) and I need to access separate partitions. Unfortunately, the patch allowing partitions on loop devices to be accessed via their own device nodes does not appear to be in the latest (Debian) 2.6.18 kernels — the loop module does not have a max_partmodinfo. parameter, according to

    So this time I sat down to come up with a recipe on how to access the partitions, and after some arithmetic and much swearing at disk manufacturers, and especially the designers of the msdos partition table type, I think I have found the solution, and the urge to document it for posterity.

    It’s all about the -o parameter to losetup, which specifies how many bytes into the disk a given partition starts. Getting this number isn’t straight forward. Well, it is, if you know how, which is why I am writing this.

    Let’s take a look at a partition table, with sectors as units:
    $ /sbin/fdisk -lu disk.img
    You must set cylinders.
    You can do this from the extra functions menu.
    Disk disk.img: 0 MB, 0 bytes
    255 heads, 63 sectors/track, 0 cylinders, total 0 sectors
    Units = sectors of 1 * 512 = 512 bytes
          Device Boot      Start         End      Blocks   Id  System
    disk.imgp1   *          63       96389       48163+  83  Linux
    disk.imgp2           96390     2056319      979965   82  Linux swap / Solaris
    disk.imgp3         2056320    78140159    38041920    5  Extended
    disk.imgp5         2056383     3052349      497983+  83  Linux
    disk.imgp6         3052413    10859939     3903763+  83  Linux
    disk.imgp7        10860003    68372639    28756318+  83  Linux
    disk.imgp8        68372703    76180229     3903763+  83  Linux
    disk.imgp9        76180293    78140159      979933+  83  Linux
    The first few lines is fdisk complaining not being able to extract the number of cylinders, since it has to operate on a file which does not provide an ioctl interface.

    The first important data are the units, which are stated to be 512 bytes per sector. We take note of this value as the factor for use in the next operation.
    Let’s say we want to access the 7th partition, which is 10860003 sectors into the disk, according to the fdisk output. We know that each sector is 512 bytes, so:
    10860003 * 512 = 5560321536
    Passing this number to losetup produces the desired result:
    # losetup /dev/loop0 disk.img -o $((10860003 * 512))
    # file -s /dev/loop0
    /dev/loop0: Linux rev 1.0 ext3 filesystem data
    # mount /dev/loop0 /mnt
    # umount /mnt
    # losetup -d /dev/loop0
    If the partition really holds a normal filesystem, you can also let mount set up the loop device, and manage it automatically:
    # mount -o loop,offset=$((10860003 * 512)) disk.img /mnt
    # umount /mnt
    And since there’s aparently no means to automate the whole process for an entire disk, I hacked up plosetup. Enjoy:
    # plosetup lapse.hda .
    I: partition 1 of lapse.hda will become ./lapse.hda_p1 (/dev/loop0)...
    I: plosetup: skipping partition 2 of type 82...
    I: plosetup: skipping partition 3 of type 5...
    I: partition 5 of lapse.hda will become ./lapse.hda_p5 (/dev/loop1)...
    I: partition 6 of lapse.hda will become ./lapse.hda_p6 (/dev/loop2)...
    I: partition 7 of lapse.hda will become ./lapse.hda_p7 (/dev/loop3)...
    I: partition 8 of lapse.hda will become ./lapse.hda_p8 (/dev/loop4)...
    I: partition 9 of lapse.hda will become ./lapse.hda_p9 (/dev/loop5)...
    # ls -l
    total 0
    lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p1 -> /dev/loop0
    lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p5 -> /dev/loop1
    lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p6 -> /dev/loop2
    lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p7 -> /dev/loop3
    lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p8 -> /dev/loop4
    lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p9 -> /dev/loop5
    # plosetup -c .
    # ls -l
    total 0
    Kpartx can be used to set up device mappings for the partitions of any 
    partitioned block device. It is part of the Linux multipath-tools. With 
    kpartx -l imagefile you get an overview of the partitions in the image 
    file and with kpartx -a imagefile the partitions will accessible 
    via /dev/mapper/loop0pX (X is the number of the partition). 
    You can mount it now with mount /dev/mapper/loop0pX /mnt/ -o loop,ro
    After unmounting you can disconnect the mapper devices with kpartx -d 

    No comments:

    Post a Comment