From: Christian Brauner Date: Sun, 16 Jul 2017 22:02:14 +0000 (+0200) Subject: btrfs: switch to btrfs_create_{clone,snapshot}() X-Git-Tag: lxc-2.1.0~32^2~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b196516bc9ce4107467c007dab46a77e2d2d96aa;p=thirdparty%2Flxc.git btrfs: switch to btrfs_create_{clone,snapshot}() Signed-off-by: Christian Brauner --- diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c index 5ae3ba657..9d8c0172b 100644 --- a/src/lxc/bdev/bdev.c +++ b/src/lxc/bdev/bdev.c @@ -96,8 +96,8 @@ static const struct bdev_ops btrfs_ops = { .clone_paths = &btrfs_clonepaths, .destroy = &btrfs_destroy, .create = &btrfs_create, - .create_clone = NULL, - .create_snapshot = NULL, + .create_clone = &btrfs_create_clone, + .create_snapshot = &btrfs_create_snapshot, .can_snapshot = true, .can_backup = true, }; @@ -415,6 +415,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, bdevtype = "dir"; else if (!bdevtype) bdevtype = orig->type; + + /* get new bdev type */ new = bdev_get(bdevtype); if (!new) { ERROR("no such block device type: %s", @@ -424,17 +426,24 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, } TRACE("Detected \"%s\" storage driver", new->type); - if (bdevtype && !strcmp(orig->type, "btrfs") && - !strcmp(new->type, "btrfs")) - snap = 1; - + /* create new paths */ if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath, snap, newsize, c0->lxc_conf) < 0) { ERROR("Failed getting pathnames for clone of \"%s\"", src); goto err; } - /* If the storage driver is "btrfs" then the we will create snapshot. */ + if (!strcmp(orig->type, "btrfs") && !strcmp(new->type, "btrfs")) { + bool bret = false; + if (snap || btrfs_same_fs(orig->dest, new->dest) == 0) + bret = new->ops->create_snapshot(c0->lxc_conf, orig, new); + else + bret = new->ops->create_clone(c0->lxc_conf, orig, new, 0); + if (!bret) + return NULL; + return new; + } + if (strcmp(bdevtype, "btrfs")) { if (!strcmp(new->type, "overlay") || !strcmp(new->type, "overlayfs")) diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c index b8a317afb..0a9cf9133 100644 --- a/src/lxc/bdev/lxcbtrfs.c +++ b/src/lxc/bdev/lxcbtrfs.c @@ -375,7 +375,6 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, const char *lxcpath, int snap, uint64_t newsize, struct lxc_conf *conf) { - int ret; char *src; if (!orig->dest || !orig->src) @@ -396,7 +395,7 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, ERROR("Failed to create new rootfs path"); return -1; } - TRACE("Created new rootfs path \"%s\"", new->src); + TRACE("Constructed new rootfs path \"%s\"", new->src); src = lxc_storage_get_path(new->src, "btrfs"); new->dest = strdup(src); @@ -414,39 +413,95 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, } } - if (snap) { - struct rsync_data_char sdata; - if (!am_unpriv()) { - ret = btrfs_snapshot(orig->dest, new->dest); - if (ret < 0) { - SYSERROR("Failed to create btrfs snapshot " - "\"%s\" from \"%s\"", - new->dest, orig->dest); - return -1; - } - TRACE("Created btrfs snapshot \"%s\" from \"%s\"", - new->dest, orig->dest); - return 0; - } + return 0; +} - sdata.dest = new->dest; - sdata.src = orig->dest; - return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata, - "btrfs_snapshot_wrapper"); - } +bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig, + struct bdev *new, uint64_t newsize) +{ + int pid, ret; + struct rsync_data data; ret = rmdir(new->dest); - if (ret < 0 && errno != ENOENT) { - SYSERROR("Failed to remove directory \"%s\"", new->dest); - return -1; - } + if (ret < 0 && errno != ENOENT) + return false; ret = btrfs_subvolume_create(new->dest); - if (ret < 0) + if (ret < 0) { SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest); + return false; + } + + /* rsync contents */ + pid = fork(); + if (pid < 0) { + SYSERROR("fork"); + return false; + } + + if (pid > 0) { + int ret = wait_for_pid(pid); + bdev_put(orig); + if (ret < 0) { + bdev_put(new); + return false; + } + return true; + } + + data.orig = orig; + data.new = new; + + if (am_unpriv()) + ret = userns_exec_1(conf, rsync_rootfs_wrapper, &data, + "rsync_rootfs_wrapper"); else - TRACE("Created btrfs subvolume \"%s\"", new->dest); - return ret; + ret = rsync_rootfs(&data); + if (ret < 0) { + ERROR("Failed to rsync"); + return false; + } + + TRACE("Created btrfs subvolume \"%s\"", new->dest); + return true; +} + +bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig, + struct bdev *new) +{ + int ret; + + ret = rmdir(new->dest); + if (ret < 0 && errno != ENOENT) + return false; + + if (am_unpriv()) { + struct rsync_data_char args; + + args.src = orig->dest; + args.dest = new->dest; + + ret = userns_exec_1(conf, btrfs_snapshot_wrapper, &args, + "btrfs_snapshot_wrapper"); + if (ret < 0) { + ERROR("Failed to run \"btrfs_snapshot_wrapper\""); + return false; + } + + TRACE("Created btrfs snapshot \"%s\" from \"%s\"", new->dest, + orig->dest); + return true; + } + + ret = btrfs_snapshot(orig->dest, new->dest); + if (ret < 0) { + SYSERROR("Failed to create btrfs snapshot \"%s\" from \"%s\"", + new->dest, orig->dest); + return false; + } + + TRACE("Created btrfs snapshot \"%s\" from \"%s\"", new->dest, orig->dest); + return true; } static int btrfs_do_destroy_subvol(const char *path) diff --git a/src/lxc/bdev/lxcbtrfs.h b/src/lxc/bdev/lxcbtrfs.h index b2ebb3739..13b483994 100644 --- a/src/lxc/bdev/lxcbtrfs.h +++ b/src/lxc/bdev/lxcbtrfs.h @@ -413,5 +413,9 @@ bool btrfs_try_remove_subvol(const char *path); int btrfs_same_fs(const char *orig, const char *new); int btrfs_snapshot(const char *orig, const char *new); int btrfs_snapshot_wrapper(void *data); +bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig, + struct bdev *new, uint64_t newsize); +bool btrfs_create_snapshot(struct lxc_conf *conf, struct bdev *orig, + struct bdev *new); #endif // __LXC_BTRFS_H