aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/ioctl.c12
-rw-r--r--fs/btrfs/qgroup.c21
-rw-r--r--include/uapi/linux/btrfs.h1
4 files changed, 36 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index a365400e38da..e36e97b473a8 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1613,6 +1613,7 @@ struct btrfs_fs_info {
1613 struct mutex qgroup_rescan_lock; /* protects the progress item */ 1613 struct mutex qgroup_rescan_lock; /* protects the progress item */
1614 struct btrfs_key qgroup_rescan_progress; 1614 struct btrfs_key qgroup_rescan_progress;
1615 struct btrfs_workers qgroup_rescan_workers; 1615 struct btrfs_workers qgroup_rescan_workers;
1616 struct completion qgroup_rescan_completion;
1616 1617
1617 /* filesystem state */ 1618 /* filesystem state */
1618 unsigned long fs_state; 1619 unsigned long fs_state;
@@ -3820,6 +3821,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
3820int btrfs_quota_disable(struct btrfs_trans_handle *trans, 3821int btrfs_quota_disable(struct btrfs_trans_handle *trans,
3821 struct btrfs_fs_info *fs_info); 3822 struct btrfs_fs_info *fs_info);
3822int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info); 3823int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
3824int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info);
3823int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, 3825int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
3824 struct btrfs_fs_info *fs_info, u64 src, u64 dst); 3826 struct btrfs_fs_info *fs_info, u64 src, u64 dst);
3825int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, 3827int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0f81d67cdc8d..1e0dda1feefe 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3937,6 +3937,16 @@ static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg)
3937 return ret; 3937 return ret;
3938} 3938}
3939 3939
3940static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg)
3941{
3942 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
3943
3944 if (!capable(CAP_SYS_ADMIN))
3945 return -EPERM;
3946
3947 return btrfs_qgroup_wait_for_completion(root->fs_info);
3948}
3949
3940static long btrfs_ioctl_set_received_subvol(struct file *file, 3950static long btrfs_ioctl_set_received_subvol(struct file *file,
3941 void __user *arg) 3951 void __user *arg)
3942{ 3952{
@@ -4179,6 +4189,8 @@ long btrfs_ioctl(struct file *file, unsigned int
4179 return btrfs_ioctl_quota_rescan(file, argp); 4189 return btrfs_ioctl_quota_rescan(file, argp);
4180 case BTRFS_IOC_QUOTA_RESCAN_STATUS: 4190 case BTRFS_IOC_QUOTA_RESCAN_STATUS:
4181 return btrfs_ioctl_quota_rescan_status(file, argp); 4191 return btrfs_ioctl_quota_rescan_status(file, argp);
4192 case BTRFS_IOC_QUOTA_RESCAN_WAIT:
4193 return btrfs_ioctl_quota_rescan_wait(file, argp);
4182 case BTRFS_IOC_DEV_REPLACE: 4194 case BTRFS_IOC_DEV_REPLACE:
4183 return btrfs_ioctl_dev_replace(root, argp); 4195 return btrfs_ioctl_dev_replace(root, argp);
4184 case BTRFS_IOC_GET_FSLABEL: 4196 case BTRFS_IOC_GET_FSLABEL:
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 7f38cce2528d..d059d86c3131 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -2070,6 +2070,8 @@ out:
2070 } else { 2070 } else {
2071 pr_err("btrfs: qgroup scan failed with %d\n", err); 2071 pr_err("btrfs: qgroup scan failed with %d\n", err);
2072 } 2072 }
2073
2074 complete_all(&fs_info->qgroup_rescan_completion);
2073} 2075}
2074 2076
2075static void 2077static void
@@ -2110,6 +2112,7 @@ btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info)
2110 fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN; 2112 fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN;
2111 memset(&fs_info->qgroup_rescan_progress, 0, 2113 memset(&fs_info->qgroup_rescan_progress, 0,
2112 sizeof(fs_info->qgroup_rescan_progress)); 2114 sizeof(fs_info->qgroup_rescan_progress));
2115 init_completion(&fs_info->qgroup_rescan_completion);
2113 2116
2114 /* clear all current qgroup tracking information */ 2117 /* clear all current qgroup tracking information */
2115 for (n = rb_first(&fs_info->qgroup_tree); n; n = rb_next(n)) { 2118 for (n = rb_first(&fs_info->qgroup_tree); n; n = rb_next(n)) {
@@ -2126,3 +2129,21 @@ btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info)
2126 2129
2127 return 0; 2130 return 0;
2128} 2131}
2132
2133int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info)
2134{
2135 int running;
2136 int ret = 0;
2137
2138 mutex_lock(&fs_info->qgroup_rescan_lock);
2139 spin_lock(&fs_info->qgroup_lock);
2140 running = fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN;
2141 spin_unlock(&fs_info->qgroup_lock);
2142 mutex_unlock(&fs_info->qgroup_rescan_lock);
2143
2144 if (running)
2145 ret = wait_for_completion_interruptible(
2146 &fs_info->qgroup_rescan_completion);
2147
2148 return ret;
2149}
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index 5ef0df545a2a..5b683b5f63cd 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -530,6 +530,7 @@ struct btrfs_ioctl_send_args {
530 struct btrfs_ioctl_quota_rescan_args) 530 struct btrfs_ioctl_quota_rescan_args)
531#define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \ 531#define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \
532 struct btrfs_ioctl_quota_rescan_args) 532 struct btrfs_ioctl_quota_rescan_args)
533#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
533#define BTRFS_IOC_GET_FSLABEL _IOR(BTRFS_IOCTL_MAGIC, 49, \ 534#define BTRFS_IOC_GET_FSLABEL _IOR(BTRFS_IOCTL_MAGIC, 49, \
534 char[BTRFS_LABEL_SIZE]) 535 char[BTRFS_LABEL_SIZE])
535#define BTRFS_IOC_SET_FSLABEL _IOW(BTRFS_IOCTL_MAGIC, 50, \ 536#define BTRFS_IOC_SET_FSLABEL _IOW(BTRFS_IOCTL_MAGIC, 50, \