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(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/lxc/lxc_container.c | 44 +----------------------------
src/lxc/lxc_container.h | 2 --
src/lxc/lxc_driver.c | 7 +++--
src/util/virprocess.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virprocess.h | 10 +++++++
6 files changed, 89 insertions(+), 47 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9c74d35c4..d02d23b35 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2275,6 +2275,7 @@ virProcessGetPids;
virProcessGetStartTime;
virProcessKill;
virProcessKillPainfully;
+virProcessNamespaceAvailable;
virProcessRunInMountNamespace;
virProcessSchedPolicyTypeFromString;
virProcessSchedPolicyTypeToString;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 32c0c3a4a..e5619b168 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -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;
diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h
index 33eaab49c..fbdfc998a 100644
--- a/src/lxc/lxc_container.h
+++ b/src/lxc/lxc_container.h
@@ -65,8 +65,6 @@ int lxcContainerStart(virDomainDefPtr def,
size_t nttyPaths,
char **ttyPaths);
-int lxcContainerAvailable(int features);
-
int lxcContainerSetupHostdevCapsMakePath(const char *dev);
virArch lxcContainerGetAlt32bitArch(virArch arch);
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 04a4b8c2a..a2c1052c6 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -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;
}
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 1ebe863fb..f5c7ebb96 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -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:
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index c76a1fbc5..3c5a88277 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -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__ */
--
2.11.0