lxc: Move lxcContainerAvailable to virprocess

Other drivers (like qemu) would like to know if the namespaces
are available therefore it makes sense to move this function to
a shared module.

At the same time, this function had some default namespaces that
are checked with every call. It is not necessary - let callers
pass just those namespaces they are interested in.

With the move the function is renamed to
virProcessNamespaceAvailable.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2017-01-11 10:23:39 +01:00
parent 2ff8c30548
commit 083fcd06d3
6 changed files with 89 additions and 52 deletions

View File

@ -2275,6 +2275,7 @@ virProcessGetPids;
virProcessGetStartTime;
virProcessKill;
virProcessKillPainfully;
virProcessNamespaceAvailable;
virProcessRunInMountNamespace;
virProcessSchedPolicyTypeFromString;
virProcessSchedPolicyTypeToString;

View File

@ -27,7 +27,6 @@
#include <config.h>
#include <fcntl.h>
#include <sched.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
@ -2265,7 +2264,7 @@ static int lxcContainerChild(void *data)
static int userns_supported(void)
{
return lxcContainerAvailable(LXC_CONTAINER_FEATURE_USER) == 0;
return virProcessNamespaceAvailable(VIR_PROCESS_NAMESPACE_USER) == 0;
}
static int userns_required(virDomainDefPtr def)
@ -2399,47 +2398,6 @@ int lxcContainerStart(virDomainDefPtr def,
return pid;
}
ATTRIBUTE_NORETURN static int
lxcContainerDummyChild(void *argv ATTRIBUTE_UNUSED)
{
_exit(0);
}
int lxcContainerAvailable(int features)
{
int flags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|
CLONE_NEWIPC|SIGCHLD;
int cpid;
char *childStack;
char *stack;
int stacksize = getpagesize() * 4;
if (features & LXC_CONTAINER_FEATURE_USER)
flags |= CLONE_NEWUSER;
if (features & LXC_CONTAINER_FEATURE_NET)
flags |= CLONE_NEWNET;
if (VIR_ALLOC_N(stack, stacksize) < 0)
return -1;
childStack = stack + stacksize;
cpid = clone(lxcContainerDummyChild, childStack, flags, NULL);
VIR_FREE(stack);
if (cpid < 0) {
char ebuf[1024] ATTRIBUTE_UNUSED;
VIR_DEBUG("clone call returned %s, container support is not enabled",
virStrerror(errno, ebuf, sizeof(ebuf)));
return -1;
} else if (virProcessWait(cpid, NULL, false) < 0) {
return -1;
}
VIR_DEBUG("container support is enabled");
return 0;
}
int lxcContainerChown(virDomainDefPtr def, const char *path)
{
uid_t uid;

View File

@ -28,11 +28,6 @@
# include "lxc_domain.h"
# include "security/security_manager.h"
enum {
LXC_CONTAINER_FEATURE_NET = (1 << 0),
LXC_CONTAINER_FEATURE_USER = (1 << 1),
};
# define LXC_DEV_MAJ_MEMORY 1
# define LXC_DEV_MIN_NULL 3
# define LXC_DEV_MIN_ZERO 5
@ -65,8 +60,6 @@ int lxcContainerStart(virDomainDefPtr def,
size_t nttyPaths,
char **ttyPaths);
int lxcContainerAvailable(int features);
int lxcContainerSetupHostdevCapsMakePath(const char *dev);
virArch lxcContainerGetAlt32bitArch(virArch arch);

View File

@ -1575,7 +1575,7 @@ static int lxcCheckNetNsSupport(void)
if (virRun(argv, &ip_rc) < 0 || ip_rc == 255)
return 0;
if (lxcContainerAvailable(LXC_CONTAINER_FEATURE_NET) < 0)
if (virProcessNamespaceAvailable(VIR_PROCESS_NAMESPACE_NET) < 0)
return 0;
return 1;
@ -1633,7 +1633,10 @@ static int lxcStateInitialize(bool privileged,
}
/* Check that this is a container enabled kernel */
if (lxcContainerAvailable(0) < 0) {
if (virProcessNamespaceAvailable(VIR_PROCESS_NAMESPACE_MNT |
VIR_PROCESS_NAMESPACE_PID |
VIR_PROCESS_NAMESPACE_UTS |
VIR_PROCESS_NAMESPACE_IPC) < 0) {
VIR_INFO("LXC support not available in this kernel, disabling driver");
return 0;
}

View File

@ -1183,6 +1183,78 @@ virProcessSetupPrivateMountNS(void)
}
#endif /* !defined(HAVE_SYS_MOUNT_H) || !defined(HAVE_UNSHARE) */
#if defined(__linux__)
ATTRIBUTE_NORETURN static int
virProcessDummyChild(void *argv ATTRIBUTE_UNUSED)
{
_exit(0);
}
/**
* virProcessNamespaceAvailable:
* @ns: what namespaces to check (bitwise-OR of virProcessNamespaceFlags)
*
* Check if given list of namespaces (@ns) is available.
* If not, appropriate error message is produced.
*
* Returns: 0 on success (all the namespaces from @flags are available),
* -1 on error (with error message reported).
*/
int
virProcessNamespaceAvailable(unsigned int ns)
{
int flags = 0;
int cpid;
char *childStack;
char *stack;
int stacksize = getpagesize() * 4;
if (ns & VIR_PROCESS_NAMESPACE_MNT)
flags |= CLONE_NEWNS;
if (ns & VIR_PROCESS_NAMESPACE_IPC)
flags |= CLONE_NEWIPC;
if (ns & VIR_PROCESS_NAMESPACE_NET)
flags |= CLONE_NEWNET;
if (ns & VIR_PROCESS_NAMESPACE_PID)
flags |= CLONE_NEWPID;
if (ns & VIR_PROCESS_NAMESPACE_USER)
flags |= CLONE_NEWUSER;
if (ns & VIR_PROCESS_NAMESPACE_UTS)
flags |= CLONE_NEWUTS;
/* Signal parent as soon as the child dies. RIP. */
flags |= SIGCHLD;
if (VIR_ALLOC_N(stack, stacksize) < 0)
return -1;
childStack = stack + stacksize;
cpid = clone(virProcessDummyChild, childStack, flags, NULL);
VIR_FREE(stack);
if (cpid < 0) {
char ebuf[1024] ATTRIBUTE_UNUSED;
VIR_DEBUG("clone call returned %s, container support is not enabled",
virStrerror(errno, ebuf, sizeof(ebuf)));
return -1;
} else if (virProcessWait(cpid, NULL, false) < 0) {
return -1;
}
VIR_DEBUG("All namespaces (%x) are enabled", ns);
return 0;
}
#else /* !defined(__linux__) */
int
virProcessNamespaceAvailable(unsigned int ns ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
_("Namespaces are not supported on this platform."));
return -1;
}
#endif /* !defined(__linux__) */
/**
* virProcessExitWithStatus:

View File

@ -95,5 +95,15 @@ int virProcessSetupPrivateMountNS(void);
int virProcessSetScheduler(pid_t pid,
virProcessSchedPolicy policy,
int priority);
typedef enum {
VIR_PROCESS_NAMESPACE_MNT = (1 << 1),
VIR_PROCESS_NAMESPACE_IPC = (1 << 2),
VIR_PROCESS_NAMESPACE_NET = (1 << 3),
VIR_PROCESS_NAMESPACE_PID = (1 << 4),
VIR_PROCESS_NAMESPACE_USER = (1 << 5),
VIR_PROCESS_NAMESPACE_UTS = (1 << 6),
} virProcessNamespaceFlags;
int virProcessNamespaceAvailable(unsigned int ns);
#endif /* __VIR_PROCESS_H__ */