mirror of
git://github.com/lxc/lxc
synced 2025-09-05 10:49:38 +00:00
overlay: correctly restore from snapshot
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
@@ -106,7 +106,8 @@ static bool do_lxcapi_destroy(struct lxc_container *c);
|
||||
static const char *lxcapi_get_config_path(struct lxc_container *c);
|
||||
#define do_lxcapi_get_config_path(c) lxcapi_get_config_path(c)
|
||||
static bool do_lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v);
|
||||
static bool container_destroy(struct lxc_container *c);
|
||||
static bool container_destroy(struct lxc_container *c,
|
||||
struct lxc_storage *storage);
|
||||
static bool get_snappath_dir(struct lxc_container *c, char *snappath);
|
||||
static bool lxcapi_snapshot_destroy_all(struct lxc_container *c);
|
||||
static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file);
|
||||
@@ -1742,7 +1743,7 @@ out_unlock:
|
||||
remove_partial(c, partial_fd);
|
||||
out:
|
||||
if (!ret)
|
||||
container_destroy(c);
|
||||
container_destroy(c, NULL);
|
||||
free_tpath:
|
||||
free(tpath);
|
||||
return ret;
|
||||
@@ -2580,11 +2581,21 @@ static int lxc_rmdir_onedev_wrapper(void *data)
|
||||
return lxc_rmdir_onedev(arg, "snaps");
|
||||
}
|
||||
|
||||
static bool container_destroy(struct lxc_container *c)
|
||||
static int lxc_unlink_exec_wrapper(void *data)
|
||||
{
|
||||
char *arg = data;
|
||||
return unlink(arg);
|
||||
}
|
||||
|
||||
static bool container_destroy(struct lxc_container *c,
|
||||
struct lxc_storage *storage)
|
||||
{
|
||||
const char *p1;
|
||||
size_t len;
|
||||
struct lxc_conf *conf;
|
||||
char *path = NULL;
|
||||
bool bret = false;
|
||||
int ret = 0;
|
||||
struct lxc_conf *conf;
|
||||
|
||||
if (!c || !do_lxcapi_is_defined(c))
|
||||
return false;
|
||||
@@ -2601,28 +2612,27 @@ static bool container_destroy(struct lxc_container *c)
|
||||
|
||||
if (conf && !lxc_list_empty(&conf->hooks[LXCHOOK_DESTROY])) {
|
||||
/* Start of environment variable setup for hooks */
|
||||
if (c->name && setenv("LXC_NAME", c->name, 1)) {
|
||||
SYSERROR("failed to set environment variable for container name");
|
||||
}
|
||||
if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) {
|
||||
SYSERROR("failed to set environment variable for config path");
|
||||
}
|
||||
if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) {
|
||||
SYSERROR("failed to set environment variable for rootfs mount");
|
||||
}
|
||||
if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) {
|
||||
SYSERROR("failed to set environment variable for rootfs mount");
|
||||
}
|
||||
if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) {
|
||||
SYSERROR("failed to set environment variable for console path");
|
||||
}
|
||||
if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) {
|
||||
SYSERROR("failed to set environment variable for console log");
|
||||
}
|
||||
if (c->name && setenv("LXC_NAME", c->name, 1))
|
||||
SYSERROR("Failed to set environment variable for container name");
|
||||
|
||||
if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1))
|
||||
SYSERROR("Failed to set environment variable for config path");
|
||||
|
||||
if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1))
|
||||
SYSERROR("Failed to set environment variable for rootfs mount");
|
||||
|
||||
if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1))
|
||||
SYSERROR("Failed to set environment variable for rootfs mount");
|
||||
|
||||
if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1))
|
||||
SYSERROR("Failed to set environment variable for console path");
|
||||
|
||||
if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1))
|
||||
SYSERROR("Failed to set environment variable for console log");
|
||||
/* End of environment variable setup for hooks */
|
||||
|
||||
if (run_lxc_hooks(c->name, "destroy", conf, c->get_config_path(c), NULL)) {
|
||||
ERROR("Error executing clone hook for %s", c->name);
|
||||
ERROR("Failed to execute clone hook for \"%s\"", c->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -2645,23 +2655,72 @@ static bool container_destroy(struct lxc_container *c)
|
||||
|
||||
mod_all_rdeps(c, false);
|
||||
|
||||
const char *p1 = do_lxcapi_get_config_path(c);
|
||||
char *path = alloca(strlen(p1) + strlen(c->name) + 2);
|
||||
sprintf(path, "%s/%s", p1, c->name);
|
||||
p1 = do_lxcapi_get_config_path(c);
|
||||
/* strlen(p1)
|
||||
* +
|
||||
* /
|
||||
* +
|
||||
* strlen(c->name)
|
||||
* +
|
||||
* /
|
||||
* +
|
||||
* strlen("config") = 6
|
||||
* +
|
||||
* \0
|
||||
*/
|
||||
len = strlen(p1) + 1 + strlen(c->name) + 1 + 6 + 1;
|
||||
path = malloc(len);
|
||||
if (!path) {
|
||||
ERROR("Failed to allocate memory");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* For an overlay container the rootfs is considered immutable and
|
||||
* cannot be removed when restoring from a snapshot.
|
||||
*/
|
||||
if (storage && (!strcmp(storage->type, "overlay") ||
|
||||
!strcmp(storage->type, "overlayfs")) &&
|
||||
(storage->flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)) {
|
||||
ret = snprintf(path, len, "%s/%s/config", p1, c->name);
|
||||
if (ret < 0 || (size_t)ret >= len)
|
||||
goto out;
|
||||
|
||||
if (am_unpriv())
|
||||
ret = userns_exec_1(conf, lxc_unlink_exec_wrapper, path,
|
||||
"lxc_unlink_exec_wrapper");
|
||||
else
|
||||
ret = unlink(path);
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to destroy config file \"%s\" for \"%s\"",
|
||||
path, c->name);
|
||||
goto out;
|
||||
}
|
||||
INFO("Destroyed config file \"%s\" for \"%s\"", path, c->name);
|
||||
|
||||
bret = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = snprintf(path, len, "%s/%s", p1, c->name);
|
||||
if (ret < 0 || (size_t)ret >= len)
|
||||
goto out;
|
||||
if (am_unpriv())
|
||||
ret = userns_exec_1(conf, lxc_rmdir_onedev_wrapper, path,
|
||||
"lxc_rmdir_onedev_wrapper");
|
||||
else
|
||||
ret = lxc_rmdir_onedev(path, "snaps");
|
||||
if (ret < 0) {
|
||||
ERROR("Error destroying container directory for %s", c->name);
|
||||
ERROR("Failed to destroy directory \"%s\" for \"%s\"", path,
|
||||
c->name);
|
||||
goto out;
|
||||
}
|
||||
INFO("Destroyed directory for %s", c->name);
|
||||
INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name);
|
||||
|
||||
bret = true;
|
||||
|
||||
out:
|
||||
if (path)
|
||||
free(path);
|
||||
container_disk_unlock(c);
|
||||
return bret;
|
||||
}
|
||||
@@ -2680,7 +2739,7 @@ static bool do_lxcapi_destroy(struct lxc_container *c)
|
||||
return false;
|
||||
}
|
||||
|
||||
return container_destroy(c);
|
||||
return container_destroy(c, NULL);
|
||||
}
|
||||
|
||||
WRAP_API(bool, lxcapi_destroy)
|
||||
@@ -3314,14 +3373,15 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
|
||||
const char *bdevtype, const char *bdevdata, uint64_t newsize,
|
||||
char **hookargs)
|
||||
{
|
||||
struct lxc_container *c2 = NULL;
|
||||
char newpath[MAXPATHLEN];
|
||||
int ret, storage_copied = 0;
|
||||
char *origroot = NULL, *saved_unexp_conf = NULL;
|
||||
int ret;
|
||||
struct clone_update_data data;
|
||||
size_t saved_unexp_len;
|
||||
FILE *fout;
|
||||
pid_t pid;
|
||||
int storage_copied = 0;
|
||||
char *origroot = NULL, *saved_unexp_conf = NULL;
|
||||
struct lxc_container *c2 = NULL;
|
||||
|
||||
if (!c || !do_lxcapi_is_defined(c))
|
||||
return NULL;
|
||||
@@ -3344,6 +3404,7 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
|
||||
SYSERROR("clone: failed making config pathname");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (file_exists(newpath)) {
|
||||
ERROR("error: clone: %s exists", newpath);
|
||||
goto out;
|
||||
@@ -3394,9 +3455,18 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
|
||||
SYSERROR("clone: failed making rootfs pathname");
|
||||
goto out;
|
||||
}
|
||||
if (mkdir(newpath, 0755) < 0) {
|
||||
SYSERROR("error creating %s", newpath);
|
||||
goto out;
|
||||
|
||||
ret = mkdir(newpath, 0755);
|
||||
if (ret < 0) {
|
||||
/* For an overlay container the rootfs is considered immutable
|
||||
* and will not have been removed when restoring from a
|
||||
* snapshot.
|
||||
*/
|
||||
if (errno != ENOENT &&
|
||||
!(flags & LXC_STORAGE_INTERNAL_OVERLAY_RESTORE)) {
|
||||
SYSERROR("Failed to create directory \"%s\"", newpath);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (am_unpriv()) {
|
||||
@@ -3539,7 +3609,7 @@ static bool do_lxcapi_rename(struct lxc_container *c, const char *newname)
|
||||
if (newc && lxcapi_is_defined(newc))
|
||||
lxc_container_put(newc);
|
||||
|
||||
if (!container_destroy(c)) {
|
||||
if (!container_destroy(c, NULL)) {
|
||||
ERROR("Could not destroy existing container %s", c->name);
|
||||
return false;
|
||||
}
|
||||
@@ -3873,12 +3943,21 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
|
||||
return false;
|
||||
}
|
||||
|
||||
bdev = storage_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
|
||||
bdev = storage_init(c->lxc_conf, c->lxc_conf->rootfs.path,
|
||||
c->lxc_conf->rootfs.mount, NULL);
|
||||
if (!bdev) {
|
||||
ERROR("Failed to find original backing store type");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For an overlay container the rootfs is considered immutable
|
||||
* and cannot be removed when restoring from a snapshot. We pass this
|
||||
* internal flag along to communicate this to various parts of the
|
||||
* codebase.
|
||||
*/
|
||||
if (!strcmp(bdev->type, "overlay") || !strcmp(bdev->type, "overlayfs"))
|
||||
bdev->flags |= LXC_STORAGE_INTERNAL_OVERLAY_RESTORE;
|
||||
|
||||
if (!newname)
|
||||
newname = c->name;
|
||||
|
||||
@@ -3891,13 +3970,14 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
|
||||
snap = lxc_container_new(snapname, clonelxcpath);
|
||||
if (!snap || !lxcapi_is_defined(snap)) {
|
||||
ERROR("Could not open snapshot %s", snapname);
|
||||
if (snap) lxc_container_put(snap);
|
||||
if (snap)
|
||||
lxc_container_put(snap);
|
||||
storage_put(bdev);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(c->name, newname) == 0) {
|
||||
if (!container_destroy(c)) {
|
||||
if (!strcmp(c->name, newname)) {
|
||||
if (!container_destroy(c, bdev)) {
|
||||
ERROR("Could not destroy existing container %s", newname);
|
||||
lxc_container_put(snap);
|
||||
storage_put(bdev);
|
||||
@@ -3907,6 +3987,9 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
|
||||
|
||||
if (strcmp(bdev->type, "dir") != 0 && strcmp(bdev->type, "loop") != 0)
|
||||
flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT;
|
||||
|
||||
if (!strcmp(bdev->type, "overlay") || !strcmp(bdev->type, "overlayfs"))
|
||||
flags |= LXC_STORAGE_INTERNAL_OVERLAY_RESTORE;
|
||||
rest = lxcapi_clone(snap, newname, c->config_path, flags,
|
||||
bdev->type, NULL, 0, NULL);
|
||||
storage_put(bdev);
|
||||
@@ -3914,6 +3997,7 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
|
||||
b = true;
|
||||
if (rest)
|
||||
lxc_container_put(rest);
|
||||
|
||||
lxc_container_put(snap);
|
||||
return b;
|
||||
}
|
||||
@@ -4414,7 +4498,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
|
||||
|
||||
if (ongoing_create(c) == 2) {
|
||||
ERROR("Error: %s creation was not completed", c->name);
|
||||
container_destroy(c);
|
||||
container_destroy(c, NULL);
|
||||
lxcapi_clear_config(c);
|
||||
}
|
||||
c->daemonize = true;
|
||||
|
@@ -438,8 +438,8 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
|
||||
data.orig = orig;
|
||||
data.new = new;
|
||||
if (am_unpriv()) {
|
||||
ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &data,
|
||||
"lxc_rsync_exec_wrapper");
|
||||
ret = userns_exec_1(conf, lxc_storage_rsync_exec_wrapper, &data,
|
||||
"lxc_storage_rsync_exec_wrapper");
|
||||
if (ret < 0) {
|
||||
ERROR("Failed to rsync from \"%s\" into \"%s\"",
|
||||
orig->dest, new->dest);
|
||||
@@ -450,7 +450,7 @@ bool btrfs_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
|
||||
}
|
||||
|
||||
ret = run_command(cmd_output, sizeof(cmd_output),
|
||||
lxc_rsync_exec_wrapper, (void *)&data);
|
||||
lxc_storage_rsync_exec_wrapper, (void *)&data);
|
||||
if (ret < 0) {
|
||||
ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest,
|
||||
new->dest, cmd_output);
|
||||
|
@@ -507,7 +507,7 @@ bool lvm_create_clone(struct lxc_conf *conf, struct lxc_storage *orig,
|
||||
data.orig = orig;
|
||||
data.new = new;
|
||||
ret = run_command(cmd_output, sizeof(cmd_output),
|
||||
lxc_rsync_exec_wrapper, (void *)&data);
|
||||
lxc_storage_rsync_exec_wrapper, (void *)&data);
|
||||
if (ret < 0) {
|
||||
ERROR("Failed to rsync from \"%s\" to \"%s\"", orig->dest,
|
||||
new->dest);
|
||||
|
@@ -43,7 +43,7 @@ static char *ovl_name;
|
||||
static char *ovl_version[] = {"overlay", "overlayfs"};
|
||||
|
||||
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);
|
||||
static int ovl_remount_on_enodev(const char *lower, const char *target,
|
||||
const char *name, unsigned long mountflags,
|
||||
@@ -292,14 +292,16 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
|
||||
free(osrc);
|
||||
free(ndelta);
|
||||
if (ret < 0 || (size_t)ret >= len) {
|
||||
ERROR("Failed to create string");
|
||||
free(osrc);
|
||||
free(ndelta);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ovl_do_rsync(orig, new, conf);
|
||||
ret = ovl_do_rsync(odelta, ndelta, conf);
|
||||
free(osrc);
|
||||
free(ndelta);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
@@ -462,6 +464,12 @@ int ovl_destroy(struct lxc_storage *orig)
|
||||
if (!ovl && strncmp(upper, "overlayfs:", 10))
|
||||
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)
|
||||
upper += 8;
|
||||
else
|
||||
@@ -953,28 +961,25 @@ static char *ovl_detect_name(void)
|
||||
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)
|
||||
{
|
||||
int ret = -1;
|
||||
struct rsync_data rdata = {0, 0};
|
||||
struct rsync_data_char rdata = {0};
|
||||
char cmd_output[MAXPATHLEN] = {0};
|
||||
|
||||
rdata.orig = orig;
|
||||
rdata.new = new;
|
||||
if (am_unpriv()) {
|
||||
rdata.src = (char *)src;
|
||||
rdata.dest = (char *)dest;
|
||||
if (am_unpriv())
|
||||
ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &rdata,
|
||||
"lxc_rsync_exec_wrapper");
|
||||
if (ret < 0)
|
||||
ERROR("Failed to rsync from \"%s\" into \"%s\"",
|
||||
orig->dest, new->dest);
|
||||
} else {
|
||||
else
|
||||
ret = run_command(cmd_output, sizeof(cmd_output),
|
||||
lxc_rsync_exec_wrapper, (void *)&rdata);
|
||||
if (ret < 0)
|
||||
ERROR("Failed to rsync from \"%s\" into \"%s\": %s",
|
||||
orig->dest, new->dest, cmd_output);
|
||||
}
|
||||
if (ret < 0)
|
||||
ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", src, dest,
|
||||
cmd_output[0] != '\0' ? ": " : "",
|
||||
cmd_output[0] != '\0' ? cmd_output : "");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -39,12 +39,28 @@
|
||||
|
||||
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;
|
||||
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 ret;
|
||||
@@ -70,8 +86,8 @@ int lxc_rsync_exec(const char *src, const char *dest)
|
||||
int lxc_rsync(struct rsync_data *data)
|
||||
{
|
||||
int ret;
|
||||
struct lxc_storage *orig = data->orig, *new = data->new;
|
||||
char *dest, *src;
|
||||
struct lxc_storage *orig = data->orig, *new = data->new;
|
||||
|
||||
ret = unshare(CLONE_NEWNS);
|
||||
if (ret < 0) {
|
||||
@@ -101,6 +117,7 @@ int lxc_rsync(struct rsync_data *data)
|
||||
ret = lxc_switch_uid_gid(0, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
ret = lxc_setgroups(0, NULL);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
@@ -39,6 +39,7 @@ struct rsync_data_char {
|
||||
|
||||
/* new helpers */
|
||||
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(struct rsync_data *data);
|
||||
|
||||
|
@@ -502,11 +502,11 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
|
||||
data.orig = orig;
|
||||
data.new = new;
|
||||
if (am_unpriv())
|
||||
ret = userns_exec_1(c->lxc_conf, lxc_rsync_exec_wrapper, &data,
|
||||
"lxc_rsync_exec_wrapper");
|
||||
ret = userns_exec_1(c->lxc_conf, lxc_storage_rsync_exec_wrapper,
|
||||
&data, "lxc_storage_rsync_exec_wrapper");
|
||||
else
|
||||
ret = run_command(cmd_output, sizeof(cmd_output),
|
||||
lxc_rsync_exec_wrapper, (void *)&data);
|
||||
lxc_storage_rsync_exec_wrapper, (void *)&data);
|
||||
if (ret < 0) {
|
||||
ERROR("Failed to rsync from \"%s\" into \"%s\"%s%s", orig->dest,
|
||||
new->dest,
|
||||
@@ -598,6 +598,8 @@ struct lxc_storage *storage_init(struct lxc_conf *conf, const char *src,
|
||||
struct lxc_storage *bdev;
|
||||
const struct lxc_storage_type *q;
|
||||
|
||||
BUILD_BUG_ON(LXC_STORAGE_INTERNAL_OVERLAY_RESTORE <= LXC_CLONE_MAXFLAGS);
|
||||
|
||||
if (!src)
|
||||
src = conf->rootfs.path;
|
||||
|
||||
|
@@ -57,6 +57,8 @@
|
||||
#define DEFAULT_FS_SIZE 1073741824
|
||||
#define DEFAULT_FSTYPE "ext3"
|
||||
|
||||
#define LXC_STORAGE_INTERNAL_OVERLAY_RESTORE (1 << 6)
|
||||
|
||||
struct lxc_storage;
|
||||
|
||||
struct lxc_storage_ops {
|
||||
@@ -97,6 +99,7 @@ struct lxc_storage {
|
||||
int lofd;
|
||||
/* index for the connected nbd device. */
|
||||
int nbd_idx;
|
||||
int flags;
|
||||
};
|
||||
|
||||
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,
|
||||
data.orig = orig;
|
||||
data.new = new;
|
||||
ret = run_command(cmd_output, sizeof(cmd_output),
|
||||
lxc_rsync_exec_wrapper, (void *)&data);
|
||||
lxc_storage_rsync_exec_wrapper, (void *)&data);
|
||||
if (ret < 0) {
|
||||
ERROR("Failed to rsync from \"%s\" into \"%s\": %s", orig->dest,
|
||||
new->dest, cmd_output);
|
||||
|
Reference in New Issue
Block a user