static int btrfs_subvolume_create(const char *path)
{
- int ret, saved_errno;
- struct btrfs_ioctl_vol_args args;
- char *p, *newfull;
- int fd = -1;
+ int ret, fd = -1;
+ struct btrfs_ioctl_vol_args args;
+ char *p, *newfull = strdup(path);
- newfull = strdup(path);
if (!newfull) {
- errno = ENOMEM;
- return -ENOMEM;
+ ERROR("Error: out of memory");
+ return -1;
}
p = strrchr(newfull, '/');
if (!p) {
+ ERROR("bad path: %s", path);
free(newfull);
- errno = EINVAL;
- return -EINVAL;
+ return -1;
}
*p = '\0';
fd = open(newfull, O_RDONLY);
- free(newfull);
if (fd < 0) {
- return -errno;
+ ERROR("Error opening %s", newfull);
+ free(newfull);
+ return -1;
}
memset(&args, 0, sizeof(args));
- strncpy(args.name, p + 1, BTRFS_SUBVOL_NAME_MAX);
- args.name[BTRFS_SUBVOL_NAME_MAX - 1] = 0;
-
+ strncpy(args.name, p+1, BTRFS_SUBVOL_NAME_MAX);
+ args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
ret = ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args);
- saved_errno = errno;
+ INFO("btrfs: snapshot create ioctl returned %d", ret);
+ free(newfull);
close(fd);
- errno = saved_errno;
return ret;
}
int btrfs_snapshot(const char *orig, const char *new)
{
- struct btrfs_ioctl_vol_args_v2 args;
- char *newdir, *newname;
- char *newfull = NULL;
- int saved_errno = -1;
int fd = -1, fddst = -1, ret = -1;
+ struct btrfs_ioctl_vol_args_v2 args;
+ char *newdir, *newname, *newfull = NULL;
newfull = strdup(new);
- if (!newfull)
+ if (!newfull) {
+ ERROR("Error: out of memory");
goto out;
-
- ret = rmdir(newfull);
- if (ret < 0 && errno != ENOENT)
+ }
+ // make sure the directory doesn't already exist
+ if (rmdir(newfull) < 0 && errno != ENOENT) {
+ SYSERROR("Error removing empty new rootfs");
goto out;
-
+ }
newname = basename(newfull);
+ newdir = dirname(newfull);
fd = open(orig, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
+ SYSERROR("Error opening original rootfs %s", orig);
goto out;
-
- newdir = dirname(newfull);
+ }
fddst = open(newdir, O_RDONLY);
- if (fddst < 0)
+ if (fddst < 0) {
+ SYSERROR("Error opening new container dir %s", newdir);
goto out;
+ }
memset(&args, 0, sizeof(args));
args.fd = fd;
strncpy(args.name, newname, BTRFS_SUBVOL_NAME_MAX);
- args.name[BTRFS_SUBVOL_NAME_MAX - 1] = 0;
-
+ args.name[BTRFS_SUBVOL_NAME_MAX-1] = 0;
ret = ioctl(fddst, BTRFS_IOC_SNAP_CREATE_V2, &args);
- saved_errno = errno;
+ INFO("btrfs: snapshot create ioctl returned %d", ret);
out:
if (fddst != -1)
if (fd != -1)
close(fd);
free(newfull);
-
- if (saved_errno >= 0)
- errno = saved_errno;
return ret;
}
}
if (setgroups(0, NULL) < 0)
WARN("Failed to clear groups");
-
if (setuid(0) < 0) {
ERROR("Failed to setuid to 0");
return -1;
}
src = lxc_storage_get_path(arg->src, "btrfs");
+
return btrfs_snapshot(src, arg->dest);
}
const char *lxcpath, int snap, uint64_t newsize,
struct lxc_conf *conf)
{
- int ret;
char *src;
if (!orig->dest || !orig->src)
(const char *[]){"btrfs:", *lxcpath != '/' ? lxcpath : ++lxcpath,
cname, "rootfs", NULL},
false);
- if (!new->src) {
- ERROR("Failed to create new rootfs path");
+ if (!new->src)
return -1;
- }
- TRACE("Created new rootfs path \"%s\"", new->src);
src = lxc_storage_get_path(new->src, "btrfs");
new->dest = strdup(src);
- if (!new->dest) {
- ERROR("Failed to duplicate string \"%s\"", src);
+ if (!new->dest)
return -1;
- }
- if (orig->mntopts) {
- new->mntopts = strdup(orig->mntopts);
- if (!new->mntopts) {
- ERROR("Failed to duplicate string \"%s\"",
- orig->mntopts);
- return -1;
- }
- }
+ if (orig->mntopts && (new->mntopts = strdup(orig->mntopts)) == NULL)
+ return -1;
if (snap) {
struct rsync_data_char sdata;
"btrfs_snapshot_wrapper");
}
- ret = rmdir(new->dest);
- if (ret < 0 && errno != ENOENT) {
- SYSERROR("Failed to remove directory \"%s\"", new->dest);
+ if (rmdir(new->dest) < 0 && errno != ENOENT) {
+ SYSERROR("removing %s", new->dest);
return -1;
}
- ret = btrfs_subvolume_create(new->dest);
- if (ret < 0)
- SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest);
- return ret;
+ return btrfs_subvolume_create(new->dest);
}
static int btrfs_do_destroy_subvol(const char *path)