1

I have an ext2 filesystem with corrupted/deleted inodes. The data I need does not appear to have corrupt inodes but the directory that the data is in does.

$ ls -l
ls: cannot access 'data_dir': Structure needs cleaning
total 96
drwxr-xr-x   2 root root  4096 Apr 19  2016 bin
drwxr-xr-x   2 root root  4096 May 12  2016 boot
drwxr-xr-x   7 root root  4096 Jan  1  1970 dev
drwxr-xr-x   6 root root  4096 Apr 19  2016 lib
drwxr-xr-x   3 root root 16384 Apr 29  2021 lost+found
drwxr-xr-x   7 root root  4096 Apr 29  2021 media
drwxr-xr-x   2 root root  4096 Apr 19  2016 mnt
drwxr-xr-x   2 root root  4096 Apr 19  2016 opt
drwxr-x---   2 root root  4096 Apr 19  2016 root
drwxr-xr-x   4 root root  4096 Apr 29  2021 run
drwxr-xr-x   2 root root  4096 Apr 19  2016 sbin
drwxr-xr-x   3 root root  4096 Apr 19  2016 share
???????????  ? ?    ?        ?            ? data_dir
drwxr-xr-x   2 root root  4096 Apr 19  2016 sys
drwxrwxrwt   2 root root  4096 Apr 29  2021 tmp
drwxr-xr-x  10 root root  4096 Apr 19  2016 usr
drwxr-xr-x   9 root root  4096 Apr 19  2016 var

I have run e2fsck and fixing the inode on "data_dir" just makes it go away. I have also run ddrescue and it completed with no errors, presumably because it is not a bad block. I also ran e2fsck while specifying a backup superblock and got nothing different.

Question is, how do I access the data inside data_dir? Is there a way to simply flatten the entire filesystem?

0

1 Answer 1

2

So I'll post what I ended up doing for posterity.

Using debugfs you can dump the contents of an inode to a file and you can give it a list of commands using the -f flag.

So I used dumpe2fs /dev/sdx > dump_output to give me all the free inodes.

Then I converted the list of known free inodes into a list of used inodes with Python:

#!/usr/bin/env python
# coding: utf-8
import re
import numpy as np

inodes_list = []
with open('dump_output', 'r') as f:
    content = f.read()
    inode_count = int(re.search(r'Inode count: *((?P<count>[0-9].*)?)$', content, re.M).group('count'))
    inodes = re.finditer(r'^  Free inodes: ((?P<inodes>[0-9].*)?)$', content, re.M)
    
    for i in inodes:
        inodes_list.append(i.group('inodes'))

# print(inode_count)

free_inodes = np.array([])
for j in inodes_list:
    elements = j.split(', ')
    for ele in elements:
        if '-' in ele:
            range_list = ele.split('-')
            range_start = int(range_list[0])
            range_end = int(range_list[1])
            free_inodes = np.append(free_inodes, np.arange(range_start, range_end+1))
        else:
            free_inodes = np.append(free_inodes, int(ele))

inode_array = np.arange(0,inode_count)
used_inodes = np.setdiff1d(inode_array, free_inodes)

with open('debugfs_inode_dump_script.txt', 'w') as o:
    for inode in used_inodes:
        o.write(f'dump <{inode}> inode_dump/{inode}.inode\n')

Then I took that file and ran it with debugfs -f debugfs_inode_dump_script.txt /dev/sdx. I had to create the inode_dump directory first, however.

This actually worked for what I wanted it to do: I got all the files on the filesystem in one flat level. Bad news is my data was not in the list.

1
  • Any chance it could have been thrown into lost+found ?
    – MC68020
    Sep 2, 2022 at 23:03

You must log in to answer this question.

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