Commit a17b1e65 by Stéphane Graber

Implement lxc.rootfs.options

This introduces a new lxc.rootfs.options which lets you pass new mountflags/mountdata when mounting the root filesystem. Signed-off-by: 's avatarStéphane Graber <stgraber@ubuntu.com> Acked-by: 's avatarSerge E. Hallyn <serge.hallyn@ubuntu.com>
parent 44fa8e7e
...@@ -864,6 +864,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ...@@ -864,6 +864,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<varlistentry> <varlistentry>
<term> <term>
<option>lxc.rootfs.options</option>
</term>
<listitem>
<para>
extra mount options to use when mounting the rootfs.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>lxc.pivotdir</option> <option>lxc.pivotdir</option>
</term> </term>
<listitem> <listitem>
......
...@@ -121,9 +121,11 @@ static int find_fstype_cb(char* buffer, void *data) ...@@ -121,9 +121,11 @@ static int find_fstype_cb(char* buffer, void *data)
struct cbarg { struct cbarg {
const char *rootfs; const char *rootfs;
const char *target; const char *target;
int mntopt; const char *options;
} *cbarg = data; } *cbarg = data;
unsigned long mntflags;
char *mntdata;
char *fstype; char *fstype;
/* we don't try 'nodev' entries */ /* we don't try 'nodev' entries */
...@@ -137,29 +139,38 @@ static int find_fstype_cb(char* buffer, void *data) ...@@ -137,29 +139,38 @@ static int find_fstype_cb(char* buffer, void *data)
DEBUG("trying to mount '%s'->'%s' with fstype '%s'", DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
cbarg->rootfs, cbarg->target, fstype); cbarg->rootfs, cbarg->target, fstype);
if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) { if (parse_mntopts(cbarg->options, &mntflags, &mntdata) < 0) {
free(mntdata);
return 0;
}
if (mount(cbarg->rootfs, cbarg->target, fstype, mntflags, mntdata)) {
DEBUG("mount failed with error: %s", strerror(errno)); DEBUG("mount failed with error: %s", strerror(errno));
free(mntdata);
return 0; return 0;
} }
free(mntdata);
INFO("mounted '%s' on '%s', with fstype '%s'", INFO("mounted '%s' on '%s', with fstype '%s'",
cbarg->rootfs, cbarg->target, fstype); cbarg->rootfs, cbarg->target, fstype);
return 1; return 1;
} }
static int mount_unknown_fs(const char *rootfs, const char *target, int mntopt) static int mount_unknown_fs(const char *rootfs, const char *target,
const char *options)
{ {
int i; int i;
struct cbarg { struct cbarg {
const char *rootfs; const char *rootfs;
const char *target; const char *target;
int mntopt; const char *options;
} cbarg = { } cbarg = {
.rootfs = rootfs, .rootfs = rootfs,
.target = target, .target = target,
.mntopt = mntopt, .options = options,
}; };
/* /*
...@@ -291,7 +302,7 @@ static int detect_fs(struct bdev *bdev, char *type, int len) ...@@ -291,7 +302,7 @@ static int detect_fs(struct bdev *bdev, char *type, int len)
if (unshare(CLONE_NEWNS) < 0) if (unshare(CLONE_NEWNS) < 0)
exit(1); exit(1);
ret = mount_unknown_fs(srcdev, bdev->dest, 0); ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
if (ret < 0) { if (ret < 0) {
ERROR("failed mounting %s onto %s to detect fstype", srcdev, bdev->dest); ERROR("failed mounting %s onto %s to detect fstype", srcdev, bdev->dest);
exit(1); exit(1);
...@@ -355,11 +366,23 @@ static int dir_detect(const char *path) ...@@ -355,11 +366,23 @@ static int dir_detect(const char *path)
// //
static int dir_mount(struct bdev *bdev) static int dir_mount(struct bdev *bdev)
{ {
unsigned long mntflags;
char *mntdata;
int ret;
if (strcmp(bdev->type, "dir")) if (strcmp(bdev->type, "dir"))
return -22; return -22;
if (!bdev->src || !bdev->dest) if (!bdev->src || !bdev->dest)
return -22; return -22;
return mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC, NULL);
if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -22;
}
ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
free(mntdata);
return ret;
} }
static int dir_umount(struct bdev *bdev) static int dir_umount(struct bdev *bdev)
...@@ -532,11 +555,23 @@ static int zfs_detect(const char *path) ...@@ -532,11 +555,23 @@ static int zfs_detect(const char *path)
static int zfs_mount(struct bdev *bdev) static int zfs_mount(struct bdev *bdev)
{ {
unsigned long mntflags;
char *mntdata;
int ret;
if (strcmp(bdev->type, "zfs")) if (strcmp(bdev->type, "zfs"))
return -22; return -22;
if (!bdev->src || !bdev->dest) if (!bdev->src || !bdev->dest)
return -22; return -22;
return mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC, NULL);
if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -22;
}
ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
free(mntdata);
return ret;
} }
static int zfs_umount(struct bdev *bdev) static int zfs_umount(struct bdev *bdev)
...@@ -783,7 +818,7 @@ static int lvm_mount(struct bdev *bdev) ...@@ -783,7 +818,7 @@ static int lvm_mount(struct bdev *bdev)
return -22; return -22;
/* if we might pass in data sometime, then we'll have to enrich /* if we might pass in data sometime, then we'll have to enrich
* mount_unknown_fs */ * mount_unknown_fs */
return mount_unknown_fs(bdev->src, bdev->dest, 0); return mount_unknown_fs(bdev->src, bdev->dest, bdev->mntopts);
} }
static int lvm_umount(struct bdev *bdev) static int lvm_umount(struct bdev *bdev)
...@@ -996,9 +1031,9 @@ static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldna ...@@ -996,9 +1031,9 @@ static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldna
return -1; return -1;
} }
if (orig->data) { if (orig->mntopts) {
new->data = strdup(orig->data); new->mntopts = strdup(orig->mntopts);
if (!new->data) if (!new->mntopts)
return -1; return -1;
} }
...@@ -1191,11 +1226,23 @@ static int btrfs_detect(const char *path) ...@@ -1191,11 +1226,23 @@ static int btrfs_detect(const char *path)
static int btrfs_mount(struct bdev *bdev) static int btrfs_mount(struct bdev *bdev)
{ {
unsigned long mntflags;
char *mntdata;
int ret;
if (strcmp(bdev->type, "btrfs")) if (strcmp(bdev->type, "btrfs"))
return -22; return -22;
if (!bdev->src || !bdev->dest) if (!bdev->src || !bdev->dest)
return -22; return -22;
return mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC, NULL);
if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -22;
}
ret = mount(bdev->src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags, mntdata);
free(mntdata);
return ret;
} }
static int btrfs_umount(struct bdev *bdev) static int btrfs_umount(struct bdev *bdev)
...@@ -1356,7 +1403,7 @@ static int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *old ...@@ -1356,7 +1403,7 @@ static int btrfs_clonepaths(struct bdev *orig, struct bdev *new, const char *old
if ((new->dest = strdup(new->src)) == NULL) if ((new->dest = strdup(new->src)) == NULL)
return -1; return -1;
if (orig->data && (new->data = strdup(orig->data)) == NULL) if (orig->mntopts && (new->mntopts = strdup(orig->mntopts)) == NULL)
return -1; return -1;
if (snap) if (snap)
...@@ -1508,7 +1555,7 @@ static int loop_mount(struct bdev *bdev) ...@@ -1508,7 +1555,7 @@ static int loop_mount(struct bdev *bdev)
goto out; goto out;
} }
ret = mount_unknown_fs(loname, bdev->dest, 0); ret = mount_unknown_fs(loname, bdev->dest, bdev->mntopts);
if (ret < 0) if (ret < 0)
ERROR("Error mounting %s\n", bdev->src); ERROR("Error mounting %s\n", bdev->src);
else else
...@@ -1717,6 +1764,8 @@ static int overlayfs_mount(struct bdev *bdev) ...@@ -1717,6 +1764,8 @@ static int overlayfs_mount(struct bdev *bdev)
{ {
char *options, *dup, *lower, *upper; char *options, *dup, *lower, *upper;
int len; int len;
unsigned long mntflags;
char *mntdata;
int ret; int ret;
if (strcmp(bdev->type, "overlayfs")) if (strcmp(bdev->type, "overlayfs"))
...@@ -1735,15 +1784,30 @@ static int overlayfs_mount(struct bdev *bdev) ...@@ -1735,15 +1784,30 @@ static int overlayfs_mount(struct bdev *bdev)
*upper = '\0'; *upper = '\0';
upper++; upper++;
if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -22;
}
// TODO We should check whether bdev->src is a blockdev, and if so // TODO We should check whether bdev->src is a blockdev, and if so
// but for now, only support overlays of a basic directory // but for now, only support overlays of a basic directory
len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=") + 1; if (mntdata) {
options = alloca(len); len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper, lower); options = alloca(len);
if (ret < 0 || ret >= len) ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s", upper, lower, mntdata);
}
else {
len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=") + 1;
options = alloca(len);
ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper, lower);
}
if (ret < 0 || ret >= len) {
free(mntdata);
return -1; return -1;
ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL, options); }
ret = mount(lower, bdev->dest, "overlayfs", MS_MGC_VAL | mntflags, options);
if (ret < 0) if (ret < 0)
SYSERROR("overlayfs: error mounting %s onto %s options %s", SYSERROR("overlayfs: error mounting %s onto %s options %s",
lower, bdev->dest, options); lower, bdev->dest, options);
...@@ -1946,8 +2010,8 @@ static const size_t numbdevs = sizeof(bdevs) / sizeof(struct bdev_type); ...@@ -1946,8 +2010,8 @@ static const size_t numbdevs = sizeof(bdevs) / sizeof(struct bdev_type);
void bdev_put(struct bdev *bdev) void bdev_put(struct bdev *bdev)
{ {
if (bdev->data) if (bdev->mntopts)
free(bdev->data); free(bdev->mntopts);
if (bdev->src) if (bdev->src)
free(bdev->src); free(bdev->src);
if (bdev->dest) if (bdev->dest)
...@@ -1975,7 +2039,7 @@ struct bdev *bdev_get(const char *type) ...@@ -1975,7 +2039,7 @@ struct bdev *bdev_get(const char *type)
return bdev; return bdev;
} }
struct bdev *bdev_init(const char *src, const char *dst, const char *data) struct bdev *bdev_init(const char *src, const char *dst, const char *mntopts)
{ {
int i; int i;
struct bdev *bdev; struct bdev *bdev;
...@@ -1995,8 +2059,8 @@ struct bdev *bdev_init(const char *src, const char *dst, const char *data) ...@@ -1995,8 +2059,8 @@ struct bdev *bdev_init(const char *src, const char *dst, const char *data)
memset(bdev, 0, sizeof(struct bdev)); memset(bdev, 0, sizeof(struct bdev));
bdev->ops = bdevs[i].ops; bdev->ops = bdevs[i].ops;
bdev->type = bdevs[i].name; bdev->type = bdevs[i].name;
if (data) if (mntopts)
bdev->data = strdup(data); bdev->mntopts = strdup(mntopts);
if (src) if (src)
bdev->src = strdup(src); bdev->src = strdup(src);
if (dst) if (dst)
......
...@@ -78,7 +78,7 @@ struct bdev { ...@@ -78,7 +78,7 @@ struct bdev {
const char *type; const char *type;
char *src; char *src;
char *dest; char *dest;
char *data; char *mntopts;
// turn the following into a union if need be // turn the following into a union if need be
// lofd is the open fd for the mounted loopback file // lofd is the open fd for the mounted loopback file
int lofd; int lofd;
......
...@@ -424,9 +424,11 @@ static int find_fstype_cb(char* buffer, void *data) ...@@ -424,9 +424,11 @@ static int find_fstype_cb(char* buffer, void *data)
struct cbarg { struct cbarg {
const char *rootfs; const char *rootfs;
const char *target; const char *target;
int mntopt; const char *options;
} *cbarg = data; } *cbarg = data;
unsigned long mntflags;
char *mntdata;
char *fstype; char *fstype;
/* we don't try 'nodev' entries */ /* we don't try 'nodev' entries */
...@@ -440,10 +442,17 @@ static int find_fstype_cb(char* buffer, void *data) ...@@ -440,10 +442,17 @@ static int find_fstype_cb(char* buffer, void *data)
DEBUG("trying to mount '%s'->'%s' with fstype '%s'", DEBUG("trying to mount '%s'->'%s' with fstype '%s'",
cbarg->rootfs, cbarg->target, fstype); cbarg->rootfs, cbarg->target, fstype);
if (mount(cbarg->rootfs, cbarg->target, fstype, cbarg->mntopt, NULL)) { if (parse_mntopts(cbarg->options, &mntflags, &mntdata) < 0) {
free(mntdata);
return -1;
}
if (mount(cbarg->rootfs, cbarg->target, fstype, mntflags, mntdata)) {
DEBUG("mount failed with error: %s", strerror(errno)); DEBUG("mount failed with error: %s", strerror(errno));
free(mntdata);
return 0; return 0;
} }
free(mntdata);
INFO("mounted '%s' on '%s', with fstype '%s'", INFO("mounted '%s' on '%s', with fstype '%s'",
cbarg->rootfs, cbarg->target, fstype); cbarg->rootfs, cbarg->target, fstype);
...@@ -451,18 +460,19 @@ static int find_fstype_cb(char* buffer, void *data) ...@@ -451,18 +460,19 @@ static int find_fstype_cb(char* buffer, void *data)
return 1; return 1;
} }
static int mount_unknown_fs(const char *rootfs, const char *target, int mntopt) static int mount_unknown_fs(const char *rootfs, const char *target,
const char *options)
{ {
int i; int i;
struct cbarg { struct cbarg {
const char *rootfs; const char *rootfs;
const char *target; const char *target;
int mntopt; const char *options;
} cbarg = { } cbarg = {
.rootfs = rootfs, .rootfs = rootfs,
.target = target, .target = target,
.mntopt = mntopt, .options = options,
}; };
/* /*
...@@ -496,9 +506,22 @@ static int mount_unknown_fs(const char *rootfs, const char *target, int mntopt) ...@@ -496,9 +506,22 @@ static int mount_unknown_fs(const char *rootfs, const char *target, int mntopt)
return -1; return -1;
} }
static int mount_rootfs_dir(const char *rootfs, const char *target) static int mount_rootfs_dir(const char *rootfs, const char *target,
const char *options)
{ {
return mount(rootfs, target, "none", MS_BIND | MS_REC, NULL); unsigned long mntflags;
char *mntdata;
int ret;
if (parse_mntopts(options, &mntflags, &mntdata) < 0) {
free(mntdata);
return -1;
}
ret = mount(rootfs, target, "none", MS_BIND | MS_REC | mntflags, mntdata);
free(mntdata);
return ret;
} }
static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo) static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
...@@ -533,7 +556,8 @@ out: ...@@ -533,7 +556,8 @@ out:
return ret; return ret;
} }
static int mount_rootfs_file(const char *rootfs, const char *target) static int mount_rootfs_file(const char *rootfs, const char *target,
const char *options)
{ {
struct dirent dirent, *direntp; struct dirent dirent, *direntp;
struct loop_info64 loinfo; struct loop_info64 loinfo;
...@@ -585,7 +609,7 @@ static int mount_rootfs_file(const char *rootfs, const char *target) ...@@ -585,7 +609,7 @@ static int mount_rootfs_file(const char *rootfs, const char *target)
ret = setup_lodev(rootfs, fd, &loinfo); ret = setup_lodev(rootfs, fd, &loinfo);
if (!ret) if (!ret)
ret = mount_unknown_fs(path, target, 0); ret = mount_unknown_fs(path, target, options);
close(fd); close(fd);
break; break;
...@@ -597,9 +621,10 @@ static int mount_rootfs_file(const char *rootfs, const char *target) ...@@ -597,9 +621,10 @@ static int mount_rootfs_file(const char *rootfs, const char *target)
return ret; return ret;
} }
static int mount_rootfs_block(const char *rootfs, const char *target) static int mount_rootfs_block(const char *rootfs, const char *target,
const char *options)
{ {
return mount_unknown_fs(rootfs, target, 0); return mount_unknown_fs(rootfs, target, options);
} }
/* /*
...@@ -729,13 +754,13 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_cg ...@@ -729,13 +754,13 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_cg
return 0; return 0;
} }
static int mount_rootfs(const char *rootfs, const char *target) static int mount_rootfs(const char *rootfs, const char *target, const char *options)
{ {
char absrootfs[MAXPATHLEN]; char absrootfs[MAXPATHLEN];
struct stat s; struct stat s;
int i; int i;
typedef int (*rootfs_cb)(const char *, const char *); typedef int (*rootfs_cb)(const char *, const char *, const char *);
struct rootfs_type { struct rootfs_type {
int type; int type;
...@@ -766,7 +791,7 @@ static int mount_rootfs(const char *rootfs, const char *target) ...@@ -766,7 +791,7 @@ static int mount_rootfs(const char *rootfs, const char *target)
if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type)) if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
continue; continue;
return rtfs_type[i].cb(absrootfs, target); return rtfs_type[i].cb(absrootfs, target, options);
} }
ERROR("unsupported rootfs type for '%s'", absrootfs); ERROR("unsupported rootfs type for '%s'", absrootfs);
...@@ -1530,7 +1555,7 @@ static int setup_rootfs(struct lxc_conf *conf) ...@@ -1530,7 +1555,7 @@ static int setup_rootfs(struct lxc_conf *conf)
} }
// First try mounting rootfs using a bdev // First try mounting rootfs using a bdev
struct bdev *bdev = bdev_init(rootfs->path, rootfs->mount, NULL); struct bdev *bdev = bdev_init(rootfs->path, rootfs->mount, rootfs->options);
if (bdev && bdev->ops->mount(bdev) == 0) { if (bdev && bdev->ops->mount(bdev) == 0) {
bdev_put(bdev); bdev_put(bdev);
DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount); DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
...@@ -1538,7 +1563,7 @@ static int setup_rootfs(struct lxc_conf *conf) ...@@ -1538,7 +1563,7 @@ static int setup_rootfs(struct lxc_conf *conf)
} }
if (bdev) if (bdev)
bdev_put(bdev); bdev_put(bdev);
if (mount_rootfs(rootfs->path, rootfs->mount)) { if (mount_rootfs(rootfs->path, rootfs->mount, rootfs->options)) {
ERROR("failed to mount rootfs"); ERROR("failed to mount rootfs");
return -1; return -1;
} }
...@@ -1791,7 +1816,7 @@ static void parse_mntopt(char *opt, unsigned long *flags, char **data) ...@@ -1791,7 +1816,7 @@ static void parse_mntopt(char *opt, unsigned long *flags, char **data)
strcat(*data, opt); strcat(*data, opt);
} }
static int parse_mntopts(const char *mntopts, unsigned long *mntflags, int parse_mntopts(const char *mntopts, unsigned long *mntflags,
char **mntdata) char **mntdata)
{ {
char *s, *data; char *s, *data;
...@@ -1865,11 +1890,6 @@ static inline int mount_entry_on_systemfs(const struct mntent *mntent) ...@@ -1865,11 +1890,6 @@ static inline int mount_entry_on_systemfs(const struct mntent *mntent)
FILE *pathfile = NULL; FILE *pathfile = NULL;
char* pathdirname = NULL; char* pathdirname = NULL;
if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
return -1;
}
if (hasmntopt(mntent, "create=dir")) { if (hasmntopt(mntent, "create=dir")) {
if (!mkdir_p(mntent->mnt_dir, 0755)) { if (!mkdir_p(mntent->mnt_dir, 0755)) {
WARN("Failed to create mount target '%s'", mntent->mnt_dir); WARN("Failed to create mount target '%s'", mntent->mnt_dir);
...@@ -1890,6 +1910,11 @@ static inline int mount_entry_on_systemfs(const struct mntent *mntent) ...@@ -1890,6 +1910,11 @@ static inline int mount_entry_on_systemfs(const struct mntent *mntent)
fclose(pathfile); fclose(pathfile);
} }
if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -1;
}
ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir, ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
mntent->mnt_type, mntflags, mntdata); mntent->mnt_type, mntflags, mntdata);
...@@ -1915,11 +1940,6 @@ static int mount_entry_on_absolute_rootfs(const struct mntent *mntent, ...@@ -1915,11 +1940,6 @@ static int mount_entry_on_absolute_rootfs(const struct mntent *mntent,
FILE *pathfile = NULL; FILE *pathfile = NULL;
char *pathdirname = NULL; char *pathdirname = NULL;
if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
return -1;
}
lxcpath = lxc_global_config_value("lxc.lxcpath"); lxcpath = lxc_global_config_value("lxc.lxcpath");
if (!lxcpath) { if (!lxcpath) {
ERROR("Out of memory"); ERROR("Out of memory");
...@@ -1976,15 +1996,21 @@ skipabs: ...@@ -1976,15 +1996,21 @@ skipabs:
fclose(pathfile); fclose(pathfile);
} }
if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -1;
}
ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
mntflags, mntdata); mntflags, mntdata);
free(mntdata);
if (hasmntopt(mntent, "optional") != NULL) if (hasmntopt(mntent, "optional") != NULL)
ret = 0; ret = 0;
out: out:
free(pathdirname); free(pathdirname);
free(mntdata);
return ret; return ret;
} }
...@@ -1998,11 +2024,6 @@ static int mount_entry_on_relative_rootfs(const struct mntent *mntent, ...@@ -1998,11 +2024,6 @@ static int mount_entry_on_relative_rootfs(const struct mntent *mntent,
FILE *pathfile = NULL; FILE *pathfile = NULL;
char *pathdirname = NULL; char *pathdirname = NULL;
if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
return -1;
}
/* relative to root mount point */ /* relative to root mount point */
ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir); ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
if (ret >= sizeof(path)) { if (ret >= sizeof(path)) {
...@@ -2030,6 +2051,11 @@ static int mount_entry_on_relative_rootfs(const struct mntent *mntent, ...@@ -2030,6 +2051,11 @@ static int mount_entry_on_relative_rootfs(const struct mntent *mntent,
fclose(pathfile); fclose(pathfile);
} }
if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
free(mntdata);
return -1;
}
ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
mntflags, mntdata); mntflags, mntdata);
...@@ -3906,6 +3932,8 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -3906,6 +3932,8 @@ void lxc_conf_free(struct lxc_conf *conf)
free(conf->console.path); free(conf->console.path);
if (conf->rootfs.mount) if (conf->rootfs.mount)
free(conf->rootfs.mount); free(conf->rootfs.mount);
if (conf->rootfs.options)
free(conf->rootfs.options);
if (conf->rootfs.path) if (conf->rootfs.path)
free(conf->rootfs.path); free(conf->rootfs.path);
if (conf->rootfs.pivot) if (conf->rootfs.pivot)
......
...@@ -219,6 +219,7 @@ struct lxc_rootfs { ...@@ -219,6 +219,7 @@ struct lxc_rootfs {
char *path; char *path;
char *mount; char *mount;
char *pivot; char *pivot;
char *options;
}; };
/* /*
...@@ -375,4 +376,6 @@ extern int mapped_hostid(int id, struct lxc_conf *conf); ...@@ -375,4 +376,6 @@ extern int mapped_hostid(int id, struct lxc_conf *conf);
extern int chown_mapped_root(char *path, struct lxc_conf *conf); extern int chown_mapped_root(char *path, struct lxc_conf *conf);
extern int ttys_shift_ids(struct lxc_conf *c); extern int ttys_shift_ids(struct lxc_conf *c);
extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data); extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data);
extern int parse_mntopts(const char *mntopts, unsigned long *mntflags,
char **mntdata);
#endif #endif
...@@ -65,6 +65,7 @@ static int config_logfile(const char *, const char *, struct lxc_conf *); ...@@ -65,6 +65,7 @@ static int config_logfile(const char *, const char *, struct lxc_conf *);
static int config_mount(const char *, const char *, struct lxc_conf *); static int config_mount(const char *, const char *, struct lxc_conf *);
static int config_rootfs(const char *, const char *, struct lxc_conf *); static int config_rootfs(const char *, const char *, struct lxc_conf *);
static int config_rootfs_mount(const char *, const char *, struct lxc_conf *); static int config_rootfs_mount(const char *, const char *, struct lxc_conf *);
static int config_rootfs_options(const char *, const char *, struct lxc_conf *);
static int config_pivotdir(const char *, const char *, struct lxc_conf *); static int config_pivotdir(const char *, const char *, struct lxc_conf *);
static int config_utsname(const char *, const char *, struct lxc_conf *); static int config_utsname(const char *, const char *, struct lxc_conf *);
static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf); static int config_hook(const char *, const char *, struct lxc_conf *lxc_conf);
...@@ -110,6 +111,7 @@ static struct lxc_config_t config[] = { ...@@ -110,6 +111,7 @@ static struct lxc_config_t config[] = {
{ "lxc.logfile", config_logfile }, { "lxc.logfile", config_logfile },
{ "lxc.mount", config_mount }, { "lxc.mount", config_mount },
{ "lxc.rootfs.mount", config_rootfs_mount }, { "lxc.rootfs.mount", config_rootfs_mount },
{ "lxc.rootfs.options", config_rootfs_options },
{ "lxc.rootfs", config_rootfs }, { "lxc.rootfs", config_rootfs },
{ "lxc.pivotdir", config_pivotdir }, { "lxc.pivotdir", config_pivotdir },
{ "lxc.utsname", config_utsname }, { "lxc.utsname", config_utsname },
...@@ -1566,6 +1568,12 @@ static int config_rootfs_mount(const char *key, const char *value, ...@@ -1566,6 +1568,12 @@ static int config_rootfs_mount(const char *key, const char *value,
return config_path_item(&lxc_conf->rootfs.mount, value); return config_path_item(&lxc_conf->rootfs.mount, value);
} }
static int config_rootfs_options(const char *key, const char *value,
struct lxc_conf *lxc_conf)
{
return config_string_item(&lxc_conf->rootfs.options, value);
}
static int config_pivotdir(const char *key, const char *value, static int config_pivotdir(const char *key, const char *value,
struct lxc_conf *lxc_conf) struct lxc_conf *lxc_conf)
{ {
...@@ -2096,6 +2104,8 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv, ...@@ -2096,6 +2104,8 @@ int lxc_get_config_item(struct lxc_conf *c, const char *key, char *retv,
v = c->console.path; v = c->console.path;
else if (strcmp(key, "lxc.rootfs.mount") == 0) else if (strcmp(key, "lxc.rootfs.mount") == 0)
v = c->rootfs.mount; v = c->rootfs.mount;
else if (strcmp(key, "lxc.rootfs.options") == 0)
v = c->rootfs.options;
else if (strcmp(key, "lxc.rootfs") == 0) else if (strcmp(key, "lxc.rootfs") == 0)
v = c->rootfs.path; v = c->rootfs.path;
else if (strcmp(key, "lxc.pivotdir") == 0) else if (strcmp(key, "lxc.pivotdir") == 0)
...@@ -2313,6 +2323,8 @@ void write_config(FILE *fout, struct lxc_conf *c) ...@@ -2313,6 +2323,8 @@ void write_config(FILE *fout, struct lxc_conf *c)
fprintf(fout, "lxc.rootfs = %s\n", c->rootfs.path); fprintf(fout, "lxc.rootfs = %s\n", c->rootfs.path);
if (c->rootfs.mount && strcmp(c->rootfs.mount, LXCROOTFSMOUNT) != 0) if (c->rootfs.mount && strcmp(c->rootfs.mount, LXCROOTFSMOUNT) != 0)
fprintf(fout, "lxc.rootfs.mount = %s\n", c->rootfs.mount); fprintf(fout, "lxc.rootfs.mount = %s\n", c->rootfs.mount);
if (c->rootfs.options)
fprintf(fout, "lxc.rootfs.options = %s\n", c->rootfs.options);
if (c->rootfs.pivot) if (c->rootfs.pivot)
fprintf(fout, "lxc.pivotdir = %s\n", c->rootfs.pivot); fprintf(fout, "lxc.pivotdir = %s\n", c->rootfs.pivot);
if (c->start_auto) if (c->start_auto)
......
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