How to undelete files on btrfs partition?

20

13

How do I undelete (recover) a deleted file on a btrfs partition?

I have not taken a snapshot yet, so I can't use that feature. I know there are some tools for other Linux file systems, but google has not turned up anything specific to btrfs. I came across one vague mention that btrfs includes an undelete tool, but I can't find it. Before trying tools for another file system, I'm asking here.

More info:

  • The (two) deleted files were deleted by a remote rsync command gone wrong.
  • These were small plain text files.
  • I know the names of the files.
  • I might be able to remember some strings in the files.
  • The disk is a regular HDD, but it is large (2TB).
  • I'm running Kubuntu 12.04 (beta2) with all latest updates.
  • I have not written any new data to the partition the files were deleted from.
  • I don't have a snapshot or a backup of these files. (The last backup is just a few hours older than these files.)
  • Strangely, a COW file system seems to have fewer file undelete options than ext3/4...

MountainX

Posted 2012-04-21T17:59:41.573

Reputation: 1 735

Answers

7

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.

Durval Menezes

Posted 2012-04-21T17:59:41.573

Reputation: 86

4

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.

Sameer

Posted 2012-04-21T17:59:41.573

Reputation: 181

3Worth noting is that the said script has at least one path hardcoded (presumably by mistake) and has a few other problems, so buyers beware that it must be edited before use. – gamen – 2014-07-15T06:32:02.953

3

Here's a cleaned up version of the original script: https://gist.github.com/Changaco/45f8d171027ea2655d74

– Changaco – 2015-10-30T17:03:55.477

1"As it is licensed under GPLv2, I cannot include it here" - maybe you should read what the GPLv2 says, because that makes no sense whatsoever. – slang – 2016-12-12T23:37:38.480

4@slang maybe you should read the terms of service of this site? Contributions must be licensed under the Creative Commons Attribution Share Alike 3.0 license. – suriv – 2017-01-07T16:37:33.460

@suriv - I guess I can understand their reasons for doing that, but that's pretty annoying. Especially since CC-BY-SA is only slightly more restrictive than the GPL (aside from GPLv3s patent stuff). – Omnifarious – 2018-09-08T06:53:26.283

Note old versions of btrfs-find-root don't work very well - I had this going for hours at 100% CPU. This was on 4.10. Upgrading to 4.19 Fixed the problem. – Luciano – 2019-05-19T16:10:35.030

2

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

Catalin Hritcu

Posted 2012-04-21T17:59:41.573

Reputation: 123

Tested this on a Fedora 26 system - and there the btrfs-find-root step never terminates (i.e. runs at 100% CPU for 3 hours on a < 250 GB FS). See also a similar story https://www.spinics.net/lists/linux-btrfs/msg61361.html.

– maxschlepzig – 2017-07-22T12:29:03.803