--- /dev/null
+From 5c78a5e7aa835c4f08a7c90fe02d19f95a776f29 Mon Sep 17 00:00:00 2001
+From: Anand Jain <anand.jain@oracle.com>
+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 <anand.jain@oracle.com>
+
+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 <josef@toxicpanda.com>
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
--- /dev/null
+From 5d03dbebba2594d2e6fbf3b5dd9060c5a835de3b Mon Sep 17 00:00:00 2001
+From: Li Zhang <zhanglikernel@gmail.com>
+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 <zhanglikernel@gmail.com>
+
+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 <zhanglikernel@gmail.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+
--- /dev/null
+From 10adb1152d957a4d570ad630f93a88bb961616c1 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Thu, 14 Oct 2021 17:26:04 +0100
+Subject: btrfs: fix lost error handling when replaying directory deletes
+
+From: Filipe Manana <fdmanana@suse.com>
+
+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 <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
+ }
+