From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (mail.openvz.org [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id B3A6B80E7E for ; Wed, 28 Oct 2026 12:48:06 +0000 (UTC) Received: from mail.openvz.org (localhost [127.0.0.1]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 69SCkrVT020080; Wed, 28 Oct 2026 15:46:54 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69SCkrVT020080 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="MbFz39k5" Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 69SCkkQs020058 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Wed, 28 Oct 2026 15:46:46 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69SCkkQs020058 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-48e0af48c18so720713f8f.2 for ; Wed, 28 Oct 2026 05:46:46 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvBzdttBBQKKsgF+gkvjs8H6SZoNu34Br0SqJFOD4maNejdysJUcjSFPZ9ZJbNRdCFUDFATMwdQ==@openvz.org X-Gm-Message-State: AFq9FYKhzZrOKJekKeN3tLfaTJNf+4XVI8scoZZqCQ+Ml8ySYYIj1qs9 GYXFb87E+VjxMJ89X8/wwQl8pEPHZpod1hrz8xbPUkgysHCI0ezrYw/gPT+xvV9Ja8DMZN+js0o trFpZX4zjtoPHyXKMCgXk3ZXYNSzFNN91lkG4gwjN6zjahokmYN1Apg== X-Gm-Gg: AYBFou1LiciGbjdZQvVosvv7zW2r23gNzG9uElFBDPlVx40emX4s8wq7JvfO5XwdaMn IYdi7ob2GHhbCAbI8HAO+10LqtesHmrxMhMs3tiQdhAO0zKpAlcPfPlURW2Aq9qjc2zGPA2psbE R71QeawV73woldCCs/PNVVzL71eQYexXsWEHw10Q6CkvUqudI4QOaL58W4voOQYOQ7oLamkkAil qfLuXCnhMp0NGQMXSzReoP/zZzdsIRhRM/7zomwknlD7+i8OGPVfX9N8B1H928aXWyJPc7IR8W4 iRHmiHaqoS4nYxDfhHGAJExm+/24/1fQ9Rv4+tk616yr424JOkxjlfe9Mm9C0WyYxLAo7hqc9f0 niEVzhTGQb0kNNWp1uw1SUPrRv5TZ X-Received: by 2002:a05:6000:4809:b0:48e:5d33:da5c with SMTP id ffacd0b85a97d-48e5d33dac4mr5727897f8f.1.1793191604665; Wed, 28 Oct 2026 05:46:44 -0700 (PDT) X-Received: by 2002:a05:6000:4809:b0:48e:5d33:da5c with SMTP id ffacd0b85a97d-48e5d33dac4mr5727819f8f.1.1793191603999; Wed, 28 Oct 2026 05:46:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1793191603; cv=none; d=google.com; s=arc-20260327; b=fUF5uGs1sntWah/bCT80xf0mXaUszUxxzqdVoTAn5c4CRIQcTzEseDZlu61CWeuhhr uaRlIWBzrGG+ZMvUXl716cTokXCBFZtpKz+QRdadzVxUpBxVuv2Htm7RTWMd7nTOSAzE poz9DlGgjCPSDfNGzHTZY90HsZ9P3mj4P6LohSBwKfSsKBUaZSVxeMUQnwRcxt4VfSDz T4wqpoKAo2Y5whaxIplOyaa1AXfCyw9eQffQEU3FFgOp7b161RrCAzlwX9zo9WNlQAs1 4vkL4dhwJmFfTxEsIBsSdVm2iz3RCm6W9Irgy56boZP+KdPv3bVE/9Ct12NqrcHPrdgd t0kw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:dkim-signature; bh=sTIjjjjqkJ67EGPWbAEk7NRg7y1q9JcTqYYPTpXXcwQ=; fh=5hQRK+XZF8m8FADH0g5yAiDkSoTAVGTSxnnvVVATGZQ=; b=RfeA3CTfw+wbHCwwbfRwI4lTNtghJnUhKiSAfmaGzHSEzUD36dkRTrdC0nY61OlppH ayd8jpN1sRAZ3uQFtMq3BY/VksLHMFNWd9XhRaaMyinzq3sBvwYBHNwp8UPd1uZcdySr xB7mLYNpJG19P5RbIMBWDzeLvL0y5z4yLhl+G4cNlrXqbuVzJZ/RLK2CsAljg71Y/jGX GRm+LXp7JpkY4VbMc0SwFloYsDkQgWSVEBQCc11cu844v25RWEjzmsNH0zkZ/tm+SR8Y lSaq1SIWgt/jWHG8puNNXWm3hbc6vRaEWY76OzPKhvxIDVz6OOhrsZ7tcYKAFVGbLZ4l NNwg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=MbFz39k5; spf=pass (google.com: domain of vladimir.riabchun@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=vladimir.riabchun@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com Received: from relay.virtuozzo.com (relay.virtuozzo.com. [130.117.225.111]) by mx.google.com with ESMTPS id ffacd0b85a97d-48e3ece8812si25243813f8f.178.2026.10.28.05.46.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Oct 2026 05:46:43 -0700 (PDT) Received-SPF: pass (google.com: domain of vladimir.riabchun@virtuozzo.com designates 130.117.225.111 as permitted sender) client-ip=130.117.225.111; Authentication-Results: mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=MbFz39k5; spf=pass (google.com: domain of vladimir.riabchun@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=vladimir.riabchun@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=Message-Id:Content-Type:MIME-Version:Subject:Date :From; bh=sTIjjjjqkJ67EGPWbAEk7NRg7y1q9JcTqYYPTpXXcwQ=; b=MbFz39k5eYHMsrVb1RI 5xRgi/EYe4URoFSGdonuQYTLrc3SVNgQO0hiI7m5ZhJr5uNY8FNJyz8GL21+BwqHbDWjprnr/ue0R DHWSsxJTuHFoTi5Wm+KaMKXaEq/JgvkUvDfyYLQa0n4eNB3emFbqAqK0a5EmJunQK0wJfGAL63v+Y A9b6hEb9wjTk09XB25pu8Dlej2emQDp2GtwV2KyQ6QnB9lK16VBaqd2IoMYstZt4K8VsWxBrHAm1L mYz8UfdaiAv8Aetfry9cGWpFtnzYqf6+d3eeCMNsSAQnDyZRM92rYNdITiTT4fY4aQbOvxZxUQzH0 KEZ/eCxEp2GyM2w==; Received: from ch-demo-asa.virtuozzo.com ([130.117.225.8] helo=192.168.1.87) by relay.virtuozzo.com with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1xM2zR-007lg7-1h; Wed, 28 Oct 2026 13:46:43 +0100 From: Vladimir Riabchun Date: Wed, 28 Oct 2026 13:46:38 +0100 MIME-Version: 1.0 Message-Id: <20261028-ct-invalid-nrpoc-v2-2-968fe985ce27@virtuozzo.com> References: <20261028-ct-invalid-nrpoc-v2-0-968fe985ce27@virtuozzo.com> In-Reply-To: <20261028-ct-invalid-nrpoc-v2-0-968fe985ce27@virtuozzo.com> To: ptikhomirov@virtuozzo.com, Konstantin Khorenko X-Mailer: b4 0.16.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 v2 2/2] selftests: ve: Test sched_getaffinity in VE X-BeenThere: devel@openvz.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: OpenVZ development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: devel-bounces@openvz.org Errors-To: devel-bounces@openvz.org Add a new selftest that verifies that sched_getaffinity respects both cgroup cpuset and nr_cpus limits. https://virtuozzo.atlassian.net/browse/VSTOR-141682 Signed-off-by: Vladimir Riabchun --- tools/testing/selftests/ve/.gitignore | 1 + tools/testing/selftests/ve/Makefile | 1 + .../selftests/ve/ve_sched_getaffinity_test.c | 213 +++++++++++++++++++++ 3 files changed, 215 insertions(+) diff --git a/tools/testing/selftests/ve/.gitignore b/tools/testing/selftests/ve/.gitignore index 8ab1bfe6f5e4..178de0ee1822 100644 --- a/tools/testing/selftests/ve/.gitignore +++ b/tools/testing/selftests/ve/.gitignore @@ -3,3 +3,4 @@ ve_perms_test ve_mount_accounting_test ve_cpuid_override_test ve_vtty_stress +ve_sched_getaffinity_test diff --git a/tools/testing/selftests/ve/Makefile b/tools/testing/selftests/ve/Makefile index 51f9316beb99..d53e724205f7 100644 --- a/tools/testing/selftests/ve/Makefile +++ b/tools/testing/selftests/ve/Makefile @@ -6,6 +6,7 @@ TEST_GEN_PROGS += ve_ns_owner_test TEST_GEN_PROGS += ve_perms_test TEST_GEN_PROGS += ve_mount_accounting_test TEST_GEN_PROGS += ve_vtty_stress +TEST_GEN_PROGS += ve_sched_getaffinity_test # CPUID faulting is x86-64 only. ARCH says "x86" for 32-bit too and lib.mk # picks the clang target by its emptiness, so decide by the compiler. diff --git a/tools/testing/selftests/ve/ve_sched_getaffinity_test.c b/tools/testing/selftests/ve/ve_sched_getaffinity_test.c new file mode 100644 index 000000000000..376b65a215f1 --- /dev/null +++ b/tools/testing/selftests/ve/ve_sched_getaffinity_test.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ve_mount_accounting selftests + * + * Tests to check cpuset virtualization. + * Not suitable for running inside CT. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../kselftest_harness.h" +#include "ve_selftest.h" + +FIXTURE(ve_getaff_test) +{ + int cgv2_fd; + int ctid; + struct namespace_ctx ns_ctx; + cpu_set_t orig_cpuset; + int orig_cpucount; +}; + +static int __getaffinity_ve(void *cpuset) +{ + cpu_set_t *dst = cpuset; + + return sched_getaffinity(getpid(), sizeof(*dst), dst); +} + +static int getaffinity_ve(FIXTURE_DATA(ve_getaff_test) * self, cpu_set_t *dst) +{ + int ret = -1; + cpu_set_t *tmp = mmap(NULL, sizeof(cpu_set_t), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + + if (tmp == MAP_FAILED) { + fprintf(stderr, "Failed to mmap shared region: %s\n", strerror(errno)); + return -1; + } + CPU_ZERO(tmp); + CPU_ZERO(dst); + + ret = run_in_ve(self->cgv2_fd, self->ctid, &self->ns_ctx, + CLONE_NEWVE, __getaffinity_ve, tmp); + + if (!ret) + memcpy(dst, tmp, sizeof(cpu_set_t)); + + munmap(tmp, sizeof(cpu_set_t)); + return ret; +} + +static int check_cpumask_is_prefix(cpu_set_t *mask, int expected) +{ + int i, count = CPU_COUNT(mask); + + if (expected >= 0 && expected != count) { + fprintf(stderr, "cpumask count mismatch: %d != %d\n", expected, count); + return 0; + } + for (i = 0; i < count; i++) { + if (!CPU_ISSET(i, mask)) { + fprintf(stderr, "cpumask is not a prefix: %d is OFF\n", i); + return 0; + } + } + return 1; +} + +static int get_nth_cpu(cpu_set_t *mask, int n) +{ + int i; + + for (i = 0; i < sizeof(*mask); i++) { + if (!CPU_ISSET(i, mask) || --n) + continue; + + return i; + } + return -1; +} + +FIXTURE_SETUP(ve_getaff_test) +{ + self->cgv2_fd = mount_cg2_fd(); + ASSERT_GE(self->cgv2_fd, 0); + + ASSERT_EQ(write_file_at(self->cgv2_fd, "cgroup.subtree_control", + VE_CONTROLLERS), 0); + + self->ctid = make_ve(self->cgv2_fd, CTID_MIN); + ASSERT_GE(self->ctid, 0); + + ASSERT_EQ(prepare_namespaces(&self->ns_ctx, CLONE_NEWVE, + self->cgv2_fd, self->ctid), 0); + + + ASSERT_EQ(sched_getaffinity(getpid(), sizeof(cpu_set_t), &self->orig_cpuset), 0); + if (CPU_COUNT(&self->orig_cpuset) < 2) + SKIP(return, "Not enough CPUs available"); + + self->orig_cpucount = CPU_COUNT(&self->orig_cpuset); +}; + +FIXTURE_TEARDOWN(ve_getaff_test) +{ + close_namespace_fds(&self->ns_ctx); + destroy_ve(self->cgv2_fd, self->ctid); + close(self->cgv2_fd); +} + +/* Test correct processing of cpuset.cpus updates */ +TEST_F(ve_getaff_test, update_cg_cpuset) +{ + char path[PATH_MAX]; + int cpu_leave; + cpu_set_t in_ve; + + snprintf(path, sizeof(path), "%d/cpuset.cpus", self->ctid); + if (faccessat(self->cgv2_fd, path, F_OK, 0)) + SKIP(return, "CT cgroup doesn't have cpuset.cpus entry"); + + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, self->orig_cpucount)); + + /* Find two CPUs and leave the second via cgroup interface */ + cpu_leave = get_nth_cpu(&self->orig_cpuset, 2); + ASSERT_GE(cpu_leave, 0); + ASSERT_EQ(write_u64_at(self->cgv2_fd, path, cpu_leave), 0); + + /* Verify sched_getaffinity sees 1 CPU, that is the first one */ + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, 1)); +} + +/* Test correct processing of cpu.nr_cpus updates */ +TEST_F(ve_getaff_test, nr_proc_bound) +{ + char path[PATH_MAX]; + cpu_set_t in_ve; + + snprintf(path, sizeof(path), "%d/cpu.nr_cpus", self->ctid); + if (faccessat(self->cgv2_fd, path, F_OK, 0)) + SKIP(return, "CT cgroup doesn't have cpu.nr_cpus entry"); + + /* We expect here CPU_COUNT >= 2 */ + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, self->orig_cpucount)); + + /* Leave one vCPU */ + ASSERT_EQ(write_u64_at(self->cgv2_fd, path, 1), 0); + + /* Verify sched_getaffinity sees only one vCPU */ + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, 1)); +} + +/* Test correct interaction of cpu.nr_cpus and cpuset.cpus */ +TEST_F(ve_getaff_test, limits_interaction) +{ + char path_nr[PATH_MAX], path_set[PATH_MAX], tmp[128]; + int c1, c3; + cpu_set_t in_ve; + + snprintf(path_nr, sizeof(path_nr), "%d/cpu.nr_cpus", self->ctid); + if (faccessat(self->cgv2_fd, path_nr, F_OK, 0)) + SKIP(return, "CT cgroup doesn't have cpu.nr_cpus entry"); + + snprintf(path_set, sizeof(path_set), "%d/cpuset.cpus", self->ctid); + if (faccessat(self->cgv2_fd, path_set, F_OK, 0)) + SKIP(return, "CT cgroup doesn't have cpuset.cpus entry"); + + if (self->orig_cpucount < 3) + SKIP(return, "This test requires at least 3 CPUs"); + + /* We expect here CPU_COUNT >= 3 */ + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, self->orig_cpucount)); + + /* Leave two CPUs in cpuset */ + c1 = get_nth_cpu(&self->orig_cpuset, 1); + c3 = get_nth_cpu(&self->orig_cpuset, 3); + ASSERT_TRUE(c1 >= 0 && c3 >= 0); + + snprintf(tmp, sizeof(tmp), "%d,%d", c1, c3); + ASSERT_EQ(write_file_at(self->cgv2_fd, path_set, tmp), 0); + + /* Verify sched_getaffinity sees two vCPU */ + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, 2)); + + /* Set vCPU limit to 2 and check that we still have two vCPUs */ + ASSERT_EQ(write_u64_at(self->cgv2_fd, path_nr, 2), 0); + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, 2)); + + /* Set vCPU limit to 1 and check that we have one vCPU only */ + ASSERT_EQ(write_u64_at(self->cgv2_fd, path_nr, 1), 0); + ASSERT_EQ(getaffinity_ve(self, &in_ve), 0); + ASSERT_TRUE(check_cpumask_is_prefix(&in_ve, 1)); + +} + +TEST_HARNESS_MAIN -- 2.52.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel