aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.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/ioctl.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/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 908c3d4b48c6..a578620e06a8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2177,9 +2177,7 @@ static long btrfs_ioctl_trans_start(struct file *file)
2177 if (ret) 2177 if (ret)
2178 goto out; 2178 goto out;
2179 2179
2180 mutex_lock(&root->fs_info->trans_mutex); 2180 atomic_inc(&root->fs_info->open_ioctl_trans);
2181 root->fs_info->open_ioctl_trans++;
2182 mutex_unlock(&root->fs_info->trans_mutex);
2183 2181
2184 ret = -ENOMEM; 2182 ret = -ENOMEM;
2185 trans = btrfs_start_ioctl_transaction(root); 2183 trans = btrfs_start_ioctl_transaction(root);
@@ -2190,9 +2188,7 @@ static long btrfs_ioctl_trans_start(struct file *file)
2190 return 0; 2188 return 0;
2191 2189
2192out_drop: 2190out_drop:
2193 mutex_lock(&root->fs_info->trans_mutex); 2191 atomic_dec(&root->fs_info->open_ioctl_trans);
2194 root->fs_info->open_ioctl_trans--;
2195 mutex_unlock(&root->fs_info->trans_mutex);
2196 mnt_drop_write(file->f_path.mnt); 2192 mnt_drop_write(file->f_path.mnt);
2197out: 2193out:
2198 return ret; 2194 return ret;
@@ -2426,9 +2422,7 @@ long btrfs_ioctl_trans_end(struct file *file)
2426 2422
2427 btrfs_end_transaction(trans, root); 2423 btrfs_end_transaction(trans, root);
2428 2424
2429 mutex_lock(&root->fs_info->trans_mutex); 2425 atomic_dec(&root->fs_info->open_ioctl_trans);
2430 root->fs_info->open_ioctl_trans--;
2431 mutex_unlock(&root->fs_info->trans_mutex);
2432 2426
2433 mnt_drop_write(file->f_path.mnt); 2427 mnt_drop_write(file->f_path.mnt);
2434 return 0; 2428 return 0;