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;
 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,
 
        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)
 {
                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:
 
        } else {
                pr_err("btrfs: qgroup scan failed with %d\n", err);
        }
+
+       complete_all(&fs_info->qgroup_rescan_completion);
 }
 
 static void
        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)) {
 
        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;
+}
 
                               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, \