diff options
Diffstat (limited to 'fs/btrfs')
| -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, |
