btrfs: remove spurious WARN_ON(ref->count < 0) in find_parent_nodes

"Linux Kernel Mailing List" <[email protected]> Fri, 16 Feb 2018 17:44:23 +0000 (UTC)
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/c8195a7b1ad5648857ce20ba24f384faed8512bc
Commit:     c8195a7b1ad5648857ce20ba24f384faed8512bc
Parent:     952bd3db0dada9994fa7edd891178075abcc045d
Refname:    refs/heads/master
Author:     Zygo Blaxell <[email protected]>
AuthorDate: Tue Jan 23 22:22:09 2018 -0500
Committer:  David Sterba <[email protected]>
CommitDate: Fri Feb 2 16:25:33 2018 +0100

    btrfs: remove spurious WARN_ON(ref->count < 0) in find_parent_nodes
    
    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
    <[email protected]> on the linux-btrfs mailing list.
    
    Fixes: 8da6d5815c59 ("Btrfs: added btrfs_find_all_roots()")
    Signed-off-by: Zygo Blaxell <[email protected]>
    Reviewed-by: Lu Fengqi <[email protected]>
    Signed-off-by: David Sterba <[email protected]>
---
 fs/btrfs/backref.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index e4054e533f6d..f94b2d8c744a 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1264,7 +1264,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) {
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html