Mastering Debugfs: A Comprehensive Guide to Ext2 File System Data Recovery

ext2/ext3/ext4 file system debugger

debugfs

Without relying on third-party data recovery software, the program that comes with Linux suitable for regular data recovery is debugfs. This command is powerful and has been frequently mentioned in the earlier articles of my data recovery series. However, there is limited and incomplete detailed usage introduction of debugfs domestically. Therefore, I dedicated an article to introduce the use of debugfs, which can provide a deeper understanding of data recovery.

Experimental Environment

  • Tencent Cloud CVM
  • System Environment Ubuntu 18.04.4 LTS
  • debugfs 1.44.1 (24-Mar-2018)
  • /debugfsTest is a separately mounted cloud disk /dev/vdb
root@VM-8-15-ubuntu:/# cd /debugfsTest/
root@VM-8-15-ubuntu:/debugfsTest# touch {1..10}.txt
root@VM-8-15-ubuntu:/debugfsTest# ls
1.txt  10.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt

Common Options of debugfs

-V

Check the current version of debugfs

root@VM-8-15-ubuntu:/debugfsTest# debugfs -V
debugfs 1.44.1 (24-Mar-2018)
        Using EXT2FS Library version 1.44.1

-w

Specify that the file system should be opened in write mode. Without this option, the file system is opened in read-only mode, and errors will occur when executing some write subcommands.

root@VM-8-15-ubuntu:/debugfsTest# debugfs /dev/vda1 
debugfs 1.44.1 (24-Mar-2018)
debugfs:  rm /debugfsTest/1.txt 
rm: Filesystem opened read/only     # No -w parameter, indicating the file system is read-only
root@VM-8-15-ubuntu:/debugfsTest# debugfs -w /dev/vda1
debugfs 1.44.1 (24-Mar-2018)
debugfs:  rm /debugfsTest/1.txt     # Executed successfully

-f cmd_file

debugfs reads commands from the cmd_file file and executes them. When debugfs completes executing the commands, it exits.

root@VM-8-15-ubuntu:/debugfsTest# echo pwd > testDebugfs.sh
root@VM-8-15-ubuntu:/debugfsTest# debugfs  /dev/vda1 -f testDebugfs.sh 
debugfs 1.44.1 (24-Mar-2018)
debugfs: pwd
[pwd]   INODE:      2  PATH: /
[root]  INODE:      2  PATH: /

-R request

Use debugfs to execute a single command request and then exit.

root@VM-8-15-ubuntu:/debugfsTest# debugfs  /dev/vdb -R "pwd"
debugfs 1.44.1 (24-Mar-2018)
[pwd]   INODE:      2  PATH: /
[root]  INODE:      2  PATH: /

-z undo_file

Before overwriting file system blocks, write the old contents of the blocks to an undo file. This undo file can be used with e2undo to restore the old contents of the file system in case of problems.

root@VM-8-15-ubuntu:/debugfsTest# debugfs -w /dev/vdb -z /tmp/undo
debugfs 1.44.1 (24-Mar-2018)
Overwriting existing filesystem; this can be undone using the command:
    e2undo /tmp/undo /dev/vdb

Specifying Files in debugfs

Many debugfs commands use filespec as a parameter to specify an inode in the currently open file system of debugfs (rather than a pathname). The filespec parameter can be specified in two forms.

  1. The first form is the inode number, enclosed in angle brackets, e.g., <2>.
  2. The second form is the pathname; if the pathname is prefixed with a forward slash (‘/’), it is interpreted relative to the root of the file system currently open in debugfs.

Common Subcommands of debugfs

help

Print help information for all subcommands.

debugfs:  help
show_debugfs_params, params    Display debugfs parameters
open_filesys, open    Open a file system
close_filesys, close    Close file system
freefrag, e2freefrag    Report available space fragments
feature, features    Set/print superblock features
dirty_filesys, dirty    Mark the file system as dirty
init_filesys    Initialize file system (DESTROYS DATA)
show_super_stats, stats    Display superblock statistics
ncheck    Do inode->name translation
icheck    Do block->inode translation
change_root_directory, chroot    Change root directory
change_working_directory, cd    Change working directory
list_directory, ls    List directory
show_inode_info, stat    Display inode information
dump_extents, extents, ex    Dump extent information
blocks    Print blocks used by inode
filefrag    Report fragmentation of an inode
link, ln    Create directory link
unlink    Remove directory link
mkdir    Create directory
rmdir    Remove directory
rm    Remove file (unlink and kill_file if appropriate)
kill_file    Free an inode and its blocks
copy_inode    Copy inode structure
clri    Clear the contents of an inode
freei    Clear an inode's in-use flag
seti    Set an inode's in-use flag
testi    Test an inode's in-use flag
freeb    Clear block's in-use flag
setb    Set block's in-use flag
testb    Test a block's in-use flag
modify_inode, mi    Modify an inode by structure
find_free_block, ffb    Find free block
find_free_inode, ffi    Find free inode
print_working_directory, pwd    Print current working directory
expand_dir, expand    Expand directory
mknod    Create a special file
list_deleted_inodes, lsdel    List deleted inodes
undelete, undel    Undelete file
write    Copy a file from your local file system
dump_inode, dump    Dump an inode to a file
cat    Output the contents of an inode to stdout
lcd    Change current directory on local file system
rdump    Recursively dump directory to local file system
set_super_value, ssv    Set superblock value
set_inode_field, sif    Set inode field
set_block_group, set_bg    Set block group descriptor field
logdump    Dump the contents of the journal
htree_dump, htree    Dump a hash-indexed directory
dx_hash, hash    Compute directory hash of a filename
dirsearch    Search for a specific filename in a directory
bmap    Compute logical->physical block mapping of an inode
fallocate    Allocate uninitialized blocks to an inode
punch, truncate    Punch (or truncate) blocks from an inode by deallocating
symlink    Create symbolic link
imap    Compute the location of an inode
dump_unused    Dump unused blocks
set_current_time    Set the current time used by file system fields
supported_features    Print features supported by this version of e2fsprogs
dump_mmp    Dump MMP information
set_mmp_value, smmp    Set MMP value
extent_open, eo    Open inode for extent operations
zap_block, zap    Zap block: fill with 0, pattern, flip bits, etc.
block_dump, bdump, bd    Dump contents of a block
ea_list    List extended attributes of an inode
ea_get    Get an extended attribute of an inode
ea_set    Set an extended attribute of an inode
ea_rm    Remove an extended attribute of an inode
list_quota, lq    List quotas
get_quota, gq    Get quota
inode_dump, idump, id    Dump inode structure in hex
journal_open, jo    Open journal
journal_close, jc    Close journal
journal_write, jw    Write transaction to journal
journal_run, jr    Recover journal
help    Show information about command or topic.
list_requests, lr, ?    List available commands.
quit, q    Leave subsystem.

params

Display debugfs parameters

root@VM-8-15-ubuntu:~# debugfs /dev/vdb -w
debugfs 1.44.1 (24-Mar-2018)
debugfs:  params 
Open mode: read-write
Filesystem in use: /dev/vdb

blocks filespec

Output the block pointed to by the inode file.

root@VM-8-15-ubuntu:~# ls -i /etc/passwd
270146 /etc/passwd
root@VM-8-15-ubuntu:~# debugfs /dev/vda1 -R "blocks <270146>"
debugfs 1.44.1 (24-Mar-2018)
1124527 

The value of blocks obtained here is the actual location of the file on the disk.

open, close

Open/close the file system. When using debugfs, it is usually followed directly by the file system. You can also enter debugfs and then open/close a specified file system.

root@VM-8-15-ubuntu:~# debugfs
debugfs 1.44.1 (24-Mar-2018)
debugfs:  ls
ls: Filesystem not open
debugfs:  open /dev/vdb
debugfs:  ls
debugfs:  close
debugfs:  ls
ls: Filesystem not open

freefrag

Report available space fragments.

debugfs:  freefrag
Device: /dev/vdb
Blocksize: 4096 bytes
Total blocks: 10485760
Free blocks: 10243382 (97.7%)

Min. free extent: 16 KB 
Max. free extent: 2064256 KB
Avg. free extent: 1241620 KB
Num. free extent: 33

HISTOGRAM OF FREE EXTENT SIZES:
Extent Size Range :  Free extents   Free Blocks  Percent
   16K...   32K-  :             1             4    0.00%
   64M...  128M-  :             4         97140    0.95%
  128M...  256M-  :             5        322529    3.15%
  256M...  512M-  :             2        187354    1.83%
  512M... 1024M-  :             2        391156    3.82%
    1G...    2G-  :            19       9245198   90.26%

dirty

Set the file system state to dirty, which will perform a deep check of each file’s integrity when mounted. There is no return after execution.

debugfs:  dirty

init_filesys

Initialize the file system, deleting data.

root@VM-8-15-ubuntu:~# debugfs /dev/vdb -w
debugfs 1.44.1 (24-Mar-2018)
debugfs:  init_filesys
init_filesys: Usage: initialize  
debugfs:  init_filesys /dev/vdb 33798
init_filesys: Filesystem /dev/vdb is still open.  Close it first.
root@VM-8-15-ubuntu:~# umount /dev/vdb
root@VM-8-15-ubuntu:~# debugfs
debugfs 1.44.1 (24-Mar-2018)
debugfs:  blocks /passwd
blocks: Filesystem not open
debugfs:   init_filesys /dev/vdb 33798
root@VM-8-15-ubuntu:~# mount /dev/vdb /debugfsTest/
mount: /debugfsTest: mount(2) system call failed: Structure needs cleaning.

After initializing the file system, mounting again results in an error. The mount fails with “Structure needs cleaning,” use the command fsck.ext4 /dev/vdb to repair.

root@VM-8-15-ubuntu:~# fsck.ext4 /dev/vdb
e2fsck 1.44.1 (24-Mar-2018)
ext2fs_check_desc: Corrupt group descriptor: bad block for block bitmap
fsck.ext4: Group descriptors look bad... trying backup blocks...
Block bitmap for group 0 is not in group.  (block 0)
Relocate? yes
Inode bitmap for group 0 is not in group.  (block 0)
......
Free inodes count wrong (8479, counted=8469).
Fix? yes
/dev/vdb: ** FILE SYSTEM WAS MODIFIED **
/dev/vdb: 11/8480 files (0.0% non-contiguous), 1083/33798 blocks
root@VM-8-15-ubuntu:~# mount /dev/vdb /debugfsTest/
root@VM-8-15-ubuntu:~# cd /debugfsTest/
root@VM-8-15-ubuntu:/debugfsTest# ls
lost+found

Data is lost after file system repair, and this operation is very dangerous.

stats

Display superblock statistics

root@VM-8-15-ubuntu:~# debugfs /dev/vdb -R "stats" |more
debugfs 1.44.1 (24-Mar-2018)
Filesystem volume name:   
Last mounted on:          /debugfsTest
Filesystem UUID:          5841c171-06b9-4ea4-9030-597236944d37
Filesystem magic number:  0xEF53
Filesystem revision #:    0 (original)
Filesystem features:      (none)
Filesystem flags:         signed_directory_hash 
Default mount options:    (none)
Filesystem state:         not clean
Errors behavior:          Continue
Filesystem OS type:       Linux

This is similar to the information seen when executing dumpe2fs /dev/vdb.

ncheck, icheck

ncheck translates inode numbers to filenames, icheck translates block numbers to inode numbers

root@VM-8-15-ubuntu:~# ls -i /etc/passwd
270146 /etc/passwd
root@VM-8-15-ubuntu:~# debugfs /dev/vda1 -R "ncheck 270146"
debugfs 1.44.1 (24-Mar-2018)
Inode   Pathname
270146  /etc/passwd
root@VM-8-15-ubuntu:~# debugfs /dev/vda1 -R "blocks /etc/passwd"
debugfs 1.44.1 (24-Mar-2018)
1124527 
root@VM-8-15-ubuntu:~# debugfs /dev/vda1 -R "icheck 1124527"
debugfs 1.44.1 (24-Mar-2018)
Block   Inode number
1124527 270146

stat

Print inode information, the principle is to read the inode’s table structure from the disk. It records several timestamps of the file, providing more detailed information than the stat command in the shell. The EXTENTS records the block values corresponding to the inode.

Inode: 270146   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 1919007159    Version: 0x00000000:00000001
User:     0   Group:     0   Project:     0   Size: 1954
File ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x623033ec:cfb832f4 -- Tue Mar 15 14:36:28 2022
 atime: 0x6243fa8d:997af09c -- Wed Mar 30 14:37:01 2022
 mtime: 0x623033ec:cfb832f4 -- Tue Mar 15 14:36:28 2022
crtime: 0x623033ec:cfb832f4 -- Tue Mar 15 14:36:28 2022
Size of extra inode fields: 32
Inode checksum: 0xcde2ce28
EXTENTS:
(0):1124527