conf: stash lxc_storage into lxc_rootfs and bind to its lifetime

parent c910e00d
......@@ -483,6 +483,43 @@ int run_script(const char *name, const char *section, const char *script, ...)
return run_buffer(buffer);
}
int lxc_storage_prepare(struct lxc_conf *conf)
{
int ret;
struct lxc_rootfs *rootfs = &conf->rootfs;
if (!rootfs->path) {
ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0);
if (ret < 0)
return log_error_errno(-1, errno, "Failed to recursively turn root mount tree into dependent mount");
rootfs->dfd_mnt = open_at(-EBADF, "/", PROTECT_OPATH_DIRECTORY, PROTECT_LOOKUP_ABSOLUTE, 0);
if (rootfs->dfd_mnt < 0)
return -errno;
return 0;
}
ret = access(rootfs->mount, F_OK);
if (ret != 0)
return log_error_errno(-1, errno, "Failed to access to \"%s\". Check it is present",
rootfs->mount);
rootfs->storage = storage_init(conf);
if (!rootfs->storage)
return log_error(-1, "Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"",
rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)");
return 0;
}
void lxc_storage_put(struct lxc_conf *conf)
{
storage_put(conf->rootfs.storage);
conf->rootfs.storage = NULL;
}
/* lxc_rootfs_prepare
* if rootfs is a directory, then open ${rootfs}/.lxc-keep for writing for
* the duration of the container run, to prevent the container from marking
......@@ -490,12 +527,17 @@ int run_script(const char *name, const char *section, const char *script, ...)
* no name pollution is happens.
* don't unlink on NFS to avoid random named stale handles.
*/
int lxc_rootfs_prepare(struct lxc_rootfs *rootfs, bool userns)
int lxc_rootfs_prepare(struct lxc_conf *conf, bool userns)
{
__do_close int dfd_path = -EBADF, fd_pin = -EBADF, fd_userns = -EBADF;
int ret;
struct stat st;
struct statfs stfs;
struct lxc_rootfs *rootfs = &conf->rootfs;
ret = lxc_storage_prepare(conf);
if (ret)
return syserror_set(-EINVAL, "Failed to prepare rootfs storage");
if (!is_empty_string(rootfs->mnt_opts.userns_path)) {
if (!rootfs->path)
......@@ -1286,11 +1328,9 @@ static int lxc_fill_autodev(struct lxc_rootfs *rootfs)
return 0;
}
static int lxc_mount_rootfs(struct lxc_conf *conf)
static int lxc_mount_rootfs(struct lxc_rootfs *rootfs)
{
int ret;
struct lxc_storage *bdev;
struct lxc_rootfs *rootfs = &conf->rootfs;
if (!rootfs->path) {
ret = mount("", "/", NULL, MS_SLAVE | MS_REC, 0);
......@@ -1309,14 +1349,7 @@ static int lxc_mount_rootfs(struct lxc_conf *conf)
return log_error_errno(-1, errno, "Failed to access to \"%s\". Check it is present",
rootfs->mount);
bdev = storage_init(conf);
if (!bdev)
return log_error(-1, "Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"",
rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)");
ret = bdev->ops->mount(bdev);
storage_put(bdev);
ret = rootfs->storage->ops->mount(rootfs->storage);
if (ret < 0)
return log_error(-1, "Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\"",
rootfs->path, rootfs->mount,
......@@ -3361,7 +3394,7 @@ int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name,
if (ret < 0)
return log_error(-1, "Failed to run pre-mount hooks");
ret = lxc_mount_rootfs(conf);
ret = lxc_mount_rootfs(&conf->rootfs);
if (ret < 0)
return log_error(-1, "Failed to setup rootfs for");
......
......@@ -24,6 +24,7 @@
#include "memory_utils.h"
#include "ringbuf.h"
#include "start.h"
#include "storage/storage.h"
#include "string_utils.h"
#include "terminal.h"
......@@ -232,6 +233,7 @@ struct lxc_rootfs {
char *data;
bool managed;
struct lxc_mount_options mnt_opts;
struct lxc_storage *storage;
};
/*
......@@ -500,7 +502,9 @@ extern thread_local struct lxc_conf *current_config;
__hidden extern int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, char *argv[]);
__hidden extern struct lxc_conf *lxc_conf_init(void);
__hidden extern void lxc_conf_free(struct lxc_conf *conf);
__hidden extern int lxc_rootfs_prepare(struct lxc_rootfs *rootfs, bool userns);
__hidden extern int lxc_storage_prepare(struct lxc_conf *conf);
__hidden extern int lxc_rootfs_prepare(struct lxc_conf *conf, bool userns);
__hidden extern void lxc_storage_put(struct lxc_conf *conf);
__hidden extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid);
__hidden extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
__hidden extern void lxc_delete_tty(struct lxc_tty_info *ttys);
......@@ -590,6 +594,8 @@ static inline void put_lxc_rootfs(struct lxc_rootfs *rootfs, bool unpin)
close_prot_errno_disarm(rootfs->mnt_opts.userns_fd);
if (unpin)
close_prot_errno_disarm(rootfs->fd_path_pin);
storage_put(rootfs->storage);
rootfs->storage = NULL;
}
}
......
......@@ -964,6 +964,10 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
if (unshare(CLONE_NEWNS))
goto out_fini_handler;
ret = lxc_storage_prepare(c->lxc_conf);
if (ret)
goto out_fini_handler;
/* CRIU needs the lxc root bind mounted so that it is the root of some
* mount. */
rootfs = &c->lxc_conf->rootfs;
......
......@@ -1345,11 +1345,12 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
_exit(EXIT_FAILURE);
}
bdev = storage_init(c->lxc_conf);
if (!bdev) {
ret = lxc_storage_prepare(conf);
if (ret) {
ERROR("Failed to initialize storage");
_exit(EXIT_FAILURE);
}
bdev = conf->rootfs.storage;
euid = geteuid();
if (euid == 0) {
......@@ -3654,14 +3655,15 @@ static int clone_update_rootfs(struct clone_update_data *data)
if (unshare(CLONE_NEWNS) < 0)
return -1;
bdev = storage_init(c->lxc_conf);
if (!bdev)
ret = lxc_storage_prepare(conf);
if (ret)
return -1;
bdev = conf->rootfs.storage;
if (!strequal(bdev->type, "dir")) {
if (unshare(CLONE_NEWNS) < 0) {
ERROR("error unsharing mounts");
storage_put(bdev);
lxc_storage_put(conf);
return -1;
}
......@@ -3669,7 +3671,7 @@ static int clone_update_rootfs(struct clone_update_data *data)
SYSERROR("Failed to recursively turn root mount tree into dependent mount. Continuing...");
if (bdev->ops->mount(bdev) < 0) {
storage_put(bdev);
lxc_storage_put(conf);
return -1;
}
} else { /* TODO come up with a better way */
......@@ -3696,14 +3698,14 @@ static int clone_update_rootfs(struct clone_update_data *data)
if (run_lxc_hooks(c->name, "clone", conf, hookargs)) {
ERROR("Error executing clone hook for %s", c->name);
storage_put(bdev);
lxc_storage_put(conf);
return -1;
}
}
if (!(flags & LXC_CLONE_KEEPNAME)) {
ret = strnprintf(path, sizeof(path), "%s/etc/hostname", bdev->dest);
storage_put(bdev);
lxc_storage_put(conf);
if (ret < 0)
return -1;
......@@ -3724,7 +3726,7 @@ static int clone_update_rootfs(struct clone_update_data *data)
if (fclose(fout) < 0)
return -1;
} else {
storage_put(bdev);
lxc_storage_put(conf);
}
return 0;
......@@ -3993,14 +3995,14 @@ static bool do_lxcapi_rename(struct lxc_container *c, const char *newname)
return false;
}
bdev = storage_init(c->lxc_conf);
if (!bdev) {
if (lxc_storage_prepare(c->lxc_conf)) {
ERROR("Failed to find original backing store type");
return false;
}
bdev = c->lxc_conf->rootfs.storage;
newc = lxcapi_clone(c, newname, c->config_path, LXC_CLONE_KEEPMACADDR, NULL, bdev->type, 0, NULL);
storage_put(bdev);
lxc_storage_put(c->lxc_conf);
if (!newc) {
lxc_container_put(newc);
return false;
......@@ -4376,11 +4378,11 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
return false;
}
bdev = storage_init(c->lxc_conf);
if (!bdev) {
if (lxc_storage_prepare(c->lxc_conf)) {
ERROR("Failed to find original backing store type");
return false;
}
bdev = c->lxc_conf->rootfs.storage;
/* For an overlay container the rootfs is considered immutable
* and cannot be removed when restoring from a snapshot. We pass this
......@@ -4394,7 +4396,7 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
newname = c->name;
if (!get_snappath_dir(c, clonelxcpath)) {
storage_put(bdev);
lxc_storage_put(c->lxc_conf);
return false;
}
/* how should we lock this? */
......@@ -4406,7 +4408,7 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
if (snap)
lxc_container_put(snap);
storage_put(bdev);
lxc_storage_put(c->lxc_conf);
return false;
}
......@@ -4414,7 +4416,7 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
if (!container_destroy(c, bdev)) {
ERROR("Could not destroy existing container %s", newname);
lxc_container_put(snap);
storage_put(bdev);
lxc_storage_put(c->lxc_conf);
return false;
}
}
......@@ -4427,7 +4429,7 @@ static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char *snap
rest = lxcapi_clone(snap, newname, c->config_path, flags, bdev->type,
NULL, 0, NULL);
storage_put(bdev);
lxc_storage_put(c->lxc_conf);
if (rest && lxcapi_is_defined(rest))
b = true;
......
......@@ -2034,7 +2034,7 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
* it readonly.
* If the container is unprivileged then skip rootfs pinning.
*/
ret = lxc_rootfs_prepare(&conf->rootfs, !lxc_list_empty(&conf->id_map));
ret = lxc_rootfs_prepare(conf, !lxc_list_empty(&conf->id_map));
if (ret) {
ERROR("Failed to handle rootfs pinning for container \"%s\"", handler->name);
ret = -1;
......
......@@ -86,12 +86,14 @@ int lxc_rsync(struct rsync_data *data)
ERROR("Failed mounting \"%s\" on \"%s\"", orig->src, orig->dest);
return -1;
}
TRACE("Mounted \"%s\" on \"%s\"", orig->src, orig->dest);
ret = new->ops->mount(new);
if (ret < 0) {
ERROR("Failed mounting \"%s\" onto \"%s\"", new->src, new->dest);
return -1;
}
TRACE("Mounted \"%s\" on \"%s\"", new->src, new->dest);
if (!lxc_switch_uid_gid(0, 0))
return -1;
......
......@@ -314,6 +314,15 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
const char *oldpath = c->config_path;
char cmd_output[PATH_MAX] = {0};
struct rsync_data data = {0};
struct lxc_rootfs new_rootfs = {
.managed = true,
.dfd_mnt = -EBADF,
.dfd_dev = -EBADF,
.dfd_host = -EBADF,
.fd_path_pin = -EBADF,
.dfd_idmapped = -EBADF,
.mnt_opts.userns_fd = -EBADF,
};
if (!src) {
ERROR("No rootfs specified");
......@@ -329,11 +338,21 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
return NULL;
}
orig = storage_init(c->lxc_conf);
if (!orig) {
ret = lxc_storage_prepare(c->lxc_conf);
if (ret) {
ERROR("Failed to detect storage driver for \"%s\"", oldname);
return NULL;
}
orig = c->lxc_conf->rootfs.storage;
if (c->lxc_conf->rootfs.dfd_idmapped >= 0) {
new_rootfs.dfd_idmapped = dup_cloexec(new_rootfs.dfd_idmapped);
if (new_rootfs.dfd_idmapped < 0) {
SYSERROR("Failed to duplicate user namespace file descriptor");
lxc_storage_put(c->lxc_conf);
return NULL;
}
}
if (!orig->dest) {
size_t len;
......@@ -404,6 +423,7 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
goto on_error_put_orig;
}
TRACE("Initialized %s storage driver", new->type);
new->rootfs = &new_rootfs;
/* create new paths */
ret = new->ops->clone_paths(orig, new, oldname, cname, oldpath, lxcpath,
......@@ -499,7 +519,7 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
}
on_success:
storage_put(orig);
lxc_storage_put(c->lxc_conf);
return new;
......@@ -507,7 +527,7 @@ on_error_put_new:
storage_put(new);
on_error_put_orig:
storage_put(orig);
lxc_storage_put(c->lxc_conf);
return NULL;
}
......@@ -643,10 +663,12 @@ bool storage_is_dir(struct lxc_conf *conf)
void storage_put(struct lxc_storage *bdev)
{
free(bdev->mntopts);
free(bdev->src);
free(bdev->dest);
free(bdev);
if (bdev) {
free_disarm(bdev->mntopts);
free_disarm(bdev->src);
free_disarm(bdev->dest);
free_disarm(bdev);
}
}
bool rootfs_is_blockdev(struct lxc_conf *conf)
......
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