btrfs: Adjust loop in free_extent_buffer
authorNikolay Borisov <nborisov@suse.com>
Mon, 15 Oct 2018 14:04:01 +0000 (17:04 +0300)
committerDavid Sterba <dsterba@suse.com>
Mon, 17 Dec 2018 13:51:31 +0000 (14:51 +0100)
The loop construct in free_extent_buffer was added in
242e18c7c1a8 ("Btrfs: reduce lock contention on extent buffer locks")
as means of reducing the times the eb lock is taken, the non-last ref
count is decremented and lock is released. As the special handling
of UNMAPPED extent buffers was removed now there is only one decrement
op which is happening for EXTENT_BUFFER_UNMAPPED case.

This commit modifies the loop condition so that in case of UNMAPPED
buffers the eb's lock is taken only if we are 100% sure the eb is going
to be freed by the current executor of the code. Additionally, remove
superfluous ref count ops in btrfs test.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c
fs/btrfs/tests/btrfs-tests.c
fs/btrfs/tests/inode-tests.c

index 39a41e8777fc5dbd4062ad1026cfc7f171500117..e7cbd3f98404231db609b34abebd9ac965a0fe1c 100644 (file)
@@ -5074,7 +5074,9 @@ void free_extent_buffer(struct extent_buffer *eb)
 
        while (1) {
                refs = atomic_read(&eb->refs);
 
        while (1) {
                refs = atomic_read(&eb->refs);
-               if (refs <= 3)
+               if ((!test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) && refs <= 3)
+                   || (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) &&
+                       refs == 1))
                        break;
                old = atomic_cmpxchg(&eb->refs, refs, refs - 1);
                if (old == refs)
                        break;
                old = atomic_cmpxchg(&eb->refs, refs, refs - 1);
                if (old == refs)
index 4cb8fcfd3ec41e822727b5db56fdd3964f2cd582..8a59597f188385a711458fc01a00acde8cfa6f38 100644 (file)
@@ -177,8 +177,6 @@ void btrfs_free_dummy_root(struct btrfs_root *root)
        if (root->node) {
                /* One for allocate_extent_buffer */
                free_extent_buffer(root->node);
        if (root->node) {
                /* One for allocate_extent_buffer */
                free_extent_buffer(root->node);
-               /* One for get_exent_buffer */
-               free_extent_buffer(root->node);
        }
        kfree(root);
 }
        }
        kfree(root);
 }
index 64043f02882067b5ab94695cb0267dacbd837c65..af0c8e30d9e219a13d36e5e8263baee8617f2f47 100644 (file)
@@ -254,11 +254,6 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
                goto out;
        }
 
                goto out;
        }
 
-       /*
-        * We will just free a dummy node if it's ref count is 2 so we need an
-        * extra ref so our searches don't accidentally release our page.
-        */
-       extent_buffer_get(root->node);
        btrfs_set_header_nritems(root->node, 0);
        btrfs_set_header_level(root->node, 0);
        ret = -EINVAL;
        btrfs_set_header_nritems(root->node, 0);
        btrfs_set_header_level(root->node, 0);
        ret = -EINVAL;
@@ -860,7 +855,6 @@ static int test_hole_first(u32 sectorsize, u32 nodesize)
                goto out;
        }
 
                goto out;
        }
 
-       extent_buffer_get(root->node);
        btrfs_set_header_nritems(root->node, 0);
        btrfs_set_header_level(root->node, 0);
        BTRFS_I(inode)->root = root;
        btrfs_set_header_nritems(root->node, 0);
        btrfs_set_header_level(root->node, 0);
        BTRFS_I(inode)->root = root;