aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ioctl.c34
-rw-r--r--fs/btrfs/ioctl.h2
-rw-r--r--fs/btrfs/transaction.c52
-rw-r--r--fs/btrfs/transaction.h1
4 files changed, 89 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 93d69b32028e..dc5a19ed07f3 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2028,6 +2028,36 @@ long btrfs_ioctl_trans_end(struct file *file)
2028 return 0; 2028 return 0;
2029} 2029}
2030 2030
2031static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp)
2032{
2033 struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;
2034 struct btrfs_trans_handle *trans;
2035 u64 transid;
2036
2037 trans = btrfs_start_transaction(root, 0);
2038 transid = trans->transid;
2039 btrfs_commit_transaction_async(trans, root, 0);
2040
2041 if (argp)
2042 if (copy_to_user(argp, &transid, sizeof(transid)))
2043 return -EFAULT;
2044 return 0;
2045}
2046
2047static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp)
2048{
2049 struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;
2050 u64 transid;
2051
2052 if (argp) {
2053 if (copy_from_user(&transid, argp, sizeof(transid)))
2054 return -EFAULT;
2055 } else {
2056 transid = 0; /* current trans */
2057 }
2058 return btrfs_wait_for_commit(root, transid);
2059}
2060
2031long btrfs_ioctl(struct file *file, unsigned int 2061long btrfs_ioctl(struct file *file, unsigned int
2032 cmd, unsigned long arg) 2062 cmd, unsigned long arg)
2033{ 2063{
@@ -2078,6 +2108,10 @@ long btrfs_ioctl(struct file *file, unsigned int
2078 case BTRFS_IOC_SYNC: 2108 case BTRFS_IOC_SYNC:
2079 btrfs_sync_fs(file->f_dentry->d_sb, 1); 2109 btrfs_sync_fs(file->f_dentry->d_sb, 1);
2080 return 0; 2110 return 0;
2111 case BTRFS_IOC_START_SYNC:
2112 return btrfs_ioctl_start_sync(file, argp);
2113 case BTRFS_IOC_WAIT_SYNC:
2114 return btrfs_ioctl_wait_sync(file, argp);
2081 } 2115 }
2082 2116
2083 return -ENOTTY; 2117 return -ENOTTY;
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index 424694aa517f..16e1442523b7 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -178,4 +178,6 @@ struct btrfs_ioctl_space_args {
178#define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64) 178#define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64)
179#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ 179#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \
180 struct btrfs_ioctl_space_args) 180 struct btrfs_ioctl_space_args)
181#define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
182#define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
181#endif 183#endif
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 9f40bfc9c45c..1fffbc017bdf 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -279,6 +279,58 @@ static noinline int wait_for_commit(struct btrfs_root *root,
279 return 0; 279 return 0;
280} 280}
281 281
282int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
283{
284 struct btrfs_transaction *cur_trans = NULL, *t;
285 int ret;
286
287 mutex_lock(&root->fs_info->trans_mutex);
288
289 ret = 0;
290 if (transid) {
291 if (transid <= root->fs_info->last_trans_committed)
292 goto out_unlock;
293
294 /* find specified transaction */
295 list_for_each_entry(t, &root->fs_info->trans_list, list) {
296 if (t->transid == transid) {
297 cur_trans = t;
298 break;
299 }
300 if (t->transid > transid)
301 break;
302 }
303 ret = -EINVAL;
304 if (!cur_trans)
305 goto out_unlock; /* bad transid */
306 } else {
307 /* find newest transaction that is committing | committed */
308 list_for_each_entry_reverse(t, &root->fs_info->trans_list,
309 list) {
310 if (t->in_commit) {
311 if (t->commit_done)
312 goto out_unlock;
313 cur_trans = t;
314 break;
315 }
316 }
317 if (!cur_trans)
318 goto out_unlock; /* nothing committing|committed */
319 }
320
321 cur_trans->use_count++;
322 mutex_unlock(&root->fs_info->trans_mutex);
323
324 wait_for_commit(root, cur_trans);
325
326 mutex_lock(&root->fs_info->trans_mutex);
327 put_transaction(cur_trans);
328 ret = 0;
329out_unlock:
330 mutex_unlock(&root->fs_info->trans_mutex);
331 return ret;
332}
333
282#if 0 334#if 0
283/* 335/*
284 * rate limit against the drop_snapshot code. This helps to slow down new 336 * rate limit against the drop_snapshot code. This helps to slow down new
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index e1908e6872fe..f104b57ad4ef 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -97,6 +97,7 @@ struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root
97 int num_blocks); 97 int num_blocks);
98struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, 98struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r,
99 int num_blocks); 99 int num_blocks);
100int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid);
100int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, 101int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
101 struct btrfs_root *root); 102 struct btrfs_root *root);
102int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, 103int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,