From a681b40ca290eb4c870bb0421141e2e5e1edb970 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 14 Jun 2011 14:24:32 -0400 Subject: [PATCH] --- yaml --- r: 253811 b: refs/heads/master c: 71d7aed014457147e8f71a843d5fbf03235e4a85 h: refs/heads/master i: 253809: b7521d43dece81653f6a7efab7f952ce26d45842 253807: dda7050e0d880f3adc08ba9b6a7aecdcd0b8430f v: v3 --- [refs] | 2 +- trunk/fs/btrfs/ctree.h | 14 ------- trunk/fs/btrfs/disk-io.c | 5 +-- trunk/fs/btrfs/extent-tree.c | 4 ++ trunk/fs/btrfs/inode.c | 1 + trunk/fs/btrfs/relocation.c | 30 +++++---------- trunk/fs/btrfs/transaction.c | 73 ++---------------------------------- 7 files changed, 20 insertions(+), 109 deletions(-) diff --git a/[refs] b/[refs] index b6540ef82696..0a7c36d3be96 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7585717f304f5ed005cc4ad933a69aab3efbd136 +refs/heads/master: 71d7aed014457147e8f71a843d5fbf03235e4a85 diff --git a/trunk/fs/btrfs/ctree.h b/trunk/fs/btrfs/ctree.h index a2c91a102b72..8490ee063709 100644 --- a/trunk/fs/btrfs/ctree.h +++ b/trunk/fs/btrfs/ctree.h @@ -967,12 +967,6 @@ struct btrfs_fs_info { struct srcu_struct subvol_srcu; spinlock_t trans_lock; - /* - * the reloc mutex goes with the trans lock, it is taken - * during commit to protect us from the relocation code - */ - struct mutex reloc_mutex; - struct list_head trans_list; struct list_head hashers; struct list_head dead_roots; @@ -1178,14 +1172,6 @@ struct btrfs_root { u32 type; u64 highest_objectid; - - /* btrfs_record_root_in_trans is a multi-step process, - * and it can race with the balancing code. But the - * race is very small, and only the first time the root - * is added to each transaction. So in_trans_setup - * is used to tell us when more checks are required - */ - unsigned long in_trans_setup; int ref_cows; int track_dirty; int in_radix; diff --git a/trunk/fs/btrfs/disk-io.c b/trunk/fs/btrfs/disk-io.c index 0b2b4b759136..9f68c6898653 100644 --- a/trunk/fs/btrfs/disk-io.c +++ b/trunk/fs/btrfs/disk-io.c @@ -1312,9 +1312,7 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, spin_lock_init(&root->cache_lock); init_waitqueue_head(&root->cache_wait); - ret = set_anon_super(&root->anon_super, NULL); - if (ret) - goto fail; + set_anon_super(&root->anon_super, NULL); if (btrfs_root_refs(&root->root_item) == 0) { ret = -ENOENT; @@ -1620,7 +1618,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, spin_lock_init(&fs_info->fs_roots_radix_lock); spin_lock_init(&fs_info->delayed_iput_lock); spin_lock_init(&fs_info->defrag_inodes_lock); - mutex_init(&fs_info->reloc_mutex); init_completion(&fs_info->kobj_unregister); fs_info->tree_root = tree_root; diff --git a/trunk/fs/btrfs/extent-tree.c b/trunk/fs/btrfs/extent-tree.c index 1f61bf5b4960..b42efc2ded51 100644 --- a/trunk/fs/btrfs/extent-tree.c +++ b/trunk/fs/btrfs/extent-tree.c @@ -3314,6 +3314,10 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, if (reserved == 0) return 0; + /* nothing to shrink - nothing to reclaim */ + if (root->fs_info->delalloc_bytes == 0) + return 0; + max_reclaim = min(reserved, to_reclaim); while (loops < 1024) { diff --git a/trunk/fs/btrfs/inode.c b/trunk/fs/btrfs/inode.c index c15636b17874..5813dec5101c 100644 --- a/trunk/fs/btrfs/inode.c +++ b/trunk/fs/btrfs/inode.c @@ -3076,6 +3076,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, root, dir); BUG_ON(ret); + btrfs_free_path(path); return 0; } diff --git a/trunk/fs/btrfs/relocation.c b/trunk/fs/btrfs/relocation.c index 086b1e6b8614..f25b10a22a0a 100644 --- a/trunk/fs/btrfs/relocation.c +++ b/trunk/fs/btrfs/relocation.c @@ -1368,7 +1368,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, int ret; if (!root->reloc_root) - goto out; + return 0; reloc_root = root->reloc_root; root_item = &reloc_root->root_item; @@ -1390,8 +1390,6 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, ret = btrfs_update_root(trans, root->fs_info->tree_root, &reloc_root->root_key, root_item); BUG_ON(ret); - -out: return 0; } @@ -2144,11 +2142,10 @@ int prepare_to_merge(struct reloc_control *rc, int err) u64 num_bytes = 0; int ret; - mutex_lock(&root->fs_info->reloc_mutex); + spin_lock(&root->fs_info->trans_lock); rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; rc->merging_rsv_size += rc->nodes_relocated * 2; - mutex_unlock(&root->fs_info->reloc_mutex); - + spin_unlock(&root->fs_info->trans_lock); again: if (!err) { num_bytes = rc->merging_rsv_size; @@ -2217,16 +2214,9 @@ int merge_reloc_roots(struct reloc_control *rc) int ret; again: root = rc->extent_root; - - /* - * this serializes us with btrfs_record_root_in_transaction, - * we have to make sure nobody is in the middle of - * adding their roots to the list while we are - * doing this splice - */ - mutex_lock(&root->fs_info->reloc_mutex); + spin_lock(&root->fs_info->trans_lock); list_splice_init(&rc->reloc_roots, &reloc_roots); - mutex_unlock(&root->fs_info->reloc_mutex); + spin_unlock(&root->fs_info->trans_lock); while (!list_empty(&reloc_roots)) { found = 1; @@ -3600,19 +3590,17 @@ int find_next_extent(struct btrfs_trans_handle *trans, static void set_reloc_control(struct reloc_control *rc) { struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; - - mutex_lock(&fs_info->reloc_mutex); + spin_lock(&fs_info->trans_lock); fs_info->reloc_ctl = rc; - mutex_unlock(&fs_info->reloc_mutex); + spin_unlock(&fs_info->trans_lock); } static void unset_reloc_control(struct reloc_control *rc) { struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; - - mutex_lock(&fs_info->reloc_mutex); + spin_lock(&fs_info->trans_lock); fs_info->reloc_ctl = NULL; - mutex_unlock(&fs_info->reloc_mutex); + spin_unlock(&fs_info->trans_lock); } static int check_extent_flags(u64 flags) diff --git a/trunk/fs/btrfs/transaction.c b/trunk/fs/btrfs/transaction.c index 833996a0c628..2b3590b9fe98 100644 --- a/trunk/fs/btrfs/transaction.c +++ b/trunk/fs/btrfs/transaction.c @@ -126,85 +126,28 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail) * to make sure the old root from before we joined the transaction is deleted * when the transaction commits */ -static int record_root_in_trans(struct btrfs_trans_handle *trans, +int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, struct btrfs_root *root) { if (root->ref_cows && root->last_trans < trans->transid) { WARN_ON(root == root->fs_info->extent_root); WARN_ON(root->commit_root != root->node); - /* - * see below for in_trans_setup usage rules - * we have the reloc mutex held now, so there - * is only one writer in this function - */ - root->in_trans_setup = 1; - - /* make sure readers find in_trans_setup before - * they find our root->last_trans update - */ - smp_wmb(); - spin_lock(&root->fs_info->fs_roots_radix_lock); if (root->last_trans == trans->transid) { spin_unlock(&root->fs_info->fs_roots_radix_lock); return 0; } + root->last_trans = trans->transid; radix_tree_tag_set(&root->fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); spin_unlock(&root->fs_info->fs_roots_radix_lock); - root->last_trans = trans->transid; - - /* this is pretty tricky. We don't want to - * take the relocation lock in btrfs_record_root_in_trans - * unless we're really doing the first setup for this root in - * this transaction. - * - * Normally we'd use root->last_trans as a flag to decide - * if we want to take the expensive mutex. - * - * But, we have to set root->last_trans before we - * init the relocation root, otherwise, we trip over warnings - * in ctree.c. The solution used here is to flag ourselves - * with root->in_trans_setup. When this is 1, we're still - * fixing up the reloc trees and everyone must wait. - * - * When this is zero, they can trust root->last_trans and fly - * through btrfs_record_root_in_trans without having to take the - * lock. smp_wmb() makes sure that all the writes above are - * done before we pop in the zero below - */ btrfs_init_reloc_root(trans, root); - smp_wmb(); - root->in_trans_setup = 0; } return 0; } - -int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, - struct btrfs_root *root) -{ - if (!root->ref_cows) - return 0; - - /* - * see record_root_in_trans for comments about in_trans_setup usage - * and barriers - */ - smp_rmb(); - if (root->last_trans == trans->transid && - !root->in_trans_setup) - return 0; - - mutex_lock(&root->fs_info->reloc_mutex); - record_root_in_trans(trans, root); - mutex_unlock(&root->fs_info->reloc_mutex); - - return 0; -} - /* wait for commit against the current transaction to become unblocked * when this is done, it is safe to start a new transaction, but the current * transaction might not be fully on disk. @@ -939,7 +882,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, parent = dget_parent(dentry); parent_inode = parent->d_inode; parent_root = BTRFS_I(parent_inode)->root; - record_root_in_trans(trans, parent_root); + btrfs_record_root_in_trans(trans, parent_root); /* * insert the directory item @@ -957,7 +900,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ret = btrfs_update_inode(trans, parent_root, parent_inode); BUG_ON(ret); - record_root_in_trans(trans, root); + btrfs_record_root_in_trans(trans, root); btrfs_set_root_last_snapshot(&root->root_item, trans->transid); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); btrfs_check_and_init_root_item(new_root_item); @@ -1304,13 +1247,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, } while (atomic_read(&cur_trans->num_writers) > 1 || (should_grow && cur_trans->num_joined != joined)); - /* - * the reloc mutex makes sure that we stop - * the balancing code from coming in and moving - * extents around in the middle of the commit - */ - mutex_lock(&root->fs_info->reloc_mutex); - ret = create_pending_snapshots(trans, root->fs_info); BUG_ON(ret); @@ -1376,7 +1312,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, root->fs_info->running_transaction = NULL; root->fs_info->trans_no_join = 0; spin_unlock(&root->fs_info->trans_lock); - mutex_unlock(&root->fs_info->reloc_mutex); wake_up(&root->fs_info->transaction_wait);