Commit a2135011 authored by Chris Mason's avatar Chris Mason

Btrfs: Replace the big fs_mutex with a collection of other locks

Extent alloctions are still protected by a large alloc_mutex.
Objectid allocations are covered by a objectid mutex
Other btree operations are protected by a lock on individual btree nodes
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 925baedd
...@@ -63,6 +63,9 @@ void btrfs_free_path(struct btrfs_path *p) ...@@ -63,6 +63,9 @@ void btrfs_free_path(struct btrfs_path *p)
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
{ {
int i; int i;
int skip = p->skip_locking;
int keep = p->keep_locks;
for (i = 0; i < BTRFS_MAX_LEVEL; i++) { for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
if (!p->nodes[i]) if (!p->nodes[i])
continue; continue;
...@@ -73,6 +76,8 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) ...@@ -73,6 +76,8 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
free_extent_buffer(p->nodes[i]); free_extent_buffer(p->nodes[i]);
} }
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
p->skip_locking = skip;
p->keep_locks = keep;
} }
struct extent_buffer *btrfs_root_node(struct btrfs_root *root) struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
...@@ -1202,13 +1207,19 @@ static void unlock_up(struct btrfs_path *path, int level, int lowest_unlock) ...@@ -1202,13 +1207,19 @@ static void unlock_up(struct btrfs_path *path, int level, int lowest_unlock)
u32 nritems; u32 nritems;
t = path->nodes[i]; t = path->nodes[i];
nritems = btrfs_header_nritems(t); nritems = btrfs_header_nritems(t);
if (path->slots[i] >= nritems - 1) { if (nritems < 2 || path->slots[i] >= nritems - 2) {
if (path->keep_locks) {
//printk("path %p skip level now %d\n", path, skip_level);
}
skip_level = i + 1; skip_level = i + 1;
continue; continue;
} }
} }
t = path->nodes[i]; t = path->nodes[i];
if (i >= lowest_unlock && i > skip_level && path->locks[i]) { if (i >= lowest_unlock && i > skip_level && path->locks[i]) {
if (path->keep_locks) {
//printk("path %p unlocking level %d slot %d nritems %d skip_level %d\n", path, i, path->slots[i], btrfs_header_nritems(t), skip_level);
}
btrfs_tree_unlock(t); btrfs_tree_unlock(t);
path->locks[i] = 0; path->locks[i] = 0;
} }
...@@ -1243,7 +1254,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1243,7 +1254,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
lowest_level = p->lowest_level; lowest_level = p->lowest_level;
WARN_ON(lowest_level && ins_len); WARN_ON(lowest_level && ins_len);
WARN_ON(p->nodes[0] != NULL); WARN_ON(p->nodes[0] != NULL);
// WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
WARN_ON(root == root->fs_info->extent_root && WARN_ON(root == root->fs_info->extent_root &&
!mutex_is_locked(&root->fs_info->alloc_mutex)); !mutex_is_locked(&root->fs_info->alloc_mutex));
WARN_ON(root == root->fs_info->chunk_root && WARN_ON(root == root->fs_info->chunk_root &&
...@@ -1321,7 +1331,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1321,7 +1331,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
b = read_node_slot(root, b, slot); b = read_node_slot(root, b, slot);
if (!p->skip_locking) if (!p->skip_locking)
btrfs_tree_lock(b); btrfs_tree_lock(b);
unlock_up(p, level, lowest_unlock); unlock_up(p, level + 1, lowest_unlock);
} else { } else {
p->slots[level] = slot; p->slots[level] = slot;
if (ins_len > 0 && btrfs_leaf_free_space(root, b) < if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
...@@ -1804,6 +1814,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1804,6 +1814,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
if (slot >= btrfs_header_nritems(upper) - 1) if (slot >= btrfs_header_nritems(upper) - 1)
return 1; return 1;
WARN_ON(!btrfs_tree_locked(path->nodes[1]));
right = read_node_slot(root, upper, slot + 1); right = read_node_slot(root, upper, slot + 1);
btrfs_tree_lock(right); btrfs_tree_lock(right);
free_space = btrfs_leaf_free_space(root, right); free_space = btrfs_leaf_free_space(root, right);
...@@ -1981,6 +1993,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1981,6 +1993,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
return 1; return 1;
} }
WARN_ON(!btrfs_tree_locked(path->nodes[1]));
left = read_node_slot(root, path->nodes[1], slot - 1); left = read_node_slot(root, path->nodes[1], slot - 1);
btrfs_tree_lock(left); btrfs_tree_lock(left);
free_space = btrfs_leaf_free_space(root, left); free_space = btrfs_leaf_free_space(root, left);
...@@ -2957,15 +2971,16 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) ...@@ -2957,15 +2971,16 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1); btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
path->keep_locks = 1;
btrfs_release_path(root, path); btrfs_release_path(root, path);
path->keep_locks = 1;
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
path->keep_locks = 0; path->keep_locks = 0;
if (ret < 0) if (ret < 0)
return ret; return ret;
if (path->slots[0] < nritems - 1) { nritems = btrfs_header_nritems(path->nodes[0]);
if (nritems > 0 && path->slots[0] < nritems - 1) {
goto done; goto done;
} }
...@@ -2992,8 +3007,17 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) ...@@ -2992,8 +3007,17 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
reada_for_search(root, path, level, slot, 0); reada_for_search(root, path, level, slot, 0);
next = read_node_slot(root, c, slot); next = read_node_slot(root, c, slot);
if (!path->skip_locking) if (!path->skip_locking) {
if (!btrfs_tree_locked(c)) {
int i;
WARN_ON(1);
printk("path %p no lock on level %d\n", path, level);
for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
printk("path %p level %d slot %d nritems %d\n", path, i, path->slots[i], btrfs_header_nritems(path->nodes[i]));
}
}
btrfs_tree_lock(next); btrfs_tree_lock(next);
}
break; break;
} }
path->slots[level] = slot; path->slots[level] = slot;
...@@ -3011,9 +3035,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) ...@@ -3011,9 +3035,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
if (level == 1 && path->locks[1] && path->reada) if (level == 1 && path->locks[1] && path->reada)
reada_for_search(root, path, level, slot, 0); reada_for_search(root, path, level, slot, 0);
next = read_node_slot(root, next, 0); next = read_node_slot(root, next, 0);
if (!path->skip_locking) if (!path->skip_locking) {
WARN_ON(!btrfs_tree_locked(path->nodes[level]));
btrfs_tree_lock(next); btrfs_tree_lock(next);
} }
}
done: done:
unlock_up(path, 0, 1); unlock_up(path, 0, 1);
return 0; return 0;
......
...@@ -519,9 +519,9 @@ struct btrfs_fs_info { ...@@ -519,9 +519,9 @@ struct btrfs_fs_info {
struct backing_dev_info bdi; struct backing_dev_info bdi;
spinlock_t hash_lock; spinlock_t hash_lock;
struct mutex trans_mutex; struct mutex trans_mutex;
struct mutex fs_mutex;
struct mutex alloc_mutex; struct mutex alloc_mutex;
struct mutex chunk_mutex; struct mutex chunk_mutex;
struct mutex drop_mutex;
struct list_head trans_list; struct list_head trans_list;
struct list_head hashers; struct list_head hashers;
struct list_head dead_roots; struct list_head dead_roots;
...@@ -554,7 +554,7 @@ struct btrfs_fs_info { ...@@ -554,7 +554,7 @@ struct btrfs_fs_info {
struct completion kobj_unregister; struct completion kobj_unregister;
int do_barriers; int do_barriers;
int closing; int closing;
unsigned long throttles; atomic_t throttles;
u64 total_pinned; u64 total_pinned;
struct list_head dirty_cowonly_roots; struct list_head dirty_cowonly_roots;
...@@ -594,6 +594,7 @@ struct btrfs_root { ...@@ -594,6 +594,7 @@ struct btrfs_root {
struct inode *inode; struct inode *inode;
struct kobject root_kobj; struct kobject root_kobj;
struct completion kobj_unregister; struct completion kobj_unregister;
struct mutex objectid_mutex;
u64 objectid; u64 objectid;
u64 last_trans; u64 last_trans;
......
...@@ -724,6 +724,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, ...@@ -724,6 +724,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
INIT_LIST_HEAD(&root->dirty_list); INIT_LIST_HEAD(&root->dirty_list);
spin_lock_init(&root->node_lock); spin_lock_init(&root->node_lock);
mutex_init(&root->objectid_mutex);
memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_key, 0, sizeof(root->root_key));
memset(&root->root_item, 0, sizeof(root->root_item)); memset(&root->root_item, 0, sizeof(root->root_item));
memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
...@@ -1146,6 +1147,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1146,6 +1147,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
INIT_LIST_HEAD(&fs_info->space_info); INIT_LIST_HEAD(&fs_info->space_info);
btrfs_mapping_init(&fs_info->mapping_tree); btrfs_mapping_init(&fs_info->mapping_tree);
atomic_set(&fs_info->nr_async_submits, 0); atomic_set(&fs_info->nr_async_submits, 0);
atomic_set(&fs_info->throttles, 0);
fs_info->sb = sb; fs_info->sb = sb;
fs_info->max_extent = (u64)-1; fs_info->max_extent = (u64)-1;
fs_info->max_inline = 8192 * 1024; fs_info->max_inline = 8192 * 1024;
...@@ -1199,7 +1201,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1199,7 +1201,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS);
mutex_init(&fs_info->trans_mutex); mutex_init(&fs_info->trans_mutex);
mutex_init(&fs_info->fs_mutex); mutex_init(&fs_info->drop_mutex);
mutex_init(&fs_info->alloc_mutex); mutex_init(&fs_info->alloc_mutex);
mutex_init(&fs_info->chunk_mutex); mutex_init(&fs_info->chunk_mutex);
...@@ -1278,8 +1280,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1278,8 +1280,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
goto fail_sb_buffer; goto fail_sb_buffer;
} }
mutex_lock(&fs_info->fs_mutex);
mutex_lock(&fs_info->chunk_mutex); mutex_lock(&fs_info->chunk_mutex);
ret = btrfs_read_sys_array(tree_root); ret = btrfs_read_sys_array(tree_root);
mutex_unlock(&fs_info->chunk_mutex); mutex_unlock(&fs_info->chunk_mutex);
...@@ -1342,7 +1342,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1342,7 +1342,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->metadata_alloc_profile = (u64)-1; fs_info->metadata_alloc_profile = (u64)-1;
fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
mutex_unlock(&fs_info->fs_mutex);
return tree_root; return tree_root;
fail_extent_root: fail_extent_root:
...@@ -1350,7 +1349,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -1350,7 +1349,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fail_tree_root: fail_tree_root:
free_extent_buffer(tree_root->node); free_extent_buffer(tree_root->node);
fail_sys_array: fail_sys_array:
mutex_unlock(&fs_info->fs_mutex);
fail_sb_buffer: fail_sb_buffer:
extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree); extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree);
btrfs_stop_workers(&fs_info->workers); btrfs_stop_workers(&fs_info->workers);
...@@ -1562,8 +1560,9 @@ int close_ctree(struct btrfs_root *root) ...@@ -1562,8 +1560,9 @@ int close_ctree(struct btrfs_root *root)
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
fs_info->closing = 1; fs_info->closing = 1;
smp_mb();
btrfs_transaction_flush_work(root); btrfs_transaction_flush_work(root);
mutex_lock(&fs_info->fs_mutex);
btrfs_defrag_dirty_roots(root->fs_info); btrfs_defrag_dirty_roots(root->fs_info);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
...@@ -1574,7 +1573,6 @@ int close_ctree(struct btrfs_root *root) ...@@ -1574,7 +1573,6 @@ int close_ctree(struct btrfs_root *root)
BUG_ON(ret); BUG_ON(ret);
write_ctree_super(NULL, root); write_ctree_super(NULL, root);
mutex_unlock(&fs_info->fs_mutex);
btrfs_transaction_flush_work(root); btrfs_transaction_flush_work(root);
...@@ -1679,7 +1677,8 @@ void btrfs_throttle(struct btrfs_root *root) ...@@ -1679,7 +1677,8 @@ void btrfs_throttle(struct btrfs_root *root)
struct backing_dev_info *bdi; struct backing_dev_info *bdi;
bdi = &root->fs_info->bdi; bdi = &root->fs_info->bdi;
if (root->fs_info->throttles && bdi_write_congested(bdi)) { if (atomic_read(&root->fs_info->throttles) &&
bdi_write_congested(bdi)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
congestion_wait(WRITE, HZ/20); congestion_wait(WRITE, HZ/20);
#else #else
......
...@@ -1577,9 +1577,11 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1577,9 +1577,11 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
} }
/* block accounting for super block */ /* block accounting for super block */
spin_lock_irq(&info->delalloc_lock);
super_used = btrfs_super_bytes_used(&info->super_copy); super_used = btrfs_super_bytes_used(&info->super_copy);
btrfs_set_super_bytes_used(&info->super_copy, btrfs_set_super_bytes_used(&info->super_copy,
super_used - num_bytes); super_used - num_bytes);
spin_unlock_irq(&info->delalloc_lock);
/* block accounting for root item */ /* block accounting for root item */
root_used = btrfs_root_used(&root->root_item); root_used = btrfs_root_used(&root->root_item);
...@@ -1968,8 +1970,10 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, ...@@ -1968,8 +1970,10 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
} }
/* block accounting for super block */ /* block accounting for super block */
spin_lock_irq(&info->delalloc_lock);
super_used = btrfs_super_bytes_used(&info->super_copy); super_used = btrfs_super_bytes_used(&info->super_copy);
btrfs_set_super_bytes_used(&info->super_copy, super_used + num_bytes); btrfs_set_super_bytes_used(&info->super_copy, super_used + num_bytes);
spin_unlock_irq(&info->delalloc_lock);
/* block accounting for root item */ /* block accounting for root item */
root_used = btrfs_root_used(&root->root_item); root_used = btrfs_root_used(&root->root_item);
...@@ -2172,12 +2176,12 @@ static void noinline reada_walk_down(struct btrfs_root *root, ...@@ -2172,12 +2176,12 @@ static void noinline reada_walk_down(struct btrfs_root *root,
continue; continue;
} }
} }
mutex_unlock(&root->fs_info->fs_mutex); mutex_unlock(&root->fs_info->alloc_mutex);
ret = readahead_tree_block(root, bytenr, blocksize, ret = readahead_tree_block(root, bytenr, blocksize,
btrfs_node_ptr_generation(node, i)); btrfs_node_ptr_generation(node, i));
last = bytenr + blocksize; last = bytenr + blocksize;
cond_resched(); cond_resched();
mutex_lock(&root->fs_info->fs_mutex); mutex_lock(&root->fs_info->alloc_mutex);
if (ret) if (ret)
break; break;
} }
...@@ -2254,11 +2258,9 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans, ...@@ -2254,11 +2258,9 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
free_extent_buffer(next); free_extent_buffer(next);
reada_walk_down(root, cur, path->slots[*level]); reada_walk_down(root, cur, path->slots[*level]);
mutex_unlock(&root->fs_info->fs_mutex);
mutex_unlock(&root->fs_info->alloc_mutex); mutex_unlock(&root->fs_info->alloc_mutex);
next = read_tree_block(root, bytenr, blocksize, next = read_tree_block(root, bytenr, blocksize,
ptr_gen); ptr_gen);
mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->alloc_mutex); mutex_lock(&root->fs_info->alloc_mutex);
/* we've dropped the lock, double check */ /* we've dropped the lock, double check */
...@@ -2381,6 +2383,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -2381,6 +2383,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
int orig_level; int orig_level;
struct btrfs_root_item *root_item = &root->root_item; struct btrfs_root_item *root_item = &root->root_item;
WARN_ON(!mutex_is_locked(&root->fs_info->drop_mutex));
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
...@@ -2710,7 +2713,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, ...@@ -2710,7 +2713,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root,
*last_file_root == ref_root) *last_file_root == ref_root)
goto out; goto out;
mutex_unlock(&extent_root->fs_info->fs_mutex);
inode = btrfs_iget_locked(extent_root->fs_info->sb, inode = btrfs_iget_locked(extent_root->fs_info->sb,
ref_objectid, found_root); ref_objectid, found_root);
if (inode->i_state & I_NEW) { if (inode->i_state & I_NEW) {
...@@ -2727,7 +2729,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, ...@@ -2727,7 +2729,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root,
* the latest version of the tree root * the latest version of the tree root
*/ */
if (is_bad_inode(inode)) { if (is_bad_inode(inode)) {
mutex_lock(&extent_root->fs_info->fs_mutex);
goto out; goto out;
} }
*last_file_objectid = inode->i_ino; *last_file_objectid = inode->i_ino;
...@@ -2736,7 +2737,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root, ...@@ -2736,7 +2737,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root,
relocate_inode_pages(inode, ref_offset, extent_key->offset); relocate_inode_pages(inode, ref_offset, extent_key->offset);
iput(inode); iput(inode);
mutex_lock(&extent_root->fs_info->fs_mutex);
} else { } else {
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
struct extent_buffer *eb; struct extent_buffer *eb;
...@@ -3033,9 +3033,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) ...@@ -3033,9 +3033,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start)
if (progress && need_resched()) { if (progress && need_resched()) {
memcpy(&key, &found_key, sizeof(key)); memcpy(&key, &found_key, sizeof(key));
mutex_unlock(&root->fs_info->fs_mutex);
cond_resched(); cond_resched();
mutex_lock(&root->fs_info->fs_mutex);
btrfs_release_path(root, path); btrfs_release_path(root, path);
btrfs_search_slot(NULL, root, &key, path, 0, 0); btrfs_search_slot(NULL, root, &key, path, 0, 0);
progress = 0; progress = 0;
...@@ -3068,9 +3066,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) ...@@ -3068,9 +3066,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start)
trans = btrfs_start_transaction(tree_root, 1); trans = btrfs_start_transaction(tree_root, 1);
btrfs_commit_transaction(trans, tree_root); btrfs_commit_transaction(trans, tree_root);
mutex_unlock(&root->fs_info->fs_mutex);
btrfs_clean_old_snapshots(tree_root); btrfs_clean_old_snapshots(tree_root);
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(tree_root, 1); trans = btrfs_start_transaction(tree_root, 1);
btrfs_commit_transaction(trans, tree_root); btrfs_commit_transaction(trans, tree_root);
......
...@@ -252,7 +252,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans, ...@@ -252,7 +252,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
end_of_last_block = start_pos + num_bytes - 1; end_of_last_block = start_pos + num_bytes - 1;
lock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS); lock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS);
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
if (!trans) { if (!trans) {
err = -ENOMEM; err = -ENOMEM;
...@@ -341,7 +340,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans, ...@@ -341,7 +340,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
failed: failed:
err = btrfs_end_transaction(trans, root); err = btrfs_end_transaction(trans, root);
out_unlock: out_unlock:
mutex_unlock(&root->fs_info->fs_mutex);
unlock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS); unlock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS);
return err; return err;
} }
...@@ -905,9 +903,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, ...@@ -905,9 +903,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
WARN_ON(num_pages > nrptrs); WARN_ON(num_pages > nrptrs);
memset(pages, 0, sizeof(pages)); memset(pages, 0, sizeof(pages));
mutex_lock(&root->fs_info->fs_mutex);
ret = btrfs_check_free_space(root, write_bytes, 0); ret = btrfs_check_free_space(root, write_bytes, 0);
mutex_unlock(&root->fs_info->fs_mutex);
if (ret) if (ret)
goto out; goto out;
...@@ -998,9 +994,9 @@ static int btrfs_sync_file(struct file *file, ...@@ -998,9 +994,9 @@ static int btrfs_sync_file(struct file *file,
* check the transaction that last modified this inode * check the transaction that last modified this inode
* and see if its already been committed * and see if its already been committed
*/ */
mutex_lock(&root->fs_info->fs_mutex);
if (!BTRFS_I(inode)->last_trans) if (!BTRFS_I(inode)->last_trans)
goto out; goto out;
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
if (BTRFS_I(inode)->last_trans <= if (BTRFS_I(inode)->last_trans <=
root->fs_info->last_trans_committed) { root->fs_info->last_trans_committed) {
...@@ -1023,7 +1019,6 @@ static int btrfs_sync_file(struct file *file, ...@@ -1023,7 +1019,6 @@ static int btrfs_sync_file(struct file *file,
} }
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
out: out:
mutex_unlock(&root->fs_info->fs_mutex);
return ret > 0 ? EIO : ret; return ret > 0 ? EIO : ret;
} }
......
...@@ -69,6 +69,12 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, ...@@ -69,6 +69,12 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
struct btrfs_key search_key; struct btrfs_key search_key;
u64 search_start = dirid; u64 search_start = dirid;
mutex_lock(&root->objectid_mutex);
if (root->last_inode_alloc) {
*objectid = ++root->last_inode_alloc;
mutex_unlock(&root->objectid_mutex);
return 0;
}
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
search_start = root->last_inode_alloc; search_start = root->last_inode_alloc;
...@@ -124,9 +130,11 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, ...@@ -124,9 +130,11 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
btrfs_release_path(root, path); btrfs_release_path(root, path);
btrfs_free_path(path); btrfs_free_path(path);
BUG_ON(*objectid < search_start); BUG_ON(*objectid < search_start);
mutex_unlock(&root->objectid_mutex);
return 0; return 0;
error: error:
btrfs_release_path(root, path); btrfs_release_path(root, path);
btrfs_free_path(path); btrfs_free_path(path);
mutex_unlock(&root->objectid_mutex);
return ret; return ret;
} }
This diff is collapsed.
...@@ -63,7 +63,6 @@ static noinline int create_subvol(struct btrfs_root *root, char *name, ...@@ -63,7 +63,6 @@ static noinline int create_subvol(struct btrfs_root *root, char *name,
u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
unsigned long nr = 1; unsigned long nr = 1;
mutex_lock(&root->fs_info->fs_mutex);
ret = btrfs_check_free_space(root, 1, 0); ret = btrfs_check_free_space(root, 1, 0);
if (ret) if (ret)
goto fail_commit; goto fail_commit;
...@@ -164,7 +163,6 @@ static noinline int create_subvol(struct btrfs_root *root, char *name, ...@@ -164,7 +163,6 @@ static noinline int create_subvol(struct btrfs_root *root, char *name,
if (err && !ret) if (err && !ret)
ret = err; ret = err;
fail_commit: fail_commit:
mutex_unlock(&root->fs_info->fs_mutex);
btrfs_btree_balance_dirty(root, nr); btrfs_btree_balance_dirty(root, nr);
btrfs_throttle(root); btrfs_throttle(root);
return ret; return ret;
...@@ -181,7 +179,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) ...@@ -181,7 +179,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
if (!root->ref_cows) if (!root->ref_cows)
return -EINVAL; return -EINVAL;
mutex_lock(&root->fs_info->fs_mutex);
ret = btrfs_check_free_space(root, 1, 0); ret = btrfs_check_free_space(root, 1, 0);
if (ret) if (ret)
goto fail_unlock; goto fail_unlock;
...@@ -208,7 +205,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) ...@@ -208,7 +205,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
err = btrfs_commit_transaction(trans, root); err = btrfs_commit_transaction(trans, root);
fail_unlock: fail_unlock:
mutex_unlock(&root->fs_info->fs_mutex);
btrfs_btree_balance_dirty(root, nr); btrfs_btree_balance_dirty(root, nr);
btrfs_throttle(root); btrfs_throttle(root);
return ret; return ret;
...@@ -228,9 +224,7 @@ int btrfs_defrag_file(struct file *file) ...@@ -228,9 +224,7 @@ int btrfs_defrag_file(struct file *file)
unsigned long i; unsigned long i;
int ret; int ret;
mutex_lock(&root->fs_info->fs_mutex);
ret = btrfs_check_free_space(root, inode->i_size, 0); ret = btrfs_check_free_space(root, inode->i_size, 0);
mutex_unlock(&root->fs_info->fs_mutex);
if (ret) if (ret)
return -ENOSPC; return -ENOSPC;
...@@ -315,7 +309,8 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) ...@@ -315,7 +309,8 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
goto out; goto out;
} }
mutex_lock(&root->fs_info->fs_mutex); mutex_lock(&root->fs_info->alloc_mutex);
mutex_lock(&root->fs_info->chunk_mutex);
sizestr = vol_args->name; sizestr = vol_args->name;
devstr = strchr(sizestr, ':'); devstr = strchr(sizestr, ':');
if (devstr) { if (devstr) {
...@@ -385,7 +380,8 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) ...@@ -385,7 +380,8 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
} }
out_unlock: out_unlock:
mutex_unlock(&root->fs_info->fs_mutex); mutex_lock(&root->fs_info->alloc_mutex);
mutex_lock(&root->fs_info->chunk_mutex);
out: out:
kfree(vol_args); kfree(vol_args);
return ret; return ret;
...@@ -428,11 +424,9 @@ static noinline int btrfs_ioctl_snap_create(struct btrfs_root *root, ...@@ -428,11 +424,9 @@ static noinline int btrfs_ioctl_snap_create(struct btrfs_root *root,
} }
root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, root_dirid = root->fs_info->sb->s_root->d_inode->i_ino,
mutex_lock(&root->fs_info->fs_mutex);
di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root,
path, root_dirid, path, root_dirid,
vol_args->name, namelen, 0); vol_args->name, namelen, 0);
mutex_unlock(&root->fs_info->fs_mutex);
btrfs_free_path(path); btrfs_free_path(path);
if (di && !IS_ERR(di)) { if (di && !IS_ERR(di)) {
...@@ -445,10 +439,12 @@ static noinline int btrfs_ioctl_snap_create(struct btrfs_root *root, ...@@ -445,10 +439,12 @@ static noinline int btrfs_ioctl_snap_create(struct btrfs_root *root,
goto out; goto out;
} }
mutex_lock(&root->fs_info->drop_mutex);
if (root == root->fs_info->tree_root) if (root == root->fs_info->tree_root)
ret = create_subvol(root, vol_args->name, namelen); ret = create_subvol(root, vol_args->name, namelen);
else else
ret = create_snapshot(root, vol_args->name, namelen); ret = create_snapshot(root, vol_args->name, namelen);
mutex_unlock(&root->fs_info->drop_mutex);
out: out:
kfree(vol_args); kfree(vol_args);
return ret; return ret;
...@@ -461,10 +457,8 @@ static int btrfs_ioctl_defrag(struct file *file) ...@@ -461,10 +457,8 @@ static int btrfs_ioctl_defrag(struct file *file)
switch (inode->i_mode & S_IFMT) { switch (inode->i_mode & S_IFMT) {
case S_IFDIR: case S_IFDIR:
mutex_lock(&root->fs_info->fs_mutex);
btrfs_defrag_root(root, 0); btrfs_defrag_root(root, 0);
btrfs_defrag_root(root->fs_info->extent_root, 0); btrfs_defrag_root(root->fs_info->extent_root, 0);
mutex_unlock(&root->fs_info->fs_mutex);
break; break;
case S_IFREG: case S_IFREG:
btrfs_defrag_file(file); btrfs_defrag_file(file);
...@@ -588,7 +582,6 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd) ...@@ -588,7 +582,6 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
unlock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS); unlock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS);
} }
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 0); trans = btrfs_start_transaction(root, 0);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) { if (!path) {
...@@ -685,7 +678,6 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd) ...@@ -685,7 +678,6 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
unlock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS); unlock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS);
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
mutex_unlock(&root->fs_info->fs_mutex);
out_unlock: out_unlock:
mutex_unlock(&src->i_mutex); mutex_unlock(&src->i_mutex);
...@@ -711,7 +703,6 @@ long btrfs_ioctl_trans_start(struct file *file) ...@@ -711,7 +703,6 @@ long btrfs_ioctl_trans_start(struct file *file)
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
mutex_lock(&root->fs_info->fs_mutex);
if (file->private_data) { if (file->private_data) {
ret = -EINPROGRESS; ret = -EINPROGRESS;
goto out; goto out;
...@@ -723,7 +714,6 @@ long btrfs_ioctl_trans_start(struct file *file) ...@@ -723,7 +714,6 @@ long btrfs_ioctl_trans_start(struct file *file)
ret = -ENOMEM; ret = -ENOMEM;
/*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/ /*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/
out: out:
mutex_unlock(&root->fs_info->fs_mutex);
return ret; return ret;
} }
...@@ -740,7 +730,6 @@ long btrfs_ioctl_trans_end(struct file *file) ...@@ -740,7 +730,6 @@ long btrfs_ioctl_trans_end(struct file *file)
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
int ret = 0; int ret = 0;
mutex_lock(&root->fs_info->fs_mutex);
trans = file->private_data; trans = file->private_data;
if (!trans) { if (!trans) {
ret = -EINVAL; ret = -EINVAL;
...@@ -749,7 +738,6 @@ long btrfs_ioctl_trans_end(struct file *file) ...@@ -749,7 +738,6 @@ long btrfs_ioctl_trans_end(struct file *file)
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
file->private_data = 0; file->private_data = 0;
out: out:
mutex_unlock(&root->fs_info->fs_mutex);
return ret; return ret;
} }
......
...@@ -366,12 +366,10 @@ int btrfs_sync_fs(struct super_block *sb, int wait) ...@@ -366,12 +366,10 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
return 0; return 0;
} }
btrfs_clean_old_snapshots(root); btrfs_clean_old_snapshots(root);
mutex_lock(&root->fs_info->fs_mutex);
btrfs_defrag_dirty_roots(root->fs_info); btrfs_defrag_dirty_roots(root->fs_info);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
sb->s_dirt = 0; sb->s_dirt = 0;
mutex_unlock(&root->fs_info->fs_mutex);
return ret; return ret;
} }
......
...@@ -370,6 +370,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) ...@@ -370,6 +370,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
unsigned long nr; unsigned long nr;
smp_mb();
if (root->defrag_running) if (root->defrag_running)
return 0; return 0;
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
...@@ -378,16 +379,15 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) ...@@ -378,16 +379,15 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
ret = btrfs_defrag_leaves(trans, root, cacheonly); ret = btrfs_defrag_leaves(trans, root, cacheonly);
nr = trans->blocks_used; nr = trans->blocks_used;
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
mutex_unlock(&info->fs_mutex);
btrfs_btree_balance_dirty(info->tree_root, nr); btrfs_btree_balance_dirty(info->tree_root, nr);
cond_resched(); cond_resched();
mutex_lock(&info->fs_mutex);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
if (ret != -EAGAIN) if (ret != -EAGAIN)
break; break;
} }
root->defrag_running = 0; root->defrag_running = 0;
smp_mb();
radix_tree_tag_clear(&info->fs_roots_radix, radix_tree_tag_clear(&info->fs_roots_radix,
(unsigned long)root->root_key.objectid, (unsigned long)root->root_key.objectid,
BTRFS_ROOT_DEFRAG_TAG); BTRFS_ROOT_DEFRAG_TAG);
...@@ -435,14 +435,14 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, ...@@ -435,14 +435,14 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
while(!list_empty(list)) { while(!list_empty(list)) {
struct btrfs_root *root; struct btrfs_root *root;
mutex_lock(&tree_root->fs_info->fs_mutex);
dirty = list_entry(list->next, struct dirty_root, list); dirty = list_entry(list->next, struct dirty_root, list);
list_del_init(&dirty->list); list_del_init(&dirty->list);
num_bytes = btrfs_root_used(&dirty->root->root_item); num_bytes = btrfs_root_used(&dirty->root->root_item);
root = dirty->latest_root; root = dirty->latest_root;
root->fs_info->throttles++; atomic_inc(&root->fs_info->throttles);
mutex_lock(&root->fs_info->drop_mutex);
while(1) { while(1) {
trans = btrfs_start_transaction(tree_root, 1); trans = btrfs_start_transaction(tree_root, 1);
ret = btrfs_drop_snapshot(trans, dirty->root); ret = btrfs_drop_snapshot(trans, dirty->root);
...@@ -459,14 +459,16 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, ...@@ -459,14 +459,16 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
nr = trans->blocks_used; nr = trans->blocks_used;
ret = btrfs_end_transaction(trans, tree_root); ret = btrfs_end_transaction(trans, tree_root);
BUG_ON(ret); BUG_ON(ret);
mutex_unlock(&tree_root->fs_info->fs_mutex);
mutex_unlock(&root->fs_info->drop_mutex);
btrfs_btree_balance_dirty(tree_root, nr); btrfs_btree_balance_dirty(tree_root, nr);
cond_resched(); cond_resched();
mutex_lock(&tree_root->fs_info->fs_mutex); mutex_lock(&root->fs_info->drop_mutex);
} }
BUG_ON(ret); BUG_ON(ret);
root->fs_info->throttles--; atomic_dec(&root->fs_info->throttles);
mutex_lock(&root->fs_info->alloc_mutex);
num_bytes -= btrfs_root_used(&dirty->root->root_item); num_bytes -= btrfs_root_used(&dirty->root->root_item);
bytes_used = btrfs_root_used(&root->root_item); bytes_used = btrfs_root_used(&root->root_item);
if (num_bytes) { if (num_bytes) {
...@@ -474,11 +476,15 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, ...@@ -474,11 +476,15 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
btrfs_set_root_used(&root->root_item, btrfs_set_root_used(&root->root_item,
bytes_used - num_bytes); bytes_used - num_bytes);
} }
mutex_unlock(&root->fs_info->alloc_mutex);
ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key);
if (ret) { if (ret) {
BUG(); BUG();
break; break;
} }
mutex_unlock(&root->fs_info->drop_mutex);
nr = trans->blocks_used; nr = trans->blocks_used;
ret = btrfs_end_transaction(trans, tree_root); ret = btrfs_end_transaction(trans, tree_root);
BUG_ON(ret); BUG_ON(ret);
...@@ -486,7 +492,6 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, ...@@ -486,7 +492,6 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
free_extent_buffer(dirty->root->node); free_extent_buffer(dirty->root->node);
kfree(dirty->root); kfree(dirty->root);
kfree(dirty); kfree(dirty);
mutex_unlock(&tree_root->fs_info->fs_mutex);
btrfs_btree_balance_dirty(tree_root, nr); btrfs_btree_balance_dirty(tree_root, nr);
cond_resched(); cond_resched();
...@@ -503,7 +508,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, ...@@ -503,7 +508,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
u64 objectid = 0; u64 objectid = 0;
int ret; int ret;
root->fs_info->throttles++; atomic_inc(&root->fs_info->throttles);
while(1) { while(1) {
ret = btrfs_find_first_ordered_inode( ret = btrfs_find_first_ordered_inode(
&cur_trans->ordered_inode_tree, &cur_trans->ordered_inode_tree,
...@@ -512,7 +517,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, ...@@ -512,7 +517,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
break; break;
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
mutex_unlock(&root->fs_info->fs_mutex);
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
atomic_inc(&BTRFS_I(inode)->ordered_writeback); atomic_inc(&BTRFS_I(inode)->ordered_writeback);
...@@ -521,7 +525,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, ...@@ -521,7 +525,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
} }
iput(inode); iput(inode);
mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
} }
while(1) { while(1) {
...@@ -533,7 +536,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, ...@@ -533,7 +536,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
if (!ret) if (!ret)
break; break;
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
mutex_unlock(&root->fs_info->fs_mutex);
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
atomic_inc(&BTRFS_I(inode)->ordered_writeback); atomic_inc(&BTRFS_I(inode)->ordered_writeback);
...@@ -543,10 +545,9 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans, ...@@ -543,10 +545,9 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
atomic_dec(&inode->i_count); atomic_dec(&inode->i_count);
iput(inode); iput(inode);
mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
} }
root->fs_info->throttles--; atomic_dec(&root->fs_info->throttles);
return 0; return 0;
} }
...@@ -661,7 +662,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -661,7 +662,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
mutex_unlock(&root->fs_info->fs_mutex);
ret = wait_for_commit(root, cur_trans); ret = wait_for_commit(root, cur_trans);
BUG_ON(ret); BUG_ON(ret);
...@@ -669,7 +669,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -669,7 +669,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
put_transaction(cur_trans); put_transaction(cur_trans);
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
mutex_lock(&root->fs_info->fs_mutex);
return 0; return 0;
} }
...@@ -687,12 +686,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -687,12 +686,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
struct btrfs_transaction, list); struct btrfs_transaction, list);
if (!prev_trans->commit_done) { if (!prev_trans->commit_done) {
prev_trans->use_count++; prev_trans->use_count++;
mutex_unlock(&root->fs_info->fs_mutex);
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
wait_for_commit(root, prev_trans); wait_for_commit(root, prev_trans);
mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
put_transaction(prev_trans); put_transaction(prev_trans);
} }
...@@ -709,12 +706,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -709,12 +706,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
else else
timeout = 1; timeout = 1;
mutex_unlock(&root->fs_info->fs_mutex);
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
schedule_timeout(timeout); schedule_timeout(timeout);
mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
finish_wait(&cur_trans->writer_wait, &wait); finish_wait(&cur_trans->writer_wait, &wait);
ret = btrfs_write_ordered_inodes(trans, root); ret = btrfs_write_ordered_inodes(trans, root);
...@@ -755,12 +750,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -755,12 +750,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
btrfs_copy_pinned(root, pinned_copy); btrfs_copy_pinned(root, pinned_copy);
mutex_unlock(&root->fs_info->trans_mutex); mutex_unlock(&root->fs_info->trans_mutex);
mutex_unlock(&root->fs_info->fs_mutex);
ret = btrfs_write_and_wait_transaction(trans, root); ret = btrfs_write_and_wait_transaction(trans, root);
BUG_ON(ret); BUG_ON(ret);
write_ctree_super(trans, root); write_ctree_super(trans, root);
mutex_lock(&root->fs_info->fs_mutex);
btrfs_finish_extent_commit(trans, root, pinned_copy); btrfs_finish_extent_commit(trans, root, pinned_copy);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
...@@ -781,9 +774,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -781,9 +774,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
kmem_cache_free(btrfs_trans_handle_cachep, trans); kmem_cache_free(btrfs_trans_handle_cachep, trans);
if (root->fs_info->closing) { if (root->fs_info->closing) {
mutex_unlock(&root->fs_info->fs_mutex);
drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots); drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots);
mutex_lock(&root->fs_info->fs_mutex);
} }
return ret; return ret;
} }
...@@ -823,7 +814,7 @@ void btrfs_transaction_cleaner(struct work_struct *work) ...@@ -823,7 +814,7 @@ void btrfs_transaction_cleaner(struct work_struct *work)
unsigned long delay = HZ * 30; unsigned long delay = HZ * 30;
int ret; int ret;
mutex_lock(&root->fs_info->fs_mutex); smp_mb();
if (root->fs_info->closing) if (root->fs_info->closing)
goto out; goto out;
...@@ -844,7 +835,6 @@ void btrfs_transaction_cleaner(struct work_struct *work) ...@@ -844,7 +835,6 @@ void btrfs_transaction_cleaner(struct work_struct *work)
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root); ret = btrfs_commit_transaction(trans, root);
out: out:
mutex_unlock(&root->fs_info->fs_mutex);
btrfs_clean_old_snapshots(root); btrfs_clean_old_snapshots(root);
btrfs_transaction_queue_work(root, delay); btrfs_transaction_queue_work(root, delay);
} }
......
...@@ -866,7 +866,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) ...@@ -866,7 +866,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
u64 devid; u64 devid;
int ret = 0; int ret = 0;
mutex_lock(&root->fs_info->fs_mutex); mutex_lock(&root->fs_info->alloc_mutex);
mutex_lock(&root->fs_info->chunk_mutex);
mutex_lock(&uuid_mutex); mutex_lock(&uuid_mutex);
all_avail = root->fs_info->avail_data_alloc_bits | all_avail = root->fs_info->avail_data_alloc_bits |
...@@ -984,7 +985,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) ...@@ -984,7 +985,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
close_bdev_excl(bdev); close_bdev_excl(bdev);
out: out:
mutex_unlock(&uuid_mutex); mutex_unlock(&uuid_mutex);
mutex_unlock(&root->fs_info->fs_mutex); mutex_unlock(&root->fs_info->chunk_mutex);
mutex_unlock(&root->fs_info->alloc_mutex);
return ret; return ret;
} }
...@@ -1003,7 +1005,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ...@@ -1003,7 +1005,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
if (!bdev) { if (!bdev) {
return -EIO; return -EIO;
} }
mutex_lock(&root->fs_info->fs_mutex);
mutex_lock(&root->fs_info->alloc_mutex);
mutex_lock(&root->fs_info->chunk_mutex);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
devices = &root->fs_info->fs_devices->devices; devices = &root->fs_info->fs_devices->devices;
list_for_each(cur, devices) { list_for_each(cur, devices) {
...@@ -1057,7 +1062,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ...@@ -1057,7 +1062,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
root->fs_info->fs_devices->open_devices++; root->fs_info->fs_devices->open_devices++;
out: out:
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
mutex_unlock(&root->fs_info->fs_mutex); mutex_unlock(&root->fs_info->chunk_mutex);
mutex_unlock(&root->fs_info->alloc_mutex);
return ret; return ret;
out_close_bdev: out_close_bdev:
...@@ -1297,9 +1304,10 @@ int btrfs_balance(struct btrfs_root *dev_root) ...@@ -1297,9 +1304,10 @@ int btrfs_balance(struct btrfs_root *dev_root)
struct btrfs_key found_key; struct btrfs_key found_key;
BUG(); /* FIXME, needs locking */
dev_root = dev_root->fs_info->dev_root; dev_root = dev_root->fs_info->dev_root;
mutex_lock(&dev_root->fs_info->fs_mutex);
/* step one make some room on all the devices */ /* step one make some room on all the devices */
list_for_each(cur, devices) { list_for_each(cur, devices) {
device = list_entry(cur, struct btrfs_device, dev_list); device = list_entry(cur, struct btrfs_device, dev_list);
...@@ -1368,7 +1376,6 @@ int btrfs_balance(struct btrfs_root *dev_root) ...@@ -1368,7 +1376,6 @@ int btrfs_balance(struct btrfs_root *dev_root)
ret = 0; ret = 0;
error: error:
btrfs_free_path(path); btrfs_free_path(path);
mutex_unlock(&dev_root->fs_info->fs_mutex);
return ret; return ret;
} }
......
...@@ -153,7 +153,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, ...@@ -153,7 +153,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index,
return -ENOMEM; return -ENOMEM;
} }
mutex_lock(&root->fs_info->fs_mutex);
/* lookup the xattr by name */ /* lookup the xattr by name */
di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name,
strlen(name), 0); strlen(name), 0);
...@@ -181,7 +180,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index, ...@@ -181,7 +180,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index,
ret = btrfs_dir_data_len(leaf, di); ret = btrfs_dir_data_len(leaf, di);
out: out:
mutex_unlock(&root->fs_info->fs_mutex);
kfree(name); kfree(name);
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
...@@ -210,7 +208,6 @@ int btrfs_xattr_set(struct inode *inode, int name_index, ...@@ -210,7 +208,6 @@ int btrfs_xattr_set(struct inode *inode, int name_index,
return -ENOMEM; return -ENOMEM;
} }
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
btrfs_set_trans_block_group(trans, inode); btrfs_set_trans_block_group(trans, inode);
...@@ -260,7 +257,6 @@ int btrfs_xattr_set(struct inode *inode, int name_index, ...@@ -260,7 +257,6 @@ int btrfs_xattr_set(struct inode *inode, int name_index,
} }
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
mutex_unlock(&root->fs_info->fs_mutex);
kfree(name); kfree(name);
btrfs_free_path(path); btrfs_free_path(path);
...@@ -297,8 +293,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) ...@@ -297,8 +293,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
return -ENOMEM; return -ENOMEM;
path->reada = 2; path->reada = 2;
mutex_lock(&root->fs_info->fs_mutex);
/* search for our xattrs */ /* search for our xattrs */
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0) if (ret < 0)
...@@ -379,15 +373,13 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) ...@@ -379,15 +373,13 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
ret = total_size; ret = total_size;
err: err:
mutex_unlock(&root->fs_info->fs_mutex);
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
} }
/* /*
* delete all the xattrs associated with the inode. fs_mutex should be * delete all the xattrs associated with the inode.
* held when we come into here
*/ */
int btrfs_delete_xattrs(struct btrfs_trans_handle *trans, int btrfs_delete_xattrs(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode) struct btrfs_root *root, struct inode *inode)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment