October 23, 2006

CLI Magic: Salvage lost partitions with gpart

Author: Mayank Sharma

Messing up your hard disk's partition table doesn't take much effort, especially when you're preparing a dual-boot machine. Even a mistimed fdisk /mbr can spell disaster, erasing the master boot record (MBR) and making the disk unusable. But victims of damaged MBRs rejoice -- gpart can save your day. This utility scans a hard disk and prepares a partition table of areas that resemble a partition, which you can use to make the disk bootable again.

Gpart is short for "guess partitions," and it can do just that with a variety of filesystems, including FAT 16/32, NTFS, EXT2/3, Linux Swap, ReiserFS, *BSD Disklabels, and several others. To install it, download the source code and compile it with make and make install (as root). Gpart is also included in live distributions such as Knoppix, which makes it more accessible.

To let gpart take a look at your disk, run it (as root) without any switches:

gpart /dev/hda

Depending on the size of your disk and the machine's processing power, gpart can take a while to complete. On my 1.4GHz Celeron machine with 256MB RAM, scanning a 40GB disk took about 20 minutes, and this is what it reported:

Begin scan...
Possible partition(DOS FAT), size(5004mb), offset(0mb)
Possible partition(Linux ext2), size(14307mb), offset(5004mb)
Possible extended partition at offset(19312mb)
  Possible partition(Linux swap), size(486mb), offset(19312mb)
  Possible partition(Linux ext2), size(7632mb), offset(19798mb)
Possible extended partition at offset(30623mb)
  Possible partition(Linux ext2), size(7530mb), offset(30623mb)
End scan.

Checking partitions...
Partition(DOS or Windows 95 with 32 bit FAT, LBA): primary
Partition(Linux ext2 filesystem): primary
  Partition(Linux swap or Solaris/x86): logical
  Partition(Linux ext2 filesystem): logical
Partition(Linux ext2 filesystem): primary

Guessed primary partition table:
Primary partition(1)
  type: 012(0x0C)(DOS or Windows 95 with 32 bit FAT, LBA)
  size: 5004mb #s(10249407) s(63-10249469)
  chs:  (0/1/1)-(637/254/63)d (0/1/1)-(637/254/63)r

Primary partition(2)
  type: 131(0x83)(Linux ext2 filesystem)
  size: 14307mb #s(29302560) s(10249470-39552029)
  chs:  (638/0/1)-(1023/254/63)d (638/0/1)-(2461/254/63)r

Primary partition(3)
  type: 015(0x0F)(Extended DOS, LBA)
  size: 8118mb #s(16627275) s(39552030-56179304)
  chs:  (1023/254/63)-(1023/254/63)d (2462/0/1)-(3496/254/63)r

Primary partition(4)
  type: 131(0x83)(Linux ext2 filesystem)
  size: 7530mb #s(15422336) s(62717823-78140158)
  chs:  (1023/254/63)-(1023/254/63)d (3904/1/1)-(4863/254/62)r

Apart from the fact that it marked all the ext3 partitions as ext2, gpart detected my five partitions and their sizes correctly.

Valuable MBR

The first 512 bytes of a disk make up its master boot record. The MBR includes a partition table, which specifies the location of the partitions on the disk and their type. Gpart reconstructs this partition table if it is damaged or erased. The MBR also contains a boot loader, such as GRUB or LILO, which help the computer load an operating disk.

It is a good strategy to keep a copy of the MBR in a safe place in case it is damaged. You can create a copy with the command:

dd if=/dev/hda of=mbr.save bs=512 count=1

The mbr.save file should be stored outside the system. It's a good idea to keep it on a multisession CD that can be updated whenever the MBR is modified.

To restore the MBR, use a command like:

dd if=mbr.save of=/dev/hda bs=512 count=1

This will place the contents of the mbr.save file onto the MBR, and you should be on your way.

I tried gpart on another disk and was surprised when it reported several orphaned and unused partitions. One possible reason for the error in judgment, as per gpart's man page, can be incorrect disk information. Some Linux distributions pick up the wrong disk geometry -- the cylinders, heads, and sectors (CHS). To find out the correct specifications of your disk, compare the output of dmesg (dmesg | grep CHS) with that of fdisk (fdisk -l). They should agree, but for various reasons they might not; if that's the case, try both sets of values:

gpart -C C,H,S /dev/hda

Substitute C, H, and S with the actual number of cylinder, heads, and sectors.

When I did that, gpart was able to guess the structure of my second disk correctly. But on a third disk, it failed yet again. I gave it the correct disk geometry, and it was able to scan the disk properly, but it failed while checking individuals partitions, reporting them to be empty.

I then asked gpart to scan the disk fully (gpart -f /dev/hda), even checking sectors occupied by identified partitions, which it normally skips. It took several hours, and listed quite a few duplicate partitions, but still failed to get correct details about the extended partitions.

As a last resort I asked gpart to ignore the extended partitions by using the -E switch (gpart -E /dev/hda). To my surprise this worked, and gpart was able to correctly probe three partitions. It ignored the one extended DOS partition, which was causing all the trouble. Although the information gpart returns isn't complete, it can still resurrect the disk.

If you want gpart to be more verbose, use the -v option. Repeating the option will cause gpart to list a lot of information about the disk as well as the identified partitions.

Once you are satisfied with the output of gpart, you can write the guessed partition table to the MBR using the -W switch:

gpart -W /dev/hda /dev/hda

Apart from the one disk that gpart was able to restore only partially, it worked on all the disks I threw at it. Turns out that the troublesome disk wasn't formatted properly to begin with, and even partition tools such as gparted complained about the disk structure.

Gpart is one of the select utilities that act as a last line of defense in situations which can result in a loss of information, time, or money. It's worth having around if you don't backup your MBR.