Btrfs: add ioctl to wait for qgroup rescan completion
authorJan Schmidt <list.btrfs@jan-o-sch.net>
Mon, 6 May 2013 19:14:17 +0000 (19:14 +0000)
committerJosef Bacik <jbacik@fusionio.com>
Fri, 14 Jun 2013 15:29:22 +0000 (11:29 -0400)
btrfs_qgroup_wait_for_completion waits until the currently running qgroup
operation completes. It returns immediately when no rescan process is in
progress. This is useful to automate things around the rescan process (e.g.
testing).

Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
fs/btrfs/ctree.h
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
include/uapi/linux/btrfs.h

index a365400e38da708c36c741a969df5a6e146edff8..e36e97b473a841555fa1712ab8dad75e0e7efbd4 100644 (file)
@@ -1613,6 +1613,7 @@ struct btrfs_fs_info {
        struct mutex qgroup_rescan_lock; /* protects the progress item */
        struct btrfs_key qgroup_rescan_progress;
        struct btrfs_workers qgroup_rescan_workers;
+       struct completion qgroup_rescan_completion;
 
        /* filesystem state */
        unsigned long fs_state;
@@ -3820,6 +3821,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
 int btrfs_quota_disable(struct btrfs_trans_handle *trans,
                        struct btrfs_fs_info *fs_info);
 int btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info);
+int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info);
 int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
                              struct btrfs_fs_info *fs_info, u64 src, u64 dst);
 int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
index 0f81d67cdc8da651890df1a89c01df9188667d97..1e0dda1feefe1cab3be452f06ea579dd449c3bfd 100644 (file)
@@ -3937,6 +3937,16 @@ static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg)
        return ret;
 }
 
+static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg)
+{
+       struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       return btrfs_qgroup_wait_for_completion(root->fs_info);
+}
+
 static long btrfs_ioctl_set_received_subvol(struct file *file,
                                            void __user *arg)
 {
@@ -4179,6 +4189,8 @@ long btrfs_ioctl(struct file *file, unsigned int
                return btrfs_ioctl_quota_rescan(file, argp);
        case BTRFS_IOC_QUOTA_RESCAN_STATUS:
                return btrfs_ioctl_quota_rescan_status(file, argp);
+       case BTRFS_IOC_QUOTA_RESCAN_WAIT:
+               return btrfs_ioctl_quota_rescan_wait(file, argp);
        case BTRFS_IOC_DEV_REPLACE:
                return btrfs_ioctl_dev_replace(root, argp);
        case BTRFS_IOC_GET_FSLABEL:
index 7f38cce2528d73fb3214fb47329373f217129d73..d059d86c31312d3c170850a7ed9dafb2e715d2c2 100644 (file)
@@ -2070,6 +2070,8 @@ out:
        } else {
                pr_err("btrfs: qgroup scan failed with %d\n", err);
        }
+
+       complete_all(&fs_info->qgroup_rescan_completion);
 }
 
 static void
@@ -2110,6 +2112,7 @@ btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info)
        fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN;
        memset(&fs_info->qgroup_rescan_progress, 0,
                sizeof(fs_info->qgroup_rescan_progress));
+       init_completion(&fs_info->qgroup_rescan_completion);
 
        /* clear all current qgroup tracking information */
        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)
 
        return 0;
 }
+
+int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info)
+{
+       int running;
+       int ret = 0;
+
+       mutex_lock(&fs_info->qgroup_rescan_lock);
+       spin_lock(&fs_info->qgroup_lock);
+       running = fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN;
+       spin_unlock(&fs_info->qgroup_lock);
+       mutex_unlock(&fs_info->qgroup_rescan_lock);
+
+       if (running)
+               ret = wait_for_completion_interruptible(
+                                       &fs_info->qgroup_rescan_completion);
+
+       return ret;
+}
index 5ef0df545a2a17f137ad0d75d13e11f46a967cee..5b683b5f63cd3b5c5931e69b05d0bed989bd4507 100644 (file)
@@ -530,6 +530,7 @@ struct btrfs_ioctl_send_args {
                               struct btrfs_ioctl_quota_rescan_args)
 #define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \
                               struct btrfs_ioctl_quota_rescan_args)
+#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
 #define BTRFS_IOC_GET_FSLABEL _IOR(BTRFS_IOCTL_MAGIC, 49, \
                                   char[BTRFS_LABEL_SIZE])
 #define BTRFS_IOC_SET_FSLABEL _IOW(BTRFS_IOCTL_MAGIC, 50, \