@@ -1223,13 +1223,13 @@ struct btrfs_root {
spinlock_t log_extents_lock[2];
struct list_head logged_list[2];
- spinlock_t inode_lock;
+ struct mutex inode_mutex;
/* red-black tree that keeps track of in-memory inodes */
struct rb_root inode_tree;
/*
* Xarray that keeps track of delayed nodes of every inode, protected
- * by inode_lock
+ * by @inode_mutex.
*/
struct xarray delayed_nodes;
/*
@@ -65,14 +65,14 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(
return node;
}
- spin_lock(&root->inode_lock);
+ mutex_lock(&root->inode_mutex);
node = xa_load(&root->delayed_nodes, ino);
if (node) {
if (btrfs_inode->delayed_node) {
refcount_inc(&node->refs); /* can be accessed */
BUG_ON(btrfs_inode->delayed_node != node);
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return node;
}
@@ -99,10 +99,10 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(
node = NULL;
}
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return node;
}
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return NULL;
}
@@ -129,17 +129,17 @@ static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
/* Cached in the inode and can be accessed */
refcount_set(&node->refs, 2);
- spin_lock(&root->inode_lock);
+ mutex_lock(&root->inode_mutex);
ret = xa_insert(&root->delayed_nodes, ino, node, GFP_NOFS);
if (ret) {
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
kmem_cache_free(delayed_node_cache, node);
if (ret != -EBUSY)
return ERR_PTR(ret);
}
} while (ret);
btrfs_inode->delayed_node = node;
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return node;
}
@@ -252,14 +252,14 @@ static void __btrfs_release_delayed_node(
if (refcount_dec_and_test(&delayed_node->refs)) {
struct btrfs_root *root = delayed_node->root;
- spin_lock(&root->inode_lock);
+ mutex_lock(&root->inode_mutex);
/*
* Once our refcount goes to zero, nobody is allowed to bump it
* back up. We can delete it now.
*/
ASSERT(refcount_read(&delayed_node->refs) == 0);
xa_erase(&root->delayed_nodes, delayed_node->inode_id);
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
kmem_cache_free(delayed_node_cache, delayed_node);
}
}
@@ -1954,9 +1954,9 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root)
while (1) {
int n = 0;
- spin_lock(&root->inode_lock);
+ mutex_lock(&root->inode_mutex);
if (xa_empty(&root->delayed_nodes)) {
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return;
}
@@ -1973,7 +1973,7 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root)
break;
}
index++;
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
for (int i = 0; i < n; i++) {
__btrfs_kill_delayed_node(delayed_nodes[i]);
@@ -1079,7 +1079,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
INIT_LIST_HEAD(&root->reloc_dirty_list);
INIT_LIST_HEAD(&root->logged_list[0]);
INIT_LIST_HEAD(&root->logged_list[1]);
- spin_lock_init(&root->inode_lock);
+ mutex_init(&root->inode_mutex);
spin_lock_init(&root->delalloc_lock);
spin_lock_init(&root->ordered_extent_lock);
spin_lock_init(&root->accounting_lock);
@@ -4496,8 +4496,8 @@ static void btrfs_prune_dentries(struct btrfs_root *root)
if (!BTRFS_FS_ERROR(fs_info))
WARN_ON(btrfs_root_refs(&root->root_item) != 0);
- spin_lock(&root->inode_lock);
again:
+ mutex_lock(&root->inode_mutex);
node = root->inode_tree.rb_node;
prev = NULL;
while (node) {
@@ -4526,7 +4526,7 @@ static void btrfs_prune_dentries(struct btrfs_root *root)
objectid = btrfs_ino(entry) + 1;
inode = igrab(&entry->vfs_inode);
if (inode) {
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
if (atomic_read(&inode->i_count) > 1)
d_prune_aliases(inode);
/*
@@ -4535,16 +4535,18 @@ static void btrfs_prune_dentries(struct btrfs_root *root)
*/
iput(inode);
cond_resched();
- spin_lock(&root->inode_lock);
goto again;
}
- if (cond_resched_lock(&root->inode_lock))
+ if (need_resched()) {
+ mutex_unlock(&root->inode_mutex);
+ cond_resched();
goto again;
+ }
node = rb_next(node);
}
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
}
int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry)
@@ -5551,7 +5553,7 @@ static void inode_tree_add(struct inode *inode)
if (inode_unhashed(inode))
return;
parent = NULL;
- spin_lock(&root->inode_lock);
+ mutex_lock(&root->inode_mutex);
p = &root->inode_tree.rb_node;
while (*p) {
parent = *p;
@@ -5566,13 +5568,13 @@ static void inode_tree_add(struct inode *inode)
(I_WILL_FREE | I_FREEING)));
rb_replace_node(parent, new, &root->inode_tree);
RB_CLEAR_NODE(parent);
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return;
}
}
rb_link_node(new, parent, p);
rb_insert_color(new, &root->inode_tree);
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
}
static void inode_tree_del(struct btrfs_inode *inode)
@@ -5580,18 +5582,18 @@ static void inode_tree_del(struct btrfs_inode *inode)
struct btrfs_root *root = inode->root;
int empty = 0;
- spin_lock(&root->inode_lock);
+ mutex_lock(&root->inode_mutex);
if (!RB_EMPTY_NODE(&inode->rb_node)) {
rb_erase(&inode->rb_node, &root->inode_tree);
RB_CLEAR_NODE(&inode->rb_node);
empty = RB_EMPTY_ROOT(&root->inode_tree);
}
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
if (empty && btrfs_root_refs(&root->root_item) == 0) {
- spin_lock(&root->inode_lock);
+ mutex_lock(&root->inode_mutex);
empty = RB_EMPTY_ROOT(&root->inode_tree);
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
if (empty)
btrfs_add_dead_root(root);
}
@@ -956,8 +956,8 @@ static struct inode *find_next_inode(struct btrfs_root *root, u64 objectid)
struct btrfs_inode *entry;
struct inode *inode;
- spin_lock(&root->inode_lock);
again:
+ mutex_lock(&root->inode_mutex);
node = root->inode_tree.rb_node;
prev = NULL;
while (node) {
@@ -985,17 +985,20 @@ static struct inode *find_next_inode(struct btrfs_root *root, u64 objectid)
entry = rb_entry(node, struct btrfs_inode, rb_node);
inode = igrab(&entry->vfs_inode);
if (inode) {
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return inode;
}
objectid = btrfs_ino(entry) + 1;
- if (cond_resched_lock(&root->inode_lock))
+ if (need_resched()) {
+ mutex_unlock(&root->inode_mutex);
+ cond_resched();
goto again;
+ }
node = rb_next(node);
}
- spin_unlock(&root->inode_lock);
+ mutex_unlock(&root->inode_mutex);
return NULL;
}