Approximate partition table backup with sfdisk

data-recoveryhard-diskpartitionsfdisk

I wanted to convert some logical partitions to extended ones, so I was following this accepted answer. However, at the step of backing up my current partition table, I messed up and typed the following instead of what was written.

sfdisk -f /dev/sda > /mnt/parts.txt

Which resulted in this:

Disk /dev/sda: 30401 cylinders, 255 heads, 63 sectors/track
Old situation:
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/sda1          0+    304-    304-   2441214+  82  Linux swap / Solaris
/dev/sda2   *    304+    565-    262-   2097152   83  Linux
/dev/sda3        565+   4486-   3921-  31495168   83  Linux
/dev/sda4       4486+  30401-  25916- 208163840    5  Extended
/dev/sda5       4486+  24026-  19540- 156954624   83  Linux

As you can see, units are cylinders and blocks, which probably makes a loss of precision compared to a correct export with sectors.

The problem is, I have broken my partition table, and now I have to exploit this incomplete (or is it?) backup.

So far, I've tried to rewrite the partition table using sector as an unit (cylinders doesn't lead anywhere) knowing that one block is two sectors (I don't know if it's general, but exporting the partition table in sectors tells you that 1 sector = 512 bytes, and as 1 block = 1024 bytes…).

root@debian:/home/user# sfdisk -u S /dev/sda
Checking that no-one is using this disk right now ...
OK

Disk /dev/sda: 30401 cylinders, 255 heads, 63 sectors/track
Old situation:
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
/dev/sda1             1   4882429    4882429  82  Linux swap / Solaris
/dev/sda2       4882430   9076733    4194304  83  Linux
/dev/sda3       9076734  72067069   62990336  83  Linux
/dev/sda4      72067070 488394749  416327680  83  Linux
Input in the following format; absent fields get a default value.
<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>
Usually you only need to specify <start> and <size> (and perhaps <type>).

/dev/sda1 :1 4882429 S
/dev/sda1             1   4882429    4882429  82  Linux swap / Solaris
/dev/sda2 :4882430 4194304 L *
/dev/sda2   *   4882430   9076733    4194304  83  Linux
/dev/sda3 :9076734 62990336
/dev/sda3       9076734  72067069   62990336  83  Linux
/dev/sda4 :72067070 416327680 E
/dev/sda4      72067070 488394749  416327680   5  Extended
/dev/sda5 :72067071 313909248
/dev/sda5      72067071 385976318  313909248  83  Linux
/dev/sda6 :
/dev/sda6     385976320 488394749  102418430  83  Linux
/dev/sda7 :
No room for more
New situation:
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
/dev/sda1             1   4882429    4882429  82  Linux swap / Solaris
/dev/sda2   *   4882430   9076733    4194304  83  Linux
/dev/sda3       9076734  72067069   62990336  83  Linux
/dev/sda4      72067070 488394749  416327680   5  Extended
/dev/sda5      72067071 385976318  313909248  83  Linux
/dev/sda6     385976320 488394749  102418430  83  Linux
Warning: partition 1 does not end at a cylinder boundary
Warning: partition 2 does not start at a cylinder boundary
Warning: partition 2 does not end at a cylinder boundary
Warning: partition 3 does not start at a cylinder boundary
Warning: partition 3 does not end at a cylinder boundary
Warning: partition 4 does not start at a cylinder boundary
Warning: partition 4 does not end at a cylinder boundary
Warning: partition 5 does not end at a cylinder boundary
Warning: partition [6] does not start at a cylinder boundary
Warning: partition [6] does not end at a cylinder boundary
Warning: partition 6 does not end at a cylinder boundary
Do you want to write this to disk? [ynq] y
Successfully wrote the new partition table

Re-reading the partition table ...

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes:  dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)

It says: no partition start/stop on a cylinder boundary. I don't know what this means, but as there are + and , that means that the number have been rounded, on the original export, I assume this is normal.

I also issued the same mistaken command to see if the output were the same:

Disk /dev/sda: 30401 cylinders, 255 heads, 63 sectors/track
Old situation:
Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/sda1          0+    303-    304-   2441214+  82  Linux swap / Solaris
/dev/sda2   *    303+    565-    262-   2097152   83  Linux
/dev/sda3        565+   4485-   3921-  31495168   83  Linux
/dev/sda4       4485+  30401-  25916- 208163840    5  Extended
/dev/sda5       4485+  24025-  19540- 156954624   83  Linux
/dev/sda6      24025+  30401-   6376-  51209215   83  Linux

It's close, but it's not exactly the same. Also, gparted doesn't seem to recognize any partition filesystem (everything is "unknown").

Also, how can /dev/sda1 be 304- cylinders large, but ends at 303- cylinders?


I guess that I'm close to the solution, but I can't get the exact numbers that are required, probably because I miscalculated something or I'm doing it wrong. But I can't change them one by one to see which combination works (I can, but it would require some bash coding and processing time, and I wouldn't know what was wrong).

I have recent backups of the most important for this disk, but if I could fix it without reinstalling and copying files, that could be nice.

Best Answer

This is going to be tricky to fix by hand. I hope you haven't modified any more data on this disk, apart from the broken partition table you wrote to it.

Using sfdisk, fdisk, etc to create a backup of the partition table is a good idea (when you don't accidentally type the wrong command :) ). But for extra insurance I like to back up the boot sectors of my drives using dd.

Are you sure that sda1 starts at block 1, or was that a guess? It used to be common that only 1 block was used at the start of a disk, since that's all you need to hold the MBR and (primary) partition table, but in recent years it's been common for partitioning software to reserve more space, eg a starting sector of 63 for the 1st partition is not unusual. I've also seen partitioning software (gparted, IIRC) reserve a megabyte at the start of a drive and then force all subsequent partitions onto megabyte boundaries.

On older systems it was important for partitions to start and stop on cylinder boundaries. IOW, unpartitioned region at the start of the disk should be a whole number of cylinders, and so should each subsequent primary partition; there will generally also be unallocated space at the end of the disk. But that's generally not been an issue for many years, but a lot of partitioning software still mentions it, just in case you're interested. :)

However, partitions do have to start and stop on sector boundaries. And that makes analysis of your block-oriented data in the 1st listing a lot easier. Thus 2441214+ blocks can only refer to 2441214.5 blocks = 4882429 sectors = 2499803648 bytes.

But rather than trying to fix this by hand, you should seriously consider using a tool like testdisk. You may even have it already installed on your distro, if not, it should be in your repos.