s[l-2] = '/';
s[l-1] = '\0';
- return execlp("rsync", "rsync", "-a", s, dest, (char *)NULL);
+ execlp("rsync", "rsync", "-a", s, dest, (char *)NULL);
+ exit(1);
}
static int blk_getsize(const char *path, unsigned long *size)
if (pid > 0)
return wait_for_pid(pid);
- return execlp("mkfs", "mkfs", "-t", fstype, path, NULL);
+ execlp("mkfs", "mkfs", "-t", fstype, path, NULL);
+ exit(1);
}
static char *linkderef(char *path, char *dest)
const char *cname, const char *oldpath, const char *lxcpath, int snap,
unsigned long newsize)
{
+ int len, ret;
+
if (snap) {
ERROR("directories cannot be snapshotted. Try overlayfs.");
return -1;
}
- if (strcmp(orig->type, "dir")) {
- ERROR("Directory clone from %s backing store is not supported",
- orig->type);
- return -1;
- }
-
if (!orig->dest || !orig->src)
return -1;
- if (orig->data) {
- new->data = strdup(orig->data);
- if (!new->data)
- return -1;
- }
- new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath);
- if (!new->dest)
- return -1;
- new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath);
+ len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
+ new->src = malloc(len);
if (!new->src)
return -1;
+ ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname);
+ if (ret < 0 || ret >= len)
+ return -1;
+ if ((new->dest = strdup(new->src)) == NULL)
+ return -1;
return 0;
}
int ret;
pid_t pid;
- if (zfs_list_entry(opath, output) < 0)
- return -1;
+ if (!zfs_list_entry(opath, output))
+ // default is tank. I'd prefer lxc, but apparently this is
+ // tradition.
+ sprintf(output, "tank");
if ((p = index(output, ' ')) == NULL)
return -1;
ret = snprintf(dev, MAXPATHLEN, "%s/%s", output, nname);
if (ret < 0 || ret >= MAXPATHLEN)
exit(1);
- return execlp("zfs", "zfs", "create", option, dev, NULL);
+ execlp("zfs", "zfs", "create", option, dev, NULL);
+ exit(1);
}
return wait_for_pid(pid);
} else {
if ((pid = fork()) < 0)
return -1;
if (!pid) {
- return execlp("zfs", "zfs", "destroy", path1, NULL);
+ execlp("zfs", "zfs", "destroy", path1, NULL);
+ exit(1);
}
// it probably doesn't exist so destroy probably will fail.
(void) wait_for_pid(pid);
if ((pid = fork()) < 0)
return -1;
if (!pid) {
- return execlp("zfs", "zfs", "snapshot", path1, NULL);
+ execlp("zfs", "zfs", "snapshot", path1, NULL);
+ exit(1);
}
if (wait_for_pid(pid) < 0)
return -1;
if ((pid = fork()) < 0)
return -1;
if (!pid) {
- return execlp("zfs", "zfs", "clone", option, path1, path2, NULL);
+ execlp("zfs", "zfs", "clone", option, path1, path2, NULL);
+ exit(1);
}
return wait_for_pid(pid);
}
const char *cname, const char *oldpath, const char *lxcpath, int snap,
unsigned long newsize)
{
+ int len, ret;
+
if (!orig->src || !orig->dest)
return -1;
- if (strcmp(orig->type, "zfs")) {
- ERROR("zfs clone from %s backing store is not supported",
+ if (snap && strcmp(orig->type, "zfs")) {
+ ERROR("zfs snapshot from %s backing store is not supported",
orig->type);
return -1;
}
- if (orig->data) {
- new->data = strdup(orig->data);
- if (!new->data)
- return -1;
- }
- new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath);
- if (!new->dest)
- return -1;
-
- new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath);
+ len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
+ new->src = malloc(len);
if (!new->src)
return -1;
+ ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname);
+ if (ret < 0 || ret >= len)
+ return -1;
+ if ((new->dest = strdup(new->src)) == NULL)
+ return -1;
return zfs_clone(orig->src, new->src, oldname, cname, lxcpath, snap);
}
if (!vg)
exit(1);
vg++;
- ret = execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL);
+ execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL);
free(pathdup);
- return ret;
+ exit(1);
}
static int lvm_snapshot(const char *orig, const char *path, unsigned long size)
ret = execlp("lvcreate", "lvcreate", "-s", "-L", sz, "-n", lv, orig, (char *)NULL);
free(pathdup);
- return ret;
+ exit(1);
+}
+
+// this will return 1 for physical disks, qemu-nbd, loop, etc
+// right now only lvm is a block device
+static int is_blktype(struct bdev *b)
+{
+ if (strcmp(b->type, "lvm") == 0)
+ return 1;
+ return 0;
}
static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
{
char fstype[100];
unsigned long size = newsize;
+ int len, ret;
if (!orig->src || !orig->dest)
return -1;
if (strcmp(orig->type, "lvm")) {
- ERROR("LVM clone from %s backing store is not supported",
- orig->type);
- return -1;
+ if (snap) {
+ ERROR("LVM snapshot from %s backing store is not supported",
+ orig->type);
+ return -1;
+ }
+ // Use VG 'lxc' by default
+ // We will want to support custom VGs, at least as specified through
+ // /etc/lxc/lxc.conf, preferably also over cmdline
+ len = strlen("/dev/lxc/") + strlen(cname) + 1;
+ if ((new->src = malloc(len)) == NULL)
+ return -1;
+ ret = snprintf(new->src, len, "/dev/lxc/%s", cname);
+ if (ret < 0 || ret >= len)
+ return -1;
+ } else {
+ new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath);
+ if (!new->src)
+ return -1;
}
if (orig->data) {
if (!new->data)
return -1;
}
- new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath);
+
+ len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
+ new->dest = malloc(len);
if (!new->dest)
return -1;
- if (mkdir_p(new->dest, 0755) < 0)
+ ret = snprintf(new->dest, len, "%s/%s/rootfs", lxcpath, cname);
+ if (ret < 0 || ret >= len)
return -1;
-
-
- new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath);
- if (!new->src)
+ if (mkdir_p(new->dest, 0755) < 0)
return -1;
- if (!newsize && blk_getsize(orig->src, &size) < 0) {
- ERROR("Error getting size of %s", orig->src);
- return -1;
+ if (is_blktype(orig)) {
+ if (!newsize && blk_getsize(orig->src, &size) < 0) {
+ ERROR("Error getting size of %s", orig->src);
+ return -1;
+ }
+ if (detect_fs(orig, fstype, 100) < 0) {
+ INFO("could not find fstype for %s, using ext3", orig->src);
+ return -1;
+ }
+ } else {
+ sprintf(fstype, "ext3");
+ if (!newsize)
+ size = 1000000000; // default to 1G
}
+
if (snap) {
if (lvm_snapshot(orig->src, new->src, size) < 0) {
ERROR("could not create %s snapshot of %s", new->src, orig->src);
ERROR("Error creating new lvm blockdev");
return -1;
}
- if (detect_fs(orig, fstype, 100) < 0) {
- ERROR("could not find fstype for %s", orig->src);
- return -1;
- }
if (do_mkfs(new->src, fstype) < 0) {
ERROR("Error creating filesystem type %s on %s", fstype,
new->src);
return -1;
if (strcmp(orig->type, "btrfs")) {
- ERROR("btrfs cloen from %s backing store is not supported",
- orig->type);
- return -1;
- }
+ int len, ret;
+ if (snap) {
+ ERROR("btrfs snapshot from %s backing store is not supported",
+ orig->type);
+ return -1;
+ }
+ len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 3;
+ new->src = malloc(len);
+ if (!new->src)
+ return -1;
+ ret = snprintf(new->src, len, "%s/%s/rootfs", lxcpath, cname);
+ if (ret < 0 || ret >= len)
+ return -1;
+ } else {
+ // in case rootfs is in custom path, reuse it
+ if ((new->src = dir_new_path(orig->src, oldname, cname, oldpath, lxcpath)) == NULL)
+ return -1;
- if ((new->dest = dir_new_path(orig->dest, oldname, cname, oldpath, lxcpath)) == NULL)
- return -1;
+ }
- if ((new->src = strdup(new->dest)) == NULL)
+ if ((new->dest = strdup(new->src)) == NULL)
return -1;
if (orig->data && (new->data = strdup(orig->data)) == NULL)