aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/relocation.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-04-11 17:25:13 -0400
committerJosef Bacik <josef@redhat.com>2011-05-23 13:00:57 -0400
commita4abeea41adfa3c143c289045f4625dfaeba2212 (patch)
tree792e2a398d8ba77447ba3f9f2c4266a1ce2f611c /fs/btrfs/relocation.c
parent2a1eb4614d984d5cd4c928784e9afcf5c07f93be (diff)
Btrfs: kill trans_mutex
We use trans_mutex for lots of things, here's a basic list 1) To serialize trans_handles joining the currently running transaction 2) To make sure that no new trans handles are started while we are committing 3) To protect the dead_roots list and the transaction lists Really the serializing trans_handles joining is not too hard, and can really get bogged down in acquiring a reference to the transaction. So replace the trans_mutex with a trans_lock spinlock and use it to do the following 1) Protect fs_info->running_transaction. All trans handles have to do is check this, and then take a reference of the transaction and keep on going. 2) Protect the fs_info->trans_list. This doesn't get used too much, basically it just holds the current transactions, which will usually just be the currently committing transaction and the currently running transaction at most. 3) Protect the dead roots list. This is only ever processed by splicing the list so this is relatively simple. 4) Protect the fs_info->reloc_ctl stuff. This is very lightweight and was using the trans_mutex before, so this is a pretty straightforward change. 5) Protect fs_info->no_trans_join. Because we don't hold the trans_lock over the entirety of the commit we need to have a way to block new people from creating a new transaction while we're doing our work. So we set no_trans_join and in join_transaction we test to see if that is set, and if it is we do a wait_on_commit. 6) Make the transaction use count atomic so we don't need to take locks to modify it when we're dropping references. 7) Add a commit_lock to the transaction to make sure multiple people trying to commit the same transaction don't race and commit at the same time. 8) Make open_ioctl_trans an atomic so we don't have to take any locks for ioctl trans. I have tested this with xfstests, but obviously it is a pretty hairy change so lots of testing is greatly appreciated. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r--fs/btrfs/relocation.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 8bb256667f2d..09c30d37d43e 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2136,10 +2136,10 @@ int prepare_to_merge(struct reloc_control *rc, int err)
2136 u64 num_bytes = 0; 2136 u64 num_bytes = 0;
2137 int ret; 2137 int ret;
2138 2138
2139 mutex_lock(&root->fs_info->trans_mutex); 2139 spin_lock(&root->fs_info->trans_lock);
2140 rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; 2140 rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2;
2141 rc->merging_rsv_size += rc->nodes_relocated * 2; 2141 rc->merging_rsv_size += rc->nodes_relocated * 2;
2142 mutex_unlock(&root->fs_info->trans_mutex); 2142 spin_unlock(&root->fs_info->trans_lock);
2143again: 2143again:
2144 if (!err) { 2144 if (!err) {
2145 num_bytes = rc->merging_rsv_size; 2145 num_bytes = rc->merging_rsv_size;
@@ -2208,9 +2208,9 @@ int merge_reloc_roots(struct reloc_control *rc)
2208 int ret; 2208 int ret;
2209again: 2209again:
2210 root = rc->extent_root; 2210 root = rc->extent_root;
2211 mutex_lock(&root->fs_info->trans_mutex); 2211 spin_lock(&root->fs_info->trans_lock);
2212 list_splice_init(&rc->reloc_roots, &reloc_roots); 2212 list_splice_init(&rc->reloc_roots, &reloc_roots);
2213 mutex_unlock(&root->fs_info->trans_mutex); 2213 spin_unlock(&root->fs_info->trans_lock);
2214 2214
2215 while (!list_empty(&reloc_roots)) { 2215 while (!list_empty(&reloc_roots)) {
2216 found = 1; 2216 found = 1;
@@ -3583,17 +3583,17 @@ next:
3583static void set_reloc_control(struct reloc_control *rc) 3583static void set_reloc_control(struct reloc_control *rc)
3584{ 3584{
3585 struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 3585 struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
3586 mutex_lock(&fs_info->trans_mutex); 3586 spin_lock(&fs_info->trans_lock);
3587 fs_info->reloc_ctl = rc; 3587 fs_info->reloc_ctl = rc;
3588 mutex_unlock(&fs_info->trans_mutex); 3588 spin_unlock(&fs_info->trans_lock);
3589} 3589}
3590 3590
3591static void unset_reloc_control(struct reloc_control *rc) 3591static void unset_reloc_control(struct reloc_control *rc)
3592{ 3592{
3593 struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; 3593 struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
3594 mutex_lock(&fs_info->trans_mutex); 3594 spin_lock(&fs_info->trans_lock);
3595 fs_info->reloc_ctl = NULL; 3595 fs_info->reloc_ctl = NULL;
3596 mutex_unlock(&fs_info->trans_mutex); 3596 spin_unlock(&fs_info->trans_lock);
3597} 3597}
3598 3598
3599static int check_extent_flags(u64 flags) 3599static int check_extent_flags(u64 flags)