aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorArne Jansen <sensille@gmx.net>2011-09-14 09:53:51 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-07-12 04:54:39 -0400
commit5d13a37bd5327220e13329943d1228acfbe5934a (patch)
tree4d50268f569454798adb46d1e1984c0e53d5ba26 /fs/btrfs
parentc556723794b3487a79de1ecd6354975b1389f5ff (diff)
Btrfs: add qgroup ioctls
Ioctls to control the qgroup feature like adding and removing qgroups and assigning qgroups. Signed-off-by: Arne Jansen <sensille@gmx.net>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ioctl.c185
-rw-r--r--fs/btrfs/ioctl.h27
2 files changed, 212 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0e92e5763005..55a7283a9e18 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3390,6 +3390,183 @@ out:
3390 return ret; 3390 return ret;
3391} 3391}
3392 3392
3393static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg)
3394{
3395 struct btrfs_ioctl_quota_ctl_args *sa;
3396 struct btrfs_trans_handle *trans = NULL;
3397 int ret;
3398 int err;
3399
3400 if (!capable(CAP_SYS_ADMIN))
3401 return -EPERM;
3402
3403 if (root->fs_info->sb->s_flags & MS_RDONLY)
3404 return -EROFS;
3405
3406 sa = memdup_user(arg, sizeof(*sa));
3407 if (IS_ERR(sa))
3408 return PTR_ERR(sa);
3409
3410 if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) {
3411 trans = btrfs_start_transaction(root, 2);
3412 if (IS_ERR(trans)) {
3413 ret = PTR_ERR(trans);
3414 goto out;
3415 }
3416 }
3417
3418 switch (sa->cmd) {
3419 case BTRFS_QUOTA_CTL_ENABLE:
3420 ret = btrfs_quota_enable(trans, root->fs_info);
3421 break;
3422 case BTRFS_QUOTA_CTL_DISABLE:
3423 ret = btrfs_quota_disable(trans, root->fs_info);
3424 break;
3425 case BTRFS_QUOTA_CTL_RESCAN:
3426 ret = btrfs_quota_rescan(root->fs_info);
3427 break;
3428 default:
3429 ret = -EINVAL;
3430 break;
3431 }
3432
3433 if (copy_to_user(arg, sa, sizeof(*sa)))
3434 ret = -EFAULT;
3435
3436 if (trans) {
3437 err = btrfs_commit_transaction(trans, root);
3438 if (err && !ret)
3439 ret = err;
3440 }
3441
3442out:
3443 kfree(sa);
3444 return ret;
3445}
3446
3447static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg)
3448{
3449 struct btrfs_ioctl_qgroup_assign_args *sa;
3450 struct btrfs_trans_handle *trans;
3451 int ret;
3452 int err;
3453
3454 if (!capable(CAP_SYS_ADMIN))
3455 return -EPERM;
3456
3457 if (root->fs_info->sb->s_flags & MS_RDONLY)
3458 return -EROFS;
3459
3460 sa = memdup_user(arg, sizeof(*sa));
3461 if (IS_ERR(sa))
3462 return PTR_ERR(sa);
3463
3464 trans = btrfs_join_transaction(root);
3465 if (IS_ERR(trans)) {
3466 ret = PTR_ERR(trans);
3467 goto out;
3468 }
3469
3470 /* FIXME: check if the IDs really exist */
3471 if (sa->assign) {
3472 ret = btrfs_add_qgroup_relation(trans, root->fs_info,
3473 sa->src, sa->dst);
3474 } else {
3475 ret = btrfs_del_qgroup_relation(trans, root->fs_info,
3476 sa->src, sa->dst);
3477 }
3478
3479 err = btrfs_end_transaction(trans, root);
3480 if (err && !ret)
3481 ret = err;
3482
3483out:
3484 kfree(sa);
3485 return ret;
3486}
3487
3488static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg)
3489{
3490 struct btrfs_ioctl_qgroup_create_args *sa;
3491 struct btrfs_trans_handle *trans;
3492 int ret;
3493 int err;
3494
3495 if (!capable(CAP_SYS_ADMIN))
3496 return -EPERM;
3497
3498 if (root->fs_info->sb->s_flags & MS_RDONLY)
3499 return -EROFS;
3500
3501 sa = memdup_user(arg, sizeof(*sa));
3502 if (IS_ERR(sa))
3503 return PTR_ERR(sa);
3504
3505 trans = btrfs_join_transaction(root);
3506 if (IS_ERR(trans)) {
3507 ret = PTR_ERR(trans);
3508 goto out;
3509 }
3510
3511 /* FIXME: check if the IDs really exist */
3512 if (sa->create) {
3513 ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid,
3514 NULL);
3515 } else {
3516 ret = btrfs_remove_qgroup(trans, root->fs_info, sa->qgroupid);
3517 }
3518
3519 err = btrfs_end_transaction(trans, root);
3520 if (err && !ret)
3521 ret = err;
3522
3523out:
3524 kfree(sa);
3525 return ret;
3526}
3527
3528static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg)
3529{
3530 struct btrfs_ioctl_qgroup_limit_args *sa;
3531 struct btrfs_trans_handle *trans;
3532 int ret;
3533 int err;
3534 u64 qgroupid;
3535
3536 if (!capable(CAP_SYS_ADMIN))
3537 return -EPERM;
3538
3539 if (root->fs_info->sb->s_flags & MS_RDONLY)
3540 return -EROFS;
3541
3542 sa = memdup_user(arg, sizeof(*sa));
3543 if (IS_ERR(sa))
3544 return PTR_ERR(sa);
3545
3546 trans = btrfs_join_transaction(root);
3547 if (IS_ERR(trans)) {
3548 ret = PTR_ERR(trans);
3549 goto out;
3550 }
3551
3552 qgroupid = sa->qgroupid;
3553 if (!qgroupid) {
3554 /* take the current subvol as qgroup */
3555 qgroupid = root->root_key.objectid;
3556 }
3557
3558 /* FIXME: check if the IDs really exist */
3559 ret = btrfs_limit_qgroup(trans, root->fs_info, qgroupid, &sa->lim);
3560
3561 err = btrfs_end_transaction(trans, root);
3562 if (err && !ret)
3563 ret = err;
3564
3565out:
3566 kfree(sa);
3567 return ret;
3568}
3569
3393long btrfs_ioctl(struct file *file, unsigned int 3570long btrfs_ioctl(struct file *file, unsigned int
3394 cmd, unsigned long arg) 3571 cmd, unsigned long arg)
3395{ 3572{
@@ -3476,6 +3653,14 @@ long btrfs_ioctl(struct file *file, unsigned int
3476 return btrfs_ioctl_get_dev_stats(root, argp, 0); 3653 return btrfs_ioctl_get_dev_stats(root, argp, 0);
3477 case BTRFS_IOC_GET_AND_RESET_DEV_STATS: 3654 case BTRFS_IOC_GET_AND_RESET_DEV_STATS:
3478 return btrfs_ioctl_get_dev_stats(root, argp, 1); 3655 return btrfs_ioctl_get_dev_stats(root, argp, 1);
3656 case BTRFS_IOC_QUOTA_CTL:
3657 return btrfs_ioctl_quota_ctl(root, argp);
3658 case BTRFS_IOC_QGROUP_ASSIGN:
3659 return btrfs_ioctl_qgroup_assign(root, argp);
3660 case BTRFS_IOC_QGROUP_CREATE:
3661 return btrfs_ioctl_qgroup_create(root, argp);
3662 case BTRFS_IOC_QGROUP_LIMIT:
3663 return btrfs_ioctl_qgroup_limit(root, argp);
3479 } 3664 }
3480 3665
3481 return -ENOTTY; 3666 return -ENOTTY;
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index a8a2230f4c5c..9dd50c4656b3 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -319,6 +319,25 @@ struct btrfs_ioctl_get_dev_stats {
319 __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */ 319 __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
320}; 320};
321 321
322#define BTRFS_QUOTA_CTL_ENABLE 1
323#define BTRFS_QUOTA_CTL_DISABLE 2
324#define BTRFS_QUOTA_CTL_RESCAN 3
325struct btrfs_ioctl_quota_ctl_args {
326 __u64 cmd;
327 __u64 status;
328};
329
330struct btrfs_ioctl_qgroup_assign_args {
331 __u64 assign;
332 __u64 src;
333 __u64 dst;
334};
335
336struct btrfs_ioctl_qgroup_create_args {
337 __u64 create;
338 __u64 qgroupid;
339};
340
322#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ 341#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
323 struct btrfs_ioctl_vol_args) 342 struct btrfs_ioctl_vol_args)
324#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ 343#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -388,4 +407,12 @@ struct btrfs_ioctl_get_dev_stats {
388#define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \ 407#define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \
389 struct btrfs_ioctl_get_dev_stats) 408 struct btrfs_ioctl_get_dev_stats)
390 409
410#define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \
411 struct btrfs_ioctl_quota_ctl_args)
412#define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \
413 struct btrfs_ioctl_qgroup_assign_args)
414#define BTRFS_IOC_QGROUP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 42, \
415 struct btrfs_ioctl_qgroup_create_args)
416#define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \
417 struct btrfs_ioctl_qgroup_limit_args)
391#endif 418#endif