Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patched btrfsck to allow rebuilding a superblock from an old tree / generation. #11

Open
wants to merge 40 commits into
base: master
Choose a base branch
from

Conversation

lakeman
Copy link

@lakeman lakeman commented Jul 30, 2012

Facing a 3.0 kernel corrupt superblock I wanted a way to use the output of find-root to fix it without needing to find enough storage space for a full restore and rebuild (though I may end up needing to do that anyway...).
So I patched btrfsck so it can take a tree & generation parameter, and optionally commit the changes.

Obviously this should be considered a last resort when trying to recover a failed filesystem.

Modifying btrfs-select-super might have made more sense, but I've gotten past my issue now and can mount my filesystem so I don't need to test this process again.

Josef Bacik and others added 30 commits November 1, 2011 14:26
If the normal fs tree is hosed and the user has multiple subvolumes it's handy
to be able to specify just one of the subvolumes to restore.  It's also handy if
a user only wants to restore say /home instead of his entire disk.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
This will make the restore program fall back on other mirrors if it fails to
decompress an extent for whatever reason.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
If we hit a bad disk and the read doesn't work, try other mirrors in case we
have other disks with good copies.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Fixes for my Raid10 restore issues.
Signed-off-by: David Marcin <djmarcin@google.com>
btrfs-progs: Check metadata mirrors in find-root.
…ameters

search_dir() recurses down the btrfs tree, and used to take the output
path for every item (i.e. in the running system, output root directory
concatenated with btrfs-local pathname) passed as the only path
parameter. Moving the output root directory to a separate parameter
and passing the btrfs-local pathname for each file and directory
separately allows easy filtering based on the btrfs-local pathname.

Signed-off-by: Peter Stuge <peter@stuge.se>
Signed-off-by: Josef Bacik <josef@redhat.com>
The option -m is used to specify the regex string. -c is used to
specify case insensitive matching. -i was already taken.

In order to restore only a single folder somewhere in the btrfs
tree, it is unfortunately neccessary to construct a slightly
nontrivial regex, e.g.:

restore -m '^/(|home(|/username(|/Desktop(|/.*))))$' /dev/sdb2 /output

This is needed in order to match each directory along the way to the
Desktop directory, as well as all contents below the Desktop directory.

Signed-off-by: Peter Stuge <peter@stuge.se>
Signed-off-by: Josef Bacik <josef@redhat.com>
Signed-off-by: David Marcin <djmarcin@google.com>
Signed-off-by: David Marcin <djmarcin@google.com>
…ning the ctree.

Signed-off-by: David Marcin <djmarcin@google.com>
…nfirmation to btrfs-select-super.

Signed-off-by: David Marcin <djmarcin@google.com>
btrfs-progs: In find-root, dump bytenr for every slot.
btrfs-progs: Utilities for dumping and rolling back to oldest super on filesystem
This patch simply adds support to decompress lzo compressed extents in restore.

Signed-off-by: Josef Bacik <josef@redhat.com>
We were unconditionally executing our regular expression, even though we may not
have one, so check to make sure mreg is not null before calling regexec.
Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
…ced by refactoring.

Signed-off-by: David Marcin <djmarcin@google.com>
btrfs-progs: Fix compilation errors with btrfs-select-super.c introduced...
We don't need most of the roots when doing restore, like the extent tree.  So if
the recovery open_ctree fails because it's trying to open one of these useless
roots just fall back to open_ctree_broken.  This will just open the chunk root
which is the bare minimum of what we need to operate.  Then from there we can
setup the tree_root and the fs_root, and if either of those are gone we can't
restore anyway.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Return an error instead of BUG()'ing out.

Signed-off-by: Josef Bacik <josef@redhat.com>
Don't BUG(), return an error so the recovery program can work its mojo.

Signed-off-by: Josef Bacik <josef@redhat.com>
We were checking for a null root coming back from btrfs_read_fs_root but thats
not right since it returns a ERR_PTR.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Since restore has the ability to open really really screwed up file systems, add
a list roots option to it so we can still get the contents of the tree root on a
horribly broken fs.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
In order to figure out what exactly is broken on a fs we need to spit out the
current offset we are on and the size of the fs to know if the super is wrong
and we just need to ignore it, or if the offset we got is bad and we should just
keep searching.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Trying to track down why we can't find roots, add some verbose output so we know
what chunks we're scanning and when we move to new chunks.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
We were using the wrong variable for the root location if we specified -f when
doing restore.  Fix this.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Our logical offsets may be beyond what we think the size of the disk is, so our
check is bogus, remove it.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
If we have to build our fs_info by hand don't read from the cache when looking
for the fs_root just in case we set something up last time.  Also actually print
the right error, not the root which is ok.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Josef Bacik and others added 10 commits January 4, 2012 10:50
We need to know if we find a valid fs tree when doing find root, so print the
objectid of the roots we find when we find a tree root.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
We need to be able to handle the case where we want to restore from a specific
root if the fs is really really really toast, this patch does that.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
It may be used elsewhere and in the case of a broken fs it won't be there at all
and it makes an assertion trip.  Thanks,

Signed-off-by: Josef Bacik <josef@redhat.com>
Small fixes to compilation/linking
fix for a simple typo
@josefbacik josefbacik force-pushed the master branch 2 times, most recently from 868d3dc to d9b978f Compare October 3, 2014 14:59
josefbacik pushed a commit that referenced this pull request Jan 9, 2020
…_info_cache()

This bug is exposed by fsck-test with D=asan, hit by test case 020, with
the following error report:

=================================================================
==10740==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x621000061580 at pc 0x56051f0db6cd bp 0x7ffe170f3e20 sp 0x7ffe170f3e10
READ of size 1 at 0x621000061580 thread T0
    #0 0x56051f0db6cc in btrfs_extent_inline_ref_type /home/adam/btrfs/btrfs-progs/ctree.h:1727
    #1 0x56051f13b669 in build_roots_info_cache /home/adam/btrfs/btrfs-progs/cmds-check.c:14306
    #2 0x56051f13c86a in repair_root_items /home/adam/btrfs/btrfs-progs/cmds-check.c:14450
    #3 0x56051f13ea89 in cmd_check /home/adam/btrfs/btrfs-progs/cmds-check.c:14965
    #4 0x56051efe75bb in main /home/adam/btrfs/btrfs-progs/btrfs.c:302
    #5 0x7f04ddbb0f49 in __libc_start_main (/usr/lib/libc.so.6+0x20f49)
    #6 0x56051efe68c9 in _start (/home/adam/btrfs/btrfs-progs/btrfs+0x5b8c9)

0x621000061580 is located 0 bytes to the right of 4224-byte region [0x621000060500,0x621000061580)
allocated by thread T0 here:
    #0 0x7f04ded50ce1 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:70
    #1 0x56051f04685e in __alloc_extent_buffer /home/adam/btrfs/btrfs-progs/extent_io.c:553
    #2 0x56051f047563 in alloc_extent_buffer /home/adam/btrfs/btrfs-progs/extent_io.c:687
    #3 0x56051efff1d1 in btrfs_find_create_tree_block /home/adam/btrfs/btrfs-progs/disk-io.c:187
    #4 0x56051f000133 in read_tree_block /home/adam/btrfs/btrfs-progs/disk-io.c:327
    #5 0x56051efeddb8 in read_node_slot /home/adam/btrfs/btrfs-progs/ctree.c:652
    #6 0x56051effb0d9 in btrfs_next_leaf /home/adam/btrfs/btrfs-progs/ctree.c:2853
    #7 0x56051f13b343 in build_roots_info_cache /home/adam/btrfs/btrfs-progs/cmds-check.c:14267
    #8 0x56051f13c86a in repair_root_items /home/adam/btrfs/btrfs-progs/cmds-check.c:14450
    #9 0x56051f13ea89 in cmd_check /home/adam/btrfs/btrfs-progs/cmds-check.c:14965
    #10 0x56051efe75bb in main /home/adam/btrfs/btrfs-progs/btrfs.c:302
    #11 0x7f04ddbb0f49 in __libc_start_main (/usr/lib/libc.so.6+0x20f49)

It's completely possible that one extent/metadata item has no inline
reference, while build_roots_info_cache() doesn't have such check.

Fix it by checking @iref against item end to avoid such problem.

Issue: #92
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
josefbacik pushed a commit that referenced this pull request Jan 9, 2020
…y wrong condition to free delayed ref/head.

[BUG]
When btrfs-progs is compiled with D=asan, it can't pass even the very
basic fsck tests due to btrfs-image has memory leak:
  === START TEST /home/adam/btrfs/btrfs-progs/tests//fsck-tests/001-bad-file-extent-bytenr
  restoring image default_case.img

  =================================================================
  ==7790==ERROR: LeakSanitizer: detected memory leaks

  Direct leak of 104 byte(s) in 1 object(s) allocated from:
      #0 0x7f1d3b738389 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
      #1 0x560ca6b7f4ff in btrfs_add_delayed_tree_ref /home/adam/btrfs/btrfs-progs/delayed-ref.c:569
      #2 0x560ca6af2d0b in btrfs_free_extent /home/adam/btrfs/btrfs-progs/extent-tree.c:2155
      #3 0x560ca6ac16ca in __btrfs_cow_block /home/adam/btrfs/btrfs-progs/ctree.c:319
      #4 0x560ca6ac1d8c in btrfs_cow_block /home/adam/btrfs/btrfs-progs/ctree.c:383
      #5 0x560ca6ac6c8e in btrfs_search_slot /home/adam/btrfs/btrfs-progs/ctree.c:1153
      #6 0x560ca6ab7e83 in fixup_device_size image/main.c:2113
      #7 0x560ca6ab9279 in fixup_chunks_and_devices image/main.c:2333
      #8 0x560ca6ab9ada in restore_metadump image/main.c:2455
      #9 0x560ca6abaeba in main image/main.c:2723
      #10 0x7f1d3b148ce2 in __libc_start_main (/usr/lib/libc.so.6+0x23ce2)

  ... tons of similar leakage for delayed_tree_ref ...

  Direct leak of 96 byte(s) in 1 object(s) allocated from:
      #0 0x7f1d3b738389 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:86
      #1 0x560ca6b7f5fb in btrfs_add_delayed_tree_ref /home/adam/btrfs/btrfs-progs/delayed-ref.c:583
      #2 0x560ca6af5679 in alloc_tree_block /home/adam/btrfs/btrfs-progs/extent-tree.c:2503
      #3 0x560ca6af57ac in btrfs_alloc_free_block /home/adam/btrfs/btrfs-progs/extent-tree.c:2524
      #4 0x560ca6ac115b in __btrfs_cow_block /home/adam/btrfs/btrfs-progs/ctree.c:290
      #5 0x560ca6ac1d8c in btrfs_cow_block /home/adam/btrfs/btrfs-progs/ctree.c:383
      #6 0x560ca6b7bb15 in commit_tree_roots /home/adam/btrfs/btrfs-progs/transaction.c:98
      #7 0x560ca6b7c525 in btrfs_commit_transaction /home/adam/btrfs/btrfs-progs/transaction.c:192
      #8 0x560ca6ab92be in fixup_chunks_and_devices image/main.c:2337
      #9 0x560ca6ab9ada in restore_metadump image/main.c:2455
      #10 0x560ca6abaeba in main image/main.c:2723
      #11 0x7f1d3b148ce2 in __libc_start_main (/usr/lib/libc.so.6+0x23ce2)

  ... tons of similar leakage for delayed_ref_head ...

  SUMMARY: AddressSanitizer: 1600 byte(s) leaked in 16 allocation(s).
  failed to restore image ./default_case.img

[CAUSE]
Commit c603970 ("btrfs-progs: Add delayed refs infrastructure")
introduces delayed ref infrastructure for free space tree, however the
refcount_dec_and_test() from kernel code is wrongly backported.

refcount_dec_and_test() will return true if the refcount reaches 0.
So kernel code will free the allocated space as expected:
	if (refcount_dec_and_test(&ref->refs)) {
		kmem_cache_free();
	}

However btrfs-progs backport is using the opposite condition:
	if (--ref->refs) {
		kfree();
	}

This will not free the memory for the last user, but for refs >= 2.
Causing both use-after-free and memory leak for any offline write
operation.

[FIX]
Fix the (--ref->refs) condition to (--ref->refs == 0) to fix the
backport error.

Fixes: c603970 ("btrfs-progs: Add delayed refs infrastructure")
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants