find file by block number on ext3 fs on lvm

  1. As described in the Bad Blocks Howto, find the partition which contain the bad block and calculate the sector offset inside the partition. Suppose that the partition is /dev/sda3, and it is an LVM PV.

  2. Determine the sector offset of the first PE:

    pvs -o pe_start --units s /dev/sda3
    

    Subtract this offset from the bad sector offset to get the sector offset from the first PE. If the result is negative, the bad sector is in the LVM metadata area.

    Bad_Offset_from_1st_PE = Bad_Offset_in_Partition - First_PE_Start
    
  3. Run pvdisplay --maps --units s /dev/sda3 to obtain the list of segments in the PV; the “Physical Volume” section of this output will also show the “PE Size” field.

  4. Divide the sector offset from the first PE (which you got in the step 2) by the PE size in sectors. The integer result of the division will be the bad PE number, and the remainder will be the bad sector offset inside that PE.

    Bad_PE           = Bad_Offset_from_1st_PE / PE_Size
    Bad_Offset_in_PE = Bad_Offset_from_1st_PE % PE_Size
    
  5. Find the segment in the map which contains the bad PE. If you are lucky, the segment may be free, otherwise you will see the bad logical volume. You may stop at this step if the volume is not interesting for you (e.g., it is swap, or some temporary data you do not care about). The sector may also be beyond the last PE, which means that it is either in the unused area which is less than a full PE, or in the second metadata area at the end of PV (if such metadata area is present).

    If the bad volume is a snapshot, mapping the bad sector to the real offset in the logical volume would be very hard. If you really care about the snapshot contents, the only thing you could do is to try reading from it and hope that the bad sector was not yet used by the snapshot (and if it was used, hope that the machine won't hang completely when attempting to read it).

    If the bad volume was using something fancy such as mirroring or striping at the LVM level… don't know how to deal with this currently.

  6. Calculate Bad_LE = Bad_PE - Seg_First_PE + Seg_First_LE, where Seg_First_PE is the first physical extent of the bad segment, and Seg_First_LE is the first logical extent in the bad segment, as seen in the segment data in the map.

  7. Calculate sector offset inside the logical volume:

    Bad_LV_Offset = (Bad_LE * PE_Size) + Bad_Offset_in_PE
    
  8. Return to the Bad Blocks Howto at its second step to find the file which corresponds to the sector at Bad_LV_Offset in the filesystem.