10

I received messages in /var/log/kern.log that indicate drive failure. The messages occured while copying my $HOME between drives (ext4 -> ext3):

[ 5733.186033] sd 4:0:0:0: [sdb] Unhandled sense code
[ 5733.186038] sd 4:0:0:0: [sdb]  Result: hostbyte=invalid driverbyte=DRIVER_SENSE
[ 5733.186042] sd 4:0:0:0: [sdb]  Sense Key : Medium Error [current] 
[ 5733.186048] sd 4:0:0:0: [sdb]  Add. Sense: Unrecovered read error
[ 5733.186053] sd 4:0:0:0: [sdb] CDB: Read(10): 28 00 05 b7 2e 40 00 00 08 00
[ 5733.186064] end_request: critical target error, dev sdb, sector 95891008

The messages come in bulks, this is one of those bulks. sdb is the source drive.

How do I find out to which file/inode the sector belongs? I just want to know so I can recover the files in question from a backup. Anything faster than the following code plus a subsequent analysis of the output?

find . -type f -print \
               -exec cp \{\} /dev/null \; \
               -exec tail -n 1 /var/log/kern.log \;

OS: Ubuntu Oneiric.

EDIT: The command above also outputs to stderr the files that could not be read.

2 Answers 2

4

The rough idea would be to

  1. do some calculations to find out the filesytem's block number based on the physical sector number
  2. use debugfs testb/ncheck/icheck commands to find out if the block is in use and the name of the file(s) that are using it

There is a bad block HOWTO over at the smartmontools project site describing the process in more detail.

2
  • Thanks for the pointer. Are you aware of a tool that automates this process?
    – krlmlr
    Sep 26, 2011 at 23:06
  • 1
    No, but it should be rather easy to script something that fits the need.
    – the-wabbit
    Sep 26, 2011 at 23:10
9
  1. Find which partition the sector is in by running fdisk -lu /dev/sdb. Suppose it is "sdb2" which starts at sector 45612307.

  2. Subtract that from 95891008 to get 50278701.

  3. Next determine how many sectors per block: tune2fs -l /dev/sdb2 | grep Block. Suppose it is 4096.

  4. Calculate the block / sector ratio: 512 bytes/sector / 4096 bytes/block = 0.125 blocks/sector.

  5. Calculate the block from the sector: 50278701 * 0.125 = 6284837.625.

  6. Use debugfs to find out which is using the block. If icheck 6284837 returns inode 12345 then run ncheck 12345.

Caveats: You may need to turn off journaling. This may not work with ext4.

2
  • I would add a way to check if your computations are correct, like using stat or FIBMAP/FIEMAP iocalls.
    – neutrinus
    Sep 22, 2015 at 21:41
  • On my system, icheck (C interface ABI/API checker) won't accept a sector number as parameter?! Feb 14, 2019 at 16:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .