From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (unknown [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id 9133F8017D for ; Wed, 14 Oct 2026 17:16:59 +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 69EHFb9r001546; Wed, 14 Oct 2026 20:15:38 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69EHFb9r001546 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="eOYqI7F8" 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 69EHF73t001473 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Wed, 14 Oct 2026 20:15:07 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 69EHF73t001473 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-48b02d63407so2651303f8f.0 for ; Wed, 14 Oct 2026 10:15:07 -0700 (PDT) X-Gm-Message-State: AFq9FYLS9fqHlDRIIDI06/enDuivhTa7RuWc4VFpKdc7KpeSTOb43yQQ 8De9Xa9ifVVhH/CuNAQf8Tg09oLARv0uJPkxPPHzzA9i3lgQayjcU4+RMEUk1xH4rtVrr1aipOf e2IgtwAVFuW48yy8OAiIxIE9FprtVjy0Ty8jtVRsRWtQaUzHN7pTs/g== X-Gm-Gg: AYBFou2NR/cIdVgoMjXMX2q6L06ixqrLsZBA9Iie0cQ0kdIQUlXfnGZpGzRJH5gvaRU 6YWOaeiKQNVuBxhkaijZnykObZJvXIEHULqFVlEPsGACHxNYQaVqcVnzJ7VhZ8lJCHgbDOI/U0X feR6qeUWLYzoZL5u15VKvpe6nKUmjrYPF8zLdkgBaqHCX4XEjcuUYwsI0ujIhl0wio2p7Iq9ThH vNXotJ6EfZXEY2JMbE6FgXAqvOVVtWIL+geB0dTAedmxsYQpNsr5dfx8XFAgH8pUmGNR7/46Qkj nVMenh+6kA5MKt86I0eeI4UXGt2ltXWuHs+oeKj0dMzKXLLzRWxyYezqAvWqcY6WV/sM66KHMun CzT+U00dg1WOO8rZoMw== X-Received: by 2002:a05:6000:2688:b0:48c:6b5a:e783 with SMTP id ffacd0b85a97d-48dbace7258mr31483657f8f.41.1791998105805; Wed, 14 Oct 2026 10:15:05 -0700 (PDT) X-Received: by 2002:a05:6000:2688:b0:48c:6b5a:e783 with SMTP id ffacd0b85a97d-48dbace7258mr31483598f8f.41.1791998105307; Wed, 14 Oct 2026 10:15:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1791998105; cv=none; d=google.com; s=arc-20260327; b=CHHeZrhoOSMfoeQ+8+PNbhV/dJFc15kYHq9WP0Jpk56/r40TqIgqymibDOajON3BS2 bLJkAhiFASsEzRE4WD5iZEm54SzE7MPBDyYrQ3cM7sirhqihjyibao8waogKwIxC3T1G 8v/Hm+4/onIJPCJfIJ8bSxIJQrwzZ8Z+NW3JJvMNMxNLXkWzw4TC6AmydvwFemzEq+ff AHsFbmigizLhRkZcXdGr6Qs5dpAq+vzXA0sQwNz2rYfuL/tjwCJ77tDE6i3mp7Waz/eF aVRbpuFCZvYwVZCgdR1+29AvhE7YLRcQAnBUnmjoC4E4XqdsDAbwyS0jJtkIHdQjHH0Q U8mQ== 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=7XDV1ocja0rwt5rFmLUTOni+dU39UzJxEe8rccnlZl4=; fh=xUcS46XhSaUOWFT7CPWNuABJ4EJ7/+S5u4N+e+rlWN4=; b=einjUjtYsuV8Q/J9Qc5bFej0jDqoh/irxfJJqhCFzjxNk209eknttV3Yr8R44H/wyv cG2+2/XsKoK7Y25ezzQKuRCNwbkbwOWHbJXTYVw+f5sOQzXy/ewEqlViG4WBhXAOMeV5 ml4bUYGwT7x01dLAxHBtD1ZKE09D8nf89FypmhL/h0YLMNgQvSdMKpxfhvGlVVCFnmFh zx0nw0g+wBlymDL4X/PoNdfwlwAsM1aS0cBrP62/6HXSOaA2ogaAWV9tSBmrvN0fZiCR nf/zbRg0r1WNqjga5GAS033VLtpbwRr7+6N/gavcTeqZ8Vv6CMSGZiZcPBN/xPXnftWL 3g2w==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=eOYqI7F8; spf=pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=khorenko@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-48de0c196afsi12354117f8f.474.2026.10.14.10.15.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Oct 2026 10:15:05 -0700 (PDT) Received-SPF: pass (google.com: domain of khorenko@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=eOYqI7F8; spf=pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=khorenko@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=7XDV1ocja0rwt5rFmLUTOni+dU39UzJxEe8rccnlZl4=; b=eOYqI7F8hE7MZ+yXJwZ 0koWp9xZPJnCg7vrXDJJVvUo3pPbnA8/HHRhH+lZbBaXNTl+vNUG8iGCt6yj1cdSh+PlBUhjq8erI tzArHg6Tc/QV/QJ44YiA6tu3y56moolxe7vXvoUNQV80DJpInRCGnDzTxFvtAnN4Ei/VgMIxpK4Uk iRAMJwuhPSmr/N9bO9jNHYggMc9PDjQq2EDsueZhLSCHHDGZi/691/7ZMI3ZWbKZwIAELc+aHLAm7 291HYE1lRDvwJ1OzRAzU2cy8IvMuD9LcL9gA6xGKccvQz1O+zksgQPLaEfOAKTCj1PocC4lPehS5m KN28cJTaOXJCRHg==; Received: from ch-demo-asa.virtuozzo.com ([130.117.225.8] helo=f0.sw.ru) by relay.virtuozzo.com with esmtp (Exim 4.96) (envelope-from ) id 1xH2Vn-008657-2f; Wed, 14 Oct 2026 19:15:04 +0200 From: Konstantin Khorenko Date: Wed, 14 Oct 2026 19:15:01 +0200 MIME-Version: 1.0 Message-Id: <20261014-b4-prep-khorenko-vstor-149847-5-doexec-selftests-v1-3-b23b454691db@virtuozzo.com> References: <20261014-b4-prep-khorenko-vstor-149847-5-doexec-selftests-v1-0-b23b454691db@virtuozzo.com> In-Reply-To: <20261014-b4-prep-khorenko-vstor-149847-5-doexec-selftests-v1-0-b23b454691db@virtuozzo.com> To: Pavel Tikhomirov , Andrey Drobyshev , Vasileios Almpanis X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6963; i=khorenko@virtuozzo.com; h=from:subject:message-id; bh=TClXKxfeTxesNP4bMNdehof0XQ+3DEk22fHEdjpFRtI=; b=owEBbQKS/ZANAwAKAVGWCkf5YVwqAcsmYgBqz7iW8QZuz7URFdWZa0vvONksg1ly7OhY5Zdxo azVdR8s1QqJAjMEAAEKAB0WIQRWD23IPcXT0GO9CCxRlgpH+WFcKgUCas+4lgAKCRBRlgpH+WFc KoNID/43TR/xVUsvhZCgjU0F4XKYWuo4K6ETcpHV2gDUKTfVIoInEDCkRL+PV/152nY/FOcBmJy 5Qr3uNugiDhaqZom7WnwmSmgiBZKlKxqvcvagjQ0GqhkgSZwgTC4e5yoVMOj4+YAq0ixFzOJz8L UFEcSc3RvIr8LVYOtig2/+pvjk0mTfhRmqkQi/nhGf0GkTYpdHQgGdDar4BJGMiNRoscMotwk3/ dtq2L8DXVH4SWkgga2MnqUgaFNx50rxfemrx7GUSff/PIOdPeWO0I+Rs+iE41UMlmqeVE26Q4oE FvIZ3dP0LTfky0Mct+LnQU33Bf0O6SHnyay41+/l0wGgKgQyuwPih3lOTZR7VvLquMFuvoCeYbk 3zqlxMuUaMqpwgyOlzCMAMAy8BggNeU2t94MhCBbqJG/ViWNDLB7+FVts8DEpcWoHFz3zvFsXU9 uHYA5lwzjW6Yp3sT+U/WNLTWfQA0hdNc4kxWU07AD7Y2s8wVdsdWKqqCJzpCNrhQ70Typ1iIXl/ lMkmiZLfbFQEzth+4oH0zC+B3CwgoMAZi9EZv6vzA+GE9vuEXvPPcEOugOpP8NxamOoZDBO8pkz yAtb6KxKky9dVMC3bBVC9BFOU1HV9dQfhXZlTS4Dd4PBQJH7F2zi3zPHKXhuEbVLoW2bcmtD/Um u07opZCYlnvfDnA== X-Developer-Key: i=khorenko@virtuozzo.com; a=openpgp; fpr=560F6DC83DC5D3D063BD082C51960A47F9615C2A X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 3/7] selftests/mm: cover large, swapped and partly marked THP ranges 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 cases for the kinds of memory a preserved range can hold: - A 1 GB range touched every 2 MB, large enough for vma_dup() to split the copy into several padata jobs with CONFIG_PADATA. - A range pushed to swap with MADV_PAGEOUT, so that the copy takes swap entries and the new image swaps the pages back in. Skipped when none of the pages reaches swap. - A THP of which only the first half is marked, which splits its PMD and makes the copy batch PTEs of a large folio. Every page of the second half must be absent in the new image. Skipped unless smaps shows the range mapped by a THP before marking. Both base page cases tolerate EINVAL from MADV_NOHUGEPAGE, which a kernel without THP returns. https://virtuozzo.atlassian.net/browse/VSTOR-150234 Feature: oracle/mm: MADV_DOEXEC madvise() flag Assisted-by: LLM Signed-off-by: Konstantin Khorenko --- tools/testing/selftests/mm/doexec.c | 132 +++++++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/mm/doexec.c b/tools/testing/selftests/mm/doexec.c index 5eaf752b8413c..ab1d461de5517 100644 --- a/tools/testing/selftests/mm/doexec.c +++ b/tools/testing/selftests/mm/doexec.c @@ -56,6 +56,9 @@ #ifndef MADV_WIPEONFORK #define MADV_WIPEONFORK 18 #endif +#ifndef MADV_PAGEOUT +#define MADV_PAGEOUT 21 +#endif /* The downstream ELF loader requires this opt-in in a PT_NOTE segment. */ asm(".pushsection .note.doexec,\"a\",%note\n" @@ -642,29 +645,35 @@ static int doexec_noexec(void) return ret; } -static bool smaps_has_flag(char *addr, const char *flag) +/* Copy the line of the smaps entry of the VMA at @addr that starts with @prefix. */ +static bool smaps_line(char *addr, const char *prefix, char *line, size_t len) { FILE *file = fopen("/proc/self/smaps", "r"); - char line[256], want[32]; bool in_vma = false, found = false; + char want[32]; if (!file) return false; snprintf(want, sizeof(want), "%lx-", (unsigned long)addr); - while (fgets(line, sizeof(line), file)) { + while (!found && fgets(line, len, file)) { char *space = strchr(line, ' '); - if (!space) - continue; - if (memchr(line, '-', space - line) && !memchr(line, ':', space - line)) + if (space && memchr(line, '-', space - line) && !memchr(line, ':', space - line)) in_vma = !strncmp(line, want, strlen(want)); - else if (in_vma && !strncmp(line, "VmFlags:", 8)) - found = strstr(line, flag) != NULL; + else if (in_vma) + found = !strncmp(line, prefix, strlen(prefix)); } fclose(file); return found; } +static bool smaps_has_flag(char *addr, const char *flag) +{ + char line[512]; + + return smaps_line(addr, "VmFlags:", line, sizeof(line)) && strstr(line, flag); +} + static int after_pfnmap_exec(char *bar, size_t size) { size_t page = sysconf(_SC_PAGESIZE), i; @@ -1704,6 +1713,109 @@ static int stack_overlap_exec(void) } #endif +/* Large enough for vma_dup() to split the copy between several threads. */ +static int sparse_exec(void) +{ + const size_t size = 1ul << 30, stride = 2ul << 20; + char *ram = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + size_t i; + + if (ram == MAP_FAILED) + return KSFT_SKIP; + /* EINVAL: no THP support, the range is mapped with base pages anyway. */ + if (madvise(ram, size, MADV_NOHUGEPAGE) && errno != EINVAL) + return KSFT_FAIL; + for (i = 0; i < size; i += stride) + ram[i] = 0x31; + if (madvise(ram, size, MADV_DOEXEC)) + return unsupported(); + check_exec(ram, size, stride, false); + return KSFT_FAIL; +} + +static bool page_swapped(char *addr) +{ + size_t page = sysconf(_SC_PAGESIZE); + int fd = open("/proc/self/pagemap", O_RDONLY); + uint64_t entry = 0; + + if (fd < 0) + return false; + if (pread(fd, &entry, sizeof(entry), (uintptr_t)addr / page * sizeof(entry)) != + sizeof(entry)) + entry = 0; + close(fd); + return entry & (1ull << 62); +} + +/* Swap entries are copied, and the new image swaps the pages back in. */ +static int swapped_exec(void) +{ + size_t page = sysconf(_SC_PAGESIZE), size = 64 * page, i; + char *ram = mmap(NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (ram == MAP_FAILED || + (madvise(ram, size, MADV_NOHUGEPAGE) && errno != EINVAL)) + return KSFT_FAIL; + memset(ram, 0x31, size); + if (madvise(ram, size, MADV_PAGEOUT)) + return KSFT_SKIP; + for (i = 0; i < size && !page_swapped(ram + i); i += page) + ; + if (i == size) + return KSFT_SKIP; + if (madvise(ram, size, MADV_DOEXEC)) + return unsupported(); + check_exec(ram, size, page, false); + return KSFT_FAIL; +} + +static unsigned long smaps_kb(char *addr, const char *field) +{ + char line[256]; + + if (!smaps_line(addr, field, line, sizeof(line))) + return 0; + return strtoul(line + strlen(field), NULL, 10); +} + +/* Marking half of a THP splits its PMD; the PTE-mapped half carries over. */ +static int thp_half_exec(void) +{ + size_t size = huge_page_size(); + char *area, *ram; + + if (!size) + return KSFT_SKIP; + area = mmap(NULL, 2 * size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (area == MAP_FAILED) + return KSFT_FAIL; + ram = (char *)(((uintptr_t)area + size - 1) & ~(size - 1)); + if (madvise(ram, size, MADV_HUGEPAGE)) + return KSFT_SKIP; + memset(ram, 0x31, size); + madvise(ram, size, MADV_COLLAPSE); + if (smaps_kb(ram, "AnonHugePages:") < size >> 10) + return KSFT_SKIP; + if (madvise(ram, size / 2, MADV_DOEXEC)) + return unsupported(); + exec_mode("/proc/self/exe", "--thp-half", ram, size); + return KSFT_FAIL; +} + +static int after_thp_half(char *ram, size_t size) +{ + size_t page = sysconf(_SC_PAGESIZE), off; + + for (off = size / 2; off < size; off += page) + if (range_mapped(ram + off, page)) + return fail("unmarked half preserved"); + return check_contents(ram, size / 2, 0x31); +} + struct after_mode { const char *mode; int (*fn)(char *ram, size_t size); @@ -1719,6 +1831,7 @@ static const struct after_mode after_modes[] = { { "--wipeonfork", after_wipeonfork }, { "--no-uffd", after_no_uffd }, { "--mempolicy", after_mempolicy }, + { "--thp-half", after_thp_half }, }; struct more_case { @@ -1742,6 +1855,9 @@ static const struct more_case more_cases[] = { { "opt-in note not in the last PT_NOTE: preserved", note_not_last_exec }, { "malformed opt-in note not in the last PT_NOTE: skipped", bad_note_not_last_exec }, { "preserved range under the new stack: exec kills the task", stack_overlap_exec }, + { "1 GB sparse range: preserved", sparse_exec }, + { "swapped out pages: preserved", swapped_exec }, + { "half of a THP: preserved", thp_half_exec }, }; int main(int argc, char **argv) -- 2.43.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel