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