diff options
-rw-r--r-- | fs/btrfs/ioctl.c | 34 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 52 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 1 |
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 | ||
2031 | static 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 | |||
2047 | static 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 | |||
2031 | long btrfs_ioctl(struct file *file, unsigned int | 2061 | long 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 | ||
282 | int 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; | ||
329 | out_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); |
98 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, | 98 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, |
99 | int num_blocks); | 99 | int num_blocks); |
100 | int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid); | ||
100 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 101 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
101 | struct btrfs_root *root); | 102 | struct btrfs_root *root); |
102 | int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, | 103 | int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, |