From: Stanislav Kinsburskiy <skinsbur...@virtuozzo.com>

The main and only difference with generic usermode helper is that
subprocess_info is queued via additional kthread_work member to per-container
usermode helper worker.

Signed-off-by: Stanislav Kinsburskiy <skinsbur...@virtuozzo.com>

(cherry-picked from vz8 commit 871dd2e11512 ("ve/umh: introduce per-container
user mode helper macroses and functions"))

Signed-off-by: Nikita Yushchenko <nikita.yushche...@virtuozzo.com>
---
 include/linux/umh.h | 26 +++++++++++++++++++++++
 kernel/umh.c        | 50 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/include/linux/umh.h b/include/linux/umh.h
index d91be2030375..f907e7bf1826 100644
--- a/include/linux/umh.h
+++ b/include/linux/umh.h
@@ -7,9 +7,11 @@
 #include <linux/compiler.h>
 #include <linux/workqueue.h>
 #include <linux/sysctl.h>
+#include <linux/kthread.h>
 
 struct cred;
 struct file;
+struct ve_struct;
 
 #define UMH_NO_WAIT    0       /* don't wait at all */
 #define UMH_WAIT_EXEC  1       /* wait for the exec, but not the process */
@@ -28,6 +30,10 @@ struct subprocess_info {
        void (*cleanup)(struct subprocess_info *info);
        void (*queue)(struct subprocess_info *info);
        void *data;
+#ifdef CONFIG_VE
+       struct ve_struct *ve;
+       struct kthread_work ve_work;
+#endif
 } __randomize_layout;
 
 extern int
@@ -39,6 +45,26 @@ call_usermodehelper_setup(const char *path, char **argv, 
char **envp,
                          int (*init)(struct subprocess_info *info, struct cred 
*new),
                          void (*cleanup)(struct subprocess_info *), void 
*data);
 
+#ifdef CONFIG_VE
+
+extern int
+call_usermodehelper_ve(struct ve_struct *ve, const char *path,
+                      char **argv, char **envp, int wait);
+
+extern int
+call_usermodehelper_exec_ve(struct ve_struct *ve,
+                           struct subprocess_info *info, int wait);
+
+#else /* CONFIG_VE */
+
+#define call_usermodehelper_ve(ve, ...)                \
+               call_usermodehelper(##__VA_ARGS__)
+
+#define call_usermodehelper_exec_ve(ve, ...)   \
+               call_usermodehelper_exec_ve(##__VA_ARGS__)
+
+#endif /* CONFIG_VE */
+
 extern int
 call_usermodehelper_exec(struct subprocess_info *info, int wait);
 
diff --git a/kernel/umh.c b/kernel/umh.c
index e63fd7c9430a..15574a075c2a 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -28,6 +28,7 @@
 #include <linux/async.h>
 #include <linux/uaccess.h>
 #include <linux/initrd.h>
+#include <linux/ve.h>
 
 #include <trace/events/module.h>
 
@@ -412,6 +413,55 @@ struct subprocess_info *call_usermodehelper_setup(const 
char *path, char **argv,
 }
 EXPORT_SYMBOL(call_usermodehelper_setup);
 
+#ifdef CONFIG_VE
+static void call_usermodehelper_queue_ve(struct subprocess_info *info)
+{
+       struct ve_struct *ve = info->ve;
+
+       kthread_queue_work(&ve->umh_worker, &info->ve_work);
+}
+
+static void call_usermodehelper_exec_work_ve(struct kthread_work *work)
+{
+       struct subprocess_info *sub_info =
+               container_of(work, struct subprocess_info, ve_work);
+
+       __call_usermodehelper_exec_work(sub_info);
+}
+
+int call_usermodehelper_exec_ve(struct ve_struct *ve,
+                               struct subprocess_info *sub_info, int wait)
+{
+       if (!ve_is_super(ve)) {
+               sub_info->ve = ve;
+               sub_info->queue = call_usermodehelper_queue_ve;
+               kthread_init_work(&sub_info->ve_work,
+                                 call_usermodehelper_exec_work_ve);
+       } else {
+               sub_info->queue = call_usermodehelper_queue;
+               INIT_WORK(&sub_info->work, call_usermodehelper_exec_work);
+       }
+
+       return call_usermodehelper_exec(sub_info, wait);
+}
+EXPORT_SYMBOL(call_usermodehelper_exec_ve);
+
+int call_usermodehelper_ve(struct ve_struct *ve, const char *path,
+                          char **argv, char **envp, int wait)
+{
+       struct subprocess_info *info;
+       gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
+
+       info = call_usermodehelper_setup(path, argv, envp, gfp_mask,
+                                           NULL, NULL, NULL);
+       if (info == NULL)
+               return -ENOMEM;
+
+       return call_usermodehelper_exec_ve(ve, info, wait);
+}
+EXPORT_SYMBOL(call_usermodehelper_ve);
+#endif
+
 /**
  * call_usermodehelper_exec - start a usermode application
  * @sub_info: information about the subprocess
-- 
2.30.2

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to