diff options
author | Arne Jansen <sensille@gmx.net> | 2011-09-14 09:53:51 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-07-12 04:54:39 -0400 |
commit | 5d13a37bd5327220e13329943d1228acfbe5934a (patch) | |
tree | 4d50268f569454798adb46d1e1984c0e53d5ba26 /fs/btrfs | |
parent | c556723794b3487a79de1ecd6354975b1389f5ff (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.c | 185 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 27 |
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 | ||
3393 | static 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 | |||
3442 | out: | ||
3443 | kfree(sa); | ||
3444 | return ret; | ||
3445 | } | ||
3446 | |||
3447 | static 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 | |||
3483 | out: | ||
3484 | kfree(sa); | ||
3485 | return ret; | ||
3486 | } | ||
3487 | |||
3488 | static 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 | |||
3523 | out: | ||
3524 | kfree(sa); | ||
3525 | return ret; | ||
3526 | } | ||
3527 | |||
3528 | static 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 | |||
3565 | out: | ||
3566 | kfree(sa); | ||
3567 | return ret; | ||
3568 | } | ||
3569 | |||
3393 | long btrfs_ioctl(struct file *file, unsigned int | 3570 | long 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 | ||
325 | struct btrfs_ioctl_quota_ctl_args { | ||
326 | __u64 cmd; | ||
327 | __u64 status; | ||
328 | }; | ||
329 | |||
330 | struct btrfs_ioctl_qgroup_assign_args { | ||
331 | __u64 assign; | ||
332 | __u64 src; | ||
333 | __u64 dst; | ||
334 | }; | ||
335 | |||
336 | struct 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 |