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.


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.

  • Thanks for the pointer. Are you aware of a tool that automates this process? – krlmlr Sep 26 '11 at 23:06
  • 1
    No, but it should be rather easy to script something that fits the need. – the-wabbit Sep 26 '11 at 23:10
  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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.