From: Fan Chengniang <fancn.f...@cn.fujitsu.com> add -r and -e options to enable setting max reference size and max exclusive on creating new subvolumes.
Signed-off-by: Fan Chengniang <fancn.f...@cn.fujitsu.com> --- Documentation/btrfs-subvolume.txt | 8 +++- cmds-qgroup.c | 42 ------------------ cmds-subvolume.c | 57 +++++++++++++++++++++++- ioctl.h | 3 ++ qgroup.c | 92 +++++++++++++++++++++++++++++++++++++++ qgroup.h | 3 ++ 6 files changed, 160 insertions(+), 45 deletions(-) diff --git a/Documentation/btrfs-subvolume.txt b/Documentation/btrfs-subvolume.txt index b0ae030..fe13943 100644 --- a/Documentation/btrfs-subvolume.txt +++ b/Documentation/btrfs-subvolume.txt @@ -43,7 +43,7 @@ from normal directories. SUBCOMMAND ----------- -*create* [-i <qgroupid>] [<dest>]<name>:: +*create* [-i <qgroupid>] [-r <max_rfer>] [-e <max_excl>] [<dest>]<name>:: Create a subvolume <name> in <dest>. + If <dest> is not given, subvolume <name> will be created in the currently @@ -54,6 +54,12 @@ directory. -i <qgroupid>:::: Add the newly created subvolume to a qgroup. This option can be given multiple times. ++ +-r <max_rfer>:::: +set the newly created subvolume's max reference size ++ +-e <max_excl>:::: +set the newly created subvolume's max exclusive size *delete* [options] <subvolume> [<subvolume>...]:: Delete the subvolume(s) from the filesystem. diff --git a/cmds-qgroup.c b/cmds-qgroup.c index 2172944..30f0851 100644 --- a/cmds-qgroup.c +++ b/cmds-qgroup.c @@ -106,48 +106,6 @@ static int qgroup_create(int create, int argc, char **argv) return 0; } -static int parse_limit(const char *p, unsigned long long *s) -{ - char *endptr; - unsigned long long size; - - if (strcasecmp(p, "none") == 0) { - *s = 0; - return 1; - } - size = strtoull(p, &endptr, 10); - switch (*endptr) { - case 'T': - case 't': - size *= 1024; - /* fallthrough */ - case 'G': - case 'g': - size *= 1024; - /* fallthrough */ - case 'M': - case 'm': - size *= 1024; - /* fallthrough */ - case 'K': - case 'k': - size *= 1024; - ++endptr; - break; - case 0: - break; - default: - return 0; - } - - if (*endptr) - return 0; - - *s = size; - - return 1; -} - static const char * const cmd_qgroup_assign_usage[] = { "btrfs qgroup assign <src> <dst> <path>", "Enable subvolume qgroup support for a filesystem.", diff --git a/cmds-subvolume.c b/cmds-subvolume.c index a31cb1b..f0e22ac 100644 --- a/cmds-subvolume.c +++ b/cmds-subvolume.c @@ -42,13 +42,15 @@ static const char * const subvolume_cmd_group_usage[] = { }; static const char * const cmd_subvol_create_usage[] = { - "btrfs subvolume create [-i <qgroupid>] [<dest>/]<name>", + "btrfs subvolume create [-i <qgroupid>] [-r <max_rfer>] [-e <max_excl>] [<dest>/]<name>", "Create a subvolume", "Create a subvolume <name> in <dest>. If <dest> is not given", "subvolume <name> will be created in the current directory.", "", "-i <qgroupid> add the newly created subvolume to a qgroup. This", " option can be given multiple times.", + "-r <max_rfer> set the newly created subvolume's max reference size", + "-e <max_excl> set the newly created subvolume's max exclusive size", NULL }; @@ -66,7 +68,7 @@ static int cmd_subvol_create(int argc, char **argv) optind = 1; while (1) { - int c = getopt(argc, argv, "c:i:v"); + int c = getopt(argc, argv, "c:i:r:e:v"); if (c < 0) break; @@ -85,6 +87,20 @@ static int cmd_subvol_create(int argc, char **argv) goto out; } break; + case 'r': + res = qgroup_inherit_set_maxrfer(&inherit, optarg); + if (res) { + retval = res; + goto out; + } + break; + case 'e': + res = qgroup_inherit_set_maxexcl(&inherit, optarg); + if (res) { + retval = res; + goto out; + } + break; default: usage(cmd_subvol_create_usage); } @@ -129,6 +145,43 @@ static int cmd_subvol_create(int argc, char **argv) printf("Create subvolume '%s/%s'\n", dstdir, newname); if (inherit) { struct btrfs_ioctl_vol_args_v2 args; + struct btrfs_ioctl_quota_ctl_args sa; + + printf("Set qgroup arguments:\n"); + if (inherit->num_qgroups > 0) { + __u64 index; + __u64 qgroupid; + + printf("\tparent qgroup: "); + for (index = 0; index < inherit->num_qgroups; index++) { + qgroupid = inherit->qgroups[index]; + printf("%llu/%llu ", qgroupid >> 48, + (qgroupid << 16) >> 16); + } + printf("\n"); + } + if (inherit->lim.flags) { + if (inherit->lim.flags & BTRFS_QGROUP_LIMIT_MAX_RFER) + printf("\tmax reference: %llu\n", + inherit->lim.max_referenced); + if (inherit->lim.flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) + printf("\tmax exclusive: %llu\n", + inherit->lim.max_exclusive); + } + + sa.cmd = BTRFS_QUOTA_CTL_STATUS; + res = ioctl(fddst, BTRFS_IOC_QUOTA_CTL, &sa); + if (res < 0) { + fprintf(stderr, "ERROR: cannot get quota status - %s\n", + strerror(errno)); + retval = 1; + goto out; + } + if (!(sa.status & BTRFS_QUOTA_STATUS_QUOTA_ENABLED)) { + fprintf(stderr, "ERROR: quota disabled\n"); + retval = 1; + goto out; + } memset(&args, 0, sizeof(args)); strncpy_null(args.name, newname); diff --git a/ioctl.h b/ioctl.h index d550ca6..a47eab8 100644 --- a/ioctl.h +++ b/ioctl.h @@ -450,6 +450,9 @@ struct btrfs_ioctl_get_dev_stats { /* BTRFS_IOC_SNAP_CREATE is no longer used by the btrfs command */ #define BTRFS_QUOTA_CTL_ENABLE 1 #define BTRFS_QUOTA_CTL_DISABLE 2 +#define BTRFS_QUOTA_CTL_STATUS 4 + +#define BTRFS_QUOTA_STATUS_QUOTA_ENABLED 1 /* 3 has formerly been reserved for BTRFS_QUOTA_CTL_RESCAN */ struct btrfs_ioctl_quota_ctl_args { __u64 cmd; diff --git a/qgroup.c b/qgroup.c index 5a4e393..620ec7e 100644 --- a/qgroup.c +++ b/qgroup.c @@ -1273,6 +1273,48 @@ err: exit(-1); } +int parse_limit(const char *p, unsigned long long *s) +{ + char *endptr; + unsigned long long size; + + if (strcasecmp(p, "none") == 0) { + *s = 0; + return 1; + } + size = strtoull(p, &endptr, 10); + switch (*endptr) { + case 'T': + case 't': + size *= 1024; + /* fallthrough */ + case 'G': + case 'g': + size *= 1024; + /* fallthrough */ + case 'M': + case 'm': + size *= 1024; + /* fallthrough */ + case 'K': + case 'k': + size *= 1024; + ++endptr; + break; + case 0: + break; + default: + return 0; + } + + if (*endptr) + return 0; + + *s = size; + + return 1; +} + int qgroup_inherit_size(struct btrfs_qgroup_inherit *p) { return sizeof(*p) + sizeof(p->qgroups[0]) * @@ -1302,6 +1344,8 @@ qgroup_inherit_realloc(struct btrfs_qgroup_inherit **inherit, int n, int pos) struct btrfs_qgroup_inherit *i = *inherit; int s = sizeof(out->qgroups[0]); + out->flags = i->flags; + out->lim = i->lim; out->num_qgroups = i->num_qgroups; out->num_ref_copies = i->num_ref_copies; out->num_excl_copies = i->num_excl_copies; @@ -1378,3 +1422,51 @@ bad: return 0; } + +int qgroup_inherit_set_maxrfer(struct btrfs_qgroup_inherit **inherit, char *arg) +{ + unsigned long long size; + + if(!parse_limit(arg, &size)) { + fprintf(stderr, "Invalid size argument given\n"); + return 1; + } + + if ((*inherit) == NULL) { + (*inherit) = malloc(sizeof(struct btrfs_qgroup_inherit)); + if ((*inherit) == NULL) { + fprintf(stderr, "ERROR: Not enough memory\n"); + return -ENOMEM; + } + memset((*inherit), 0, sizeof(struct btrfs_qgroup_inherit)); + } + + (*inherit)->flags |= BTRFS_QGROUP_INHERIT_SET_LIMITS; + (*inherit)->lim.flags |= BTRFS_QGROUP_LIMIT_MAX_RFER; + (*inherit)->lim.max_referenced = size; + return 0; +} + +int qgroup_inherit_set_maxexcl(struct btrfs_qgroup_inherit **inherit, char *arg) +{ + unsigned long long size; + + if(!parse_limit(arg, &size)) { + fprintf(stderr, "Invalid size argument given\n"); + return 1; + } + + if ((*inherit) == NULL) { + (*inherit) = malloc(sizeof(struct btrfs_qgroup_inherit)); + if ((*inherit) == NULL) { + fprintf(stderr, "ERROR: Not enough memory\n"); + return -ENOMEM; + } + memset((*inherit), 0, sizeof(struct btrfs_qgroup_inherit)); + } + + (*inherit)->flags |= BTRFS_QGROUP_INHERIT_SET_LIMITS; + (*inherit)->lim.flags |= BTRFS_QGROUP_LIMIT_MAX_EXCL; + (*inherit)->lim.max_exclusive = size; + return 0; +} diff --git a/qgroup.h b/qgroup.h index 6e65ef7..e5d03ca 100644 --- a/qgroup.h +++ b/qgroup.h @@ -94,9 +94,12 @@ int btrfs_qgroup_setup_comparer(struct btrfs_qgroup_comparer_set **comp_set, enum btrfs_qgroup_comp_enum comparer, int is_descending); u64 parse_qgroupid(char *p); +int parse_limit(const char *p, unsigned long long *s); int qgroup_inherit_size(struct btrfs_qgroup_inherit *p); int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg); int qgroup_inherit_add_copy(struct btrfs_qgroup_inherit **inherit, char *arg, int type); +int qgroup_inherit_set_maxrfer(struct btrfs_qgroup_inherit **inherit, char *arg); +int qgroup_inherit_set_maxexcl(struct btrfs_qgroup_inherit **inherit, char *arg); #endif -- 1.8.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html