[Devel] [PATCH 1/7] Implemented per-ve workqueue.

Valeriy Vdovin valeriy.vdovin at virtuozzo.com
Wed Apr 1 18:41:22 MSK 2020


Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
---
 include/linux/ve.h |  3 +++
 kernel/ve/ve.c     | 31 +++++++++++++++++++++++++++++++
 kernel/workqueue.c |  3 +++
 3 files changed, 37 insertions(+)

diff --git a/include/linux/ve.h b/include/linux/ve.h
index 088e274..92ec8f9 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -125,6 +125,8 @@ struct ve_struct {
 	struct cn_private	*cn;
 #endif
 	struct kmapset_key	sysfs_perms_key;
+
+	struct workqueue_struct	*wq;
 };
 
 struct ve_devmnt {
@@ -228,6 +230,7 @@ extern void monotonic_ve_to_abs(clockid_t which_clock, struct timespec *tp);
 
 void ve_stop_ns(struct pid_namespace *ns);
 void ve_exit_ns(struct pid_namespace *ns);
+int ve0_alloc_wq(void);
 
 static inline struct ve_struct *css_to_ve(struct cgroup_subsys_state *css)
 {
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index b423a96..d4d64ba 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -484,6 +484,29 @@ static const struct timespec zero_time = { };
 
 extern void cgroup_mark_ve_root(struct ve_struct *ve);
 
+static int ve_workqueue_start(struct ve_struct *ve)
+{
+	ve->wq = alloc_workqueue("ve_wq_%s",
+		WQ_SYSFS|WQ_FREEZABLE|WQ_UNBOUND, 8, ve->ve_name);
+
+	if (!ve->wq)
+		return -ENOMEM;
+	return 0;
+}
+
+int ve0_alloc_wq(void)
+{
+	ve0.wq = alloc_workqueue("ve0_wq", WQ_FREEZABLE|WQ_UNBOUND, 8);
+	return ve0.wq == NULL;
+}
+EXPORT_SYMBOL(ve0_alloc_wq);
+
+static void ve_workqueue_stop(struct ve_struct *ve)
+{
+	destroy_workqueue(ve->wq);
+}
+
+
 /* under ve->op_sem write-lock */
 static int ve_start_container(struct ve_struct *ve)
 {
@@ -533,6 +556,10 @@ static int ve_start_container(struct ve_struct *ve)
 
 	cgroup_mark_ve_root(ve);
 
+	err = ve_workqueue_start(ve);
+	if (err)
+		goto err_mark_ve;
+
 	ve->is_running = 1;
 
 	printk(KERN_INFO "CT: %s: started\n", ve_name(ve));
@@ -541,6 +568,8 @@ static int ve_start_container(struct ve_struct *ve)
 
 	return 0;
 
+err_mark_ve:
+	ve_hook_iterate_fini(VE_SS_CHAIN, ve);
 err_iterate:
 	ve_stop_umh(ve);
 err_umh:
@@ -573,6 +602,8 @@ void ve_stop_ns(struct pid_namespace *pid_ns)
 	 */
 	ve->is_running = 0;
 
+	ve_workqueue_stop(ve);
+
 	/*
 	 * Neither it can be in pseudosuper state
 	 * anymore, setup it again if needed.
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 89cc2b2..d66306e 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5486,6 +5486,8 @@ static void __init wq_numa_init(void)
 	wq_numa_enabled = true;
 }
 
+extern int ve0_alloc_wq(void);
+
 /**
  * workqueue_init_early - early init for workqueue subsystem
  *
@@ -5567,6 +5569,7 @@ int __init workqueue_init_early(void)
 	system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient",
 					      WQ_FREEZABLE | WQ_POWER_EFFICIENT,
 					      0);
+	BUG_ON(ve0_alloc_wq());
 	BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq ||
 	       !system_unbound_wq || !system_freezable_wq ||
 	       !system_power_efficient_wq ||
-- 
1.8.3.1



More information about the Devel mailing list