mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-11 12:04:22 +00:00
implement lxc.mount.auto = cgroup for cgfsng
Also add testcase for each of the cgroup{,-full}:{rw,ro,mixed} cases. Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
e6bff191fb
commit
8aa1044fd8
156
src/lxc/cgfsng.c
156
src/lxc/cgfsng.c
@ -1022,9 +1022,6 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
|
||||
|
||||
struct cgroup_ops *cgfsng_ops_init(void)
|
||||
{
|
||||
/* TODO - when cgroup_mount is implemented, drop this check */
|
||||
if (!file_exists("/proc/self/ns/cgroup"))
|
||||
return NULL;
|
||||
return &cgfsng_ops;
|
||||
}
|
||||
|
||||
@ -1223,12 +1220,161 @@ static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've safe-mounted a tmpfs as parent, so we don't need to protect against
|
||||
* symlinks any more - just use mount
|
||||
*/
|
||||
|
||||
/* mount cgroup-full if requested */
|
||||
static int mount_cgroup_full(int type, struct hierarchy *h, char *dest,
|
||||
char *container_cgroup)
|
||||
{
|
||||
if (type < LXC_AUTO_CGROUP_FULL_RO || type > LXC_AUTO_CGROUP_FULL_MIXED)
|
||||
return 0;
|
||||
if (mount(h->mountpoint, dest, "cgroup", MS_BIND, NULL) < 0) {
|
||||
SYSERROR("Error bind-mounting %s cgroup onto %s", h->mountpoint,
|
||||
dest);
|
||||
return -1;
|
||||
}
|
||||
if (type != LXC_AUTO_CGROUP_FULL_RW) {
|
||||
if (mount(NULL, dest, "cgroup", MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
|
||||
SYSERROR("Error remounting %s readonly", dest);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
INFO("Bind mounted %s onto %s", h->mountpoint, dest);
|
||||
if (type != LXC_AUTO_CGROUP_FULL_MIXED)
|
||||
return 0;
|
||||
|
||||
/* mount just the container path rw */
|
||||
char *source = must_make_path(h->mountpoint, h->base_cgroup, container_cgroup, NULL);
|
||||
char *rwpath = must_make_path(dest, container_cgroup, NULL);
|
||||
if (mount(source, rwpath, "cgroup", MS_BIND, NULL) < 0)
|
||||
WARN("Failed to mount %s read-write: %m", rwpath);
|
||||
INFO("Made %s read-write", rwpath);
|
||||
free(rwpath);
|
||||
free(source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cgroup-full:* is done, no need to create subdirs */
|
||||
static bool cg_mount_needs_subdirs(int type)
|
||||
{
|
||||
if (type >= LXC_AUTO_CGROUP_FULL_RO)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* After $rootfs/sys/fs/container/controller/the/cg/path has been
|
||||
* created, remount controller ro if needed and bindmount the
|
||||
* cgroupfs onto controll/the/cg/path
|
||||
*/
|
||||
static int
|
||||
do_secondstage_mounts_if_needed(int type, struct hierarchy *h,
|
||||
char *controllerpath, char *cgpath,
|
||||
const char *container_cgroup)
|
||||
{
|
||||
if (type == LXC_AUTO_CGROUP_RO || type == LXC_AUTO_CGROUP_MIXED) {
|
||||
if (mount(controllerpath, controllerpath, "cgroup", MS_BIND, NULL) < 0) {
|
||||
SYSERROR("Error bind-mounting %s", controllerpath);
|
||||
return -1;
|
||||
}
|
||||
if (mount(controllerpath, controllerpath, "cgroup",
|
||||
MS_REMOUNT | MS_BIND | MS_RDONLY, NULL) < 0) {
|
||||
SYSERROR("Error remounting %s read-only", controllerpath);
|
||||
return -1;
|
||||
}
|
||||
INFO("Remounted %s read-only", controllerpath);
|
||||
}
|
||||
char *sourcepath = must_make_path(h->mountpoint, h->base_cgroup, container_cgroup, NULL);
|
||||
int flags = MS_BIND;
|
||||
if (type == LXC_AUTO_CGROUP_RO)
|
||||
flags |= MS_RDONLY;
|
||||
INFO("Mounting %s onto %s", sourcepath, cgpath);
|
||||
if (mount(sourcepath, cgpath, "cgroup", flags, NULL) < 0) {
|
||||
free(sourcepath);
|
||||
SYSERROR("Error mounting cgroup %s onto %s", h->controllers[0],
|
||||
cgpath);
|
||||
return -1;
|
||||
}
|
||||
free(sourcepath);
|
||||
INFO("Completed second stage cgroup automounts for %s", cgpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool cgfsng_mount(void *hdata, const char *root, int type)
|
||||
{
|
||||
struct cgfsng_handler_data *d = hdata;
|
||||
char *tmpfspath = NULL;
|
||||
bool retval = false;
|
||||
|
||||
if ((type & LXC_AUTO_CGROUP_MASK) == 0)
|
||||
return true;
|
||||
|
||||
if (cgns_supported())
|
||||
return true;
|
||||
// TODO - implement this. Not needed for cgroup namespaces
|
||||
return false;
|
||||
|
||||
tmpfspath = must_make_path(root, "/sys/fs/cgroup", NULL);
|
||||
|
||||
if (type == LXC_AUTO_CGROUP_NOSPEC)
|
||||
type = LXC_AUTO_CGROUP_MIXED;
|
||||
else if (type == LXC_AUTO_CGROUP_FULL_NOSPEC)
|
||||
type = LXC_AUTO_CGROUP_FULL_MIXED;
|
||||
|
||||
/* Mount tmpfs */
|
||||
if (safe_mount("cgroup_root", tmpfspath, "tmpfs",
|
||||
MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME,
|
||||
"size=10240k,mode=755",
|
||||
root) < 0)
|
||||
goto bad;
|
||||
|
||||
for (int i = 0; d->hierarchies[i]; i++) {
|
||||
char *controllerpath, *path2;
|
||||
struct hierarchy *h = d->hierarchies[i];
|
||||
char *controller = strrchr(h->mountpoint, '/');
|
||||
int r;
|
||||
|
||||
if (!controller)
|
||||
continue;
|
||||
controller++;
|
||||
controllerpath = must_make_path(tmpfspath, controller, NULL);
|
||||
if (dir_exists(controllerpath)) {
|
||||
free(controllerpath);
|
||||
continue;
|
||||
}
|
||||
if (mkdir(controllerpath, 0755) < 0) {
|
||||
SYSERROR("Error creating cgroup path: %s", controllerpath);
|
||||
free(controllerpath);
|
||||
goto bad;
|
||||
}
|
||||
if (mount_cgroup_full(type, h, controllerpath, d->container_cgroup) < 0) {
|
||||
free(controllerpath);
|
||||
goto bad;
|
||||
}
|
||||
if (!cg_mount_needs_subdirs(type)) {
|
||||
free(controllerpath);
|
||||
continue;
|
||||
}
|
||||
path2 = must_make_path(controllerpath, d->container_cgroup, NULL);
|
||||
if (mkdir_p(path2, 0755) < 0) {
|
||||
free(controllerpath);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
r = do_secondstage_mounts_if_needed(type, h, controllerpath, path2,
|
||||
d->container_cgroup);
|
||||
free(controllerpath);
|
||||
free(path2);
|
||||
if (r < 0)
|
||||
goto bad;
|
||||
}
|
||||
retval = true;
|
||||
|
||||
bad:
|
||||
free(tmpfspath);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int recursive_count_nrtasks(char *dirname)
|
||||
|
1
src/lxc/liblxc.so.1
Symbolic link
1
src/lxc/liblxc.so.1
Symbolic link
@ -0,0 +1 @@
|
||||
liblxc.so
|
@ -48,7 +48,8 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
|
||||
lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove \
|
||||
lxc-test-apparmor
|
||||
|
||||
bin_SCRIPTS = lxc-test-autostart lxc-test-cloneconfig lxc-test-createconfig
|
||||
bin_SCRIPTS = lxc-test-automount lxc-test-autostart lxc-test-cloneconfig \
|
||||
lxc-test-createconfig
|
||||
|
||||
if DISTRO_UBUNTU
|
||||
bin_SCRIPTS += \
|
||||
@ -79,6 +80,7 @@ EXTRA_DIST = \
|
||||
locktests.c \
|
||||
lxcpath.c \
|
||||
lxc-test-lxc-attach \
|
||||
lxc-test-automount \
|
||||
lxc-test-autostart \
|
||||
lxc-test-apparmor-mount \
|
||||
lxc-test-checkpoint-restore \
|
||||
|
217
src/tests/lxc-test-automount
Normal file
217
src/tests/lxc-test-automount
Normal file
@ -0,0 +1,217 @@
|
||||
#!/bin/bash
|
||||
|
||||
# lxc: linux Container library
|
||||
|
||||
# Authors:
|
||||
# Serge Hallyn <serge.hallyn@ubuntu.com>
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# At the moment this only tests cgroup automount. Testing proc and
|
||||
# sys automounts would be worthwhile.
|
||||
|
||||
[ -f /proc/self/ns/cgroup ] && exit 0
|
||||
|
||||
set -ex
|
||||
|
||||
cleanup() {
|
||||
set +e
|
||||
rmdir /sys/fs/cgroup/freezer/xx
|
||||
lxc-destroy -n lxc-test-automount -f
|
||||
if [ $PHASE != "done" ]; then
|
||||
echo "automount test failed at $PHASE"
|
||||
exit 1
|
||||
fi
|
||||
echo "automount test passed"
|
||||
exit 0
|
||||
}
|
||||
|
||||
PHASE=setup
|
||||
trap cleanup EXIT
|
||||
|
||||
rmdir /sys/fs/cgroup/freezer/xx || true
|
||||
lxc-destroy -n lxc-test-automount -f || true
|
||||
lxc-create -t busybox -n lxc-test-automount
|
||||
|
||||
PHASE=no-cgroup
|
||||
echo "Starting phase $PHASE"
|
||||
config=/var/lib/lxc/lxc-test-automount/config
|
||||
sed -i '/lxc.mount.auto/d' $config
|
||||
echo "lxc.mount.auto = proc:mixed sys:mixed" >> $config
|
||||
|
||||
lxc-start -n lxc-test-automount
|
||||
pid=`lxc-info -n lxc-test-automount -p -H`
|
||||
cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup`
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1
|
||||
[ $notfound -ne 0 ]
|
||||
|
||||
# Tests are as follows:
|
||||
# 1. check that freezer controller is mounted
|
||||
# 2. check that it is cgroupfs for cgroup-full (/cgroup.procs exists) or
|
||||
# tmpfs for cgroup
|
||||
# 3. check that root cgroup dir is readonly or not (try mkdir)
|
||||
# 4. check that the container's cgroup dir is readonly or not
|
||||
# 5. check that the container's cgroup dir is cgroupfs (/cgroup.procs exists)
|
||||
|
||||
lxc-stop -n lxc-test-automount -k
|
||||
PHASE=cgroup:mixed
|
||||
echo "Starting phase $PHASE"
|
||||
sed -i '/lxc.mount.auto/d' $config
|
||||
echo "lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed" >> $config
|
||||
lxc-start -n lxc-test-automount
|
||||
pid=`lxc-info -n lxc-test-automount -p -H`
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 0 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1
|
||||
[ $ro -ne 0 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1
|
||||
[ $ro -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
|
||||
lxc-stop -n lxc-test-automount -k
|
||||
PHASE=cgroup:ro
|
||||
echo "Starting phase $PHASE"
|
||||
sed -i '/lxc.mount.auto/d' $config
|
||||
echo "lxc.mount.auto = cgroup:ro proc:mixed sys:mixed" >> $config
|
||||
lxc-start -n lxc-test-automount
|
||||
pid=`lxc-info -n lxc-test-automount -p -H`
|
||||
cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup`
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 0 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1
|
||||
[ $ro -ne 0 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1
|
||||
[ $ro -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
|
||||
lxc-stop -n lxc-test-automount -k
|
||||
PHASE=cgroup:rw
|
||||
echo "Starting phase $PHASE"
|
||||
sed -i '/lxc.mount.auto/d' $config
|
||||
echo "lxc.mount.auto = cgroup:rw proc:mixed sys:mixed" >> $config
|
||||
lxc-start -n lxc-test-automount
|
||||
pid=`lxc-info -n lxc-test-automount -p -H`
|
||||
cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup`
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 0 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1
|
||||
[ $ro -ne 1 ]
|
||||
rmdir /proc/$pid/root/sys/fs/cgroup/freezer/xx
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1
|
||||
[ $ro -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
|
||||
# cgroup-full
|
||||
|
||||
lxc-stop -n lxc-test-automount -k
|
||||
PHASE=cgroup-full:mixed
|
||||
echo "Starting phase $PHASE"
|
||||
sed -i '/lxc.mount.auto/d' $config
|
||||
echo "lxc.mount.auto = cgroup-full:mixed proc:mixed sys:mixed" >> $config
|
||||
lxc-start -n lxc-test-automount
|
||||
pid=`lxc-info -n lxc-test-automount -p -H`
|
||||
cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup`
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1
|
||||
[ $ro -ne 0 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1
|
||||
[ $ro -ne 1 ]
|
||||
rmdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
|
||||
lxc-stop -n lxc-test-automount -k
|
||||
PHASE=cgroup-full:ro
|
||||
echo "Starting phase $PHASE"
|
||||
sed -i '/lxc.mount.auto/d' $config
|
||||
echo "lxc.mount.auto = cgroup-full:ro proc:mixed sys:mixed" >> $config
|
||||
lxc-start -n lxc-test-automount
|
||||
pid=`lxc-info -n lxc-test-automount -p -H`
|
||||
cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup`
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1
|
||||
[ $ro -ne 0 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xy || ro=1
|
||||
[ $ro -ne 0 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
|
||||
lxc-stop -n lxc-test-automount -k
|
||||
PHASE=cgroup-full:rw
|
||||
echo "Starting phase $PHASE"
|
||||
sed -i '/lxc.mount.auto/d' $config
|
||||
echo "lxc.mount.auto = cgroup-full:rw proc:mixed sys:mixed" >> $config
|
||||
lxc-start -n lxc-test-automount
|
||||
pid=`lxc-info -n lxc-test-automount -p -H`
|
||||
cg=`awk -F: '/freezer/ { print $3 }' /proc/$pid/cgroup`
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
notfound=0
|
||||
stat /proc/$pid/root/sys/fs/cgroup/freezer/cgroup.procs || notfound=1
|
||||
[ $notfound -ne 1 ]
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/xx || ro=1
|
||||
[ $ro -ne 1 ]
|
||||
rmdir /proc/$pid/root/sys/fs/cgroup/freezer/xx
|
||||
ro=0
|
||||
mkdir /proc/$pid/root/sys/fs/cgroup/freezer/$cg/xx || ro=1
|
||||
[ $ro -ne 1 ]
|
||||
notfound=0
|
||||
/proc/$pid/root/sys/fs/cgroup/freezer/$cg/cgroup.procs || notfound=1
|
||||
[ $notfound -eq 1 ]
|
||||
|
||||
PHASE=done
|
Loading…
Reference in New Issue
Block a user