Hard Disk Recover 2
Following the previous article, here is yet another hard disk recovery.
The problem here, was not the bad sectors (there were few, luckily), but the tools. Contrary to what people usually thinks, some unix tools are very bad. Let me show you.
So, for some reason (electrical shock) i have a hard disk which starts to have bad blocks. The server is almost freezing each time linux tries to access this hard disk. I remove it, and install it on a dedicated computer with its own system disk, a brand new hard disk for the rescued data, and the bad disk. I put the bad disk on its very own ide cable, alone.
First thing i do is
#fdisk /dev/hdc -l Disk /dev/hdc: 163.9 GB, 163928604672 bytes 255 heads, 63 sectors/track, 19929 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System /dev/hdc1 * 1 1217 9775521 fd Linux raid autodetect /dev/hdc2 1218 3650 19543072+ fd Linux raid autodetect /dev/hdc3 3651 3687 297202+ 82 Linux swap / Solaris /dev/hdc4 3688 19929 130463865 5 Extended /dev/hdc5 3688 9767 48837568+ fd Linux raid autodetect /dev/hdc6 9768 19929 81626233+ 83 Linux
I dont care about the swap/raid partition. The only one i'm interested in is hdc6. Funnily, the kernel can't find it:
# ls /dev/hdc* /dev/hdc /dev/hdc1 /dev/hdc2 /dev/hdc3 /dev/hdc4 /dev/hdc5
You can ask the kernel to re-read the partition table. Several tools (partprobe, hdparm) allow to do that, for example:
blockdev --rereadpt /dev/hdc
But in this case, this doesn't work.
Ok, so now the problem is to know where in the hard disk the partition starts. Byte-wise, that is. The problem is that tools do not agree on that. The previous fdisk for example, says hdc6 starts on cylinder 9768, the size of a cylinder being 8225280, which would mean 9768*8225280 = 80344535040.
sfdisk -uC /dev/hdc (the -uC displays cylinder number) says:
/dev/hdc6 9767+ 19928 10162- 81626233+ 83 Linux
They dont agree on the number of cylinder! (but they do agree on the size of cylinder..)
So this one gives the start of hdc6 on : 9767 * 8225280 = 80336309760.
sfdisk can also output in sectors
/dev/hdc6 156906918 320159384 163252467 83 Linux
or blocks :
/dev/hdc6 78453459 160079692- 81626233+ 83 Linux
The size of a block is 512, the size of a block is 1024, which gives the same start for hdc6 : 78453459 * 1024 = 80336342016 = 156906918 * 512. This is the one I will use.
Based on Hard disk recovery tools, i decided (this time) to use dd_rescue.
dd_rescue -v -s 80336342016 /dev/hdc /mnt/store/rescue -l ~/rescue.errors -o ~/rescue.badblock
After few hours (i went to sleep meanwhile), it finishes. The result is not that bad:
dd_rescue: (info): /dev/hdc (160086528.0k): EOF Summary for /dev/hdc -> /mnt/store/rescue_music: dd_rescue: (info): ipos: 160086528.0k, opos: 160086528.0k, xferd: 81633069.0k errs: 650, errxfer: 325.0k, succxfer: 81632744.0k +curr.rate: 6646kB/s, avg.rate: 2781kB/s, avg.load: -6.9%
Only 325k of bad block, which is roughly 0.0004 % :-).
As i didn't specify anything for the output file, dd_rescue did a copy of /dev/hdc6, of the same size:
#ls -l -rw-r----- 1 root root 163928604672 Aug 1 06:12 rescue
The whole beginning was not copied though. The actual size on the hard disk is only half of this :
du -shx rescue 79G rescue
Now i need to use reiserfsck. For this, i would like to 1) check the exact start address for the hdc6 partion, 2) copy the relevant data to another file.
I first tried to use hexdump.
hexdump -s 80336342016 rescue_music 7fffffff 0000 0000 0000 0000 0000 0000 0000 0000 *
AHA, you see ? hexdump can't handle index more than 7fffffff. What a shame. After a while a figured out there's another tool, called 'od'. od is great : it can handle such long index. But in mostly knows about octal. How odd. For example i never managed to make it output the index number in anything else than octal.
The partition on hdc6 was using the reiserfs filesystem. The very beginning of a reiserfs filesystem is made of 64k of "nothing" and then a header. Here is an example on a real, working, partition.
od -x /dev/sdb1 |less 0000000 0000 0000 0000 0000 0000 0000 0000 0000 * 0200000 1470 02e9 ee8a 02e8 2013 0000 0012 0000 0200020 0000 0000 2000 0000 0400 0000 39a4 13fb 0200040 0384 0000 001e 0000 0000 0000 1000 03cc 0200060 0002 0002 6552 7349 7245 4632 0073 0000
(the -x is for hex output, but only display the content in hex, not the index) The "6552 7349 7245 4632" stands for "ReIsEr2F", the start of the magic signature of the header, in ascii little endian.
Doing the same on my rescue file, i find the beginning of the partition. I search (using less) for the string "6552 7349 7245 4632" and finds this :
od -x -j 80336342016 rescue |less ... 1126433176000 6110 0137 e0df 00ba 1b56 00a5 0012 0000 1126433176020 0000 0000 2000 0000 0400 0000 e490 2559 1126433176040 0384 0000 001e 0000 0000 0000 1000 03cc 1126433176060 0002 0002 6552 7349 7245 4632 0073 0000
This gives the start of the header on (dec)80336452608 = (octal)1126433176000, and hence, the start of the partition on : (octal) 01126433176000 - 0200000 = 01126432776000 In decimal : 80336387072. This is not what we had previously estimated : we did an error of80336387072 - 80336342016 = 45056 = 0xB000. Strange....
So now, i extract the data for the partition on another file :
dd_rescue -v -s 80336387072 -S 0 rescue rescue.partition6
It takes some time.