btrfs-progs/kernel-shared
Qu Wenruo 2aa4085bf7 btrfs-progs: properly handle degraded raid56 reads
[BUG]
For a degraded RAID5, btrfs check will fail to even read the chunk root:

  # mkfs.btrfs -f -m raid5 -d raid5 $dev1 $dev2 $dev3
  # wipefs -fa $dev1
  # btrfs check $dev2
  Opening filesystem to check...
  warning, device 1 is missing
  bad tree block 22036480, bytenr mismatch, want=22036480, have=0
  ERROR: cannot read chunk root
  ERROR: cannot open file system

[CAUSE]
Although read_tree_block() function from btrfs-progs is properly
iterating the mirrors (mirror 1 is reading from the disk directly,
mirror 2 will be rebuild from parity), the raid56 recovery path is not
handling the read error correctly.

The existing code will try to read the full stripe, but any read failure
(including missing device) will immediately cause an error:

	for (i = 0; i < num_stripes; i++) {
		ret = btrfs_pread(multi->stripes[i].dev->fd, pointers[i],
				  BTRFS_STRIPE_LEN, multi->stripes[i].physical,
				  fs_info->zoned);
		if (ret < BTRFS_STRIPE_LEN) {
			ret = -EIO;
			goto out;
		}
	}

[FIX]
To make failed_a/failed_b calculation much easier, and properly handle
too many missing devices, here this patch will introduce a new bitmap
based solution.

The new @failed_stripe_bitmap will represent all the failed stripes.

So the initial read will mark all the missing devices in the
@failed_stripe_bitmap, and later operations will all operate on that
bitmap.

Only before we call raid56_recov(), we convert the bitmap to the old
failed_a/failed_b interface and continue.

Now btrfs check can handle above case properly:

  # btrfs check $dev2
  Opening filesystem to check...
  warning, device 1 is missing
  Checking filesystem on /dev/test/scratch2
  UUID: 8b2e1cb4-f35b-4856-9b11-262d39d8458b
  [1/7] checking root items
  [2/7] checking extents
  [3/7] checking free space tree
  [4/7] checking fs roots
  [5/7] checking only csums items (without verifying data)
  [6/7] checking root refs
  [7/7] checking quota groups skipped (not enabled on this FS)
  found 147456 bytes used, no error found
  total csum bytes: 0
  total tree bytes: 147456
  total fs tree bytes: 32768
  total extent tree bytes: 16384
  btree space waste bytes: 139871
  file data blocks allocated: 0
   referenced 0

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2022-11-24 17:29:12 +01:00
..
backref.c btrfs-progs: remove the _nr from the item helpers 2022-03-09 15:13:13 +01:00
backref.h btrfs-progs: move extent_io.c to kernel-shared/ 2020-08-31 17:01:04 +02:00
ctree.c btrfs-progs: move repair.c from common/ to check/ 2022-10-11 09:08:09 +02:00
ctree.h btrfs-progs: unify naming of qgroup subvolid helpers 2022-10-26 09:36:44 +02:00
delayed-ref.c btrfs-progs: don't include btrfs-list.h unless necessary 2021-10-08 20:47:03 +02:00
delayed-ref.h btrfs-progs: unify GPL header comments 2021-09-07 13:58:44 +02:00
dir-item.c btrfs-progs: remove the _nr from the item helpers 2022-03-09 15:13:13 +01:00
disk-io.c btrfs-progs: use template for out of memory error messages 2022-10-11 09:08:09 +02:00
disk-io.h btrfs-progs: btrfstune: add the ability to convert to block group tree feature 2022-09-12 18:25:32 +02:00
extent-tree.c btrfs-progs: mkfs: offset inode numbers of the source filesystem 2022-10-11 09:08:10 +02:00
extent_io.c btrfs-progs: properly handle degraded raid56 reads 2022-11-24 17:29:12 +01:00
extent_io.h btrfs-progs: remove unused function extent_io_tree_init_cache_max() 2022-10-11 09:08:08 +02:00
file-item.c btrfs-progs: kernel-lib: remove radix-tree 2022-10-11 09:08:07 +02:00
file.c btrfs-progs: use read_data_from_disk() to replace read_extent_from_disk() and replace read_extent_data() 2022-04-25 19:08:30 +02:00
free-space-cache.c btrfs-progs: use read_data_from_disk() to replace read_extent_from_disk() and replace read_extent_data() 2022-04-25 19:08:30 +02:00
free-space-cache.h btrfs-progs: check: batch v1 space cache inodes when clearing 2021-07-22 16:26:05 +02:00
free-space-tree.c btrfs-progs: fix may be unused warning in load_free_space_extents 2022-10-11 09:06:11 +02:00
free-space-tree.h btrfs-progs: properly initialize block group thresholds 2022-05-20 15:54:20 +02:00
inode-item.c btrfs-progs: remove the _nr from the item helpers 2022-03-09 15:13:13 +01:00
inode.c btrfs-progs: use template for transaction commit error messages 2022-10-11 09:08:10 +02:00
print-tree.c btrfs-progs: unify naming of qgroup subvolid helpers 2022-10-26 09:36:44 +02:00
print-tree.h btrfs-progs: dump-tree: add options to dump checksums 2021-06-19 22:07:49 +02:00
root-tree.c btrfs-progs: remove the _nr from the item helpers 2022-03-09 15:13:13 +01:00
send.h btrfs-progs: receive: add support for fs-verity 2022-10-11 09:08:08 +02:00
transaction.c btrfs-progs: properly handle write error when writing back tree blocks 2022-10-11 09:08:08 +02:00
transaction.h btrfs-progs: move transaction.c to kernel-shared/ 2020-08-31 17:01:06 +02:00
ulist.c btrfs-progs: unify GPL header comments 2021-09-07 13:58:44 +02:00
ulist.h btrfs-progs: unify GPL header comments 2021-09-07 13:58:44 +02:00
uuid-tree.c btrfs-progs: remove the _nr from the item helpers 2022-03-09 15:13:13 +01:00
volumes.c btrfs-progs: device-utils: rename btrfs_device_size 2022-10-11 09:08:10 +02:00
volumes.h btrfs-progs: remove the unused btrfs_fs_info::seeding member 2022-04-29 22:13:22 +02:00
zoned.c btrfs-progs: replace strerror(errno) with %m in printf formats 2022-10-26 09:46:22 +02:00
zoned.h btrfs-progs: zoned: export sb_zone_number() and related constants 2022-04-08 23:17:35 +02:00