[Devel] [PATCH hci-8.1 3/6] ve/printk: Specify ve in printks

Vladimir Riabchun vladimir.riabchun at virtuozzo.com
Sat Oct 3 00:26:12 MSK 2026


Introduce ve_printk helpers that accept VE structure,
so we can provide correct VE where get_exec_env is unreliable.

This is true for ve_printk_deferred functions, and their users.
Now VE ratelimiting requires specified VE, and this requirement
is further forwarded to ve_net_ratelimited kind.

https://virtuozzo.atlassian.net/browse/VSTOR-146839

Feature: ve printk
Signed-off-by: Vladimir Riabchun <vladimir.riabchun at virtuozzo.com>
---
 include/linux/net.h                 | 16 ++++----
 include/linux/printk.h              | 23 ++++++++++--
 include/linux/ratelimit_types.h     |  6 ++-
 kernel/printk/printk.c              | 74 +++++++++++++++++++++++++++++++------
 lib/ratelimit.c                     |  7 ++--
 net/core/utils.c                    |  4 +-
 net/netfilter/nf_conntrack_core.c   |  2 +-
 net/netfilter/nf_conntrack_expect.c |  2 +-
 net/netfilter/xt_TCPMSS.c           |  4 +-
 9 files changed, 104 insertions(+), 34 deletions(-)

diff --git a/include/linux/net.h b/include/linux/net.h
index 3f3bbe9f149d..4c34b9a0386f 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -265,7 +265,7 @@ struct socket *sockfd_lookup(int fd, int *err);
 struct socket *sock_from_file(struct file *file);
 #define		     sockfd_put(sock) fput(sock->file)
 int net_ratelimit(void);
-int ve_net_ratelimit(int dst);
+int ve_net_ratelimit(int dst, struct ve_struct *ve);
 
 #define net_ratelimited_function(function, ...)			\
 do {								\
@@ -273,10 +273,10 @@ do {								\
 		function(__VA_ARGS__);				\
 } while (0)
 
-#define ve_net_ratelimited_function(function, dst, ...)		\
+#define ve_net_ratelimited_function(function, dst, ve, ...)	\
 do {								\
-	if (ve_net_ratelimit(dst))				\
-		function(dst, __VA_ARGS__);			\
+	if (ve_net_ratelimit(dst, ve))				\
+		function(dst, ve, __VA_ARGS__);			\
 } while (0)
 
 #define net_emerg_ratelimited(fmt, ...)				\
@@ -311,10 +311,10 @@ do {									\
 	no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
 #endif
 
-#define net_velog_ratelimited(fmt, ...)                                \
-	ve_net_ratelimited_function(ve_printk, VE_LOG, fmt, ##__VA_ARGS__)
-#define net_veboth_ratelimited(fmt, ...)                               \
-	ve_net_ratelimited_function(ve_printk, VE_LOG_BOTH, fmt, ##__VA_ARGS__)
+#define net_velog_ratelimited(ve, fmt, ...)						\
+	ve_net_ratelimited_function(__ve_printk, VE_LOG, ve, fmt, ##__VA_ARGS__)
+#define net_veboth_ratelimited(ve, fmt, ...)						\
+	ve_net_ratelimited_function(__ve_printk, VE_LOG_BOTH, ve, fmt, ##__VA_ARGS__)
 
 #define net_get_random_once(buf, nbytes)			\
 	get_random_once((buf), (nbytes))
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 3b0af0deb6c3..1478e47dc582 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -76,6 +76,7 @@ extern int console_printk[];
 #define VE0_LOG		1
 #define VE_LOG		2
 #define VE_LOG_BOTH	(VE0_LOG | VE_LOG)
+struct ve_struct;
 
 extern void console_verbose(void);
 
@@ -160,6 +161,11 @@ int ve_vprintk_emit(int facility, int level,
 		    const struct dev_printk_info *dev_info,
 		    const char *fmt, va_list args);
 
+asmlinkage __printf(5, 0)
+int __ve_vprintk_emit(struct ve_struct *ve, int facility, int level,
+		    const struct dev_printk_info *dev_info,
+		    const char *fmt, va_list args);
+
 asmlinkage __printf(1, 0)
 int vprintk(const char *fmt, va_list args);
 __printf(1, 0)
@@ -171,8 +177,11 @@ int _printk(const char *fmt, ...);
 asmlinkage __printf(2, 3) __cold
 int ve_printk(int dst, const char *fmt, ...);
 
-asmlinkage __printf(2, 3) __cold
-int ve_printk_deferred(int dst, const char *fmt, ...);
+asmlinkage __printf(3, 4) __cold
+int __ve_printk(int dst, struct ve_struct *ve, const char *fmt, ...);
+
+asmlinkage __printf(3, 4) __cold
+int ve_printk_deferred(int dst, struct ve_struct *ve, const char *fmt, ...);
 
 struct ve_struct;
 int ve_log_init(struct ve_struct *ve);
@@ -248,8 +257,13 @@ int ve_printk(int dst, const char *s, ...)
 {
 	return 0;
 }
+static inline __printf(3, 4) __cold
+int __ve_printk(int dst, struct ve_struct *ve, const char *s, ...)
+{
+	return 0;
+}
 static inline __printf(2, 3) __cold
-int ve_printk_deferred(int dst, const char *s, ...)
+int ve_printk_deferred(int dst, struct ve_struct *ve, const char *s, ...)
 {
 	return 0;
 }
@@ -747,7 +761,8 @@ struct pi_entry {
 				      DEFAULT_RATELIMIT_INTERVAL,	\
 				      DEFAULT_RATELIMIT_BURST);		\
 									\
-	if (ve_ratelimit(dst, &_rs))					\
+	WARN_ON_ONCE((dst & VE_LOG) && !in_task());			\
+	if (ve_ratelimit(dst, get_exec_env(), &_rs))			\
 		ve_printk(dst, fmt, ##__VA_ARGS__);			\
 })
 #else
diff --git a/include/linux/ratelimit_types.h b/include/linux/ratelimit_types.h
index 3902066f0fee..aa9eee2a2455 100644
--- a/include/linux/ratelimit_types.h
+++ b/include/linux/ratelimit_types.h
@@ -44,7 +44,9 @@ struct ratelimit_state {
 extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
 #define __ratelimit(state) ___ratelimit(state, __func__)
 
-extern int __ve_ratelimit(int dst, struct ratelimit_state *rs, const char *func);
-#define ve_ratelimit(dst, state) __ve_ratelimit(dst, state, __func__)
+struct ve_struct;
+extern int __ve_ratelimit(int dst, struct ve_struct *ve,
+	struct ratelimit_state *rs, const char *func);
+#define ve_ratelimit(dst, ve, state) __ve_ratelimit(dst, ve, state, __func__)
 
 #endif /* _LINUX_RATELIMIT_TYPES_H */
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index b06fc835d7c7..df7cf83fb4af 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -567,6 +567,16 @@ struct log_state *ve_log_state(void)
 	return log;
 }
 
+struct log_state *__ve_log_state(struct ve_struct *ve)
+{
+	struct log_state *log = &init_log_state;
+#ifdef CONFIG_VE
+	if (ve->log_state)
+		log = ve->log_state;
+#endif
+	return log;
+}
+
 void log_poll_wait(struct file *filp, poll_table *p)
 {
 	poll_wait(filp, &ve_log_state()->wait, p);
@@ -2525,26 +2535,45 @@ asmlinkage int ve_vprintk_emit(int facility, int level,
 }
 EXPORT_SYMBOL(ve_vprintk_emit);
 
+asmlinkage int __ve_vprintk_emit(struct ve_struct *ve, int facility, int level,
+			       const struct dev_printk_info *dev_info,
+			       const char *fmt, va_list args)
+{
+	return vprintk_emit_log(__ve_log_state(ve),
+				facility, level, dev_info,
+				fmt, args);
+}
+EXPORT_SYMBOL(__ve_vprintk_emit);
+
 int vprintk_default(const char *fmt, va_list args)
 {
 	return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
 }
 EXPORT_SYMBOL_GPL(vprintk_default);
 
-static asmlinkage int ve_vprintk(int dst, const char *fmt, va_list args)
+static asmlinkage int ve_vprintk(int dst, struct ve_struct *ve,
+				const char *fmt, va_list args)
 {
 	va_list args2;
-	int r = 0;
+	int r = 0, ve_provided = (ve != NULL);
 
 	WARN_ON_ONCE(!dst || (dst & ~VE_LOG_BOTH));
 
+	if (!ve)
+		ve = get_exec_env();
+
 	va_copy(args2, args);
 	if (ve_is_super(get_exec_env()) || (dst & VE0_LOG))
 		r = vprintk(fmt, args);
 
 	/* Report IRQ usage here - printing to VE requires explicit ve reference */
-	if ((dst & VE_LOG) && !WARN_ON_ONCE(!in_task()) && !ve_is_super(get_exec_env()))
-		r = ve_vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args2);
+	if ((dst & VE_LOG)) {
+		if (!ve_provided && WARN_ON_ONCE(!in_task()))
+			goto done;
+		if (!ve_is_super(ve))
+			r = __ve_vprintk_emit(ve, 0, LOGLEVEL_DEFAULT, NULL, fmt, args2);
+	}
+done:
 	va_end(args2);
 
 	return r;
@@ -2560,39 +2589,62 @@ asmlinkage int ve_printk(int dst, const char *fmt, ...)
 	int r;
 
 	va_start(args, fmt);
-	r = ve_vprintk(dst, fmt, args);
+	r = ve_vprintk(dst, NULL, fmt, args);
 	va_end(args);
 
 	return r;
 }
 EXPORT_SYMBOL(ve_printk);
 
-static asmlinkage int ve_vprintk_deferred(int dst, const char *fmt, va_list args)
+asmlinkage int __ve_printk(int dst, struct ve_struct *ve, const char *fmt, ...)
+{
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+	r = ve_vprintk(dst, ve, fmt, args);
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(__ve_printk);
+
+static asmlinkage int ve_vprintk_deferred(int dst, struct ve_struct *ve, 
+					const char *fmt, va_list args)
 {
 	va_list args2;
-	int r = 0;
+	int r = 0, ve_provided = (ve != NULL);
 
 	WARN_ON_ONCE(!dst || (dst & ~VE_LOG_BOTH));
 
+	if (!ve)
+		ve = get_exec_env();
+
 	va_copy(args2, args);
 	if (ve_is_super(get_exec_env()) || (dst & VE0_LOG))
 		r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args);
 
 	/* Report IRQ usage here - printing to VE requires explicit ve reference */
-	if ((dst & VE_LOG) && !WARN_ON_ONCE(!in_task()) && !ve_is_super(get_exec_env()))
-		r = ve_vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args2);
+	if ((dst & VE_LOG)) {
+		if (!ve_provided && WARN_ON_ONCE(!in_task()))
+			goto done;
+		if (!ve_is_super(ve))
+			r = __ve_vprintk_emit(ve, 0, LOGLEVEL_SCHED, NULL, fmt, args2);
+	}
+done:
 	va_end(args2);
 
 	return r;
 }
 
-asmlinkage int ve_printk_deferred(int dst, const char *fmt, ...)
+asmlinkage int ve_printk_deferred(int dst, struct ve_struct *ve,
+	const char *fmt, ...)
 {
 	va_list args;
 	int r;
 
 	va_start(args, fmt);
-	r = ve_vprintk_deferred(dst, fmt, args);
+	r = ve_vprintk_deferred(dst, ve, fmt, args);
 	va_end(args);
 
 	return r;
diff --git a/lib/ratelimit.c b/lib/ratelimit.c
index 98409e870eea..98c45bb19e50 100644
--- a/lib/ratelimit.c
+++ b/lib/ratelimit.c
@@ -11,6 +11,7 @@
 #include <linux/ratelimit.h>
 #include <linux/jiffies.h>
 #include <linux/export.h>
+#include <linux/ve_proto.h>
 
 /*
  * __ratelimit - rate limiting
@@ -24,7 +25,7 @@
  * 0 means callbacks will be suppressed.
  * 1 means go ahead and do it.
  */
-int __ve_ratelimit(int dst, struct ratelimit_state *rs, const char *func)
+int __ve_ratelimit(int dst, struct ve_struct *ve, struct ratelimit_state *rs, const char *func)
 {
 	/* Paired with WRITE_ONCE() in .proc_handler().
 	 * Changing two values seperately could be inconsistent
@@ -55,7 +56,7 @@ int __ve_ratelimit(int dst, struct ratelimit_state *rs, const char *func)
 
 		if (m) {
 			if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
-				ve_printk_deferred(dst, KERN_WARNING
+				ve_printk_deferred(dst, ve, KERN_WARNING
 						"%s: %d callbacks suppressed\n", func, m);
 			}
 		}
@@ -77,6 +78,6 @@ EXPORT_SYMBOL(__ve_ratelimit);
 
 int ___ratelimit(struct ratelimit_state *rs, const char *func)
 {
-	return __ve_ratelimit(VE0_LOG, rs, func);
+	return __ve_ratelimit(VE0_LOG, get_ve0(), rs, func);
 }
 EXPORT_SYMBOL(___ratelimit);
diff --git a/net/core/utils.c b/net/core/utils.c
index cffc3bc44baa..bf4e53205a8e 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -41,9 +41,9 @@ int net_ratelimit(void)
 }
 EXPORT_SYMBOL(net_ratelimit);
 
-int ve_net_ratelimit(int dst)
+int ve_net_ratelimit(int dst, struct ve_struct *ve)
 {
-	return ve_ratelimit(dst, &net_ratelimit_state);
+	return ve_ratelimit(dst, ve, &net_ratelimit_state);
 }
 EXPORT_SYMBOL(ve_net_ratelimit);
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index f078136edddd..8900a41b48b6 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1701,7 +1701,7 @@ __nf_conntrack_alloc(struct net *net,
 			if (!conntrack_gc_work.early_drop)
 				conntrack_gc_work.early_drop = true;
 			atomic_dec(&cnet->count);
-			net_veboth_ratelimited(KERN_WARNING "VE%s: "
+			net_veboth_ratelimited(net->owner_ve, KERN_WARNING "VE%s: "
 					       "nf_conntrack table full in netns %u, dropping packet\n",
 					       ve_name(net->owner_ve), net->ns.inum);
 			return ERR_PTR(-ENOMEM);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 4b077b2cb432..23e78957bb79 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -508,7 +508,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
 
 	cnet = nf_ct_pernet(net);
 	if (cnet->expect_count >= cnet->expect_max) {
-		net_veboth_ratelimited(KERN_WARNING "VE%s: "
+		net_veboth_ratelimited(net->owner_ve, KERN_WARNING "VE%s: "
 					"nf_conntrack: expectation table full in netns %u\n",
 					ve_name(net->owner_ve), net->ns.inum);
 		ret = -EMFILE;
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 822b3f71570e..0b9ccc8987e2 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -105,8 +105,8 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 		unsigned int min_mtu = min(dst_mtu(skb_dst(skb)), in_mtu);
 
 		if (min_mtu <= minlen) {
-			net_velog_ratelimited("unknown or invalid path-MTU (%u)\n",
-					    min_mtu);
+			net_velog_ratelimited(net->owner_ve, "unknown or invalid path-MTU (%u)\n",
+					      min_mtu);
 			return -1;
 		}
 		newmss = min_mtu - minlen;

-- 
2.52.0



More information about the Devel mailing list