How to undelete files on btrfs partition?

As your files are small and plain text, I would try scanning the output of "strings" into the device where the filesystem resides, ie,

strings /dev/sda1 | less

then use "/" to search for the strings that could be in that file. When you find the text, delimit the start of it with "m" then move to the end and use "|cat >file" to save it to a file.

I've actually done that when I had a similar situation on another filesystem without undelete, a few years back, and it worked great for me.


Jörg Walter implemented a btrfs-undelete shell script using the find-root and restore tools from btrfs-progs, which can be found here, and should help others in a similar position.

As it is licensed under GPLv2, I cannot include it here.


If your btrfs drive has subvolumes you need to pass the additional -r <subvol-id> option to btrfs restore. Unfortunately the scripts out there, like the one user414471 posted (http://oelkers.de/tips/undeleteBtrfs.sh), don't have an option for doing this, but they can probably be adapted to this.

If you want to do this by hand you need to obtain the right subvol-id, either with:

# mount /dev/sdXY /mnt/blah
# btrfs subvolume list /mnt/blah
# umount /mnt/blah

or alternatively with:

# btrfs restore -l /dev/sdXY | grep ROOT_ITEM

Afterwards you use btrfs-find-root to get the block number to which you want to revert (usually the one just before the maximum one which is the current root). For this you need to first set the default subvolume to the one from which you want to revert files (and revert this change afterwards):

# mount /dev/sdXY /mnt/blah
# btrfs subvolume set-default <subvol-id> /mnt/blah
# umount /mnt/blah
# btrfs-find-root /dev/sdXY
Well block 4321280 seems great, but generation doesn't match, have=400760, want=400984 level 0
...
Well block 9928704 seems great, but generation doesn't match, have=400764, want=400984 level 1
Well block 1094836224 seems great, but generation doesn't match, have=400983, want=400984 level 1
Found tree root at 1095270400 gen 400984 level 1

You can finally use btrfs restore with -r <subvol-id> for the recovery (initially with the --dry-run argument if you wish):

# btrfs restore -r <subvol-id> -t 9928704 -v --path-regex '^/(|dir1(|/dir2(|/dir3(|/.*))))$' /dev/sdXY /tmp/recovery

More information about all this here: https://btrfs.wiki.kernel.org/index.php/Restore