From 025462f94ed033e33deca22e98f160a83e1c3098 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 13 Nov 2021 15:12:34 +0100 Subject: [PATCH] 4.19-stable patches added patches: btrfs-call-btrfs_check_rw_degradable-only-if-there-is-a-missing-device.patch btrfs-clear-missing-device-status-bit-in-btrfs_close_one_device.patch btrfs-fix-lost-error-handling-when-replaying-directory-deletes.patch --- ...le-only-if-there-is-a-missing-device.patch | 63 ++++++++ ...status-bit-in-btrfs_close_one_device.patch | 136 ++++++++++++++++++ ...ing-when-replaying-directory-deletes.patch | 37 +++++ queue-4.19/series | 3 + 4 files changed, 239 insertions(+) create mode 100644 queue-4.19/btrfs-call-btrfs_check_rw_degradable-only-if-there-is-a-missing-device.patch create mode 100644 queue-4.19/btrfs-clear-missing-device-status-bit-in-btrfs_close_one_device.patch create mode 100644 queue-4.19/btrfs-fix-lost-error-handling-when-replaying-directory-deletes.patch diff --git a/queue-4.19/btrfs-call-btrfs_check_rw_degradable-only-if-there-is-a-missing-device.patch b/queue-4.19/btrfs-call-btrfs_check_rw_degradable-only-if-there-is-a-missing-device.patch new file mode 100644 index 00000000000..acfaaeecae6 --- /dev/null +++ b/queue-4.19/btrfs-call-btrfs_check_rw_degradable-only-if-there-is-a-missing-device.patch @@ -0,0 +1,63 @@ +From 5c78a5e7aa835c4f08a7c90fe02d19f95a776f29 Mon Sep 17 00:00:00 2001 +From: Anand Jain +Date: Tue, 19 Oct 2021 18:43:38 +0800 +Subject: btrfs: call btrfs_check_rw_degradable only if there is a missing device + +From: Anand Jain + +commit 5c78a5e7aa835c4f08a7c90fe02d19f95a776f29 upstream. + +In open_ctree() in btrfs_check_rw_degradable() [1], we check each block +group individually if at least the minimum number of devices is available +for that profile. If all the devices are available, then we don't have to +check degradable. + +[1] +open_ctree() +:: +3559 if (!sb_rdonly(sb) && !btrfs_check_rw_degradable(fs_info, NULL)) { + +Also before calling btrfs_check_rw_degradable() in open_ctee() at the +line number shown below [2] we call btrfs_read_chunk_tree() and down to +add_missing_dev() to record number of missing devices. + +[2] +open_ctree() +:: +3454 ret = btrfs_read_chunk_tree(fs_info); + +btrfs_read_chunk_tree() + read_one_chunk() / read_one_dev() + add_missing_dev() + +So, check if there is any missing device before btrfs_check_rw_degradable() +in open_ctree(). + +Also, with this the mount command could save ~16ms.[3] in the most +common case, that is no device is missing. + +[3] + 1) * 16934.96 us | btrfs_check_rw_degradable [btrfs](); + +CC: stable@vger.kernel.org # 4.19+ +Reviewed-by: Josef Bacik +Signed-off-by: Anand Jain +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/disk-io.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -3095,7 +3095,8 @@ retry_root_backup: + goto fail_sysfs; + } + +- if (!sb_rdonly(sb) && !btrfs_check_rw_degradable(fs_info, NULL)) { ++ if (!sb_rdonly(sb) && fs_info->fs_devices->missing_devices && ++ !btrfs_check_rw_degradable(fs_info, NULL)) { + btrfs_warn(fs_info, + "writeable mount is not allowed due to too many missing devices"); + goto fail_sysfs; diff --git a/queue-4.19/btrfs-clear-missing-device-status-bit-in-btrfs_close_one_device.patch b/queue-4.19/btrfs-clear-missing-device-status-bit-in-btrfs_close_one_device.patch new file mode 100644 index 00000000000..df41d201e0b --- /dev/null +++ b/queue-4.19/btrfs-clear-missing-device-status-bit-in-btrfs_close_one_device.patch @@ -0,0 +1,136 @@ +From 5d03dbebba2594d2e6fbf3b5dd9060c5a835de3b Mon Sep 17 00:00:00 2001 +From: Li Zhang +Date: Tue, 5 Oct 2021 01:15:33 +0800 +Subject: btrfs: clear MISSING device status bit in btrfs_close_one_device +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Li Zhang + +commit 5d03dbebba2594d2e6fbf3b5dd9060c5a835de3b upstream. + +Reported bug: https://github.com/kdave/btrfs-progs/issues/389 + +There's a problem with scrub reporting aborted status but returning +error code 0, on a filesystem with missing and readded device. + +Roughly these steps: + +- mkfs -d raid1 dev1 dev2 +- fill with data +- unmount +- make dev1 disappear +- mount -o degraded +- copy more data +- make dev1 appear again + +Running scrub afterwards reports that the command was aborted, but the +system log message says the exit code was 0. + +It seems that the cause of the error is decrementing +fs_devices->missing_devices but not clearing device->dev_state. Every +time we umount filesystem, it would call close_ctree, And it would +eventually involve btrfs_close_one_device to close the device, but it +only decrements fs_devices->missing_devices but does not clear the +device BTRFS_DEV_STATE_MISSING bit. Worse, this bug will cause Integer +Overflow, because every time umount, fs_devices->missing_devices will +decrease. If fs_devices->missing_devices value hit 0, it would overflow. + +With added debugging: + + loop1: detected capacity change from 0 to 20971520 + BTRFS: device fsid 56ad51f1-5523-463b-8547-c19486c51ebb devid 1 transid 21 /dev/loop1 scanned by systemd-udevd (2311) + loop2: detected capacity change from 0 to 20971520 + BTRFS: device fsid 56ad51f1-5523-463b-8547-c19486c51ebb devid 2 transid 17 /dev/loop2 scanned by systemd-udevd (2313) + BTRFS info (device loop1): flagging fs with big metadata feature + BTRFS info (device loop1): allowing degraded mounts + BTRFS info (device loop1): using free space tree + BTRFS info (device loop1): has skinny extents + BTRFS info (device loop1): before clear_missing.00000000f706684d /dev/loop1 0 + BTRFS warning (device loop1): devid 2 uuid 6635ac31-56dd-4852-873b-c60f5e2d53d2 is missing + BTRFS info (device loop1): before clear_missing.0000000000000000 /dev/loop2 1 + BTRFS info (device loop1): flagging fs with big metadata feature + BTRFS info (device loop1): allowing degraded mounts + BTRFS info (device loop1): using free space tree + BTRFS info (device loop1): has skinny extents + BTRFS info (device loop1): before clear_missing.00000000f706684d /dev/loop1 0 + BTRFS warning (device loop1): devid 2 uuid 6635ac31-56dd-4852-873b-c60f5e2d53d2 is missing + BTRFS info (device loop1): before clear_missing.0000000000000000 /dev/loop2 0 + BTRFS info (device loop1): flagging fs with big metadata feature + BTRFS info (device loop1): allowing degraded mounts + BTRFS info (device loop1): using free space tree + BTRFS info (device loop1): has skinny extents + BTRFS info (device loop1): before clear_missing.00000000f706684d /dev/loop1 18446744073709551615 + BTRFS warning (device loop1): devid 2 uuid 6635ac31-56dd-4852-873b-c60f5e2d53d2 is missing + BTRFS info (device loop1): before clear_missing.0000000000000000 /dev/loop2 18446744073709551615 + +If fs_devices->missing_devices is 0, next time it would be 18446744073709551615 + +After apply this patch, the fs_devices->missing_devices seems to be +right: + + $ truncate -s 10g test1 + $ truncate -s 10g test2 + $ losetup /dev/loop1 test1 + $ losetup /dev/loop2 test2 + $ mkfs.btrfs -draid1 -mraid1 /dev/loop1 /dev/loop2 -f + $ losetup -d /dev/loop2 + $ mount -o degraded /dev/loop1 /mnt/1 + $ umount /mnt/1 + $ mount -o degraded /dev/loop1 /mnt/1 + $ umount /mnt/1 + $ mount -o degraded /dev/loop1 /mnt/1 + $ umount /mnt/1 + $ dmesg + + loop1: detected capacity change from 0 to 20971520 + loop2: detected capacity change from 0 to 20971520 + BTRFS: device fsid 15aa1203-98d3-4a66-bcae-ca82f629c2cd devid 1 transid 5 /dev/loop1 scanned by mkfs.btrfs (1863) + BTRFS: device fsid 15aa1203-98d3-4a66-bcae-ca82f629c2cd devid 2 transid 5 /dev/loop2 scanned by mkfs.btrfs (1863) + BTRFS info (device loop1): flagging fs with big metadata feature + BTRFS info (device loop1): allowing degraded mounts + BTRFS info (device loop1): disk space caching is enabled + BTRFS info (device loop1): has skinny extents + BTRFS info (device loop1): before clear_missing.00000000975bd577 /dev/loop1 0 + BTRFS warning (device loop1): devid 2 uuid 8b333791-0b3f-4f57-b449-1c1ab6b51f38 is missing + BTRFS info (device loop1): before clear_missing.0000000000000000 /dev/loop2 1 + BTRFS info (device loop1): checking UUID tree + BTRFS info (device loop1): flagging fs with big metadata feature + BTRFS info (device loop1): allowing degraded mounts + BTRFS info (device loop1): disk space caching is enabled + BTRFS info (device loop1): has skinny extents + BTRFS info (device loop1): before clear_missing.00000000975bd577 /dev/loop1 0 + BTRFS warning (device loop1): devid 2 uuid 8b333791-0b3f-4f57-b449-1c1ab6b51f38 is missing + BTRFS info (device loop1): before clear_missing.0000000000000000 /dev/loop2 1 + BTRFS info (device loop1): flagging fs with big metadata feature + BTRFS info (device loop1): allowing degraded mounts + BTRFS info (device loop1): disk space caching is enabled + BTRFS info (device loop1): has skinny extents + BTRFS info (device loop1): before clear_missing.00000000975bd577 /dev/loop1 0 + BTRFS warning (device loop1): devid 2 uuid 8b333791-0b3f-4f57-b449-1c1ab6b51f38 is missing + BTRFS info (device loop1): before clear_missing.0000000000000000 /dev/loop2 1 + +CC: stable@vger.kernel.org # 4.19+ +Signed-off-by: Li Zhang +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/volumes.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -1051,8 +1051,10 @@ static void btrfs_close_one_device(struc + if (device->devid == BTRFS_DEV_REPLACE_DEVID) + clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); + +- if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) ++ if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) { ++ clear_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); + fs_devices->missing_devices--; ++ } + + btrfs_close_bdev(device); + diff --git a/queue-4.19/btrfs-fix-lost-error-handling-when-replaying-directory-deletes.patch b/queue-4.19/btrfs-fix-lost-error-handling-when-replaying-directory-deletes.patch new file mode 100644 index 00000000000..187ecc147e9 --- /dev/null +++ b/queue-4.19/btrfs-fix-lost-error-handling-when-replaying-directory-deletes.patch @@ -0,0 +1,37 @@ +From 10adb1152d957a4d570ad630f93a88bb961616c1 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Thu, 14 Oct 2021 17:26:04 +0100 +Subject: btrfs: fix lost error handling when replaying directory deletes + +From: Filipe Manana + +commit 10adb1152d957a4d570ad630f93a88bb961616c1 upstream. + +At replay_dir_deletes(), if find_dir_range() returns an error we break out +of the main while loop and then assign a value of 0 (success) to the 'ret' +variable, resulting in completely ignoring that an error happened. Fix +that by jumping to the 'out' label when find_dir_range() returns an error +(negative value). + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/tree-log.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -2412,7 +2412,9 @@ again: + else { + ret = find_dir_range(log, path, dirid, key_type, + &range_start, &range_end); +- if (ret != 0) ++ if (ret < 0) ++ goto out; ++ else if (ret > 0) + break; + } + diff --git a/queue-4.19/series b/queue-4.19/series index 3168c6e7301..43f1c8cdad7 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -36,3 +36,6 @@ xen-netfront-stop-tx-queues-during-live-migration.patch spi-spl022-fix-microwire-full-duplex-mode.patch watchdog-fix-omap-watchdog-early-handling.patch vmxnet3-do-not-stop-tx-queues-after-netif_device_det.patch +btrfs-clear-missing-device-status-bit-in-btrfs_close_one_device.patch +btrfs-fix-lost-error-handling-when-replaying-directory-deletes.patch +btrfs-call-btrfs_check_rw_degradable-only-if-there-is-a-missing-device.patch -- 2.47.2