OpenVZ / Virtuozzo kernel development (devel@openvz.org)
 help / color / mirror / Atom feed
* [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests
@ 2026-09-25 12:47 Konstantin Khorenko
  2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 1/3] ve_namespace: Allow entering non-running VE namespace Konstantin Khorenko
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Konstantin Khorenko @ 2026-09-25 12:47 UTC (permalink / raw)
  To: Vladimir Riabchun, Vasileios Almpanis; +Cc: devel

This change adds helpers for creating and preserving various
namespaces and running functions inside them.
This appeared useful while implementing ve mount accounting
selftests - it required keeping mount namespace alive and
doing different things at different moments of time.

To make setns work with CLONE_NEWVE without starting VE,
the first patch changes the -EINVAL return to a warning message.

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

Feature: ve selftests

Changes in v4:
- Moved the ve_namespace patch to the front, before the selftest
  helpers that rely on it.
- ve_namespace: the warning follows the "CT: %s:" format of other
  ve.c messages and prints the VE state and the offender's comm/pid;
  the commit message now explains why the warning is kept.
- namespace management helpers: prepare_namespaces() leaves ctx
  empty on any failure (mask zeroed on entry, saved fds closed on
  error), so unconditional cleanup in callers is safe; fixed a
  comment typo.
- more helpers: dropped a stray blank line in run_in_ve().
- Collected Reviewed-by tags.
- Link to v3: http://lore.virtuozzo.com/20260909-ve-selftest-improv-v3-0-4b41980d9a45@virtuozzo.com

Changes in v3:
- Patch 1: wrap flag -> (flag) in macros, undef them after use.
- Patch 2: Fix comments in run_in_ve function.
- Link to v2: http://lore.virtuozzo.com/20260909-ve-selftest-improv-v2-0-aad0a25d6569@virtuozzo.com

Changes in v2:
- Patch 1: fixed JOIN_NS order in enter_namespaces, added proper
  cleanup in prepare_namespaces.
- Patch 2: increased buf size in write_u64_at, added range check in
  read_s32_at, separated setup failures in run_in_ve from fn setup
  failures.
- Patch 3: Removed kselftests mention.
- Link to v1: http://lore.virtuozzo.com/20260907-ve-selftest-improv-v1-0-a17847abbd48@virtuozzo.com

Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
Vladimir Riabchun (3):
      ve_namespace: Allow entering non-running VE namespace
      selftests/ve: Add namespace management helpers
      selftests/ve: Add more helpers

 kernel/ve/ve_namespace.c                 |   4 +-
 tools/testing/selftests/ve/ve_selftest.h | 214 ++++++++++++++++++++++++++++++-
 2 files changed, 210 insertions(+), 8 deletions(-)
---
base-commit: f7ba712715849bef1a54e1f13fab79b094ccc0df
change-id: 20260907-ve-selftest-improv-2d043d021cae

Best regards,
--  
Konstantin Khorenko <khorenko@virtuozzo.com>

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Devel] [PATCH VZ10 v4 1/3] ve_namespace: Allow entering non-running VE namespace
  2026-09-25 12:47 [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko
@ 2026-09-25 12:47 ` Konstantin Khorenko
  2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 2/3] selftests/ve: Add namespace management helpers Konstantin Khorenko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Konstantin Khorenko @ 2026-09-25 12:47 UTC (permalink / raw)
  To: Vladimir Riabchun, Vasileios Almpanis; +Cc: devel

From: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>

The restriction doesn't bring a lot of value and makes tests more
complex: to enter a VE namespace, the VE has to be actually started.

In vzctl we have locking to prevent parallel creations.
If someone decides to skip locks and start one CT
in parallel - big mistake, but not ours.

Still, entering a non-running CT is a strange thing to do. Our
selftests do it on purpose, but if some of our userspace does the
same on a production node, that is a bug we want to know about and
fix, so leave a warning in place of the check.

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

Feature: ve selftests
Signed-off-by: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>
Reviewed-by: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Reviewed-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 kernel/ve/ve_namespace.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/kernel/ve/ve_namespace.c b/kernel/ve/ve_namespace.c
index 3dbe0dde2645d..6b12bcd605ea4 100644
--- a/kernel/ve/ve_namespace.c
+++ b/kernel/ve/ve_namespace.c
@@ -227,7 +227,9 @@ static int ve_ns_install(struct nsset *nsset, struct ns_common *new)
 		return -EPERM;
 
 	if (!VE_IS_RUNNING(ve_ns->ve))
-		return -EINVAL;
+		pr_warn_once("CT: %s: setns to the VE namespace of a non-running CT (state %d) by %s (%d)\n",
+			     ve_name(ve_ns->ve), ve_ns->ve->state,
+			     current->comm, task_pid_nr(current));
 
 	/*
 	 * Don't need to put_ve_ns(nsset->ve_ns) here,

-- 
2.43.0

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Devel] [PATCH VZ10 v4 2/3] selftests/ve: Add namespace management helpers
  2026-09-25 12:47 [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko
  2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 1/3] ve_namespace: Allow entering non-running VE namespace Konstantin Khorenko
@ 2026-09-25 12:47 ` Konstantin Khorenko
  2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 3/3] selftests/ve: Add more helpers Konstantin Khorenko
  2026-09-25 13:37 ` [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko
  3 siblings, 0 replies; 5+ messages in thread
From: Konstantin Khorenko @ 2026-09-25 12:47 UTC (permalink / raw)
  To: Vladimir Riabchun, Vasileios Almpanis; +Cc: devel

From: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>

When mount namespace is created in a child, it is destroyed
when the child dies. We may need to keep it for a while to check
how VE handles resources.

Instead of keeping a thread which lives in a new ve+mnt namespaces,
let's store open namespace file descriptors to enter them later
without keeping children alive.

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

Feature: ve selftests
Signed-off-by: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>
Reviewed-by: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Reviewed-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 tools/testing/selftests/ve/ve_selftest.h | 130 +++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/tools/testing/selftests/ve/ve_selftest.h b/tools/testing/selftests/ve/ve_selftest.h
index c53bf7900d208..bc9dc28a8d074 100644
--- a/tools/testing/selftests/ve/ve_selftest.h
+++ b/tools/testing/selftests/ve/ve_selftest.h
@@ -31,6 +31,136 @@
 #define VE_CONTROLLERS \
 	"+cpuset +cpu +cpuacct +io +memory +hugetlb +pids +rdma +misc +ve"
 
+struct namespace_ctx {
+	int ns_save_mask;	/* Mask of stored CLONE_NEW* namespaces. */
+	/* Namespace file descriptors. Name should match /proc/PID/ns/NAME */
+	int ve_fd;
+	int mnt_fd;
+};
+
+static inline void close_namespace_fds(struct namespace_ctx *ctx)
+{
+	if (ctx->ns_save_mask & CLONE_NEWVE)
+		close(ctx->ve_fd);
+	if (ctx->ns_save_mask & CLONE_NEWNS)
+		close(ctx->mnt_fd);
+
+	ctx->ns_save_mask = 0;
+}
+
+static inline int save_namespace_fds(struct namespace_ctx *ctx, int flags)
+{
+#define OPEN_NS(name, flag)                                                \
+do {                                                                       \
+	if (flags & (flag)) {                                              \
+		ctx->name##_fd = open("/proc/self/ns/" #name, O_RDONLY);   \
+		if (ctx->name##_fd < 0) {                                  \
+			fprintf(stderr, "%s: could not open fd %s: %s\n",  \
+				__func__, #name, strerror(errno));         \
+			goto err;                                          \
+		}                                                          \
+		ctx->ns_save_mask |= (flag);                               \
+	}                                                                  \
+} while (0)
+
+	ctx->ns_save_mask = 0;
+
+	OPEN_NS(ve, CLONE_NEWVE);
+	OPEN_NS(mnt, CLONE_NEWNS);
+
+#undef OPEN_NS
+	return 0;
+
+err:
+	close_namespace_fds(ctx);
+	return -1;
+}
+
+static inline int enter_namespaces(struct namespace_ctx *ctx, int flags)
+{
+#define JOIN_NS(name, flag)                                                 \
+do {                                                                        \
+	if (flags & (flag)) {                                               \
+		if (!(ctx->ns_save_mask & (flag))) {                        \
+			fprintf(stderr, "%s: could not switch ns %s:"       \
+				" no fd in context.\n", __func__, #name);   \
+			return -1;                                          \
+		}                                                           \
+		if (setns(ctx->name##_fd, (flag))) {                        \
+			fprintf(stderr, "%s: could not switch ns %s: %s\n", \
+				__func__, #name, strerror(errno));          \
+			return -1;                                          \
+		}                                                           \
+	}                                                                   \
+} while (0)
+
+	JOIN_NS(ve, CLONE_NEWVE);
+	JOIN_NS(mnt, CLONE_NEWNS);
+
+#undef JOIN_NS
+	return 0;
+}
+
+static inline int enter_cgroup(int cgv2_fd, int ctid);
+
+/*
+ * Create new namespaces and store them in ctx.
+ * CLONE_NEWVE is treated specially - before unshare corresponding
+ * CT cgroup is entered, after it root cgroup is entered (not the original one).
+ */
+static inline int prepare_namespaces(struct namespace_ctx *ctx, int flags,
+	int cgv2_fd, int ctid)
+{
+	struct namespace_ctx tmp_ctx;
+	int ret = 0;
+
+	ctx->ns_save_mask = 0;
+
+	if (save_namespace_fds(&tmp_ctx, flags) < 0)
+		return -1;
+
+	if (flags & CLONE_NEWVE) {
+		if (enter_cgroup(cgv2_fd, ctid) < 0) {
+			fprintf(stderr, "%s: failed to enter CT cgroup\n", __func__);
+			ret = -1;
+			goto restore_ns;
+		}
+	}
+
+	if (unshare(flags) < 0) {
+		fprintf(stderr, "%s: failed to unshare, flags %x: %s\n",
+			__func__, flags, strerror(errno));
+		ret = -1;
+		goto restore_cg;
+	}
+
+	if (save_namespace_fds(ctx, flags)) {
+		fprintf(stderr, "%s: failed to save new namespaces, flags %x\n",
+			__func__, flags);
+		ret = -1;
+	}
+
+restore_cg:
+	if (flags & CLONE_NEWVE) {
+		if (enter_cgroup(cgv2_fd, 0) < 0) {
+			fprintf(stderr, "%s: failed to restore root cgroup\n", __func__);
+			ret = -1;
+		}
+	}
+
+restore_ns:
+	if (enter_namespaces(&tmp_ctx, flags) < 0) {
+		fprintf(stderr, "%s: failed to restore old namespaces, flags %x\n",
+			__func__, flags);
+		ret = -1;
+	}
+
+	close_namespace_fds(&tmp_ctx);
+	if (ret < 0)
+		close_namespace_fds(ctx);
+	return ret;
+}
+
 static inline int write_file_at(int dirfd, const char *path, const char *val)
 {
 	int fd, ret;

-- 
2.43.0

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Devel] [PATCH VZ10 v4 3/3] selftests/ve: Add more helpers
  2026-09-25 12:47 [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko
  2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 1/3] ve_namespace: Allow entering non-running VE namespace Konstantin Khorenko
  2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 2/3] selftests/ve: Add namespace management helpers Konstantin Khorenko
@ 2026-09-25 12:47 ` Konstantin Khorenko
  2026-09-25 13:37 ` [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko
  3 siblings, 0 replies; 5+ messages in thread
From: Konstantin Khorenko @ 2026-09-25 12:47 UTC (permalink / raw)
  To: Vladimir Riabchun, Vasileios Almpanis; +Cc: devel

From: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>

Some more read/write helpers may be useful.

Also, add a helper to execute functions in child process with
switched namespaces and cgroup.

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

Feature: ve selftests
Signed-off-by: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>
Reviewed-by: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
Reviewed-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 tools/testing/selftests/ve/ve_selftest.h | 84 +++++++++++++++++++++++++++++---
 1 file changed, 77 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/ve/ve_selftest.h b/tools/testing/selftests/ve/ve_selftest.h
index bc9dc28a8d074..7b45f91c1d561 100644
--- a/tools/testing/selftests/ve/ve_selftest.h
+++ b/tools/testing/selftests/ve/ve_selftest.h
@@ -175,6 +175,14 @@ static inline int write_file_at(int dirfd, const char *path, const char *val)
 	return (ret == (int)len) ? 0 : -1;
 }
 
+static inline int write_u64_at(int dirfd, const char *path, unsigned long long val)
+{
+	char s[32];
+
+	snprintf(s, sizeof(s), "%llu", val);
+	return write_file_at(dirfd, path, s);
+}
+
 static inline int read_file_at(int dirfd, const char *path, char *buf,
 			       size_t buflen)
 {
@@ -205,14 +213,9 @@ static inline int read_u64_at(int dirfd, const char *path,
 			      unsigned long long *out)
 {
 	char buf[32] = {0}, *end;
-	int fd, ret;
-
-	fd = openat(dirfd, path, O_RDONLY);
-	if (fd < 0)
-		return -1;
+	int ret;
 
-	ret = read(fd, buf, sizeof(buf) - 1);
-	close(fd);
+	ret = read_file_at(dirfd, path, buf, sizeof(buf));
 	if (ret <= 0)
 		return -1;
 
@@ -223,6 +226,25 @@ static inline int read_u64_at(int dirfd, const char *path,
 	return 0;
 }
 
+static inline int read_s32_at(int dirfd, const char *path,
+			      int *out)
+{
+	char buf[32] = {0}, *end;
+	long tmp;
+	int ret;
+
+	ret = read_file_at(dirfd, path, buf, sizeof(buf));
+	if (ret <= 0)
+		return -1;
+
+	errno = 0;
+	tmp = strtol(buf, &end, 10);
+	if (errno || end == buf || tmp < INT_MIN || tmp > INT_MAX)
+		return -1;
+	*out = tmp;
+	return 0;
+}
+
 /* A fresh, private cgroup2 mount, returned as an fd to use with *at() calls. */
 static inline int mount_cg2_fd(void)
 {
@@ -266,6 +288,54 @@ static inline int enter_cgroup(int cgv2_fd, int ctid)
 	return ret;
 }
 
+/*
+ * Run function in VE cgroup and given namespaces.
+ *
+ * Namespaces are provided via namespace_ctx and entered based on flags mask.
+ *
+ * Return values:
+ *  -  0 if function returns zero
+ *  - -1 if function returns negative value
+ *  -  1 if function returns positive value
+ *  -  2 if setup fails
+ */
+static inline int run_in_ve(int cgv2_fd, int ctid, struct namespace_ctx *ctx,
+		int flags, int (*fn)(void *), void *arg)
+{
+	int status;
+	pid_t pid;
+
+	pid = fork();
+	if (pid < 0) {
+		fprintf(stderr, "%s: fork failed\n", __func__);
+		return 2;
+	}
+	if (pid == 0) {
+		int ret;
+
+		if (enter_cgroup(cgv2_fd, ctid) < 0) {
+			fprintf(stderr, "%s: enter_cgroup failed\n", __func__);
+			_exit(254);
+		}
+		if (enter_namespaces(ctx, flags) < 0)
+			_exit(254);
+
+		ret = fn(arg);
+		if (ret < 0)
+			ret = 1;
+		else if (ret > 0)
+			ret = 255;
+		_exit(ret);
+	}
+	if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status) || WEXITSTATUS(status) == 254)
+		return 2;
+	if (WEXITSTATUS(status) == 255)
+		return 1;
+	if (WEXITSTATUS(status))
+		return -1;
+	return 0;
+}
+
 /*
  * Create a fresh VE cgroup at the first free id at or after @from and unhide
  * its ve.* control files. Return the new id, or -1.

-- 
2.43.0

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests
  2026-09-25 12:47 [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko
                   ` (2 preceding siblings ...)
  2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 3/3] selftests/ve: Add more helpers Konstantin Khorenko
@ 2026-09-25 13:37 ` Konstantin Khorenko
  3 siblings, 0 replies; 5+ messages in thread
From: Konstantin Khorenko @ 2026-09-25 13:37 UTC (permalink / raw)
  To: Vladimir Riabchun, Vasileios Almpanis, Konstantin Khorenko; +Cc: devel

On Fri, 25 Sep 2026 14:47:01 +0200, Konstantin Khorenko wrote:
> Improvements for ve selftests
> 
> This change adds helpers for creating and preserving various
> namespaces and running functions inside them.
> This appeared useful while implementing ve mount accounting
> selftests - it required keeping mount namespace alive and
> doing different things at different moments of time.
> 
> [...]

Applied to branch-rh10-6.12.0-211.52.1.22.x.vz10-ovz, will be released in rh10-6.12.0-211.52.1.22.4.vz10, thanks!

[1/3] ve_namespace: Allow entering non-running VE namespace
      https://bitbucket.org/virtuozzocore/vzkernel.vzs/commits/9c6f7ef26780
[2/3] selftests/ve: Add namespace management helpers
      https://bitbucket.org/virtuozzocore/vzkernel.vzs/commits/c941a3e9e564
[3/3] selftests/ve: Add more helpers
      https://bitbucket.org/virtuozzocore/vzkernel.vzs/commits/e5808fb271c3

-- 
Konstantin Khorenko <khorenko@virtuozzo.com>

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-25 13:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-25 12:47 [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko
2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 1/3] ve_namespace: Allow entering non-running VE namespace Konstantin Khorenko
2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 2/3] selftests/ve: Add namespace management helpers Konstantin Khorenko
2026-09-25 12:47 ` [Devel] [PATCH VZ10 v4 3/3] selftests/ve: Add more helpers Konstantin Khorenko
2026-09-25 13:37 ` [Devel] [PATCH VZ10 v4 0/3] Improvements for ve selftests Konstantin Khorenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox