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: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
925baeddc5
commit
a213501153
@ -63,6 +63,9 @@ void btrfs_free_path(struct btrfs_path *p)
|
||||
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
|
||||
{
|
||||
int i;
|
||||
int skip = p->skip_locking;
|
||||
int keep = p->keep_locks;
|
||||
|
||||
for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
|
||||
if (!p->nodes[i])
|
||||
continue;
|
||||
@ -73,6 +76,8 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
|
||||
free_extent_buffer(p->nodes[i]);
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->skip_locking = skip;
|
||||
p->keep_locks = keep;
|
||||
}
|
||||
|
||||
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)
|
||||
u32 nritems;
|
||||
t = path->nodes[i];
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
t = path->nodes[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);
|
||||
path->locks[i] = 0;
|
||||
}
|
||||
@ -1243,7 +1254,6 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
lowest_level = p->lowest_level;
|
||||
WARN_ON(lowest_level && ins_len);
|
||||
WARN_ON(p->nodes[0] != NULL);
|
||||
// WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
|
||||
WARN_ON(root == root->fs_info->extent_root &&
|
||||
!mutex_is_locked(&root->fs_info->alloc_mutex));
|
||||
WARN_ON(root == root->fs_info->chunk_root &&
|
||||
@ -1321,7 +1331,7 @@ again:
|
||||
b = read_node_slot(root, b, slot);
|
||||
if (!p->skip_locking)
|
||||
btrfs_tree_lock(b);
|
||||
unlock_up(p, level, lowest_unlock);
|
||||
unlock_up(p, level + 1, lowest_unlock);
|
||||
} else {
|
||||
p->slots[level] = slot;
|
||||
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
|
||||
if (slot >= btrfs_header_nritems(upper) - 1)
|
||||
return 1;
|
||||
|
||||
WARN_ON(!btrfs_tree_locked(path->nodes[1]));
|
||||
|
||||
right = read_node_slot(root, upper, slot + 1);
|
||||
btrfs_tree_lock(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
|
||||
return 1;
|
||||
}
|
||||
|
||||
WARN_ON(!btrfs_tree_locked(path->nodes[1]));
|
||||
|
||||
left = read_node_slot(root, path->nodes[1], slot - 1);
|
||||
btrfs_tree_lock(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)
|
||||
|
||||
btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1);
|
||||
|
||||
path->keep_locks = 1;
|
||||
btrfs_release_path(root, path);
|
||||
path->keep_locks = 1;
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
path->keep_locks = 0;
|
||||
|
||||
if (ret < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2992,8 +3007,17 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
||||
reada_for_search(root, path, level, slot, 0);
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
path->slots[level] = slot;
|
||||
@ -3011,9 +3035,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
||||
if (level == 1 && path->locks[1] && path->reada)
|
||||
reada_for_search(root, path, level, slot, 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);
|
||||
}
|
||||
}
|
||||
done:
|
||||
unlock_up(path, 0, 1);
|
||||
return 0;
|
||||
|
@ -519,9 +519,9 @@ struct btrfs_fs_info {
|
||||
struct backing_dev_info bdi;
|
||||
spinlock_t hash_lock;
|
||||
struct mutex trans_mutex;
|
||||
struct mutex fs_mutex;
|
||||
struct mutex alloc_mutex;
|
||||
struct mutex chunk_mutex;
|
||||
struct mutex drop_mutex;
|
||||
struct list_head trans_list;
|
||||
struct list_head hashers;
|
||||
struct list_head dead_roots;
|
||||
@ -554,7 +554,7 @@ struct btrfs_fs_info {
|
||||
struct completion kobj_unregister;
|
||||
int do_barriers;
|
||||
int closing;
|
||||
unsigned long throttles;
|
||||
atomic_t throttles;
|
||||
|
||||
u64 total_pinned;
|
||||
struct list_head dirty_cowonly_roots;
|
||||
@ -594,6 +594,7 @@ struct btrfs_root {
|
||||
struct inode *inode;
|
||||
struct kobject root_kobj;
|
||||
struct completion kobj_unregister;
|
||||
struct mutex objectid_mutex;
|
||||
u64 objectid;
|
||||
u64 last_trans;
|
||||
|
||||
|
@ -724,6 +724,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
|
||||
|
||||
INIT_LIST_HEAD(&root->dirty_list);
|
||||
spin_lock_init(&root->node_lock);
|
||||
mutex_init(&root->objectid_mutex);
|
||||
memset(&root->root_key, 0, sizeof(root->root_key));
|
||||
memset(&root->root_item, 0, sizeof(root->root_item));
|
||||
memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
|
||||
@ -1146,6 +1147,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||
INIT_LIST_HEAD(&fs_info->space_info);
|
||||
btrfs_mapping_init(&fs_info->mapping_tree);
|
||||
atomic_set(&fs_info->nr_async_submits, 0);
|
||||
atomic_set(&fs_info->throttles, 0);
|
||||
fs_info->sb = sb;
|
||||
fs_info->max_extent = (u64)-1;
|
||||
fs_info->max_inline = 8192 * 1024;
|
||||
@ -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);
|
||||
|
||||
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->chunk_mutex);
|
||||
|
||||
@ -1278,8 +1280,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||
goto fail_sb_buffer;
|
||||
}
|
||||
|
||||
mutex_lock(&fs_info->fs_mutex);
|
||||
|
||||
mutex_lock(&fs_info->chunk_mutex);
|
||||
ret = btrfs_read_sys_array(tree_root);
|
||||
mutex_unlock(&fs_info->chunk_mutex);
|
||||
@ -1342,7 +1342,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
|
||||
fs_info->metadata_alloc_profile = (u64)-1;
|
||||
fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
|
||||
|
||||
mutex_unlock(&fs_info->fs_mutex);
|
||||
return tree_root;
|
||||
|
||||
fail_extent_root:
|
||||
@ -1350,7 +1349,6 @@ fail_extent_root:
|
||||
fail_tree_root:
|
||||
free_extent_buffer(tree_root->node);
|
||||
fail_sys_array:
|
||||
mutex_unlock(&fs_info->fs_mutex);
|
||||
fail_sb_buffer:
|
||||
extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree);
|
||||
btrfs_stop_workers(&fs_info->workers);
|
||||
@ -1562,8 +1560,9 @@ int close_ctree(struct btrfs_root *root)
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
|
||||
fs_info->closing = 1;
|
||||
smp_mb();
|
||||
|
||||
btrfs_transaction_flush_work(root);
|
||||
mutex_lock(&fs_info->fs_mutex);
|
||||
btrfs_defrag_dirty_roots(root->fs_info);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
ret = btrfs_commit_transaction(trans, root);
|
||||
@ -1574,7 +1573,6 @@ int close_ctree(struct btrfs_root *root)
|
||||
BUG_ON(ret);
|
||||
|
||||
write_ctree_super(NULL, root);
|
||||
mutex_unlock(&fs_info->fs_mutex);
|
||||
|
||||
btrfs_transaction_flush_work(root);
|
||||
|
||||
@ -1679,7 +1677,8 @@ void btrfs_throttle(struct btrfs_root *root)
|
||||
struct backing_dev_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)
|
||||
congestion_wait(WRITE, HZ/20);
|
||||
#else
|
||||
|
@ -1577,9 +1577,11 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
}
|
||||
|
||||
/* block accounting for super block */
|
||||
spin_lock_irq(&info->delalloc_lock);
|
||||
super_used = btrfs_super_bytes_used(&info->super_copy);
|
||||
btrfs_set_super_bytes_used(&info->super_copy,
|
||||
super_used - num_bytes);
|
||||
spin_unlock_irq(&info->delalloc_lock);
|
||||
|
||||
/* block accounting for root item */
|
||||
root_used = btrfs_root_used(&root->root_item);
|
||||
@ -1968,8 +1970,10 @@ again:
|
||||
}
|
||||
|
||||
/* block accounting for super block */
|
||||
spin_lock_irq(&info->delalloc_lock);
|
||||
super_used = btrfs_super_bytes_used(&info->super_copy);
|
||||
btrfs_set_super_bytes_used(&info->super_copy, super_used + num_bytes);
|
||||
spin_unlock_irq(&info->delalloc_lock);
|
||||
|
||||
/* block accounting for root item */
|
||||
root_used = btrfs_root_used(&root->root_item);
|
||||
@ -2172,12 +2176,12 @@ static void noinline reada_walk_down(struct btrfs_root *root,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
mutex_unlock(&root->fs_info->alloc_mutex);
|
||||
ret = readahead_tree_block(root, bytenr, blocksize,
|
||||
btrfs_node_ptr_generation(node, i));
|
||||
last = bytenr + blocksize;
|
||||
cond_resched();
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->alloc_mutex);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
@ -2254,11 +2258,9 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
|
||||
free_extent_buffer(next);
|
||||
reada_walk_down(root, cur, path->slots[*level]);
|
||||
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
mutex_unlock(&root->fs_info->alloc_mutex);
|
||||
next = read_tree_block(root, bytenr, blocksize,
|
||||
ptr_gen);
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->alloc_mutex);
|
||||
|
||||
/* we've dropped the lock, double check */
|
||||
@ -2381,6 +2383,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
int orig_level;
|
||||
struct btrfs_root_item *root_item = &root->root_item;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&root->fs_info->drop_mutex));
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
|
||||
@ -2710,7 +2713,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root,
|
||||
*last_file_root == ref_root)
|
||||
goto out;
|
||||
|
||||
mutex_unlock(&extent_root->fs_info->fs_mutex);
|
||||
inode = btrfs_iget_locked(extent_root->fs_info->sb,
|
||||
ref_objectid, found_root);
|
||||
if (inode->i_state & I_NEW) {
|
||||
@ -2727,7 +2729,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root,
|
||||
* the latest version of the tree root
|
||||
*/
|
||||
if (is_bad_inode(inode)) {
|
||||
mutex_lock(&extent_root->fs_info->fs_mutex);
|
||||
goto out;
|
||||
}
|
||||
*last_file_objectid = inode->i_ino;
|
||||
@ -2736,7 +2737,6 @@ static int noinline relocate_one_reference(struct btrfs_root *extent_root,
|
||||
|
||||
relocate_inode_pages(inode, ref_offset, extent_key->offset);
|
||||
iput(inode);
|
||||
mutex_lock(&extent_root->fs_info->fs_mutex);
|
||||
} else {
|
||||
struct btrfs_trans_handle *trans;
|
||||
struct extent_buffer *eb;
|
||||
@ -3033,9 +3033,7 @@ next:
|
||||
|
||||
if (progress && need_resched()) {
|
||||
memcpy(&key, &found_key, sizeof(key));
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
cond_resched();
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
progress = 0;
|
||||
@ -3068,9 +3066,7 @@ next:
|
||||
trans = btrfs_start_transaction(tree_root, 1);
|
||||
btrfs_commit_transaction(trans, tree_root);
|
||||
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_clean_old_snapshots(tree_root);
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
|
||||
trans = btrfs_start_transaction(tree_root, 1);
|
||||
btrfs_commit_transaction(trans, tree_root);
|
||||
|
@ -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;
|
||||
|
||||
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);
|
||||
if (!trans) {
|
||||
err = -ENOMEM;
|
||||
@ -341,7 +340,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
|
||||
failed:
|
||||
err = btrfs_end_transaction(trans, root);
|
||||
out_unlock:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
unlock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS);
|
||||
return err;
|
||||
}
|
||||
@ -905,9 +903,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
|
||||
WARN_ON(num_pages > nrptrs);
|
||||
memset(pages, 0, sizeof(pages));
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_check_free_space(root, write_bytes, 0);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -998,9 +994,9 @@ static int btrfs_sync_file(struct file *file,
|
||||
* check the transaction that last modified this inode
|
||||
* and see if its already been committed
|
||||
*/
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
if (!BTRFS_I(inode)->last_trans)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
if (BTRFS_I(inode)->last_trans <=
|
||||
root->fs_info->last_trans_committed) {
|
||||
@ -1023,7 +1019,6 @@ static int btrfs_sync_file(struct file *file,
|
||||
}
|
||||
ret = btrfs_commit_transaction(trans, root);
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret > 0 ? EIO : ret;
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,12 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_key search_key;
|
||||
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();
|
||||
BUG_ON(!path);
|
||||
search_start = root->last_inode_alloc;
|
||||
@ -124,9 +130,11 @@ found:
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
BUG_ON(*objectid < search_start);
|
||||
mutex_unlock(&root->objectid_mutex);
|
||||
return 0;
|
||||
error:
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
mutex_unlock(&root->objectid_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
@ -79,12 +79,15 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
|
||||
int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
|
||||
int for_del)
|
||||
{
|
||||
u64 total = btrfs_super_total_bytes(&root->fs_info->super_copy);
|
||||
u64 used = btrfs_super_bytes_used(&root->fs_info->super_copy);
|
||||
u64 total;
|
||||
u64 used;
|
||||
u64 thresh;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&root->fs_info->delalloc_lock, flags);
|
||||
total = btrfs_super_total_bytes(&root->fs_info->super_copy);
|
||||
used = btrfs_super_bytes_used(&root->fs_info->super_copy);
|
||||
if (for_del)
|
||||
thresh = total * 90;
|
||||
else
|
||||
@ -92,7 +95,6 @@ int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
|
||||
|
||||
do_div(thresh, 100);
|
||||
|
||||
spin_lock_irqsave(&root->fs_info->delalloc_lock, flags);
|
||||
if (used + root->fs_info->delalloc_bytes + num_required > thresh)
|
||||
ret = -ENOSPC;
|
||||
spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags);
|
||||
@ -115,7 +117,6 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
BUG_ON(!trans);
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
num_bytes = (end - start + blocksize) & ~(blocksize - 1);
|
||||
num_bytes = max(blocksize, num_bytes);
|
||||
@ -160,7 +161,6 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
|
||||
btrfs_add_ordered_inode(inode);
|
||||
btrfs_update_inode(trans, root, inode);
|
||||
out:
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
btrfs_end_transaction(trans, root);
|
||||
return ret;
|
||||
}
|
||||
@ -269,14 +269,13 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
|
||||
{
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
int ret;
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
|
||||
if (btrfs_test_opt(root, NODATACOW) ||
|
||||
btrfs_test_flag(inode, NODATACOW))
|
||||
ret = run_delalloc_nocow(inode, start, end);
|
||||
else
|
||||
ret = cow_file_range(inode, start, end);
|
||||
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -349,17 +348,13 @@ int __btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
|
||||
ret = btrfs_csum_one_bio(root, bio, &sums);
|
||||
BUG_ON(ret);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
btrfs_csum_file_blocks(trans, root, inode, bio, sums);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_end_transaction(trans, root);
|
||||
BUG_ON(ret);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
kfree(sums);
|
||||
|
||||
@ -404,7 +399,6 @@ int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end)
|
||||
btrfs_test_flag(inode, NODATASUM))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
path = btrfs_alloc_path();
|
||||
item = btrfs_lookup_csum(NULL, root, path, inode->i_ino, start, 0);
|
||||
if (IS_ERR(item)) {
|
||||
@ -422,7 +416,6 @@ int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end)
|
||||
out:
|
||||
if (path)
|
||||
btrfs_free_path(path);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -616,7 +609,6 @@ void btrfs_read_locked_inode(struct inode *inode)
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
|
||||
|
||||
ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
|
||||
@ -662,8 +654,6 @@ void btrfs_read_locked_inode(struct inode *inode)
|
||||
btrfs_free_path(path);
|
||||
inode_item = NULL;
|
||||
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
switch (inode->i_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
inode->i_mapping->a_ops = &btrfs_aops;
|
||||
@ -691,9 +681,7 @@ void btrfs_read_locked_inode(struct inode *inode)
|
||||
return;
|
||||
|
||||
make_bad:
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
make_bad_inode(inode);
|
||||
}
|
||||
|
||||
@ -758,7 +746,6 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans,
|
||||
btrfs_set_inode_last_trans(trans, inode);
|
||||
ret = 0;
|
||||
failed:
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
}
|
||||
@ -849,7 +836,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
unsigned long nr = 0;
|
||||
|
||||
root = BTRFS_I(dir)->root;
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
|
||||
ret = btrfs_check_free_space(root, 1, 1);
|
||||
if (ret)
|
||||
@ -871,7 +857,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
|
||||
btrfs_end_transaction(trans, root);
|
||||
fail:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
btrfs_throttle(root);
|
||||
return ret;
|
||||
@ -890,7 +875,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_check_free_space(root, 1, 1);
|
||||
if (ret)
|
||||
goto fail;
|
||||
@ -907,7 +891,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
nr = trans->blocks_used;
|
||||
ret = btrfs_end_transaction(trans, root);
|
||||
fail:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
btrfs_throttle(root);
|
||||
|
||||
@ -1129,7 +1112,6 @@ error:
|
||||
ret = btrfs_del_items(trans, root, path, pending_del_slot,
|
||||
pending_del_nr);
|
||||
}
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
inode->i_sb->s_dirt = 1;
|
||||
return ret;
|
||||
@ -1234,9 +1216,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
if (attr->ia_size <= hole_start)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
err = btrfs_check_free_space(root, 1, 0);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
@ -1245,7 +1225,6 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
lock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
|
||||
hole_size = block_end - hole_start;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
err = btrfs_drop_extents(trans, root, inode,
|
||||
@ -1262,7 +1241,6 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
btrfs_check_file(root, inode);
|
||||
}
|
||||
btrfs_end_transaction(trans, root);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
|
||||
if (err)
|
||||
return err;
|
||||
@ -1286,7 +1264,6 @@ void btrfs_delete_inode(struct inode *inode)
|
||||
}
|
||||
|
||||
inode->i_size = 0;
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
@ -1298,7 +1275,6 @@ void btrfs_delete_inode(struct inode *inode)
|
||||
clear_inode(inode);
|
||||
|
||||
btrfs_end_transaction(trans, root);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
btrfs_throttle(root);
|
||||
return;
|
||||
@ -1306,7 +1282,6 @@ void btrfs_delete_inode(struct inode *inode)
|
||||
no_delete_lock:
|
||||
nr = trans->blocks_used;
|
||||
btrfs_end_transaction(trans, root);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
btrfs_throttle(root);
|
||||
no_delete:
|
||||
@ -1402,7 +1377,6 @@ static int fixup_tree_root_location(struct btrfs_root *root,
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
|
||||
*sub_root = btrfs_read_fs_root(root->fs_info, location,
|
||||
dentry->d_name.name,
|
||||
@ -1416,7 +1390,6 @@ static int fixup_tree_root_location(struct btrfs_root *root,
|
||||
location->offset = 0;
|
||||
|
||||
btrfs_free_path(path);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1482,9 +1455,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
if (dentry->d_name.len > BTRFS_NAME_LEN)
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_inode_by_name(dir, dentry, &location);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
if (ret < 0)
|
||||
return ERR_PTR(ret);
|
||||
@ -1559,7 +1530,6 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
filp->f_pos = 1;
|
||||
}
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
key.objectid = inode->i_ino;
|
||||
path = btrfs_alloc_path();
|
||||
path->reada = 2;
|
||||
@ -1668,9 +1638,7 @@ read_dir_items:
|
||||
nopos:
|
||||
ret = 0;
|
||||
err:
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1681,11 +1649,9 @@ int btrfs_write_inode(struct inode *inode, int wait)
|
||||
int ret = 0;
|
||||
|
||||
if (wait) {
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
ret = btrfs_commit_transaction(trans, root);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -1701,12 +1667,10 @@ void btrfs_dirty_inode(struct inode *inode)
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
struct btrfs_trans_handle *trans;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
btrfs_update_inode(trans, root, inode);
|
||||
btrfs_end_transaction(trans, root);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
}
|
||||
|
||||
static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
||||
@ -1874,7 +1838,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
|
||||
if (!new_valid_dev(rdev))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
err = btrfs_check_free_space(root, 1, 0);
|
||||
if (err)
|
||||
goto fail;
|
||||
@ -1912,8 +1875,6 @@ out_unlock:
|
||||
nr = trans->blocks_used;
|
||||
btrfs_end_transaction(trans, root);
|
||||
fail:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
if (drop_inode) {
|
||||
inode_dec_link_count(inode);
|
||||
iput(inode);
|
||||
@ -1934,7 +1895,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
|
||||
unsigned long nr = 0;
|
||||
u64 objectid;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
err = btrfs_check_free_space(root, 1, 0);
|
||||
if (err)
|
||||
goto fail;
|
||||
@ -1980,8 +1940,6 @@ out_unlock:
|
||||
nr = trans->blocks_used;
|
||||
btrfs_end_transaction(trans, root);
|
||||
fail:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
if (drop_inode) {
|
||||
inode_dec_link_count(inode);
|
||||
iput(inode);
|
||||
@ -2009,7 +1967,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
#else
|
||||
inc_nlink(inode);
|
||||
#endif
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
err = btrfs_check_free_space(root, 1, 0);
|
||||
if (err)
|
||||
goto fail;
|
||||
@ -2032,8 +1989,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
nr = trans->blocks_used;
|
||||
btrfs_end_transaction(trans, root);
|
||||
fail:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
if (drop_inode) {
|
||||
inode_dec_link_count(inode);
|
||||
iput(inode);
|
||||
@ -2053,7 +2008,6 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
u64 objectid = 0;
|
||||
unsigned long nr = 1;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
err = btrfs_check_free_space(root, 1, 0);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
@ -2106,7 +2060,6 @@ out_fail:
|
||||
btrfs_end_transaction(trans, root);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
if (drop_on_err)
|
||||
iput(inode);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
@ -2199,7 +2152,6 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
|
||||
again:
|
||||
spin_lock(&em_tree->lock);
|
||||
@ -2402,7 +2354,6 @@ out:
|
||||
if (!err)
|
||||
err = ret;
|
||||
}
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
if (err) {
|
||||
free_extent_map(em);
|
||||
WARN_ON(1);
|
||||
@ -2584,9 +2535,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
|
||||
int ret;
|
||||
u64 page_start;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_check_free_space(root, PAGE_CACHE_SIZE, 0);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -2631,7 +2580,6 @@ static void btrfs_truncate(struct inode *inode)
|
||||
|
||||
btrfs_truncate_page(inode->i_mapping, inode->i_size);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
|
||||
@ -2643,7 +2591,6 @@ static void btrfs_truncate(struct inode *inode)
|
||||
|
||||
ret = btrfs_end_transaction(trans, root);
|
||||
BUG_ON(ret);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
btrfs_throttle(root);
|
||||
}
|
||||
@ -2827,7 +2774,6 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_inode = new_dentry->d_inode;
|
||||
struct inode *old_inode = old_dentry->d_inode;
|
||||
struct timespec ctime = CURRENT_TIME;
|
||||
struct btrfs_path *path;
|
||||
int ret;
|
||||
|
||||
if (S_ISDIR(old_inode->i_mode) && new_inode &&
|
||||
@ -2835,7 +2781,6 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_check_free_space(root, 1, 0);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
@ -2843,11 +2788,6 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
|
||||
btrfs_set_trans_block_group(trans, new_dir);
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
ret = -ENOMEM;
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
old_dentry->d_inode->i_nlink++;
|
||||
old_dir->i_ctime = old_dir->i_mtime = ctime;
|
||||
@ -2869,10 +2809,8 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
|
||||
goto out_fail;
|
||||
|
||||
out_fail:
|
||||
btrfs_free_path(path);
|
||||
btrfs_end_transaction(trans, root);
|
||||
out_unlock:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2898,7 +2836,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||
if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
err = btrfs_check_free_space(root, 1, 0);
|
||||
if (err)
|
||||
goto out_fail;
|
||||
@ -2979,7 +2916,6 @@ out_unlock:
|
||||
nr = trans->blocks_used;
|
||||
btrfs_end_transaction(trans, root);
|
||||
out_fail:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
if (drop_inode) {
|
||||
inode_dec_link_count(inode);
|
||||
iput(inode);
|
||||
|
@ -63,7 +63,6 @@ static noinline int create_subvol(struct btrfs_root *root, char *name,
|
||||
u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
|
||||
unsigned long nr = 1;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_check_free_space(root, 1, 0);
|
||||
if (ret)
|
||||
goto fail_commit;
|
||||
@ -164,7 +163,6 @@ fail:
|
||||
if (err && !ret)
|
||||
ret = err;
|
||||
fail_commit:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
btrfs_throttle(root);
|
||||
return ret;
|
||||
@ -181,7 +179,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
|
||||
if (!root->ref_cows)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_check_free_space(root, 1, 0);
|
||||
if (ret)
|
||||
goto fail_unlock;
|
||||
@ -208,7 +205,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
|
||||
err = btrfs_commit_transaction(trans, root);
|
||||
|
||||
fail_unlock:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(root, nr);
|
||||
btrfs_throttle(root);
|
||||
return ret;
|
||||
@ -228,9 +224,7 @@ int btrfs_defrag_file(struct file *file)
|
||||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_check_free_space(root, inode->i_size, 0);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
if (ret)
|
||||
return -ENOSPC;
|
||||
|
||||
@ -315,7 +309,8 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
|
||||
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;
|
||||
devstr = strchr(sizestr, ':');
|
||||
if (devstr) {
|
||||
@ -385,7 +380,8 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg)
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->alloc_mutex);
|
||||
mutex_lock(&root->fs_info->chunk_mutex);
|
||||
out:
|
||||
kfree(vol_args);
|
||||
return ret;
|
||||
@ -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,
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root,
|
||||
path, root_dirid,
|
||||
vol_args->name, namelen, 0);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_free_path(path);
|
||||
|
||||
if (di && !IS_ERR(di)) {
|
||||
@ -445,10 +439,12 @@ static noinline int btrfs_ioctl_snap_create(struct btrfs_root *root,
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&root->fs_info->drop_mutex);
|
||||
if (root == root->fs_info->tree_root)
|
||||
ret = create_subvol(root, vol_args->name, namelen);
|
||||
else
|
||||
ret = create_snapshot(root, vol_args->name, namelen);
|
||||
mutex_unlock(&root->fs_info->drop_mutex);
|
||||
out:
|
||||
kfree(vol_args);
|
||||
return ret;
|
||||
@ -461,10 +457,8 @@ static int btrfs_ioctl_defrag(struct file *file)
|
||||
|
||||
switch (inode->i_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
btrfs_defrag_root(root, 0);
|
||||
btrfs_defrag_root(root->fs_info->extent_root, 0);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
break;
|
||||
case S_IFREG:
|
||||
btrfs_defrag_file(file);
|
||||
@ -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);
|
||||
}
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 0);
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
@ -685,7 +678,6 @@ out:
|
||||
unlock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS);
|
||||
|
||||
btrfs_end_transaction(trans, root);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&src->i_mutex);
|
||||
@ -711,7 +703,6 @@ long btrfs_ioctl_trans_start(struct file *file)
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
if (file->private_data) {
|
||||
ret = -EINPROGRESS;
|
||||
goto out;
|
||||
@ -723,7 +714,6 @@ long btrfs_ioctl_trans_start(struct file *file)
|
||||
ret = -ENOMEM;
|
||||
/*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -740,7 +730,6 @@ long btrfs_ioctl_trans_end(struct file *file)
|
||||
struct btrfs_trans_handle *trans;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = file->private_data;
|
||||
if (!trans) {
|
||||
ret = -EINVAL;
|
||||
@ -749,7 +738,6 @@ long btrfs_ioctl_trans_end(struct file *file)
|
||||
btrfs_end_transaction(trans, root);
|
||||
file->private_data = 0;
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -366,12 +366,10 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
|
||||
return 0;
|
||||
}
|
||||
btrfs_clean_old_snapshots(root);
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
btrfs_defrag_dirty_roots(root->fs_info);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
ret = btrfs_commit_transaction(trans, root);
|
||||
sb->s_dirt = 0;
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -370,6 +370,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
|
||||
struct btrfs_trans_handle *trans;
|
||||
unsigned long nr;
|
||||
|
||||
smp_mb();
|
||||
if (root->defrag_running)
|
||||
return 0;
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
@ -378,16 +379,15 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
|
||||
ret = btrfs_defrag_leaves(trans, root, cacheonly);
|
||||
nr = trans->blocks_used;
|
||||
btrfs_end_transaction(trans, root);
|
||||
mutex_unlock(&info->fs_mutex);
|
||||
btrfs_btree_balance_dirty(info->tree_root, nr);
|
||||
cond_resched();
|
||||
|
||||
mutex_lock(&info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
if (ret != -EAGAIN)
|
||||
break;
|
||||
}
|
||||
root->defrag_running = 0;
|
||||
smp_mb();
|
||||
radix_tree_tag_clear(&info->fs_roots_radix,
|
||||
(unsigned long)root->root_key.objectid,
|
||||
BTRFS_ROOT_DEFRAG_TAG);
|
||||
@ -435,14 +435,14 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
|
||||
while(!list_empty(list)) {
|
||||
struct btrfs_root *root;
|
||||
|
||||
mutex_lock(&tree_root->fs_info->fs_mutex);
|
||||
dirty = list_entry(list->next, struct dirty_root, list);
|
||||
list_del_init(&dirty->list);
|
||||
|
||||
num_bytes = btrfs_root_used(&dirty->root->root_item);
|
||||
root = dirty->latest_root;
|
||||
root->fs_info->throttles++;
|
||||
atomic_inc(&root->fs_info->throttles);
|
||||
|
||||
mutex_lock(&root->fs_info->drop_mutex);
|
||||
while(1) {
|
||||
trans = btrfs_start_transaction(tree_root, 1);
|
||||
ret = btrfs_drop_snapshot(trans, dirty->root);
|
||||
@ -459,14 +459,16 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
|
||||
nr = trans->blocks_used;
|
||||
ret = btrfs_end_transaction(trans, tree_root);
|
||||
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);
|
||||
cond_resched();
|
||||
mutex_lock(&tree_root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->drop_mutex);
|
||||
}
|
||||
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);
|
||||
bytes_used = btrfs_root_used(&root->root_item);
|
||||
if (num_bytes) {
|
||||
@ -474,11 +476,15 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
|
||||
btrfs_set_root_used(&root->root_item,
|
||||
bytes_used - num_bytes);
|
||||
}
|
||||
mutex_unlock(&root->fs_info->alloc_mutex);
|
||||
|
||||
ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key);
|
||||
if (ret) {
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&root->fs_info->drop_mutex);
|
||||
|
||||
nr = trans->blocks_used;
|
||||
ret = btrfs_end_transaction(trans, tree_root);
|
||||
BUG_ON(ret);
|
||||
@ -486,7 +492,6 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
|
||||
free_extent_buffer(dirty->root->node);
|
||||
kfree(dirty->root);
|
||||
kfree(dirty);
|
||||
mutex_unlock(&tree_root->fs_info->fs_mutex);
|
||||
|
||||
btrfs_btree_balance_dirty(tree_root, nr);
|
||||
cond_resched();
|
||||
@ -503,7 +508,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
|
||||
u64 objectid = 0;
|
||||
int ret;
|
||||
|
||||
root->fs_info->throttles++;
|
||||
atomic_inc(&root->fs_info->throttles);
|
||||
while(1) {
|
||||
ret = btrfs_find_first_ordered_inode(
|
||||
&cur_trans->ordered_inode_tree,
|
||||
@ -512,7 +517,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
|
||||
break;
|
||||
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
atomic_inc(&BTRFS_I(inode)->ordered_writeback);
|
||||
@ -521,7 +525,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
iput(inode);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
}
|
||||
while(1) {
|
||||
@ -533,7 +536,6 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
|
||||
if (!ret)
|
||||
break;
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
atomic_inc(&BTRFS_I(inode)->ordered_writeback);
|
||||
@ -543,10 +545,9 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
|
||||
atomic_dec(&inode->i_count);
|
||||
iput(inode);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
}
|
||||
root->fs_info->throttles--;
|
||||
atomic_dec(&root->fs_info->throttles);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -661,7 +662,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
btrfs_end_transaction(trans, root);
|
||||
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
ret = wait_for_commit(root, cur_trans);
|
||||
BUG_ON(ret);
|
||||
|
||||
@ -669,7 +669,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
put_transaction(cur_trans);
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -687,12 +686,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_transaction, list);
|
||||
if (!prev_trans->commit_done) {
|
||||
prev_trans->use_count++;
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
|
||||
wait_for_commit(root, prev_trans);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
put_transaction(prev_trans);
|
||||
}
|
||||
@ -709,12 +706,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
else
|
||||
timeout = 1;
|
||||
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
|
||||
schedule_timeout(timeout);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
finish_wait(&cur_trans->writer_wait, &wait);
|
||||
ret = btrfs_write_ordered_inodes(trans, root);
|
||||
@ -755,12 +750,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
btrfs_copy_pinned(root, pinned_copy);
|
||||
|
||||
mutex_unlock(&root->fs_info->trans_mutex);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
ret = btrfs_write_and_wait_transaction(trans, root);
|
||||
BUG_ON(ret);
|
||||
write_ctree_super(trans, root);
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
btrfs_finish_extent_commit(trans, root, pinned_copy);
|
||||
mutex_lock(&root->fs_info->trans_mutex);
|
||||
|
||||
@ -781,9 +774,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
kmem_cache_free(btrfs_trans_handle_cachep, trans);
|
||||
|
||||
if (root->fs_info->closing) {
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
drop_dirty_roots(root->fs_info->tree_root, &dirty_fs_roots);
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -823,7 +814,7 @@ void btrfs_transaction_cleaner(struct work_struct *work)
|
||||
unsigned long delay = HZ * 30;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
smp_mb();
|
||||
if (root->fs_info->closing)
|
||||
goto out;
|
||||
|
||||
@ -844,7 +835,6 @@ void btrfs_transaction_cleaner(struct work_struct *work)
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
ret = btrfs_commit_transaction(trans, root);
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_clean_old_snapshots(root);
|
||||
btrfs_transaction_queue_work(root, delay);
|
||||
}
|
||||
|
@ -866,7 +866,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
|
||||
u64 devid;
|
||||
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);
|
||||
|
||||
all_avail = root->fs_info->avail_data_alloc_bits |
|
||||
@ -984,7 +985,8 @@ error_close:
|
||||
close_bdev_excl(bdev);
|
||||
out:
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1003,7 +1005,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
||||
if (!bdev) {
|
||||
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);
|
||||
devices = &root->fs_info->fs_devices->devices;
|
||||
list_for_each(cur, devices) {
|
||||
@ -1057,7 +1062,9 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
||||
root->fs_info->fs_devices->open_devices++;
|
||||
out:
|
||||
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;
|
||||
|
||||
out_close_bdev:
|
||||
@ -1297,9 +1304,10 @@ int btrfs_balance(struct btrfs_root *dev_root)
|
||||
struct btrfs_key found_key;
|
||||
|
||||
|
||||
BUG(); /* FIXME, needs locking */
|
||||
|
||||
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 */
|
||||
list_for_each(cur, devices) {
|
||||
device = list_entry(cur, struct btrfs_device, dev_list);
|
||||
@ -1368,7 +1376,6 @@ int btrfs_balance(struct btrfs_root *dev_root)
|
||||
ret = 0;
|
||||
error:
|
||||
btrfs_free_path(path);
|
||||
mutex_unlock(&dev_root->fs_info->fs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
/* lookup the xattr by name */
|
||||
di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name,
|
||||
strlen(name), 0);
|
||||
@ -181,7 +180,6 @@ ssize_t btrfs_xattr_get(struct inode *inode, int name_index,
|
||||
ret = btrfs_dir_data_len(leaf, di);
|
||||
|
||||
out:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
kfree(name);
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
@ -210,7 +208,6 @@ int btrfs_xattr_set(struct inode *inode, int name_index,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
btrfs_set_trans_block_group(trans, inode);
|
||||
|
||||
@ -260,7 +257,6 @@ out:
|
||||
}
|
||||
|
||||
btrfs_end_transaction(trans, root);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
kfree(name);
|
||||
btrfs_free_path(path);
|
||||
|
||||
@ -297,8 +293,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
return -ENOMEM;
|
||||
path->reada = 2;
|
||||
|
||||
mutex_lock(&root->fs_info->fs_mutex);
|
||||
|
||||
/* search for our xattrs */
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
@ -379,15 +373,13 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
ret = total_size;
|
||||
|
||||
err:
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
btrfs_free_path(path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete all the xattrs associated with the inode. fs_mutex should be
|
||||
* held when we come into here
|
||||
* delete all the xattrs associated with the inode.
|
||||
*/
|
||||
int btrfs_delete_xattrs(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, struct inode *inode)
|
||||
|
Loading…
Reference in New Issue
Block a user