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 979D580F2B for ; Thu, 29 Oct 2026 10:17:49 +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 69TAGYPv031231; Thu, 29 Oct 2026 13:16:35 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69TAGYPv031231 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="c7iUITro" Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 69TAGUfq031214 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Thu, 29 Oct 2026 13:16:30 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69TAGUfq031214 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-48c6a1d4034so1687956f8f.0 for ; Thu, 29 Oct 2026 03:16:30 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvBz0Gi1aN/p9rOSODD/u9hZLVH6B5u3Uw0amMrfJpQ0As+LJrtMsgSwBUft2/a3x7KclRUrULA==@openvz.org X-Gm-Message-State: AFq9FYIgW8f3ExLP9casVDKoq48CoK96ZPW7o7i2Wb4v0lkVsc0EYDco oNm0p9o8gOAR6/9ixMHyyicBKma95NDFSfS+EcwCwhbKwFD0CMRSXmx/cdElpIa1ChFlRg6r+DZ dLAUFhIxiDpH4Yh48H8IMXnGJdsPPu38HbAxZyJSu2Icpq0EMMrjJhA== X-Gm-Gg: AYBFou1XtBilIvrSsMFfeVSaNLWFoVk1zOY4FmEDsK1B7Q94fEnqevnRNu7vcdcbKq8 cLlz72ef1AE8F30zAchtoPVSijBTT7CV8SS4GKm2b0Z6eDKKoOkw8gOFfliw6FK0nUR6FiE1tiQ YtFwxNju9qLXUtsjMOGSpIPSPW4gKSmAvsTsFNDYwy7Uz7BhW0cr6HYIvkNgaMKUqflccuI1u8p ftjRwAoHFep6qIVhCmRDK7nCu8U3jezC2PuuMP4erVwdm3aVxlJoD3o1WzUOYiVVfSV2GDoVH06 FKroDZCUUpghLr+/lexm/5n0fuqyU4MFCRBc7L6fLa4KnqddQV/sRJgfFCXe+FIqDxcodtKhJoY IvSlfj+nltclBFwztGBIAhzkoZFlP X-Received: by 2002:a05:6000:240b:b0:48d:f996:1814 with SMTP id ffacd0b85a97d-48e5d31aa6dmr12097645f8f.57.1793268989807; Thu, 29 Oct 2026 03:16:29 -0700 (PDT) X-Received: by 2002:a05:6000:240b:b0:48d:f996:1814 with SMTP id ffacd0b85a97d-48e5d31aa6dmr12097588f8f.57.1793268989286; Thu, 29 Oct 2026 03:16:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1793268989; cv=none; d=google.com; s=arc-20260327; b=fLJySogsR+LGS+Un9/KJ/5SYNA1GdxQy73tJ/MSDyqVtDOys0Y50lrqlQBZVjOmcg3 pLDHElFdjmkJvKiNKelD4B8l8TRvGgH8yFT/1RiDosq6cMEXQda9j2bDo8kWpYN6CWai AKLHh5gfZBlJOJ+24jVXPHVny54VEzbs80QrKeij9IOBqMUInoxzxz+4Mfsp/vP/bHde fcGvuNPiWkDBnS0ASAXqidxlBJZ4UZHu9qzpz1CxpX/UIcwV87pO/KoIDeSLxu3hHdK+ t8zhufw1zR0M5wWxU6kFrTb3HN4H0gVNEbhLrwBQrAnH86uTUw3yTlPwsKjrfZ+SFlYX ACkw== 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=NyxL/xqwndCMPp+8JXFZWqqCxfsFBLMFxWh3zzMWZuc=; fh=KvH6Oi7EXpULPk9Xhi1cVoBuOgMONteER7B5+uz05Qo=; b=j3gyToNc8P0VlFaMHFv8qSxQlY8TzMo7NkGzePfdukg9Vpru2JJAGP/VEtmuUg6lUt C9jw5XT/1OLHsc1wWLjUad+kFkKUud7TvcmnTUHfZT0TaDDU1MWm47zJUzlvo2OhOBo5 2F3uqwug5xXb6LG+SWQkydss0iYk7EvlDQBrPBlA0XmEKtN7j9Vgrwr8IzxSEELPWVWr zVJ3EGdUiKvASU4LeQW1hI3j5T8Fwm5UxVHptLDnnrPNPu/+zDQuwTcE1zHNLnURgY34 ywT8HcddK91Q48E2I9dkbub7Q1nnNzWVH0GNCsl87EeAA827yJMO37QCgRL8xEZmgJjJ BaDg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=c7iUITro; 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-48e3ecf6cacsi30296836f8f.251.2026.10.29.03.16.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Oct 2026 03:16:29 -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=c7iUITro; 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=NyxL/xqwndCMPp+8JXFZWqqCxfsFBLMFxWh3zzMWZuc=; b=c7iUITrox1Z8VfHx031 1uSQpWu+f6RqB4KRQdtdxuTxs6cjRkZzADKgA+iN+OVko3ZkJDyC9qqGw5qELdfLBrAaOnS4wY3hD Iyc7UEYPnx0gQZV30MpgsendMjsmF2LKEAqXzH/2M2aCrZ95H92N4NTdmbNVWEuDOoTuyP4fKzaWe 3ucFQWsK6jasOWLLAysq5cO4Ya2pZhvTgDd+pMOAae6sj7G8gRE+SIY2wVHB/CKwz4WHbEgz9rqsg TthKDKpuvH2T5l5PeyCWNVj5lbbAQI2C4hk6MQVhCy4Vr7KPBMAB8sQm/BXjJnDuawiDl37SvOQDa w/I5hoZ+ROPGbBA==; 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 1xMN7Z-001e0Y-1Z; Thu, 29 Oct 2026 11:16:27 +0100 From: Vladimir Riabchun Date: Thu, 29 Oct 2026 11:16:07 +0100 MIME-Version: 1.0 Message-Id: <20261029-ct-invalid-nrpoc-v3-2-89d4b0b7d520@virtuozzo.com> References: <20261029-ct-invalid-nrpoc-v3-0-89d4b0b7d520@virtuozzo.com> In-Reply-To: <20261029-ct-invalid-nrpoc-v3-0-89d4b0b7d520@virtuozzo.com> To: Konstantin Khorenko , ptikhomirov@virtuozzo.com X-Mailer: b4 0.16.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 v3 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 | 211 +++++++++++++++++++++ 3 files changed, 213 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..98acc246ede0 --- /dev/null +++ b/tools/testing/selftests/ve/ve_sched_getaffinity_test.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ve_sched_getaffinity 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) +{ + ASSERT_EQ(sched_getaffinity(getpid(), sizeof(cpu_set_t), &self->orig_cpuset), 0); + self->orig_cpucount = CPU_COUNT(&self->orig_cpuset); + if (self->orig_cpucount < 2) + SKIP(return, "Not enough CPUs available"); + + 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); +} + +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