From: Daniel Lezcano Date: Mon, 10 May 2010 09:50:09 +0000 (+0200) Subject: fix pivot_root temporary directory X-Git-Tag: lxc-0.7.0~84 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1b09f2c057205db6f31caa76c3605eb0dc7eec86;p=thirdparty%2Flxc.git fix pivot_root temporary directory First of all, when trying to start a container in a read-only root lxc-start complains: lxc-start: Read-only file system - can't make temporary mountpoint This is in conf.c:setup_rootfs_pivot_root() function. That function uses optional parameter "lxc.pivotdir", or creates (and later removes) a temporary directory for pivot_root. Obviously there's no way to create a directory in a read-only filesystem. But lxc.pivotdir does not work either. In the function mentioned above it is used with leading dot (eg. if I specify "lxc.pivotdir=pivot" in the config file the pivot_root() syscall will be made to ".pivot" with leading dot, not to "pivot"), but later on it is used without that dot, and fails: lxc-start: No such file or directory - failed to open /pivot/proc/mounts lxc-start: No such file or directory - failed to read or parse mount list '/pivot/proc/mounts' lxc-start: failed to pivot_root to '/stage/t' (that's with "lxc.pivotdir = pivot" in the config file). After symlinking pivot to .pivot it still fails: lxc-start: Device or resource busy - could not unmount old rootfs lxc-start: failed to pivot_root to '/stage/t' Signed-off-by: Daniel Lezcano Reported-by: Michael Tokarev --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index b27a11d14..d6dd2e20a 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -51,10 +51,10 @@ #include "error.h" #include "parse.h" #include "config.h" - -#include -#include -#include /* for lxc_cgroup_set() */ +#include "utils.h" +#include "conf.h" +#include "log.h" +#include "lxc.h" /* for lxc_cgroup_set() */ lxc_log_define(lxc_conf, lxc); @@ -488,12 +488,21 @@ static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir) } pivotdir_is_temp = 1; - } - else { - snprintf(path, sizeof(path), ".%s", pivotdir); + } else { + + snprintf(path, sizeof(path), "%s/%s", rootfs, pivotdir); + + if (access(path, F_OK)) { + if (mkdir_p(path, 0755)) { + SYSERROR("failed to create pivotdir '%s'", path); + return -1; + } + + DEBUG("created '%s' directory", path); + } } - DEBUG("temporary mountpoint for old rootfs is '%s'", path); + DEBUG("mountpoint for old rootfs is '%s'", path); /* pivot_root into our new root fs */ diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 5f3745c78..6279d77b5 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "log.h" @@ -163,3 +164,30 @@ extern int get_u16(ushort *val, const char *arg, int base) return 0; } +extern int mkdir_p(char *dir, mode_t mode) +{ + int ret; + char *d; + + if (!strcmp(dir, "/")) + return 0; + + d = strdup(dir); + if (!d) + return -1; + + ret = mkdir_p(dirname(d), mode); + free(d); + if (ret) + return -1; + + if (!access(dir, F_OK)) + return 0; + + if (mkdir(dir, mode)) { + SYSERROR("failed to create directory '%s'\n", dir); + return -1; + } + + return 0; +} diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 9fd5815b5..114b6688b 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -53,3 +53,4 @@ extern int lxc_copy_file(const char *src, const char *dst); extern int lxc_setup_fs(void); extern int get_u16(ushort *val, const char *arg, int base); +extern int mkdir_p(const char *dir, mode_t mode);