Unverified Commit 618b655b by Christian Brauner Committed by Stéphane Graber

btrfs: switch to btrfs_create_{clone,snapshot}()

parent 667fa8ce
...@@ -96,8 +96,8 @@ static const struct bdev_ops btrfs_ops = { ...@@ -96,8 +96,8 @@ static const struct bdev_ops btrfs_ops = {
.clone_paths = &btrfs_clonepaths, .clone_paths = &btrfs_clonepaths,
.destroy = &btrfs_destroy, .destroy = &btrfs_destroy,
.create = &btrfs_create, .create = &btrfs_create,
.create_clone = NULL, .create_clone = &btrfs_create_clone,
.create_snapshot = NULL, .create_snapshot = &btrfs_create_snapshot,
.can_snapshot = true, .can_snapshot = true,
.can_backup = true, .can_backup = true,
}; };
...@@ -415,6 +415,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, ...@@ -415,6 +415,8 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
bdevtype = "dir"; bdevtype = "dir";
else if (!bdevtype) else if (!bdevtype)
bdevtype = orig->type; bdevtype = orig->type;
/* get new bdev type */
new = bdev_get(bdevtype); new = bdev_get(bdevtype);
if (!new) { if (!new) {
ERROR("no such block device type: %s", ERROR("no such block device type: %s",
...@@ -424,17 +426,24 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname, ...@@ -424,17 +426,24 @@ struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
} }
TRACE("Detected \"%s\" storage driver", new->type); TRACE("Detected \"%s\" storage driver", new->type);
if (bdevtype && !strcmp(orig->type, "btrfs") && /* create new paths */
!strcmp(new->type, "btrfs"))
snap = 1;
if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath, if (new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
snap, newsize, c0->lxc_conf) < 0) { snap, newsize, c0->lxc_conf) < 0) {
ERROR("Failed getting pathnames for clone of \"%s\"", src); ERROR("Failed getting pathnames for clone of \"%s\"", src);
goto err; 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(bdevtype, "btrfs")) {
if (!strcmp(new->type, "overlay") || if (!strcmp(new->type, "overlay") ||
!strcmp(new->type, "overlayfs")) !strcmp(new->type, "overlayfs"))
......
...@@ -372,7 +372,6 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, ...@@ -372,7 +372,6 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
const char *lxcpath, int snap, uint64_t newsize, const char *lxcpath, int snap, uint64_t newsize,
struct lxc_conf *conf) struct lxc_conf *conf)
{ {
int ret;
char *src; char *src;
if (!orig->dest || !orig->src) if (!orig->dest || !orig->src)
...@@ -393,7 +392,7 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, ...@@ -393,7 +392,7 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
ERROR("Failed to create new rootfs path"); ERROR("Failed to create new rootfs path");
return -1; 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"); src = lxc_storage_get_path(new->src, "btrfs");
new->dest = strdup(src); new->dest = strdup(src);
...@@ -411,39 +410,95 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname, ...@@ -411,39 +410,95 @@ int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
} }
} }
if (snap) { return 0;
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;
}
sdata.dest = new->dest; bool btrfs_create_clone(struct lxc_conf *conf, struct bdev *orig,
sdata.src = orig->dest; struct bdev *new, uint64_t newsize)
return userns_exec_1(conf, btrfs_snapshot_wrapper, &sdata, {
"btrfs_snapshot_wrapper"); int pid, ret;
} struct rsync_data data;
ret = rmdir(new->dest); ret = rmdir(new->dest);
if (ret < 0 && errno != ENOENT) { if (ret < 0 && errno != ENOENT)
SYSERROR("Failed to remove directory \"%s\"", new->dest); return false;
return -1;
}
ret = btrfs_subvolume_create(new->dest); ret = btrfs_subvolume_create(new->dest);
if (ret < 0) if (ret < 0) {
SYSERROR("Failed to create btrfs subvolume \"%s\"", new->dest); 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 else
TRACE("Created btrfs subvolume \"%s\"", new->dest); ret = rsync_rootfs(&data);
return ret; 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) static int btrfs_do_destroy_subvol(const char *path)
......
...@@ -413,5 +413,9 @@ bool btrfs_try_remove_subvol(const char *path); ...@@ -413,5 +413,9 @@ bool btrfs_try_remove_subvol(const char *path);
int btrfs_same_fs(const char *orig, const char *new); int btrfs_same_fs(const char *orig, const char *new);
int btrfs_snapshot(const char *orig, const char *new); int btrfs_snapshot(const char *orig, const char *new);
int btrfs_snapshot_wrapper(void *data); 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 #endif // __LXC_BTRFS_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment