overlay: correctly restore from snapshot

parent 7f022483
...@@ -438,8 +438,8 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig, ...@@ -438,8 +438,8 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
data.orig = orig; data.orig = orig;
data.new = new; data.new = new;
if (am_unpriv()) { if (am_unpriv()) {
ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &data, ret = userns_exec_1(conf, lxc_storage_rsync_exec_wrapper, &data,
"lxc_rsync_exec_wrapper"); "lxc_storage_rsync_exec_wrapper");
if (ret < 0) { if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\"", ERROR("Failed to rsync from \"%s\" into \"%s\"",
orig->dest, new->dest); orig->dest, new->dest);
...@@ -450,7 +450,7 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig, ...@@ -450,7 +450,7 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
} }
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_exec_wrapper, (void *)&data); lxc_storage_rsync_exec_wrapper, (void *)&data);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest, ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest,
new->dest, cmd_output); new->dest, cmd_output);
......
...@@ -507,7 +507,7 @@ bool lvm_create_clone(struct lxc_conf *conf, struct lxc_storage *orig, ...@@ -507,7 +507,7 @@ bool lvm_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
data.orig = orig; data.orig = orig;
data.new = new; data.new = new;
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_exec_wrapper, (void *)&data); lxc_storage_rsync_exec_wrapper, (void *)&data);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to rsync from \"%s\" to \"%s\"", orig->dest, ERROR("Failed to rsync from \"%s\" to \"%s\"", orig->dest,
new->dest); new->dest);
......
...@@ -43,7 +43,7 @@ static char *ovl_name; ...@@ -43,7 +43,7 @@ static char *ovl_name;
static char *ovl_version[] = {"overlay", "overlayfs"}; static char *ovl_version[] = {"overlay", "overlayfs"};
static char *ovl_detect_name(void); static char *ovl_detect_name(void);
static int ovl_do_rsync(struct lxc_storage *orig, struct lxc_storage *new, static int ovl_do_rsync(const char *src, const char *dest,
struct lxc_conf *conf); struct lxc_conf *conf);
static int ovl_remount_on_enodev(const char *lower, const char *target, static int ovl_remount_on_enodev(const char *lower, const char *target,
const char *name, unsigned long mountflags, const char *name, unsigned long mountflags,
...@@ -292,14 +292,16 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char ...@@ -292,14 +292,16 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
return -ENOMEM; return -ENOMEM;
} }
ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta); ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
free(osrc);
free(ndelta);
if (ret < 0 || (size_t)ret >= len) { if (ret < 0 || (size_t)ret >= len) {
ERROR("Failed to create string"); ERROR("Failed to create string");
free(osrc);
free(ndelta);
return -1; return -1;
} }
ret = ovl_do_rsync(orig, new, conf); ret = ovl_do_rsync(odelta, ndelta, conf);
free(osrc);
free(ndelta);
if (ret < 0) if (ret < 0)
return -1; return -1;
...@@ -462,6 +464,12 @@ int ovl_destroy(struct lxc_storage *orig) ...@@ -462,6 +464,12 @@ int ovl_destroy(struct lxc_storage *orig)
if (!ovl && strncmp(upper, "overlayfs:", 10)) if (!ovl && strncmp(upper, "overlayfs:", 10))
return -22; return -22;
/* For an overlay container the rootfs is considered immutable
* and cannot be removed when restoring from a snapshot.
*/
if (orig->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)
return 0;
if (ovl) if (ovl)
upper += 8; upper += 8;
else else
...@@ -953,28 +961,25 @@ static char *ovl_detect_name(void) ...@@ -953,28 +961,25 @@ static char *ovl_detect_name(void)
return v; return v;
} }
static int ovl_do_rsync(struct lxc_storage *orig, struct lxc_storage *new, static int ovl_do_rsync(const char *src, const char *dest,
struct lxc_conf *conf) struct lxc_conf *conf)
{ {
int ret = -1; int ret = -1;
struct rsync_data rdata = {0, 0}; struct rsync_data_char rdata = {0};
char cmd_output[MAXPATHLEN] = {0}; char cmd_output[MAXPATHLEN] = {0};
rdata.orig = orig; rdata.src = (char *)src;
rdata.new = new; rdata.dest = (char *)dest;
if (am_unpriv()) { if (am_unpriv())
ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &rdata, ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &rdata,
"lxc_rsync_exec_wrapper"); "lxc_rsync_exec_wrapper");
if (ret < 0) else
ERROR("Failed to rsync from \"%s\" into \"%s\"",
orig->dest, new->dest);
} else {
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_exec_wrapper, (void *)&rdata); lxc_rsync_exec_wrapper, (void *)&rdata);
if (ret < 0) if (ret < 0)
ERROR("Failed to rsync from \"%s\" into \"%s\": %s", ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", src, dest,
orig->dest, new->dest, cmd_output); cmd_output[0] != '\0' ? ": " : "",
} cmd_output[0] != '\0' ? cmd_output : "");
return ret; return ret;
} }
...@@ -39,12 +39,28 @@ ...@@ -39,12 +39,28 @@
lxc_log_define(rsync, lxc); lxc_log_define(rsync, lxc);
int lxc_rsync_exec_wrapper(void *data) int lxc_storage_rsync_exec_wrapper(void *data)
{ {
struct rsync_data *arg = data; struct rsync_data *arg = data;
return lxc_rsync(arg); return lxc_rsync(arg);
} }
int lxc_rsync_exec_wrapper(void *data)
{
int ret;
struct rsync_data_char *args = data;
ret = lxc_switch_uid_gid(0, 0);
if (ret < 0)
return -1;
ret = lxc_setgroups(0, NULL);
if (ret < 0)
return -1;
return lxc_rsync_exec(args->src, args->dest);
}
int lxc_rsync_exec(const char *src, const char *dest) int lxc_rsync_exec(const char *src, const char *dest)
{ {
int ret; int ret;
...@@ -70,8 +86,8 @@ int lxc_rsync_exec(const char *src, const char *dest) ...@@ -70,8 +86,8 @@ int lxc_rsync_exec(const char *src, const char *dest)
int lxc_rsync(struct rsync_data *data) int lxc_rsync(struct rsync_data *data)
{ {
int ret; int ret;
struct lxc_storage *orig = data->orig, *new = data->new;
char *dest, *src; char *dest, *src;
struct lxc_storage *orig = data->orig, *new = data->new;
ret = unshare(CLONE_NEWNS); ret = unshare(CLONE_NEWNS);
if (ret < 0) { if (ret < 0) {
...@@ -101,6 +117,7 @@ int lxc_rsync(struct rsync_data *data) ...@@ -101,6 +117,7 @@ int lxc_rsync(struct rsync_data *data)
ret = lxc_switch_uid_gid(0, 0); ret = lxc_switch_uid_gid(0, 0);
if (ret < 0) if (ret < 0)
return -1; return -1;
ret = lxc_setgroups(0, NULL); ret = lxc_setgroups(0, NULL);
if (ret < 0) if (ret < 0)
return -1; return -1;
......
...@@ -39,6 +39,7 @@ struct rsync_data_char { ...@@ -39,6 +39,7 @@ struct rsync_data_char {
/* new helpers */ /* new helpers */
extern int lxc_rsync_exec_wrapper(void *data); extern int lxc_rsync_exec_wrapper(void *data);
extern int lxc_storage_rsync_exec_wrapper(void *data);
extern int lxc_rsync_exec(const char *src, const char *dest); extern int lxc_rsync_exec(const char *src, const char *dest);
extern int lxc_rsync(struct rsync_data *data); extern int lxc_rsync(struct rsync_data *data);
......
...@@ -502,11 +502,11 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname, ...@@ -502,11 +502,11 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
data.orig = orig; data.orig = orig;
data.new = new; data.new = new;
if (am_unpriv()) if (am_unpriv())
ret = userns_exec_1(c->lxc_conf, lxc_rsync_exec_wrapper, &data, ret = userns_exec_1(c->lxc_conf, lxc_storage_rsync_exec_wrapper,
"lxc_rsync_exec_wrapper"); &data, "lxc_storage_rsync_exec_wrapper");
else else
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_exec_wrapper, (void *)&data); lxc_storage_rsync_exec_wrapper, (void *)&data);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", orig->dest, ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", orig->dest,
new->dest, new->dest,
...@@ -598,6 +598,8 @@ struct lxc_storage *storage_init(struct lxc_conf *conf, const char *src, ...@@ -598,6 +598,8 @@ struct lxc_storage *storage_init(struct lxc_conf *conf, const char *src,
struct lxc_storage *bdev; struct lxc_storage *bdev;
const struct lxc_storage_type *q; const struct lxc_storage_type *q;
BUILD_BUG_ON(LXC_STORAGE_INTERNAL_OVERLAY_RESTORE <= LXC_CLONE_MAXFLAGS);
if (!src) if (!src)
src = conf->rootfs.path; src = conf->rootfs.path;
......
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
#define DEFAULT_FS_SIZE 1073741824 #define DEFAULT_FS_SIZE 1073741824
#define DEFAULT_FSTYPE "ext3" #define DEFAULT_FSTYPE "ext3"
#define LXC_STORAGE_INTERNAL_OVERLAY_RESTORE (1 << 6)
struct lxc_storage; struct lxc_storage;
struct lxc_storage_ops { struct lxc_storage_ops {
...@@ -97,6 +99,7 @@ struct lxc_storage { ...@@ -97,6 +99,7 @@ struct lxc_storage {
int lofd; int lofd;
/* index for the connected nbd device. */ /* index for the connected nbd device. */
int nbd_idx; int nbd_idx;
int flags;
}; };
extern bool storage_is_dir(struct lxc_conf *conf, const char *path); extern bool storage_is_dir(struct lxc_conf *conf, const char *path);
......
...@@ -325,7 +325,7 @@ bool zfs_copy(struct lxc_conf *conf, struct lxc_storage *orig, ...@@ -325,7 +325,7 @@ bool zfs_copy(struct lxc_conf *conf, struct lxc_storage *orig,
data.orig = orig; data.orig = orig;
data.new = new; data.new = new;
ret = run_command(cmd_output, sizeof(cmd_output), ret = run_command(cmd_output, sizeof(cmd_output),
lxc_rsync_exec_wrapper, (void *)&data); lxc_storage_rsync_exec_wrapper, (void *)&data);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest, ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest,
new->dest, cmd_output); new->dest, cmd_output);
......
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