@@ -103,6 +103,35 @@ static int wait_for_subvolume_cleaning(int fd, int count, u64 *ids,
return 0;
}
+static int qgroup_inherit_add_group(struct btrfs_util_qgroup_inherit **inherit,
+ const char *arg)
+{
+ enum btrfs_util_error err;
+ u64 qgroupid;
+
+ if (!*inherit) {
+ err = btrfs_util_create_qgroup_inherit(0, inherit);
+ if (err) {
+ error_btrfs_util(err);
+ return -1;
+ }
+ }
+
+ qgroupid = parse_qgroupid(optarg);
+ if (qgroupid == 0) {
+ error("invalid qgroup specification, qgroupid must not be 0");
+ return -1;
+ }
+
+ err = btrfs_util_qgroup_inherit_add_group(inherit, qgroupid);
+ if (err) {
+ error_btrfs_util(err);
+ return -1;
+ }
+
+ return 0;
+}
+
static const char * const subvolume_cmd_group_usage[] = {
"btrfs subvolume <command> <args>",
NULL
@@ -121,15 +150,9 @@ static const char * const cmd_subvol_create_usage[] = {
static int cmd_subvol_create(int argc, char **argv)
{
- int retval, res, len;
- int fddst = -1;
- char *dupname = NULL;
- char *dupdir = NULL;
- char *newname;
- char *dstdir;
- char *dst;
- struct btrfs_qgroup_inherit *inherit = NULL;
- DIR *dirstream = NULL;
+ struct btrfs_util_qgroup_inherit *inherit = NULL;
+ enum btrfs_util_error err;
+ int retval = 1;
while (1) {
int c = getopt(argc, argv, "i:");
@@ -138,11 +161,8 @@ static int cmd_subvol_create(int argc, char **argv)
switch (c) {
case 'i':
- res = qgroup_inherit_add_group(&inherit, optarg);
- if (res) {
- retval = res;
+ if (qgroup_inherit_add_group(&inherit, optarg) == -1)
goto out;
- }
break;
default:
usage(cmd_subvol_create_usage);
@@ -152,70 +172,18 @@ static int cmd_subvol_create(int argc, char **argv)
if (check_argc_exact(argc - optind, 1))
usage(cmd_subvol_create_usage);
- dst = argv[optind];
-
- retval = 1; /* failure */
- res = test_isdir(dst);
- if (res < 0 && res != -ENOENT) {
- error("cannot access %s: %s", dst, strerror(-res));
- goto out;
- }
- if (res >= 0) {
- error("target path already exists: %s", dst);
- goto out;
- }
-
- dupname = strdup(dst);
- newname = basename(dupname);
- dupdir = strdup(dst);
- dstdir = dirname(dupdir);
-
- if (!test_issubvolname(newname)) {
- error("invalid subvolume name: %s", newname);
- goto out;
- }
-
- len = strlen(newname);
- if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
- error("subvolume name too long: %s", newname);
- goto out;
- }
-
- fddst = btrfs_open_dir(dstdir, &dirstream, 1);
- if (fddst < 0)
- goto out;
-
- printf("Create subvolume '%s/%s'\n", dstdir, newname);
- if (inherit) {
- struct btrfs_ioctl_vol_args_v2 args;
-
- memset(&args, 0, sizeof(args));
- strncpy_null(args.name, newname);
- args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
- args.size = qgroup_inherit_size(inherit);
- args.qgroup_inherit = inherit;
-
- res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE_V2, &args);
- } else {
- struct btrfs_ioctl_vol_args args;
-
- memset(&args, 0, sizeof(args));
- strncpy_null(args.name, newname);
-
- res = ioctl(fddst, BTRFS_IOC_SUBVOL_CREATE, &args);
- }
+ printf("Create subvolume '%s'\n", argv[optind]);
- if (res < 0) {
- error("cannot create subvolume: %m");
+ err = btrfs_util_create_subvolume(argv[optind], 0, NULL, inherit);
+ if (err) {
+ error_btrfs_util(err);
goto out;
}
- retval = 0; /* success */
+ retval = 0;
out:
- close_file_or_dir(fddst, dirstream);
- free(inherit);
- free(dupname);
- free(dupdir);
+ if (inherit)
+ btrfs_util_destroy_qgroup_inherit(inherit);
return retval;
}
@@ -650,19 +618,11 @@ static const char * const cmd_subvol_snapshot_usage[] = {
static int cmd_subvol_snapshot(int argc, char **argv)
{
- char *subvol, *dst;
- int res, retval;
- int fd = -1, fddst = -1;
- int len, readonly = 0;
- char *dupname = NULL;
- char *dupdir = NULL;
- char *newname;
- char *dstdir;
- struct btrfs_ioctl_vol_args_v2 args;
- struct btrfs_qgroup_inherit *inherit = NULL;
- DIR *dirstream1 = NULL, *dirstream2 = NULL;
+ struct btrfs_util_qgroup_inherit *inherit = NULL;
+ enum btrfs_util_error err;
+ int flags = 0;
+ int retval = 1;
- memset(&args, 0, sizeof(args));
while (1) {
int c = getopt(argc, argv, "i:r");
if (c < 0)
@@ -670,14 +630,11 @@ static int cmd_subvol_snapshot(int argc, char **argv)
switch (c) {
case 'i':
- res = qgroup_inherit_add_group(&inherit, optarg);
- if (res) {
- retval = res;
+ if (qgroup_inherit_add_group(&inherit, optarg) == -1)
goto out;
- }
break;
case 'r':
- readonly = 1;
+ flags |= BTRFS_UTIL_CREATE_SNAPSHOT_READ_ONLY;
break;
default:
usage(cmd_subvol_snapshot_usage);
@@ -687,92 +644,26 @@ static int cmd_subvol_snapshot(int argc, char **argv)
if (check_argc_exact(argc - optind, 2))
usage(cmd_subvol_snapshot_usage);
- subvol = argv[optind];
- dst = argv[optind + 1];
-
- retval = 1; /* failure */
- res = test_issubvolume(subvol);
- if (res < 0) {
- error("cannot access subvolume %s: %s", subvol, strerror(-res));
- goto out;
- }
- if (!res) {
- error("not a subvolume: %s", subvol);
- goto out;
- }
-
- res = test_isdir(dst);
- if (res < 0 && res != -ENOENT) {
- error("cannot access %s: %s", dst, strerror(-res));
- goto out;
- }
- if (res == 0) {
- error("'%s' exists and it is not a directory", dst);
- goto out;
- }
-
- if (res > 0) {
- dupname = strdup(subvol);
- newname = basename(dupname);
- dstdir = dst;
+ if (flags & BTRFS_UTIL_CREATE_SNAPSHOT_READ_ONLY) {
+ printf("Create a readonly snapshot of '%s' in '%s'\n",
+ argv[optind], argv[optind + 1]);
} else {
- dupname = strdup(dst);
- newname = basename(dupname);
- dupdir = strdup(dst);
- dstdir = dirname(dupdir);
+ printf("Create a snapshot of '%s' in '%s'\n", argv[optind],
+ argv[optind + 1]);
}
- if (!test_issubvolname(newname)) {
- error("invalid snapshot name '%s'", newname);
- goto out;
- }
-
- len = strlen(newname);
- if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
- error("snapshot name too long '%s'", newname);
- goto out;
- }
-
- fddst = btrfs_open_dir(dstdir, &dirstream1, 1);
- if (fddst < 0)
- goto out;
-
- fd = btrfs_open_dir(subvol, &dirstream2, 1);
- if (fd < 0)
- goto out;
-
- if (readonly) {
- args.flags |= BTRFS_SUBVOL_RDONLY;
- printf("Create a readonly snapshot of '%s' in '%s/%s'\n",
- subvol, dstdir, newname);
- } else {
- printf("Create a snapshot of '%s' in '%s/%s'\n",
- subvol, dstdir, newname);
- }
-
- args.fd = fd;
- if (inherit) {
- args.flags |= BTRFS_SUBVOL_QGROUP_INHERIT;
- args.size = qgroup_inherit_size(inherit);
- args.qgroup_inherit = inherit;
- }
- strncpy_null(args.name, newname);
-
- res = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
-
- if (res < 0) {
- error("cannot snapshot '%s': %m", subvol);
+ err = btrfs_util_create_snapshot(argv[optind], argv[optind + 1], flags,
+ NULL, inherit);
+ if (err) {
+ error_btrfs_util(err);
goto out;
}
- retval = 0; /* success */
+ retval = 0;
out:
- close_file_or_dir(fddst, dirstream1);
- close_file_or_dir(fd, dirstream2);
- free(inherit);
- free(dupname);
- free(dupdir);
+ if (inherit)
+ btrfs_util_destroy_qgroup_inherit(inherit);
return retval;
}
@@ -1260,67 +1260,3 @@ out:
free(opt_tmp);
return ret;
}
-
-int qgroup_inherit_size(struct btrfs_qgroup_inherit *p)
-{
- return sizeof(*p) + sizeof(p->qgroups[0]) *
- (p->num_qgroups + 2 * p->num_ref_copies +
- 2 * p->num_excl_copies);
-}
-
-static int
-qgroup_inherit_realloc(struct btrfs_qgroup_inherit **inherit, int n, int pos)
-{
- struct btrfs_qgroup_inherit *out;
- int nitems = 0;
-
- if (*inherit) {
- nitems = (*inherit)->num_qgroups +
- (*inherit)->num_ref_copies +
- (*inherit)->num_excl_copies;
- }
-
- out = calloc(sizeof(*out) + sizeof(out->qgroups[0]) * (nitems + n), 1);
- if (out == NULL) {
- error("not enough memory");
- return -ENOMEM;
- }
-
- if (*inherit) {
- struct btrfs_qgroup_inherit *i = *inherit;
- int s = sizeof(out->qgroups[0]);
-
- out->num_qgroups = i->num_qgroups;
- out->num_ref_copies = i->num_ref_copies;
- out->num_excl_copies = i->num_excl_copies;
- memcpy(out->qgroups, i->qgroups, pos * s);
- memcpy(out->qgroups + pos + n, i->qgroups + pos,
- (nitems - pos) * s);
- }
- free(*inherit);
- *inherit = out;
-
- return 0;
-}
-
-int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg)
-{
- int ret;
- u64 qgroupid = parse_qgroupid(arg);
- int pos = 0;
-
- if (qgroupid == 0) {
- error("invalid qgroup specification, qgroupid must not 0");
- return -EINVAL;
- }
-
- if (*inherit)
- pos = (*inherit)->num_qgroups;
- ret = qgroup_inherit_realloc(inherit, 1, pos);
- if (ret)
- return ret;
-
- (*inherit)->qgroups[(*inherit)->num_qgroups++] = qgroupid;
-
- return 0;
-}
@@ -90,7 +90,5 @@ struct btrfs_qgroup_comparer_set *btrfs_qgroup_alloc_comparer_set(void);
int btrfs_qgroup_setup_comparer(struct btrfs_qgroup_comparer_set **comp_set,
enum btrfs_qgroup_comp_enum comparer,
int is_descending);
-int qgroup_inherit_size(struct btrfs_qgroup_inherit *p);
-int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
#endif