Implement virProcessRunInMountNamespace, which runs callback of type
virProcessNamespaceCallback in a container namespace.
Hope it'll nail it this time.
---
src/libvirt_private.syms | 1 +
src/util/virprocess.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/virprocess.h | 6 +++++
3 files changed, 70 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2dbb8f8..e210fd0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1646,6 +1646,7 @@ virProcessGetNamespaces;
virProcessGetStartTime;
virProcessKill;
virProcessKillPainfully;
+virProcessRunInMountNamespace;
virProcessSetAffinity;
virProcessSetMaxFiles;
virProcessSetMaxMemLock;
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 9fc3207..7bb494e 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -31,6 +31,7 @@
# include <sys/resource.h>
#endif
#include <sched.h>
+#include <stdlib.h>
#ifdef __FreeBSD__
# include <sys/param.h>
@@ -847,3 +848,65 @@ int virProcessGetStartTime(pid_t pid,
return 0;
}
#endif
+
+#ifdef HAVE_SETNS
+int virProcessRunInMountNamespace(pid_t pid,
+ virProcessNamespaceCallback cb,
+ void *opaque)
+{
+ char* path = NULL;
+ int ret = -1;
+ int cpid = -1;
+ int status = -1;
+ int fd = -1;
+
+ if (virAsprintf(&path, "/proc/%llu/ns/mnt",
+ (unsigned long long)pid) < 0) {
+ goto cleanup;
+ }
+
+ if ((fd = open(path, O_RDONLY)) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Kernel does not provide mount namespace"));
+ goto cleanup;
+ }
+
+ switch (cpid = fork()) {
+ case 0:
+ if (setns(fd, 0) == -1) {
+ _exit(-1);
+ }
+
+ ret = cb(pid, opaque);
+ _exit(ret);
+ break;
+ case -1:
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Fork failed"));
+ goto cleanup;
+ default:
+ if (virProcessWait(cpid, &status) < 0 || status < 0) {
+ virReportSystemError(errno,
+ _("Callback failed with status %i"),
+ status);
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+ }
+
+cleanup:
+ VIR_FREE(path);
+ VIR_FORCE_CLOSE(fd);
+ return ret;
+}
+#else
+int virProcessRunInMountNamespace(pid_t pid ATTRIBUTE_UNUSED,
+ virProcessNamespaceCallback cb ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Mount namespaces are not available on this
platform"));
+ return -1;
+}
+#endif
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index 9f77bc5..205abf7 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -60,4 +60,10 @@ int virProcessSetNamespaces(size_t nfdlist,
int virProcessSetMaxMemLock(pid_t pid, unsigned long long bytes);
int virProcessSetMaxProcesses(pid_t pid, unsigned int procs);
int virProcessSetMaxFiles(pid_t pid, unsigned int files);
+
+typedef int (*virProcessNamespaceCallback)(pid_t pid, void *opaque);
+
+int virProcessRunInMountNamespace(pid_t pid,
+ virProcessNamespaceCallback cb,
+ void *opaque);
#endif /* __VIR_PROCESS_H__ */
--
1.7.10.4