From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id A8477C83F1B for ; Mon, 14 Jul 2025 12:26:24 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id F08FF6B007B; Mon, 14 Jul 2025 08:26:23 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id EB9E06B0089; Mon, 14 Jul 2025 08:26:23 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DA85A6B008A; Mon, 14 Jul 2025 08:26:23 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id C2D046B007B for ; Mon, 14 Jul 2025 08:26:23 -0400 (EDT) Received: from smtpin23.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 742821A0150 for ; Mon, 14 Jul 2025 12:26:23 +0000 (UTC) X-FDA: 83662793046.23.BFFB298 Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) by imf19.hostedemail.com (Postfix) with ESMTP id A972E1A0004 for ; Mon, 14 Jul 2025 12:26:21 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=Vozc2B7Z; spf=pass (imf19.hostedemail.com: domain of lianux.mm@gmail.com designates 209.85.210.175 as permitted sender) smtp.mailfrom=lianux.mm@gmail.com; dmarc=pass (policy=none) header.from=gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1752495981; a=rsa-sha256; cv=none; b=ZAXqSTz4OL1jVuOEwZJnuyg/OOEFcA7Ee+EGXPhdgEkAsXGhMSDyCm/SuDGIqnciQGg2aA LhxclFQgYDDHyah9Nm3MKpvwhXi3fVrZXIOjL4nVMaa3u1/yhbHVae1JpsR4KrzL9HddlX 7h9YvwfVSkJdv4aKLuTEDfCfAt4v3SM= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=Vozc2B7Z; spf=pass (imf19.hostedemail.com: domain of lianux.mm@gmail.com designates 209.85.210.175 as permitted sender) smtp.mailfrom=lianux.mm@gmail.com; dmarc=pass (policy=none) header.from=gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1752495981; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:references:dkim-signature; bh=50J9z665k0zC/xuWOx+EPjjMP/L04EkIhGbCyQjAIRQ=; b=jmRaTGj5Tv7z2Sk10EZvbzDj8oiDBDfdFcohX8G8RtPhkt2JyQ9zDJKgAIQRWit2tmgXCx 0an3nEs81Hgv6R3+RqQq2S794xqiznC6MOrmBStY7K1vtY7GqyTJPBwCVuxJW7x2QAxLbb zdrB9DJVVemWEngjYIFZ6Ao/asHhTlU= Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-75001b1bd76so1173867b3a.2 for ; Mon, 14 Jul 2025 05:26:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752495980; x=1753100780; darn=kvack.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=50J9z665k0zC/xuWOx+EPjjMP/L04EkIhGbCyQjAIRQ=; b=Vozc2B7ZtrFi8C6+KjqCupDRQ244tIBJzVpi4xusg0urHXk9KhD9alXC2zbdD2zMl1 aijSiquC0kREMRraV8G0BFFjlsiOM9bxloW+UIo7FqzbYlImLxMHzOz/RtI8LEoSXuoC zZ9P3mgYCr1SNfjbsp4Pv3O5n8DmseqpuFYGQKmPVEtupLkoJAvYfr4JxaLmj4zANG71 vy+9N554Sn/cs6wC5N8wGMfKG+wcss24nNdYKBlmo6UwpmJl3C7+289nH2w7gAqkKuE5 dzD9ClJ09JlG5rL4O/tOQpNfuwmtSvQwgCTCJr872Ephhl9g2eEis4nbe405YSA6j/2j xXNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752495980; x=1753100780; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=50J9z665k0zC/xuWOx+EPjjMP/L04EkIhGbCyQjAIRQ=; b=s2k9LMazBKzxbwJA3oDgk60VsAYi+ZUhCBKgEBASY4OCTlD4RjsCRdfIbadA67e+mL 8E1P01N/5nQkYtl6ZXlYpqw5EpzulYpVQKuqUpd4Kg7l3c0gKf5Cef+NaUejJ5Ze2UeG 0CcgCgMH16ExkeaAeAPye7AHVg5A6S2+yIOZ0E4gflT2iUq5b2/JgvIbTFNuisBsiy9R vuj+/u8hNiC/IQa4sUbb+tJzrA6n6LBWcd1UjzzxOJcFmHuwD/S+481DljnE184wtthp 1fM0k+PbNs7kh+16Uaszai5ZKVPKpaaDkEPme1dEuXJoDrrRW3HIb9EsK4vispaKMdcX gLgg== X-Forwarded-Encrypted: i=1; AJvYcCVeFlSlLuFur4uAv/kDCYlJSNtTCQlMQGg02f0Joz7pYDkxqOCxKPkT29uG/zwGK9fXFeKVUallIw==@kvack.org X-Gm-Message-State: AOJu0YwSV7vro8Iaki6+nHc0H/OYAGGS4Q1oPb7dtFfEzGdxN4Ry7UKh OHeFTENAAsvVkMzaJj+ExM2f+J9z2BR3WycjBp+lWAJefaE5IzRhYKch X-Gm-Gg: ASbGncslYLwdOXIN16kGECa5hgeouikC1OvuOSUkQIpqfhGAeu1T07sJoFdIoRp0xD7 duxsc/IzPqYGfxxmpMHXbf/XSmnnfdZ6h+vmD6FRAd7DpXGDsdw79C1gwyxN8DnfLFR/iQygsKi 5G7iLB6rAksZpjTAbKPiuaMaQxYFQBqcuLYPhypKXg1lKvHaANd8cuFK3JZfYuuH34H7bEyF892 P6Ced4/ejuezBuegB8LieJ+Ud6NayJODy/3MqLmsh2ZArwNbBfF6Jh9Fd3TvoSCk1AXl+HmBLzn ABs1Gk1+BHi26ctejif20KOT9tUvZe96io4NbAi9pZR7HtzuxJirNSMiz9K1U3FNMAom5lJY5g5 RKrZ3IRTw0mHqoUb5tvB1XOLbHFubet9kSwPFFHvizx8KlPSQHYh97eE= X-Google-Smtp-Source: AGHT+IFBcMfiX++AMr9iCIFPBcyM8A1+/mtArFfDZUr0zyB8GGeCCLBSdqzvVryUE7rBd5WKGlatnA== X-Received: by 2002:a05:6a00:1413:b0:74c:5a8e:dd37 with SMTP id d2e1a72fcca58-74ee2b56632mr17831323b3a.16.1752495980174; Mon, 14 Jul 2025 05:26:20 -0700 (PDT) Received: from DESKTOP-GIED850.localdomain ([114.247.113.178]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-74eb9f4c989sm10731701b3a.130.2025.07.14.05.26.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Jul 2025 05:26:19 -0700 (PDT) From: wang lian To: Andrew Morton , Mark Brown , David Hildenbrand , SeongJae Park , Lorenzo Stoakes , Zi Yan , wang lian , linux-kernel@vger.kernel.org Cc: Christian Brauner , Jann Horn , Liam Howlett , Shuah Khan , Vlastimil Babka , gkwang , p1ucky0923 , ryncsn , "zijing . zhang" , linux-kselftest@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH v5] selftests/mm: add process_madvise() tests Date: Mon, 14 Jul 2025 20:25:33 +0800 Message-ID: <20250714122533.3135-1-lianux.mm@gmail.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspam-User: X-Rspamd-Server: rspam05 X-Rspamd-Queue-Id: A972E1A0004 X-Stat-Signature: sha7dq5pf95jcy45urkr56tqpi6wm3hn X-HE-Tag: 1752495981-887476 X-HE-Meta: U2FsdGVkX19bWzV7TCZ7SrBeIx3hcMN+KzzqpfG6/z2kOd3f66vaX1TKeA+p2RQ0RlN91GyYgXSekwrxNK3zWkdqRXTR9/AeJK98Jed0Xo3vT4mk2TqFOXJqAvu8OMJWikqYwEqkv/Y9Rf5ynlVSeygJMjTtjoJVwMZqz/qc+zz54g9tOUu3lrVxqMPqgAvsTn7AY6mX/cNl8MDRNj6B3VI6HDDilN6SlwNuEprjShoQAeoy1eZET4gRFVglEY+ovy5DDqRzWe/F3ng/Sm8iQzcILfX3Fx7KbNmzxY35BjYe+/U6H2aE4D7shr07T83SFOdgxltN6MmJTIpoVnIWU5H0mEaZVCCSrtvhfOrLhdKBFyrT6wCQ6OOmfxbuNj//u09ifUm01O2eA0N4RXUveTztElOB3GJnedTlmLOwEHHFX8dufpYoYIbxH1fHFm6rFiKcr8Z7la72hiABD6vidwdyrAoM0M/1w+9kRmnFWo7h6nVPz+Kqi045+c6zNkTmlYKrNuNJw3ZYp7uukPBQTJnEyJiL4f0YxbklqjunYGGDypZNqsG5ZOtT5a1MjEfovk3XfAWMeRSvsTWjMRa/rVGla43fJDRXJyI5IzwiU7UtzaatgpFKfoxMhCtCncIaLr+RkGPbcHpv/hRXt88hdHpC1vyPZTMGR6AMKZu+zj5D0BPeARDabhk+yIt6AwUB4VLiA/EjTdwXm722HDASvC0+mKY3noIza4xISrOGKQxTqTpZGlYK5xF7BgmgvYUxQkxFSPupnpvhiHSoN+7MwQ1b1xqhmKt9xUtwajoQ5oc6thpHky28ck7RsfWKPrCI1VsJDYFtESIUcSTJ8iCn8JIOKd+O3s6sJOw3K6LIvstK5hJdCTMI+XGeT0z9P6/onaiwohLLK1drK+MKsy3xtx4d6vjIvFBDFEBIiKQg5A3SPhYQ58qMSNPn5AYsWd4nfQ6JvEKntEH45dp9hDv qbC1x0Vi 3WypGcEKFKs93XIhV6BtGRzLH4Lq+PcucHJwqsWyRjhZKIcDvr1N4/GkWPH/KIyhYK9AjncwjRjp5qgpmrC1L5Ui8Eaaz9jaXra/b9pwRwpnv+TeCpc0qoaflphAn1tmWGcH+0JRqGOSYlKvcDSQPth2sqoOXMoeFiV7Cyqeja6+RSm/EJLunYkp0RBFtGIVQKZC86xyWg7+/rUbMzUhSX61iDB0m7N809lBxKNB3ds+CUkHtOlfq2BkkgZgT1NF7YA3K4nYxEsor587WinXfVy0lSFHycwube5WGxMuUDGcAm4mlQqzdOJF4mDYwYsTteq6RmGJ+54ACOYOi1bNUXTanhnw9hhXC3Ed/SDaDvFwh3HsCWqV1eHwo9j58KpEsmQ4uMHUqJ88Zyxsx+TW5KRhJ23WzlHC3DCMGTr+lXFOrXPycbgPjfi+GYr2K5KPx2/EDDwYBhsrliyNQ5OCY8AYXGFvesAQV2HrrP3CMUFe7AeyBI1MlV5nFTQVAsLH4AspPdFujso4ULk4eTf8kU5oAHEPTGX+yus308o9BZ9V04UQe/eQtFXJ1HGOg/+G2KAHJ3H8uGSpDs1vczJifWPBTV3EofStpNu8zYAUzAq/q/nuvzBr2mG+/bRKCGOS6HVk9/X9X4E8eoJoPMPFkIsi3aQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Add tests for process_madvise(), focusing on verifying behavior under various conditions including valid usage and error cases. Signed-off-by: wang lian Suggested-by: Lorenzo Stoakes Suggested-by: David Hildenbrand Suggested-by: Zi Yan Suggested-by: Mark Brown Acked-by: SeongJae Park --- Changelog v5: - Refactor the remote_collapse test to concentrate on its primary goal confirming the successful remote invocation of process_madvise() on a child process. - Split the validation logic for invalid pidfds out of the remote test and into two new (`exited_process_pidfd` and `bad_pidfd`). - Based mm-new branch, can ensure clean application Changelog v4: https://lore.kernel.org/lkml/20250710112249.58722-1-lianux.mm@gmail.com/ - Refine resource cleanup logic in test teardown to be more robust. - Improve remote_collapse test to correctly handle different THP (Transparent Huge Page) policies ('always', 'madvise', 'never'), including handling race conditions with khugepaged. - Resolve build errors Changelog v3: https://lore.kernel.org/lkml/20250703044326.65061-1-lianux.mm@gmail.com/ - Rebased onto the latest mm-stable branch to ensure clean application. - Refactor common signal handling logic into vm_util to reduce code duplication. - Improve test robustness and diagnostics based on community feedback. - Address minor code style and script corrections. Changelog v2: https://lore.kernel.org/lkml/20250630140957.4000-1-lianux.mm@gmail.com/ - Drop MADV_DONTNEED tests based on feedback. - Focus solely on process_madvise() syscall. - Improve error handling and structure. - Add future-proof flag test. - Style and comment cleanups. -V1: https://lore.kernel.org/lkml/20250621133003.4733-1-lianux.mm@gmail.com/ tools/testing/selftests/mm/.gitignore | 1 + tools/testing/selftests/mm/Makefile | 1 + tools/testing/selftests/mm/process_madv.c | 304 ++++++++++++++++++++++ tools/testing/selftests/mm/run_vmtests.sh | 5 + 4 files changed, 311 insertions(+) create mode 100644 tools/testing/selftests/mm/process_madv.c diff --git a/tools/testing/selftests/mm/.gitignore b/tools/testing/selftests/mm/.gitignore index f2dafa0b700b..e7b23a8a05fe 100644 --- a/tools/testing/selftests/mm/.gitignore +++ b/tools/testing/selftests/mm/.gitignore @@ -21,6 +21,7 @@ on-fault-limit transhuge-stress pagemap_ioctl pfnmap +process_madv *.tmp* protection_keys protection_keys_32 diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile index ae6f994d3add..d13b3cef2a2b 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -85,6 +85,7 @@ TEST_GEN_FILES += mseal_test TEST_GEN_FILES += on-fault-limit TEST_GEN_FILES += pagemap_ioctl TEST_GEN_FILES += pfnmap +TEST_GEN_FILES += process_madv TEST_GEN_FILES += thuge-gen TEST_GEN_FILES += transhuge-stress TEST_GEN_FILES += uffd-stress diff --git a/tools/testing/selftests/mm/process_madv.c b/tools/testing/selftests/mm/process_madv.c new file mode 100644 index 000000000000..249e2ed8dfe9 --- /dev/null +++ b/tools/testing/selftests/mm/process_madv.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#define _GNU_SOURCE +#include "../kselftest_harness.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vm_util.h" + +#include "../pidfd/pidfd.h" + +FIXTURE(process_madvise) +{ + unsigned long page_size; + pid_t child_pid; + int pidfd; +}; + +FIXTURE_SETUP(process_madvise) +{ + self->page_size = (unsigned long)sysconf(_SC_PAGESIZE); + self->pidfd = PIDFD_SELF; + self->child_pid = -1; +}; + +FIXTURE_TEARDOWN_PARENT(process_madvise) +{ + if (self->child_pid > 0) { + kill(self->child_pid, SIGKILL); + waitpid(self->child_pid, NULL, 0); + } +} + +static ssize_t sys_process_madvise(int pidfd, const struct iovec *iovec, + size_t vlen, int advice, unsigned int flags) +{ + return syscall(__NR_process_madvise, pidfd, iovec, vlen, advice, flags); +} + +/* + * This test uses PIDFD_SELF to target the current process. The main + * goal is to verify the basic behavior of process_madvise() with + * a vector of non-contiguous memory ranges, not its cross-process + * capabilities. + */ +TEST_F(process_madvise, basic) +{ + const unsigned long pagesize = self->page_size; + const int madvise_pages = 4; + struct iovec vec[madvise_pages]; + int pidfd = self->pidfd; + ssize_t ret; + char *map; + + /* + * Create a single large mapping. We will pick pages from this + * mapping to advise on. This ensures we test non-contiguous iovecs. + */ + map = mmap(NULL, pagesize * 10, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (map == MAP_FAILED) + SKIP(return, "mmap failed, not enough memory.\n"); + + /* Fill the entire region with a known pattern. */ + memset(map, 'A', pagesize * 10); + + /* + * Setup the iovec to point to 4 non-contiguous pages + * within the mapping. + */ + vec[0].iov_base = &map[0 * pagesize]; + vec[0].iov_len = pagesize; + vec[1].iov_base = &map[3 * pagesize]; + vec[1].iov_len = pagesize; + vec[2].iov_base = &map[5 * pagesize]; + vec[2].iov_len = pagesize; + vec[3].iov_base = &map[8 * pagesize]; + vec[3].iov_len = pagesize; + + ret = sys_process_madvise(pidfd, vec, madvise_pages, MADV_DONTNEED, 0); + if (ret == -1 && errno == EPERM) + SKIP(return, + "process_madvise() unsupported or permission denied, try running as root.\n"); + else if (errno == EINVAL) + SKIP(return, + "process_madvise() unsupported or parameter invalid, please check arguments.\n"); + + /* The call should succeed and report the total bytes processed. */ + ASSERT_EQ(ret, madvise_pages * pagesize); + + /* Check that advised pages are now zero. */ + for (int i = 0; i < madvise_pages; i++) { + char *advised_page = (char *)vec[i].iov_base; + + /* Content must be 0, not 'A'. */ + ASSERT_EQ(*advised_page, '\0'); + } + + /* Check that an un-advised page in between is still 'A'. */ + char *unadvised_page = &map[1 * pagesize]; + + for (int i = 0; i < pagesize; i++) + ASSERT_EQ(unadvised_page[i], 'A'); + + /* Cleanup. */ + ASSERT_EQ(munmap(map, pagesize * 10), 0); +} + +/* + * This test deterministically validates process_madvise() with MADV_COLLAPSE + * on a remote process, other advices are difficult to verify reliably. + * + * The test verifies that a memory region in a child process, + * focus on process_madv remote result, only check addresses and lengths. + * The correctness of the MADV_COLLAPSE can be found in the relevant test examples in khugepaged. + */ +TEST_F(process_madvise, remote_collapse) +{ + const unsigned long pagesize = self->page_size; + int pidfd; + long huge_page_size; + int pipe_info[2]; + ssize_t ret; + struct iovec vec; + + struct child_info { + pid_t pid; + void *map_addr; + } info; + + huge_page_size = default_huge_page_size(); + if (huge_page_size <= 0) + SKIP(return, "Could not determine a valid huge page size.\n"); + + ASSERT_EQ(pipe(pipe_info), 0); + + self->child_pid = fork(); + ASSERT_NE(self->child_pid, -1); + + if (self->child_pid == 0) { + char *map; + size_t map_size = 2 * huge_page_size; + + close(pipe_info[0]); + + map = mmap(NULL, map_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_NE(map, MAP_FAILED); + + /* Fault in as small pages */ + for (size_t i = 0; i < map_size; i += pagesize) + map[i] = 'A'; + + /* Send info and pause */ + info.pid = getpid(); + info.map_addr = map; + ret = write(pipe_info[1], &info, sizeof(info)); + ASSERT_EQ(ret, sizeof(info)); + close(pipe_info[1]); + + pause(); + exit(0); + } + + close(pipe_info[1]); + + /* Receive child info */ + ret = read(pipe_info[0], &info, sizeof(info)); + if (ret <= 0) { + waitpid(self->child_pid, NULL, 0); + SKIP(return, "Failed to read child info from pipe.\n"); + } + ASSERT_EQ(ret, sizeof(info)); + close(pipe_info[0]); + self->child_pid = info.pid; + + pidfd = syscall(__NR_pidfd_open, self->child_pid, 0); + ASSERT_GE(pidfd, 0); + + vec.iov_base = info.map_addr; + vec.iov_len = huge_page_size; + + ret = sys_process_madvise(pidfd, &vec, 1, MADV_COLLAPSE, 0); + if (ret == -1) { + if (errno == EINVAL) + SKIP(return, "PROCESS_MADV_ADVISE is not supported.\n"); + else if (errno == EPERM) + SKIP(return, + "No process_madvise() permissions, try running as root.\n"); + goto cleanup; + } + + ASSERT_EQ(ret, huge_page_size); + +cleanup: + /* Cleanup */ + kill(self->child_pid, SIGKILL); + waitpid(self->child_pid, NULL, 0); + if (pidfd >= 0) + close(pidfd); +} + +/* + * Test process_madvise() with a pidfd for a process that has already + * exited to ensure correct error handling. + */ +TEST_F(process_madvise, exited_process_pidfd) +{ + struct iovec vec; + ssize_t ret; + int pidfd; + + vec.iov_base = (void *)0x1234; + vec.iov_len = 4096; + + /* + * Using a pidfd for a process that has already exited should fail + * with ESRCH. + */ + self->child_pid = fork(); + ASSERT_NE(self->child_pid, -1); + + if (self->child_pid == 0) + exit(0); + + pidfd = syscall(__NR_pidfd_open, self->child_pid, 0); + ASSERT_GE(pidfd, 0); + + /* Wait for the child to ensure it has terminated. */ + waitpid(self->child_pid, NULL, 0); + + ret = sys_process_madvise(pidfd, &vec, 1, MADV_DONTNEED, 0); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, ESRCH); + close(pidfd); +} + +/* + * Test process_madvise() with bad pidfds to ensure correct error + * handling. + */ +TEST_F(process_madvise, bad_pidfd) +{ + struct iovec vec; + ssize_t ret; + + vec.iov_base = (void *)0x1234; + vec.iov_len = 4096; + + /* Using an invalid fd number (-1) should fail with EBADF. */ + ret = sys_process_madvise(-1, &vec, 1, MADV_DONTNEED, 0); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EBADF); + + /* + * Using a valid fd that is not a pidfd (e.g. stdin) should fail + * with EBADF. + */ + ret = sys_process_madvise(STDIN_FILENO, &vec, 1, MADV_DONTNEED, 0); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EBADF); +} + +/* + * Test process_madvise() with an invalid flag value. Currently, only a flag + * value of 0 is supported. This test is reserved for the future, e.g., if + * synchronous flags are added. + */ +TEST_F(process_madvise, flag) +{ + const unsigned long pagesize = self->page_size; + unsigned int invalid_flag; + int pidfd = self->pidfd; + struct iovec vec; + char *map; + ssize_t ret; + + map = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, + 0); + if (map == MAP_FAILED) + SKIP(return, "mmap failed, not enough memory.\n"); + + vec.iov_base = map; + vec.iov_len = pagesize; + + invalid_flag = 0x80000000; + + ret = sys_process_madvise(pidfd, &vec, 1, MADV_DONTNEED, invalid_flag); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EINVAL); + + /* Cleanup. */ + ASSERT_EQ(munmap(map, pagesize), 0); +} + +TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh index a38c984103ce..471e539d82b8 100755 --- a/tools/testing/selftests/mm/run_vmtests.sh +++ b/tools/testing/selftests/mm/run_vmtests.sh @@ -65,6 +65,8 @@ separated by spaces: test pagemap_scan IOCTL - pfnmap tests for VM_PFNMAP handling +- process_madv + test for process_madv - cow test copy-on-write semantics - thp @@ -425,6 +427,9 @@ CATEGORY="madv_guard" run_test ./guard-regions # MADV_POPULATE_READ and MADV_POPULATE_WRITE tests CATEGORY="madv_populate" run_test ./madv_populate +# PROCESS_MADV test +CATEGORY="process_madv" run_test ./process_madv + CATEGORY="vma_merge" run_test ./merge if [ -x ./memfd_secret ] -- 2.43.0