aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2013-04-25 12:04:51 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:55:19 -0400
commit2f2320360b0c35b86938bfc561124474f0dac6e4 (patch)
treef7b1cbec89d9c6d030f15817e77ee42e5941244a /fs/btrfs/ioctl.c
parent46b665ceb1edd2ac149ff701313c115f52dc0348 (diff)
Btrfs: rescan for qgroups
If qgroup tracking is out of sync, a rescan operation can be started. It iterates the complete extent tree and recalculates all qgroup tracking data. This is an expensive operation and should not be used unless required. A filesystem under rescan can still be umounted. The rescan continues on the next mount. Status information is provided with a separate ioctl while a rescan operation is in progress. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c83
1 files changed, 69 insertions, 14 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index a74edc797531..f5f6af338b53 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3701,12 +3701,10 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
3701 } 3701 }
3702 3702
3703 down_write(&root->fs_info->subvol_sem); 3703 down_write(&root->fs_info->subvol_sem);
3704 if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) { 3704 trans = btrfs_start_transaction(root->fs_info->tree_root, 2);
3705 trans = btrfs_start_transaction(root->fs_info->tree_root, 2); 3705 if (IS_ERR(trans)) {
3706 if (IS_ERR(trans)) { 3706 ret = PTR_ERR(trans);
3707 ret = PTR_ERR(trans); 3707 goto out;
3708 goto out;
3709 }
3710 } 3708 }
3711 3709
3712 switch (sa->cmd) { 3710 switch (sa->cmd) {
@@ -3716,9 +3714,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
3716 case BTRFS_QUOTA_CTL_DISABLE: 3714 case BTRFS_QUOTA_CTL_DISABLE:
3717 ret = btrfs_quota_disable(trans, root->fs_info); 3715 ret = btrfs_quota_disable(trans, root->fs_info);
3718 break; 3716 break;
3719 case BTRFS_QUOTA_CTL_RESCAN:
3720 ret = btrfs_quota_rescan(root->fs_info);
3721 break;
3722 default: 3717 default:
3723 ret = -EINVAL; 3718 ret = -EINVAL;
3724 break; 3719 break;
@@ -3727,11 +3722,9 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
3727 if (copy_to_user(arg, sa, sizeof(*sa))) 3722 if (copy_to_user(arg, sa, sizeof(*sa)))
3728 ret = -EFAULT; 3723 ret = -EFAULT;
3729 3724
3730 if (trans) { 3725 err = btrfs_commit_transaction(trans, root->fs_info->tree_root);
3731 err = btrfs_commit_transaction(trans, root->fs_info->tree_root); 3726 if (err && !ret)
3732 if (err && !ret) 3727 ret = err;
3733 ret = err;
3734 }
3735out: 3728out:
3736 kfree(sa); 3729 kfree(sa);
3737 up_write(&root->fs_info->subvol_sem); 3730 up_write(&root->fs_info->subvol_sem);
@@ -3886,6 +3879,64 @@ drop_write:
3886 return ret; 3879 return ret;
3887} 3880}
3888 3881
3882static long btrfs_ioctl_quota_rescan(struct file *file, void __user *arg)
3883{
3884 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
3885 struct btrfs_ioctl_quota_rescan_args *qsa;
3886 int ret;
3887
3888 if (!capable(CAP_SYS_ADMIN))
3889 return -EPERM;
3890
3891 ret = mnt_want_write_file(file);
3892 if (ret)
3893 return ret;
3894
3895 qsa = memdup_user(arg, sizeof(*qsa));
3896 if (IS_ERR(qsa)) {
3897 ret = PTR_ERR(qsa);
3898 goto drop_write;
3899 }
3900
3901 if (qsa->flags) {
3902 ret = -EINVAL;
3903 goto out;
3904 }
3905
3906 ret = btrfs_qgroup_rescan(root->fs_info);
3907
3908out:
3909 kfree(qsa);
3910drop_write:
3911 mnt_drop_write_file(file);
3912 return ret;
3913}
3914
3915static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg)
3916{
3917 struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
3918 struct btrfs_ioctl_quota_rescan_args *qsa;
3919 int ret = 0;
3920
3921 if (!capable(CAP_SYS_ADMIN))
3922 return -EPERM;
3923
3924 qsa = kzalloc(sizeof(*qsa), GFP_NOFS);
3925 if (!qsa)
3926 return -ENOMEM;
3927
3928 if (root->fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
3929 qsa->flags = 1;
3930 qsa->progress = root->fs_info->qgroup_rescan_progress.objectid;
3931 }
3932
3933 if (copy_to_user(arg, qsa, sizeof(*qsa)))
3934 ret = -EFAULT;
3935
3936 kfree(qsa);
3937 return ret;
3938}
3939
3889static long btrfs_ioctl_set_received_subvol(struct file *file, 3940static long btrfs_ioctl_set_received_subvol(struct file *file,
3890 void __user *arg) 3941 void __user *arg)
3891{ 3942{
@@ -4124,6 +4175,10 @@ long btrfs_ioctl(struct file *file, unsigned int
4124 return btrfs_ioctl_qgroup_create(file, argp); 4175 return btrfs_ioctl_qgroup_create(file, argp);
4125 case BTRFS_IOC_QGROUP_LIMIT: 4176 case BTRFS_IOC_QGROUP_LIMIT:
4126 return btrfs_ioctl_qgroup_limit(file, argp); 4177 return btrfs_ioctl_qgroup_limit(file, argp);
4178 case BTRFS_IOC_QUOTA_RESCAN:
4179 return btrfs_ioctl_quota_rescan(file, argp);
4180 case BTRFS_IOC_QUOTA_RESCAN_STATUS:
4181 return btrfs_ioctl_quota_rescan_status(file, argp);
4127 case BTRFS_IOC_DEV_REPLACE: 4182 case BTRFS_IOC_DEV_REPLACE:
4128 return btrfs_ioctl_dev_replace(root, argp); 4183 return btrfs_ioctl_dev_replace(root, argp);
4129 case BTRFS_IOC_GET_FSLABEL: 4184 case BTRFS_IOC_GET_FSLABEL: