btrfs: free delayed node outside of root->inode_lock
authorJeff Mahoney <jeffm@suse.com>
Tue, 27 May 2014 17:53:20 +0000 (13:53 -0400)
committerChris Mason <clm@fb.com>
Tue, 10 Jun 2014 00:21:08 +0000 (17:21 -0700)
On heavy workloads, we're seeing soft lockup warnings on
root->inode_lock in __btrfs_release_delayed_node. The low hanging fruit
is to reduce the size of the critical section.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Reviewed-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/delayed-inode.c

index 33e561a84013f19bb327939e7860753bd5eaa0bf..da775bfdebc989d905c931cde0f12bd00027abc9 100644 (file)
@@ -149,8 +149,8 @@ again:
        spin_lock(&root->inode_lock);
        ret = radix_tree_insert(&root->delayed_nodes_tree, ino, node);
        if (ret == -EEXIST) {
-               kmem_cache_free(delayed_node_cache, node);
                spin_unlock(&root->inode_lock);
+               kmem_cache_free(delayed_node_cache, node);
                radix_tree_preload_end();
                goto again;
        }
@@ -267,14 +267,17 @@ static void __btrfs_release_delayed_node(
        mutex_unlock(&delayed_node->mutex);
 
        if (atomic_dec_and_test(&delayed_node->refs)) {
+               bool free = false;
                struct btrfs_root *root = delayed_node->root;
                spin_lock(&root->inode_lock);
                if (atomic_read(&delayed_node->refs) == 0) {
                        radix_tree_delete(&root->delayed_nodes_tree,
                                          delayed_node->inode_id);
-                       kmem_cache_free(delayed_node_cache, delayed_node);
+                       free = true;
                }
                spin_unlock(&root->inode_lock);
+               if (free)
+                       kmem_cache_free(delayed_node_cache, delayed_node);
        }
 }