There is a possibility to recover the partition table, but it requires 2 conditions be met:
- You have not rebooted your machine.
- The drive was in use at the time the table was changed.
How this works is that the kernel keeps the partition layout in memory. If a partition is in use, it needs to know where the partition starts, so it will refuse to reload the new table until it is no longer in use.
How to do this:
Go to /sys/block/sda
. Inside there you will see a directory for each partition (sda1
, sda2
, etc). Inside each of those is a file called start
and size
(so /sys/block/sda/sda1/start
). If you recreate your partition table using these exact same start locations and sizes, you will be fine.
Note that it does not keep the partition type. Linux doesn't care about this information. So after recreating, you will have to remember what the partition type was set to (NTFS or whatever).
Example
Original disk:
# fdisk -l /dev/sdc
Disk /dev/sdc: 8006 MB, 8006926336 bytes, 15638528 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000ce29c
Device Boot Start End Blocks Id System
/dev/sdc1 2048 2099199 1048576 83 Linux
/dev/sdc2 2099200 15638527 6769664 83 Linux
# mount | grep sdc
/dev/sdc2 on /mnt/tmp type xfs (rw)
# cat /mnt/tmp/world
hello
Wiping the partition table
# fdisk /dev/sdc
Welcome to fdisk (util-linux 2.22.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): d
Partition number (1-4): 1
Partition 1 is deleted
Command (m for help): d
Selected partition 2
Partition 2 is deleted
Command (m for help): p
Disk /dev/sdc: 8006 MB, 8006926336 bytes, 15638528 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000ce29c
Device Boot Start End Blocks Id System
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
Note that it's still mounted and accessible:
# cat /mnt/tmp/world
hello
Get the offsets
# cd /sys/class/block/sdc
# ls
alignment_offset device@ events_poll_msecs power/ ro slaves/
bdi@ discard_alignment ext_range queue/ sdc1/ stat
capability events holders/ range sdc2/ subsystem@
dev events_async inflight removable size uevent
# cat sdc1/start
2048
# cat sdc1/size
2097152
# cat sdc2/start
2099200
# cat sdc2/size
13539328
Restore the partition table
# fdisk /dev/sdc
Welcome to fdisk (util-linux 2.22.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-15638527, default 2048): 2048
Last sector, +sectors or +size{K,M,G} (2048-15638527, default 15638527): +2097151
Partition 1 of type Linux and of size 1 GiB is set
Command (m for help): n
Partition type:
p primary (1 primary, 0 extended, 3 free)
e extended
Select (default p): p
Partition number (1-4, default 2): 2
First sector (2099200-15638527, default 2099200): 2099200
Last sector, +sectors or +size{K,M,G} (2099200-15638527, default 15638527): +13539327
Partition 2 of type Linux and of size 6.5 GiB is set
Command (m for help): p
Disk /dev/sdc: 8006 MB, 8006926336 bytes, 15638528 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000ce29c
Device Boot Start End Blocks Id System
/dev/sdc1 2048 2099199 1048576 83 Linux
/dev/sdc2 2099200 15638527 6769664 83 Linux
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
!! Note that when specifying the last sector, we use the size - 1. !!
Verification
Let's unmount the drive, run partprobe
to tell the kernel to pick up the new table, then remount and verify we still get to our file.
# umount /mnt/tmp/
# partprobe /dev/sdc
# mount /dev/sdc2 /mnt/tmp
# cat /mnt/tmp/world
hello
testdisk
. – frostschutz Oct 5 '13 at 15:29