Mounting a hard disk image including partitions using Linux

A while ago I thought it would be a good idea to make a backup of my Linux server by just dumping the complete disk to a file. In retrospect, it would have been much easier had I just dumped the individual filesystems.

When I finally got around to using this backup, long after the 10GB disk had perished I realized that to use the loopback device to mount a filesystem it actually needs a filesystem to mount. What I had was a disk image, including partition table and individual partitions. To further complicate matters the data partition was also not the first partition inside this image.

For reference, I created this image using the Unix ‘dd’ tool:

# dd if=/dev/hda of=hda.img
30544113+0 records in
30544113+0 records out
# ls -lh
-rw-r--r-- 1 root    root  9.6G 2008-01-22 14:12 hda.img

I followed the instructions on http://www.trekweb.com/~jasonb/articles/linux_loopback.html to try and mount the partitions inside the disk image, but ran into two problems.

To mount a partition inside the disk image you need to calculate the offset of where the partition starts. You can use fdisk to show this information to you, but you need to specify the number of cylinders if you are using a disk image.

You then also need to multiply the start and end numbers with the calculated sectors to get a byte offset.

I found another tool more useful for this task, called parted. If you are using Ubuntu, you can install it with ‘apt-get install parted’

# parted hda.img
GNU Parted 1.7.1
Using /data/rabbit/disk_image/test2
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit
Unit?  [compact]? B
(parted) print
Disk /data/rabbit/disk_image/test2: 10262568959B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number  Start        End           Size         Type     File system  Flags
1      32256B       106928639B    106896384B   primary  ext3         boot
2      106928640B   1184440319B   1077511680B  primary  linux-swap
3      1184440320B  10256924159B  9072483840B  primary  ext3
(parted) quit

Now we have the offsets and we can use those to mount the filesystems using the loopback device:

#mount -o loop,ro,offset=32256 hda.img /mnt/rabbit

That mounted the first partition, the ‘boot’ partition, but this didn’t have the data on it that I was looking for. Lets try to mount partition number 3.

#umount /mnt/rabbit
#mount -o loop,ro,offset=1184440320 test2 /mnt/rabbit
#mount: wrong fs type, bad option, bad superblock on /dev/loop0,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail  or so

Oops, that doesn’t look right. According the article referred to above if you are using a util-linux below v2.12b then you cannot specify an offset higher than 32bits. I’m using util-inux 2.13 which shouldn’t have that problem, and besides, my offset is well below the 32bit limit.

The article also offers an alternative loopback implementation that supports mounting partitions within an image, but that requires patching and recompiling your kernel which I would rather not do.

Instead I decided to extra ct the filesystem from the image which would then allow me to mount it without specifying an offset.
Doing this is quite straightforward with ‘dd’. You need to give ‘dd’ a skip count, or, how far into the source to start copying, and a count, how much to copy.
Here you can either use the single byte offsets retrieved with parted or divide them by 512 and let ‘dd’ use 512 byte blocks. Copying just one byte at a time takes a very long time, so I suggest using a larger block size.

Here is the command I used to extract my filesystem. Skip is 2313360 (1184440320/512) and Count is 17719695 (9072483840/4)

#dd if=hda.img of=hda3.img bs=512 skip=2313360 count=17719695
17719695+0 records in
17719695+0 records out
9072483840 bytes (9.1 GB) copied, 485.679 seconds, 18.7 MB/s

After extracting the filesystem I was able to mount it without any problems.

# mount -o loop hda3.img /mnt/rabbit/
# df -h /mnt/rabbit
Filesystem            Size  Used Avail Use% Mounted on
/data/rabbit/image/hda3.img
8.4G  6.3G  1.7G  80% /mnt/rabbit

55 thoughts on “Mounting a hard disk image including partitions using Linux”

  1. This is one solution, but a more elegant solution is to use the offset-flag in loop-mounting.

    In stead of splitting up your image you can just type inn mount -o loop,offset=[same offset as calculated above].

  2. I do mention the offset option in my article, but that it has limitations. I offered the splitting as an alternative to using that if you’re having problems with it.

  3. Thanks for your article, it really heped me a lot while I was trying to find out what is wrong with my Xen disk image with multiple partitions.

  4. Very helpful!
    I spent one whole afternoon on mounting a dd image found on the DVD from the book ‘Real Digital Forensics’.
    By following your steps, it just cost me one minute.
    I love you!

  5. Makes sense. I made a backup of latptop disk with 1 ntfs partition and 1 dos partition using dd if=/dev/sda and was trying to figure out how to extract the partition. This is what I was looking for. I hope it works.

  6. Great article!

    I would just like to point to a small error :
    “.. and Count is 17719695 (9072483840/4) ”

    It should be “.. and Count is 17719695 (9072483840/512)” .

  7. All useful information – just a followup. If your ext3 partition has been uncleanly unmounted (or you took a dump from a live system, say running as a VM) then you won’t be able to mount it directly as the journal is unclean. Follow the “dd” instructions above to extract just the partition, then run

    “fsck.ext3 hda3.img”

    to repair the filesystem before mounting.

  8. To follow up on comment #8 — here’s a page I found that explains very clearly where the “wrong fs type, bad option, bad superblock” mount error is coming from, and how to deal with it.

    (Spoiler alert: Yes, it’s all because of an unclean journal. :))

  9. This worked well for me. This article also applies to loading a vmware disk image that has several partitions.

    I used this to mount my vmware disk as a disk image…

    sudo vmware-mount -f Frog/Frog.vmdk /mnt/frog/

    I could then mount individual partitions in the image like this….

    sudo mount -t ntfs -o loop,offset=10487232000B /mnt/frog/flat /mnt/toad/

    vmware-mount seems to have issues with partitioned disks. This provided a great way to work around those issues.

  10. I was just going to backup a drive with dd, realized I’d never actually mounted a partition within a (partitioned) disk image, and went looking to see if I should dd by partition instead of device. Thanks for the useful answer.

  11. The easiest way for me seems just to use the tool testdisk:

    testdisk IMAGEFILE

    you can simply see all partitions under advanced tools
    and also can extract partitions as an image file

  12. Thanks for this useful post. I often work with partial disk images and parted does not like to print information about the partition table when the partition goes beyond the end of the image. But I found an offset of 32256 works more often than not!

  13. Thank you so much. Due to the completely undocumented removal of lomount from any toolkits, including xen-utils, getting at an individual partition seemed impossible (go man pages) until I came across this article.

    Btw – if you wanted to specify a filesystem in particular for a loop mounted partition….how would you do that? I dont know why you’d want to override mount’s auto findings but still….power is power.

    Cheers
    Jon

  14. An easy way to mount a partition is the follwing command:
    IMG=”hda.img”;PART=1;mount -o loop,ro,offset=$(parted $IMG -s unit b print|awk ‘$1==’$PART’ {sub(/B/,”",$2);print $2}’) $IMG /mnt/rabbit
    .
    If you must copy this partition you can use similar subcommands to calculate the offset. You can use the bc command to calculate skip and count if the blocksize (bs) is larger as 1.

  15. Using parted to work out the partition offsets allowed me to salvage some important files from a VirtualBox disk image that I converted to a raw image as it wouldn’t boot. Thanks!

    1. Do not miss @mikko’s answer! kpartx creates the device files for your image file so you can use the partitions just like a real disk.

      kpartx -a hda.img
      mount /dev/mapper/hda.img3

      Thanks mikko.

      1. Kpartx is the easy solution to this problem. Works like a charm.
        I’m really glad I read the comments, thanks. (750Gb of disk space saved)

  16. I know its an old article, but I wanted to comment that the reason your command to mount your offset partition inside your original disk image did not work could be because of a possible typo.

    # parted hda.img
    GNU Parted 1.7.1
    Using /data/rabbit/disk_image/test2

    You say the disk image is hda.img with your parameter for parted, but then parted says you are using a whole other file (/data/rabbit/disk_image/test2). When I run parted, my output is like so:

    esoul@dionysus:/twoTB/eSoulBackup$ sudo parted ./taylor.dd
    GNU Parted 2.3
    Using /twoTB/eSoulBackup/taylor.dd

    I know the version numbers are different and mine is newer, but it doesn’t have any effect on using mount to mount the partition at an offset. What really kills it for could be your mount parameters —

    #mount -o loop,ro,offset=1184440320 test2 /mnt/rabbit

    This fails possibly because you are not in the same folder as test2. Either cd to the directory or put the full path to the disk image and all is fine. Like so —

    esoul@dionysus:/twoTB/eSoulBackup$ sudo mount -o ro,loop,offset=1573912576 taylor.dd /mnt/temp
    esoul@dionysus:/twoTB/eSoulBackup$

    No errors, no complaints, I can list directory contents just fine.

    This is also a disk image with a NTFS file system and a “hidden” partiton before it. I have plenty of disk images sitting on my backup server and everyone of them will mount partitions inside of the device image with no problems.

  17. @16
    Thanks a ton! Testdisk is infinitely better! I’ve been trying ChromeOS builds from Hexxah but since they’re built automatically sometimes they are corrupted. Using Testdisk I can quickly check to make sure that everything is ok. Testdisk even allows filebrowsing and much more! Will be using this tool from now on.

  18. In the line:
    #mount -o loop,ro,offset=1184440320 test2 /mnt/rabbit
    Was “test2″ supposed to be “test2″, or was it supposed to be “hda.img”?
    That could make a difference.

  19. At least for Ubuntu Lucid, mounting offsets well beyond a 32-bit limit works flawlessly. Thanks for saving me a ton of time and copying!

    I really prefer to image the whole drive so that I get boot sectors, etc and it can boot from a restored image with zero hassle. I just always thought that it came with the drawback of not being able to access the partitions in these images…

  20. For whoever searched for this solution and found this page… In regards to this error when mounting with an offset:

    [root@LAKITU:backup] 14# mount -o loop,ro,offset=1074790400 /media/backup/ssd.img /media/oldUbuntu/
    mount: wrong fs type, bad option, bad superblock on /dev/loop0,
    missing codepage or helper program, or other error
    In some cases useful info is found in syslog – try
    dmesg | tail or so

    The problem was:
    [ 3432.775087] Buffer I/O error on device loop0, logical block 7816661
    [ 3432.814275] EXT4-fs (loop0): INFO: recovery required on readonly filesystem
    [ 3432.814277] EXT4-fs (loop0): write access unavailable, cannot proceed

    Mounting once with write-support enabled allowed for recovery.

  21. Pingback: The Hijax!
  22. You saved my day as I was unable to boot my xen machine for the simple reason that a non xen kernel was specified in grub.conf as default.
    With your mount examples I was able to mount the boot partition of the disk image file and change the default kernel.

  23. Pingback: Mount a .img file
  24. Great solution, here’s a way to get the offset to mount with: -o loop,offset=

    echo | fdisk -l /path/to/image.img | grep -A 20 “Device Boot” | awk ‘{print $1,$3 * 512}’

    1. Made a mistake sorry, simplest solution is this and works without additional software installation:

      fdisk -l /path/to/image.img | awk ‘{print $1,$3 * 512}’

      You should discard the top 9 lines

      1. made another mistake oops, sorry for spam, here it is:

        fdisk -l /path/to/image.img | awk ‘{print $1,$2,$3 * 512,$4,$5,$6,$7}’

  25. Thanks for this post – just the info I needed and it was clearly explained. Thanks too to @mikko’s kpartx suggestion which does recovering on the filesystem for you automatically.

  26. I wish people wouldn’t act like this is a good solution. I’m trying to mount a whole image including the boot sectors, this is not going to allow that. How do I mount the entire image?

    1. The term ‘mounting’ usually refers to mounting a filesystem. I am not sure what you mean by mounting the whole image including the boot sectors? This article deals with mounting a filesystem that is contained within a whole-disk image.

  27. Thank you. I had purchased Mass Effect 3 during the steam winter sale for US$15 but I am a hopeless linux die hard and when upgrading the hardware I did the unbelievable and went from Windows XP to Windows 8. Please understand that I love linux, but also love video games. I used dd to preserve my old windows disc to linux. I upgraded to Windows 8 as part of a major upgrade to my already complex home network, backups and such. A kind of hand me down one might see in a large family. Anyhoo I was able to import my Mass Effect 2 character using the offset parameter and using dual boot linux to scp the save files. Messy beyond comprehension but bliss when it worked. I elected to be an adept and the game imported my abilities, so I shower them with singularities, pulls, and assorted nonsense.

    I really think movies are at one level, and immersive games are the next level. We want to be involved. I want to be in Lexington, or Concord, for just 20 hours. That would be a game.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>