Commit 48fd6371 by Serge Hallyn Committed by Stéphane Graber

lxc: manually move NICs back to host after container stops

This prevents things like bridges from being destroyed by the kernel. My hope is that just doing this will be enough to also ensure that the device will be available to be renamed immediately, so that we don't need to do a retry loop. Tested with a dummy device. renaming dummy0 to dummy5 in container, then shutting down container, returns dummy0 to the host. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent 5fa12815
......@@ -2558,11 +2558,49 @@ static int setup_network(struct lxc_list *network)
return 0;
}
void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf)
/* try to move physical nics to the init netns */
void restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
{
int i, ret, oldfd;
char path[MAXPATHLEN];
if (netnsfd < 0)
return;
ret = snprintf(path, MAXPATHLEN, "/proc/self/ns/net");
if (ret < 0 || ret >= MAXPATHLEN) {
WARN("Failed to open monitor netns fd");
return;
}
if ((oldfd = open(path, O_RDONLY)) < 0) {
SYSERROR("Failed to open monitor netns fd");
return;
}
if (setns(netnsfd, 0) != 0) {
SYSERROR("Failed to enter container netns to reset nics");
close(oldfd);
return;
}
for (i=0; i<conf->num_savednics; i++) {
struct saved_nic *s = &conf->saved_nics[i];
if (lxc_netdev_move_by_index(s->ifindex, 1))
WARN("Error moving nic index:%d back to host netns",
s->ifindex);
}
if (setns(oldfd, 0) != 0)
SYSERROR("Failed to re-enter monitor's netns");
close(oldfd);
}
void lxc_rename_phys_nics_on_shutdown(int netnsfd, struct lxc_conf *conf)
{
int i;
if (conf->num_savednics == 0)
return;
INFO("running to reset %d nic names", conf->num_savednics);
restore_phys_nics_to_netns(netnsfd, conf);
for (i=0; i<conf->num_savednics; i++) {
struct saved_nic *s = &conf->saved_nics[i];
INFO("resetting nic %d to %s", s->ifindex, s->orig_name);
......
......@@ -369,7 +369,7 @@ extern int lxc_clear_groups(struct lxc_conf *c);
struct cgroup_process_info;
extern int lxc_setup(struct lxc_handler *handler);
extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf);
extern void lxc_rename_phys_nics_on_shutdown(int netnsfd, struct lxc_conf *conf);
extern int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype);
extern int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype);
......
......@@ -1000,12 +1000,33 @@ out_abort:
return -1;
}
int get_netns_fd(int pid)
{
char path[MAXPATHLEN];
int ret, fd;
ret = snprintf(path, MAXPATHLEN, "/proc/%d/ns/net", pid);
if (ret < 0 || ret >= MAXPATHLEN) {
WARN("Failed to pin netns file for pid %d", pid);
return -1;
}
fd = open(path, O_RDONLY);
if (fd < 0) {
WARN("Failed to pin netns file %s for pid %d: %s",
path, pid, strerror(errno));
return -1;
}
return fd;
}
int __lxc_start(const char *name, struct lxc_conf *conf,
struct lxc_operations* ops, void *data, const char *lxcpath)
{
struct lxc_handler *handler;
int err = -1;
int status;
int netnsfd = -1;
handler = lxc_init(name, conf, lxcpath);
if (!handler) {
......@@ -1032,6 +1053,8 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
goto out_fini_nonet;
}
netnsfd = get_netns_fd(handler->pid);
err = lxc_poll(name, handler);
if (err) {
ERROR("mainloop exited with an error");
......@@ -1065,7 +1088,8 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
}
}
lxc_rename_phys_nics_on_shutdown(handler->conf);
lxc_rename_phys_nics_on_shutdown(netnsfd, handler->conf);
close(netnsfd);
if (handler->pinfd >= 0) {
close(handler->pinfd);
......
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