]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Mar 2018 16:02:11 +0000 (17:02 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Mar 2018 16:02:11 +0000 (17:02 +0100)
added patches:
btrfs-add-missing-initialization-in-btrfs_check_shared.patch
btrfs-alloc_chunk-fix-dup-stripe-size-handling.patch
btrfs-fix-memory-barriers-usage-with-device-stats-counters.patch
btrfs-fix-null-pointer-exception-in-find_bio_stripe.patch
btrfs-fix-use-after-free-when-cleaning-up-fs_devs-with-a-single-stale-device.patch
btrfs-remove-spurious-warn_on-ref-count-0-in-find_parent_nodes.patch

queue-4.14/btrfs-add-missing-initialization-in-btrfs_check_shared.patch [new file with mode: 0644]
queue-4.14/btrfs-alloc_chunk-fix-dup-stripe-size-handling.patch [new file with mode: 0644]
queue-4.14/btrfs-fix-memory-barriers-usage-with-device-stats-counters.patch [new file with mode: 0644]
queue-4.14/btrfs-fix-null-pointer-exception-in-find_bio_stripe.patch [new file with mode: 0644]
queue-4.14/btrfs-fix-use-after-free-when-cleaning-up-fs_devs-with-a-single-stale-device.patch [new file with mode: 0644]
queue-4.14/btrfs-remove-spurious-warn_on-ref-count-0-in-find_parent_nodes.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/btrfs-add-missing-initialization-in-btrfs_check_shared.patch b/queue-4.14/btrfs-add-missing-initialization-in-btrfs_check_shared.patch
new file mode 100644 (file)
index 0000000..b014ac9
--- /dev/null
@@ -0,0 +1,67 @@
+From 18bf591ba9753e3e5ba91f38f756a800693408f4 Mon Sep 17 00:00:00 2001
+From: Edmund Nadolski <enadolski@suse.com>
+Date: Wed, 14 Mar 2018 09:03:11 -0600
+Subject: btrfs: add missing initialization in btrfs_check_shared
+
+From: Edmund Nadolski <enadolski@suse.com>
+
+commit 18bf591ba9753e3e5ba91f38f756a800693408f4 upstream.
+
+This patch addresses an issue that causes fiemap to falsely
+report a shared extent.  The test case is as follows:
+
+xfs_io -f -d -c "pwrite -b 16k 0 64k" -c "fiemap -v" /media/scratch/file5
+sync
+xfs_io  -c "fiemap -v" /media/scratch/file5
+
+which gives the resulting output:
+
+wrote 65536/65536 bytes at offset 0
+64 KiB, 4 ops; 0.0000 sec (121.359 MiB/sec and 7766.9903 ops/sec)
+/media/scratch/file5:
+ EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
+   0: [0..127]:        24576..24703       128 0x2001
+/media/scratch/file5:
+ EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
+   0: [0..127]:        24576..24703       128   0x1
+
+This is because btrfs_check_shared calls find_parent_nodes
+repeatedly in a loop, passing a share_check struct to report
+the count of shared extent. But btrfs_check_shared does not
+re-initialize the count value to zero for subsequent calls
+from the loop, resulting in a false share count value. This
+is a regressive behavior from 4.13.
+
+With proper re-initialization the test result is as follows:
+
+wrote 65536/65536 bytes at offset 0
+64 KiB, 4 ops; 0.0000 sec (110.035 MiB/sec and 7042.2535 ops/sec)
+/media/scratch/file5:
+ EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
+   0: [0..127]:        24576..24703       128   0x1
+/media/scratch/file5:
+ EXT: FILE-OFFSET      BLOCK-RANGE      TOTAL FLAGS
+   0: [0..127]:        24576..24703       128   0x1
+
+which corrects the regression.
+
+Fixes: 3ec4d3238ab ("btrfs: allow backref search checks for shared extents")
+Signed-off-by: Edmund Nadolski <enadolski@suse.com>
+[ add text from cover letter to changelog ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/backref.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -1496,6 +1496,7 @@ int btrfs_check_shared(struct btrfs_root
+               if (!node)
+                       break;
+               bytenr = node->val;
++              shared.share_count = 0;
+               cond_resched();
+       }
diff --git a/queue-4.14/btrfs-alloc_chunk-fix-dup-stripe-size-handling.patch b/queue-4.14/btrfs-alloc_chunk-fix-dup-stripe-size-handling.patch
new file mode 100644 (file)
index 0000000..dcd38aa
--- /dev/null
@@ -0,0 +1,89 @@
+From 92e222df7b8f05c565009c7383321b593eca488b Mon Sep 17 00:00:00 2001
+From: Hans van Kranenburg <hans.van.kranenburg@mendix.com>
+Date: Mon, 5 Feb 2018 17:45:11 +0100
+Subject: btrfs: alloc_chunk: fix DUP stripe size handling
+
+From: Hans van Kranenburg <hans.van.kranenburg@mendix.com>
+
+commit 92e222df7b8f05c565009c7383321b593eca488b upstream.
+
+In case of using DUP, we search for enough unallocated disk space on a
+device to hold two stripes.
+
+The devices_info[ndevs-1].max_avail that holds the amount of unallocated
+space found is directly assigned to stripe_size, while it's actually
+twice the stripe size.
+
+Later on in the code, an unconditional division of stripe_size by
+dev_stripes corrects the value, but in the meantime there's a check to
+see if the stripe_size does not exceed max_chunk_size. Since during this
+check stripe_size is twice the amount as intended, the check will reduce
+the stripe_size to max_chunk_size if the actual correct to be used
+stripe_size is more than half the amount of max_chunk_size.
+
+The unconditional division later tries to correct stripe_size, but will
+actually make sure we can't allocate more than half the max_chunk_size.
+
+Fix this by moving the division by dev_stripes before the max chunk size
+check, so it always contains the right value, instead of putting a duct
+tape division in further on to get it fixed again.
+
+Since in all other cases than DUP, dev_stripes is 1, this change only
+affects DUP.
+
+Other attempts in the past were made to fix this:
+* 37db63a400 "Btrfs: fix max chunk size check in chunk allocator" tried
+to fix the same problem, but still resulted in part of the code acting
+on a wrongly doubled stripe_size value.
+* 86db25785a "Btrfs: fix max chunk size on raid5/6" unintentionally
+broke this fix again.
+
+The real problem was already introduced with the rest of the code in
+73c5de0051.
+
+The user visible result however will be that the max chunk size for DUP
+will suddenly double, while it's actually acting according to the limits
+in the code again like it was 5 years ago.
+
+Reported-by: Naohiro Aota <naohiro.aota@wdc.com>
+Link: https://www.spinics.net/lists/linux-btrfs/msg69752.html
+Fixes: 73c5de0051 ("btrfs: quasi-round-robin for chunk allocation")
+Fixes: 86db25785a ("Btrfs: fix max chunk size on raid5/6")
+Signed-off-by: Hans van Kranenburg <hans.van.kranenburg@mendix.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+[ update comment ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/volumes.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -4733,10 +4733,13 @@ static int __btrfs_alloc_chunk(struct bt
+       ndevs = min(ndevs, devs_max);
+       /*
+-       * the primary goal is to maximize the number of stripes, so use as many
+-       * devices as possible, even if the stripes are not maximum sized.
++       * The primary goal is to maximize the number of stripes, so use as
++       * many devices as possible, even if the stripes are not maximum sized.
++       *
++       * The DUP profile stores more than one stripe per device, the
++       * max_avail is the total size so we have to adjust.
+        */
+-      stripe_size = devices_info[ndevs-1].max_avail;
++      stripe_size = div_u64(devices_info[ndevs - 1].max_avail, dev_stripes);
+       num_stripes = ndevs * dev_stripes;
+       /*
+@@ -4771,8 +4774,6 @@ static int __btrfs_alloc_chunk(struct bt
+                       stripe_size = devices_info[ndevs-1].max_avail;
+       }
+-      stripe_size = div_u64(stripe_size, dev_stripes);
+-
+       /* align to BTRFS_STRIPE_LEN */
+       stripe_size = round_down(stripe_size, BTRFS_STRIPE_LEN);
diff --git a/queue-4.14/btrfs-fix-memory-barriers-usage-with-device-stats-counters.patch b/queue-4.14/btrfs-fix-memory-barriers-usage-with-device-stats-counters.patch
new file mode 100644 (file)
index 0000000..ab2f705
--- /dev/null
@@ -0,0 +1,96 @@
+From 9deae9689231964972a94bb56a79b669f9d47ac1 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Tue, 24 Oct 2017 13:47:37 +0300
+Subject: btrfs: Fix memory barriers usage with device stats counters
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 9deae9689231964972a94bb56a79b669f9d47ac1 upstream.
+
+Commit addc3fa74e5b ("Btrfs: Fix the problem that the dirty flag of dev
+stats is cleared") reworked the way device stats changes are tracked. A
+new atomic dev_stats_ccnt counter was introduced which is incremented
+every time any of the device stats counters are changed. This serves as
+a flag whether there are any pending stats changes. However, this patch
+only partially implemented the correct memory barriers necessary:
+
+- It only ordered the stores to the counters but not the reads e.g.
+  btrfs_run_dev_stats
+- It completely omitted any comments documenting the intended design and
+  how the memory barriers pair with each-other
+
+This patch provides the necessary comments as well as adds a missing
+smp_rmb in btrfs_run_dev_stats. Furthermore since dev_stats_cnt is only
+a snapshot at best there was no point in reading the counter twice -
+once in btrfs_dev_stats_dirty and then again when assigning stats_cnt.
+Just collapse both reads into 1.
+
+Fixes: addc3fa74e5b ("Btrfs: Fix the problem that the dirty flag of dev stats is cleared")
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.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 |   18 ++++++++++++++++--
+ fs/btrfs/volumes.h |   12 ++++++++++++
+ 2 files changed, 28 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -7082,10 +7082,24 @@ int btrfs_run_dev_stats(struct btrfs_tra
+       mutex_lock(&fs_devices->device_list_mutex);
+       list_for_each_entry(device, &fs_devices->devices, dev_list) {
+-              if (!device->dev_stats_valid || !btrfs_dev_stats_dirty(device))
++              stats_cnt = atomic_read(&device->dev_stats_ccnt);
++              if (!device->dev_stats_valid || stats_cnt == 0)
+                       continue;
+-              stats_cnt = atomic_read(&device->dev_stats_ccnt);
++
++              /*
++               * There is a LOAD-LOAD control dependency between the value of
++               * dev_stats_ccnt and updating the on-disk values which requires
++               * reading the in-memory counters. Such control dependencies
++               * require explicit read memory barriers.
++               *
++               * This memory barriers pairs with smp_mb__before_atomic in
++               * btrfs_dev_stat_inc/btrfs_dev_stat_set and with the full
++               * barrier implied by atomic_xchg in
++               * btrfs_dev_stats_read_and_reset
++               */
++              smp_rmb();
++
+               ret = update_dev_stat_item(trans, fs_info, device);
+               if (!ret)
+                       atomic_sub(stats_cnt, &device->dev_stats_ccnt);
+--- a/fs/btrfs/volumes.h
++++ b/fs/btrfs/volumes.h
+@@ -498,6 +498,12 @@ static inline void btrfs_dev_stat_inc(st
+                                     int index)
+ {
+       atomic_inc(dev->dev_stat_values + index);
++      /*
++       * This memory barrier orders stores updating statistics before stores
++       * updating dev_stats_ccnt.
++       *
++       * It pairs with smp_rmb() in btrfs_run_dev_stats().
++       */
+       smp_mb__before_atomic();
+       atomic_inc(&dev->dev_stats_ccnt);
+ }
+@@ -523,6 +529,12 @@ static inline void btrfs_dev_stat_set(st
+                                     int index, unsigned long val)
+ {
+       atomic_set(dev->dev_stat_values + index, val);
++      /*
++       * This memory barrier orders stores updating statistics before stores
++       * updating dev_stats_ccnt.
++       *
++       * It pairs with smp_rmb() in btrfs_run_dev_stats().
++       */
+       smp_mb__before_atomic();
+       atomic_inc(&dev->dev_stats_ccnt);
+ }
diff --git a/queue-4.14/btrfs-fix-null-pointer-exception-in-find_bio_stripe.patch b/queue-4.14/btrfs-fix-null-pointer-exception-in-find_bio_stripe.patch
new file mode 100644 (file)
index 0000000..91d9811
--- /dev/null
@@ -0,0 +1,89 @@
+From 047fdea6341966a0898e3b16c51f54d4f5ba030a Mon Sep 17 00:00:00 2001
+From: Dmitriy Gorokh <Dmitriy.Gorokh@wdc.com>
+Date: Fri, 16 Feb 2018 19:51:38 +0000
+Subject: btrfs: Fix NULL pointer exception in find_bio_stripe
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitriy Gorokh <Dmitriy.Gorokh@wdc.com>
+
+commit 047fdea6341966a0898e3b16c51f54d4f5ba030a upstream.
+
+On detaching of a disk which is a part of a RAID6 filesystem, the
+following kernel OOPS may happen:
+
+[63122.680461] BTRFS error (device sdo): bdev /dev/sdo errs: wr 0, rd 0, flush 1, corrupt 0, gen 0
+[63122.719584] BTRFS warning (device sdo): lost page write due to IO error on /dev/sdo
+[63122.719587] BTRFS error (device sdo): bdev /dev/sdo errs: wr 1, rd 0, flush 1, corrupt 0, gen 0
+[63122.803516] BTRFS warning (device sdo): lost page write due to IO error on /dev/sdo
+[63122.803519] BTRFS error (device sdo): bdev /dev/sdo errs: wr 2, rd 0, flush 1, corrupt 0, gen 0
+[63122.863902] BTRFS critical (device sdo): fatal error on device /dev/sdo
+[63122.935338] BUG: unable to handle kernel NULL pointer dereference at 0000000000000080
+[63122.946554] IP: fail_bio_stripe+0x58/0xa0 [btrfs]
+[63122.958185] PGD 9ecda067 P4D 9ecda067 PUD b2b37067 PMD 0
+[63122.971202] Oops: 0000 [#1] SMP
+[63123.006760] CPU: 0 PID: 3979 Comm: kworker/u8:9 Tainted: G W 4.14.2-16-scst34x+ #8
+[63123.007091] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
+[63123.007402] Workqueue: btrfs-worker btrfs_worker_helper [btrfs]
+[63123.007595] task: ffff880036ea4040 task.stack: ffffc90006384000
+[63123.007796] RIP: 0010:fail_bio_stripe+0x58/0xa0 [btrfs]
+[63123.007968] RSP: 0018:ffffc90006387ad8 EFLAGS: 00010287
+[63123.008140] RAX: 0000000000000002 RBX: ffff88004beaa0b8 RCX: ffff8800b2bd5690
+[63123.008359] RDX: 0000000000000000 RSI: ffff88007bb43500 RDI: ffff88004beaa000
+[63123.008621] RBP: ffffc90006387ae8 R08: 0000000099100000 R09: ffff8800b2bd5600
+[63123.008840] R10: 0000000000000004 R11: 0000000000010000 R12: ffff88007bb43500
+[63123.009059] R13: 00000000fffffffb R14: ffff880036fc5180 R15: 0000000000000004
+[63123.009278] FS: 0000000000000000(0000) GS:ffff8800b7000000(0000) knlGS:0000000000000000
+[63123.009564] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[63123.009748] CR2: 0000000000000080 CR3: 00000000b0866000 CR4: 00000000000406f0
+[63123.009969] Call Trace:
+[63123.010085] raid_write_end_io+0x7e/0x80 [btrfs]
+[63123.010251] bio_endio+0xa1/0x120
+[63123.010378] generic_make_request+0x218/0x270
+[63123.010921] submit_bio+0x66/0x130
+[63123.011073] finish_rmw+0x3fc/0x5b0 [btrfs]
+[63123.011245] full_stripe_write+0x96/0xc0 [btrfs]
+[63123.011428] raid56_parity_write+0x117/0x170 [btrfs]
+[63123.011604] btrfs_map_bio+0x2ec/0x320 [btrfs]
+[63123.011759] ? ___cache_free+0x1c5/0x300
+[63123.011909] __btrfs_submit_bio_done+0x26/0x50 [btrfs]
+[63123.012087] run_one_async_done+0x9c/0xc0 [btrfs]
+[63123.012257] normal_work_helper+0x19e/0x300 [btrfs]
+[63123.012429] btrfs_worker_helper+0x12/0x20 [btrfs]
+[63123.012656] process_one_work+0x14d/0x350
+[63123.012888] worker_thread+0x4d/0x3a0
+[63123.013026] ? _raw_spin_unlock_irqrestore+0x15/0x20
+[63123.013192] kthread+0x109/0x140
+[63123.013315] ? process_scheduled_works+0x40/0x40
+[63123.013472] ? kthread_stop+0x110/0x110
+[63123.013610] ret_from_fork+0x25/0x30
+[63123.014469] RIP: fail_bio_stripe+0x58/0xa0 [btrfs] RSP: ffffc90006387ad8
+[63123.014678] CR2: 0000000000000080
+[63123.016590] ---[ end trace a295ea7259c17880 ]—
+
+This is reproducible in a cycle, where a series of writes is followed by
+SCSI device delete command. The test may take up to few minutes.
+
+Fixes: 74d46992e0d9 ("block: replace bi_bdev with a gendisk pointer and partitions index")
+[ no signed-off-by provided ]
+Author: Dmitriy Gorokh <Dmitriy.Gorokh@wdc.com>
+Reviewed-by: Liu Bo <bo.li.liu@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/raid56.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/btrfs/raid56.c
++++ b/fs/btrfs/raid56.c
+@@ -1348,6 +1348,7 @@ static int find_bio_stripe(struct btrfs_
+               stripe_start = stripe->physical;
+               if (physical >= stripe_start &&
+                   physical < stripe_start + rbio->stripe_len &&
++                  stripe->dev->bdev &&
+                   bio->bi_disk == stripe->dev->bdev->bd_disk &&
+                   bio->bi_partno == stripe->dev->bdev->bd_partno) {
+                       return i;
diff --git a/queue-4.14/btrfs-fix-use-after-free-when-cleaning-up-fs_devs-with-a-single-stale-device.patch b/queue-4.14/btrfs-fix-use-after-free-when-cleaning-up-fs_devs-with-a-single-stale-device.patch
new file mode 100644 (file)
index 0000000..419f5ce
--- /dev/null
@@ -0,0 +1,41 @@
+From fd649f10c3d21ee9d7542c609f29978bdf73ab94 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Tue, 30 Jan 2018 16:07:37 +0200
+Subject: btrfs: Fix use-after-free when cleaning up fs_devs with a single stale device
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit fd649f10c3d21ee9d7542c609f29978bdf73ab94 upstream.
+
+Commit 4fde46f0cc71 ("Btrfs: free the stale device") introduced
+btrfs_free_stale_device which iterates the device lists for all
+registered btrfs filesystems and deletes those devices which aren't
+mounted. In a btrfs_devices structure has only 1 device attached to it
+and it is unused then btrfs_free_stale_devices will proceed to also free
+the btrfs_fs_devices struct itself. Currently this leads to a use after
+free since list_for_each_entry will try to perform a check on the
+already freed memory to see if it has to terminate the loop.
+
+The fix is to use 'break' when we know we are freeing the current
+fs_devs.
+
+Fixes: 4fde46f0cc71 ("Btrfs: free the stale device")
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: Anand Jain <anand.jain@oracle.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/volumes.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -589,6 +589,7 @@ void btrfs_free_stale_device(struct btrf
+                               btrfs_sysfs_remove_fsid(fs_devs);
+                               list_del(&fs_devs->list);
+                               free_fs_devices(fs_devs);
++                              break;
+                       } else {
+                               fs_devs->num_devices--;
+                               list_del(&dev->dev_list);
diff --git a/queue-4.14/btrfs-remove-spurious-warn_on-ref-count-0-in-find_parent_nodes.patch b/queue-4.14/btrfs-remove-spurious-warn_on-ref-count-0-in-find_parent_nodes.patch
new file mode 100644 (file)
index 0000000..60e5d9f
--- /dev/null
@@ -0,0 +1,73 @@
+From c8195a7b1ad5648857ce20ba24f384faed8512bc Mon Sep 17 00:00:00 2001
+From: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
+Date: Tue, 23 Jan 2018 22:22:09 -0500
+Subject: btrfs: remove spurious WARN_ON(ref->count < 0) in find_parent_nodes
+
+From: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
+
+commit c8195a7b1ad5648857ce20ba24f384faed8512bc upstream.
+
+Until v4.14, this warning was very infrequent:
+
+       WARNING: CPU: 3 PID: 18172 at fs/btrfs/backref.c:1391 find_parent_nodes+0xc41/0x14e0
+       Modules linked in: [...]
+       CPU: 3 PID: 18172 Comm: bees Tainted: G      D W    L  4.11.9-zb64+ #1
+       Hardware name: System manufacturer System Product Name/M5A78L-M/USB3, BIOS 2101    12/02/2014
+       Call Trace:
+        dump_stack+0x85/0xc2
+        __warn+0xd1/0xf0
+        warn_slowpath_null+0x1d/0x20
+        find_parent_nodes+0xc41/0x14e0
+        __btrfs_find_all_roots+0xad/0x120
+        ? extent_same_check_offsets+0x70/0x70
+        iterate_extent_inodes+0x168/0x300
+        iterate_inodes_from_logical+0x87/0xb0
+        ? iterate_inodes_from_logical+0x87/0xb0
+        ? extent_same_check_offsets+0x70/0x70
+        btrfs_ioctl+0x8ac/0x2820
+        ? lock_acquire+0xc2/0x200
+        do_vfs_ioctl+0x91/0x700
+        ? __fget+0x112/0x200
+        SyS_ioctl+0x79/0x90
+        entry_SYSCALL_64_fastpath+0x23/0xc6
+        ? trace_hardirqs_off_caller+0x1f/0x140
+
+Starting with v4.14 (specifically 86d5f9944252 ("btrfs: convert prelimary
+reference tracking to use rbtrees")) the WARN_ON occurs three orders of
+magnitude more frequently--almost once per second while running workloads
+like bees.
+
+Replace the WARN_ON() with a comment rationale for its removal.
+The rationale is paraphrased from an explanation by Edmund Nadolski
+<enadolski@suse.de> on the linux-btrfs mailing list.
+
+Fixes: 8da6d5815c59 ("Btrfs: added btrfs_find_all_roots()")
+Signed-off-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
+Reviewed-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/backref.c |   11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -1252,7 +1252,16 @@ again:
+       while (node) {
+               ref = rb_entry(node, struct prelim_ref, rbnode);
+               node = rb_next(&ref->rbnode);
+-              WARN_ON(ref->count < 0);
++              /*
++               * ref->count < 0 can happen here if there are delayed
++               * refs with a node->action of BTRFS_DROP_DELAYED_REF.
++               * prelim_ref_insert() relies on this when merging
++               * identical refs to keep the overall count correct.
++               * prelim_ref_insert() will merge only those refs
++               * which compare identically.  Any refs having
++               * e.g. different offsets would not be merged,
++               * and would retain their original ref->count < 0.
++               */
+               if (roots && ref->count && ref->root_id && ref->parent == 0) {
+                       if (sc && sc->root_objectid &&
+                           ref->root_id != sc->root_objectid) {
index 0895b2d84d5b9c3cdf73c37272ea4351b375bb9d..3694e4bacbfdaecbf551da8afe8796f3bd89fccc 100644 (file)
@@ -27,3 +27,9 @@ fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch
 fs-aio-use-rcu-accessors-for-kioctx_table-table.patch
 rdmavt-fix-synchronization-around-percpu_ref.patch
 irqchip-gic-v3-its-ensure-nr_ites-nr_lpis.patch
+btrfs-fix-null-pointer-exception-in-find_bio_stripe.patch
+btrfs-add-missing-initialization-in-btrfs_check_shared.patch
+btrfs-alloc_chunk-fix-dup-stripe-size-handling.patch
+btrfs-fix-use-after-free-when-cleaning-up-fs_devs-with-a-single-stale-device.patch
+btrfs-remove-spurious-warn_on-ref-count-0-in-find_parent_nodes.patch
+btrfs-fix-memory-barriers-usage-with-device-stats-counters.patch