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 C341FC77B7E for ; Sun, 28 May 2023 15:03:28 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 3CA5E6B0071; Sun, 28 May 2023 11:03:28 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 3793F6B0074; Sun, 28 May 2023 11:03:28 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 218626B0075; Sun, 28 May 2023 11:03:28 -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 0CDDF6B0071 for ; Sun, 28 May 2023 11:03:28 -0400 (EDT) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id D1C001C6EDA for ; Sun, 28 May 2023 15:03:27 +0000 (UTC) X-FDA: 80839982454.26.77AE50D Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) by imf25.hostedemail.com (Postfix) with ESMTP id 9ED0FA0015 for ; Sun, 28 May 2023 15:03:25 +0000 (UTC) Authentication-Results: imf25.hostedemail.com; dkim=pass header.d=gmail.com header.s=20221208 header.b=myY6bdOe; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf25.hostedemail.com: domain of lstoakes@gmail.com designates 209.85.221.46 as permitted sender) smtp.mailfrom=lstoakes@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1685286205; 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-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=QMl9Sb/fU6NQWI1gD+M9CLxXIiuUmnByGtiF+Vw3V6w=; b=IOu5O/0csb9CebC/h22IfOV3TlTC4F6OnnpH8JpooDYYEOoOB+cBOEP6WGGAmBa69r2o72 9d5fnAFWucRxilduMckiPSBbc+KV+f3b11Yxvrw7jQ232wp+OQDNYv3IqzAjXMfWVU2pXR Fa/ve6D0SYpkkebnsR+x6F7I4t5L06o= ARC-Authentication-Results: i=1; imf25.hostedemail.com; dkim=pass header.d=gmail.com header.s=20221208 header.b=myY6bdOe; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf25.hostedemail.com: domain of lstoakes@gmail.com designates 209.85.221.46 as permitted sender) smtp.mailfrom=lstoakes@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1685286205; a=rsa-sha256; cv=none; b=6ld70NLmPa6TM9HbFda3wbc3zpdjA3YkzslwtTdLAltUX77zrl7pbfMm5OCY+NrF2uuZH/ kC4316MTQb3xloozScBN83nQdNXaTFEubPl/GdLPLZWH8ESISCsIGMPnjQY0QwsWR5t7vY vo0TAk6WHRYZq7CDF0yi7xkAad45Flo= Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-3078a3f3b5fso2349119f8f.0 for ; Sun, 28 May 2023 08:03:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685286204; x=1687878204; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=QMl9Sb/fU6NQWI1gD+M9CLxXIiuUmnByGtiF+Vw3V6w=; b=myY6bdOezLAUNiMFQppYWvJqRPkQcp0xEZCsJHRuUc8LdFags5PGainU5Fr0gPnsEC e6BdRZma48QcFk4puHJjAETHYV1HKCmM7SHC+o/ugEcvu0WQRIWJs8oHPGUzdQLpwNxp pMxasWv0++Va2iil24uYxPwgH2qLyhwOwSh53yLBPsEw8VeHbdQmeV5v+BDgbCxhrHbg AjpYEWjMIqtFPdoNUFDoXfCxPS/1zkoEguW3EM/o5sQT1CUl6IBKTqxpybWiYRuTIAUx WkLWRjg2V8XyZPjCNK12C3eZnIZhDa3T5S8liyC3sP0CnAzJt6w9J1/WGInIj/0yhxck PqDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685286204; x=1687878204; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=QMl9Sb/fU6NQWI1gD+M9CLxXIiuUmnByGtiF+Vw3V6w=; b=i/iM3O1Ixtjosl/QxkyH0Lt0UfndSHmUto+2ZoVzUZc28J6WAG61cgy1T4XOMIKL77 9fHVtumH5KaiwL4w2ySssxuaDuyE8d7tpOyQkAo8uiHMXRKgCxLH/ifR6Fqf7I+Yy9l0 DHfs9tRon/v7b2P6I0c3OuQqnFZA+tXfBFu1Qtt4JsjfqEdNRY40nWCWM/TfiiICoPVz TjfCuheF1fmd7J5awIe8TZfJlr+Ha0EqmxetPQTMJXwEFxaxzylEpI0MK38arkrQ5db9 y35HGHWbKtPLQaT7cxm0GdUCnZkUdIt4aqcvN3BVA0zaiOaYPEFJjdlfRrrPNtHRbtRH jIJw== X-Gm-Message-State: AC+VfDxXWkHEyeBJvARSAOnEAYEVYyZRBZO4Bfbz2LH4Talb1s+yo9P8 W+pCB37KsGJHXoaeNj6R99I= X-Google-Smtp-Source: ACHHUZ4nJbz57goJmsJHHinyO0TwIPchCxkKjfEu0Icg8fSXbjHgUIKqeonYxufamabTYqWpjF9qgw== X-Received: by 2002:adf:e786:0:b0:30a:ec3b:58d5 with SMTP id n6-20020adfe786000000b0030aec3b58d5mr10153wrm.69.1685286203753; Sun, 28 May 2023 08:03:23 -0700 (PDT) Received: from localhost (host81-154-179-160.range81-154.btcentralplus.com. [81.154.179.160]) by smtp.gmail.com with ESMTPSA id g12-20020a5d488c000000b003090cb7a9e6sm10931718wrq.31.2023.05.28.08.03.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 28 May 2023 08:03:22 -0700 (PDT) Date: Sun, 28 May 2023 16:03:22 +0100 From: Lorenzo Stoakes To: David Hildenbrand Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, Andrew Morton , Shuah Khan , Jens Axboe , Peter Xu , Jason Gunthorpe , John Hubbard , Jan Kara Subject: Re: [PATCH v1 2/3] selftests/mm: gup_longterm: new functional test for FOLL_LONGTERM Message-ID: References: <20230519102723.185721-1-david@redhat.com> <20230519102723.185721-3-david@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20230519102723.185721-3-david@redhat.com> X-Rspamd-Queue-Id: 9ED0FA0015 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: 5zijcs91ik3kzmokyidaz1k55b1yj54a X-HE-Tag: 1685286205-592564 X-HE-Meta: U2FsdGVkX18YWgCJft9AGjaWJnwrNbc/4ft5HHhblmenSz251LEREpWHOkfFrcCEIvSg/Swefayp7/InD8lDEM6j0ZargMAaOgFCstdZLZDWoDTgfnXIM6uO3NvsaXHo/piFwht7lkStzzL46UGBq+ycQxfbXgvXoJFpcGohiIjQyrUxkFUtWXkH/rg+78WWQ5wJHtG6nI6e2GQZNFuh6UyaXJE5g6znyvVIZAXahm87Wvmo110sEfGBrG66z0askxC5Wx75Ms6IFOc4x/UZKs8ScWSAlvHgMbxHZFEWG56fbugLGVPuDNQ48QYl2eN4iEvX/IgbQzweK60JA3O97c3u6HfJ82lU03vAnp2fXI2+id66nRYCVpkdsTa06BM49+IDwXdI6Zy3B6pNa4tuZjiKkC6QYd26L/52kLVVaD5qkP1TsQ82JBKL2/XxukSC1URe4VPDOkR4RTt0fRZoW6ooso4lgBljrrHSjA18S7N1lnHdAVo3nAxmD8pXuOURtquAJliTbNn31moCTpMsOPoGT5ESqlu06UWuuOGVx6PX7BNC7Jl6WxdrHeMZjmt1mQ3fXXAykAyboiFRyfgtCeMfFeEa1dxpeatmJBPxYfhZNK5Slg7bQmarPyxbkKAQVbdwTtGnERuZOUXWPyA2hfCwvPRA02yziSpZEz8+Nf/BYG7bWqYbdbI+FDa1OaYJjxu/zc0CJmxgwl6/qpTiCjKGtfQBqzCTKlHzkzF99W+5irfxFbSCXuC8Fwm3QTOHv9gr661dakkdVczeQ1sUT/MJ0m1flJKbTzIFQ/gwEGCGM8NkMeB5TYYyCs/huKXPXFyEGrlPsFgGH9DrCxj/PfZO5jmhkOybvgZ5jDxLGBWYwgeVEBalo+KXB869rQ84XXMUwCMMiNvTDQU7yLcKYyHhPdkjZDjf4EHdDu2jL7HCdLAWGuTiiV1pC2mLdTzaPo/SBil29HUUM3BUpLd r3ruwa4Q QriIvvvzP1hVse9/1kEf2ENbNPxSe/0H/UkeRBKoDHeMry8TTIuctSr5hKOTyGP27DICcwQjFS8JTTbjfqeBOXet/7qc0EwV1WVjSJWV8XMfaaAEFgkoFBgzcGpMUUEGOxOHRHfwsgcGUOL1ypx53uNNYK2jGUGtm/McG0HULtcTuRWDoJn63DUaCX9MqdxRAKx8xKN+sonMQZELTGkX4gtfcLIFOcRADyaD5dBPDct7bERPMLcdqEgYWVlx/pRLdunCGIXTjET6bmzb1oxDR1jOEF5PK6aWV6fvG0PJfLdHEzJoLPtX1AuOu6YV3jPU9SeX82ugfb6truK2l4l2BdwFcTY6JNMxEFhJr9QTEsduWS8h8C3OQmbzdnhYCy14B43iG3xw01mVnAHq13u5pwsnqSbOfKIfzge+nb8XwWPTWwEjqR5tgS94oxsBijgWizdgdtbH3UsSbG8xkNt62Dzb8LHcEVxEM9HcO34O/Nn12aUQ= 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: On Fri, May 19, 2023 at 12:27:22PM +0200, David Hildenbrand wrote: > Let's add a new test for checking whether GUP long-term page pinning > works as expected (R/O vs. R/W, MAP_PRIVATE vs. MAP_SHARED, GUP vs. > GUP-fast). Note that COW handling with long-term R/O pinning in private > mappings, and pinning of anonymous memory in general, is tested by the > COW selftest. This test, therefore, focuses on page pinning in > file mappings. > > The most interesting case is probably the "local tmpfile" case, as that > will likely end up on a "real" filesystem such as ext4 or xfs, not on a > virtual one like tmpfs or hugetlb where any long-term page pinning is > always expected to succeed. > > For now, only add tests that use the "/sys/kernel/debug/gup_test" > interface. We'll add tests based on liburing separately next. > > Signed-off-by: David Hildenbrand > --- > tools/testing/selftests/mm/Makefile | 3 + > tools/testing/selftests/mm/gup_longterm.c | 386 ++++++++++++++++++++++ > tools/testing/selftests/mm/run_vmtests.sh | 4 +- > 3 files changed, 392 insertions(+), 1 deletion(-) > create mode 100644 tools/testing/selftests/mm/gup_longterm.c > > diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile > index 23af4633f0f4..95acb099315e 100644 > --- a/tools/testing/selftests/mm/Makefile > +++ b/tools/testing/selftests/mm/Makefile > @@ -34,6 +34,7 @@ LDLIBS = -lrt -lpthread > > TEST_GEN_PROGS = cow > TEST_GEN_PROGS += compaction_test > +TEST_GEN_PROGS += gup_longterm > TEST_GEN_PROGS += gup_test > TEST_GEN_PROGS += hmm-tests > TEST_GEN_PROGS += hugetlb-madvise > @@ -164,6 +165,8 @@ endif > # IOURING_EXTRA_LIBS may get set in local_config.mk, or it may be left empty. > $(OUTPUT)/cow: LDLIBS += $(IOURING_EXTRA_LIBS) > > +$(OUTPUT)/gup_longterm: LDLIBS += $(IOURING_EXTRA_LIBS) > + > $(OUTPUT)/mlock-random-test $(OUTPUT)/memfd_secret: LDLIBS += -lcap > > $(OUTPUT)/ksm_tests: LDLIBS += -lnuma > diff --git a/tools/testing/selftests/mm/gup_longterm.c b/tools/testing/selftests/mm/gup_longterm.c > new file mode 100644 > index 000000000000..44a3617fd423 > --- /dev/null > +++ b/tools/testing/selftests/mm/gup_longterm.c > @@ -0,0 +1,386 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * GUP long-term page pinning tests. > + * > + * Copyright 2023, Red Hat, Inc. > + * > + * Author(s): David Hildenbrand > + */ > +#define _GNU_SOURCE > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "local_config.h" > + > +#include "../../../../mm/gup_test.h" > +#include "../kselftest.h" > +#include "vm_util.h" > + > +static size_t pagesize; > +static int nr_hugetlbsizes; > +static size_t hugetlbsizes[10]; > +static int gup_fd; > + > +static __fsword_t get_fs_type(int fd) > +{ > + struct statfs fs; > + int ret; > + > + do { > + ret = fstatfs(fd, &fs); > + } while (ret && errno == EINTR); > + > + return ret ? 0 : fs.f_type; > +} > + > +static bool fs_is_unknown(__fsword_t fs_type) > +{ > + /* > + * We only support some filesystems in our tests when dealing with > + * R/W long-term pinning. For these filesystems, we can be fairly sure > + * whether they support it or not. > + */ > + switch (fs_type) { > + case TMPFS_MAGIC: > + case HUGETLBFS_MAGIC: > + case BTRFS_SUPER_MAGIC: > + case EXT4_SUPER_MAGIC: > + case XFS_SUPER_MAGIC: > + return false; > + default: > + return true; > + } > +} > + > +static bool fs_supports_writable_longterm_pinning(__fsword_t fs_type) > +{ > + assert(!fs_is_unknown(fs_type)); > + switch (fs_type) { > + case TMPFS_MAGIC: > + case HUGETLBFS_MAGIC: > + return true; > + default: > + return false; > + } > +} > + > +enum test_type { > + TEST_TYPE_RO, > + TEST_TYPE_RO_FAST, > + TEST_TYPE_RW, > + TEST_TYPE_RW_FAST, > +}; > + > +static void do_test(int fd, size_t size, enum test_type type, bool shared) > +{ > + __fsword_t fs_type = get_fs_type(fd); > + bool should_work; > + char *mem; > + int ret; > + > + if (ftruncate(fd, size)) { > + ksft_test_result_fail("ftruncate() failed\n"); > + return; > + } > + > + if (fallocate(fd, 0, 0, size)) { > + if (size == pagesize) > + ksft_test_result_fail("fallocate() failed\n"); > + else > + ksft_test_result_skip("need more free huge pages\n"); > + return; > + } > + > + mem = mmap(NULL, size, PROT_READ | PROT_WRITE, > + shared ? MAP_SHARED : MAP_PRIVATE, fd, 0); > + if (mem == MAP_FAILED) { > + if (size == pagesize || shared) > + ksft_test_result_fail("mmap() failed\n"); > + else > + ksft_test_result_skip("need more free huge pages\n"); > + return; > + } > + > + /* > + * Fault in the page writable such that GUP-fast can eventually pin > + * it immediately. > + */ > + memset(mem, 0, size); Nitty but why not just MAP_POPULATE? > + > + switch (type) { > + case TEST_TYPE_RO: > + case TEST_TYPE_RO_FAST: > + case TEST_TYPE_RW: > + case TEST_TYPE_RW_FAST: { > + struct pin_longterm_test args; > + const bool fast = type == TEST_TYPE_RO_FAST || > + type == TEST_TYPE_RW_FAST; + const bool rw = type == TEST_TYPE_RW || > + type == TEST_TYPE_RW_FAST; > + > + if (gup_fd < 0) { > + ksft_test_result_skip("gup_test not available\n"); > + break; > + } > + > + if (rw && shared && fs_is_unknown(fs_type)) { > + ksft_test_result_skip("Unknown filesystem\n"); > + return; > + } > + /* > + * R/O pinning or pinning in a private mapping is always > + * expected to work. Otherwise, we expect long-term R/W pinning > + * to only succeed for special fielesystems. > + */ > + should_work = !shared || !rw || > + fs_supports_writable_longterm_pinning(fs_type); > + > + args.addr = (__u64)(uintptr_t)mem; > + args.size = size; > + args.flags = fast ? PIN_LONGTERM_TEST_FLAG_USE_FAST : 0; > + args.flags |= rw ? PIN_LONGTERM_TEST_FLAG_USE_WRITE : 0; > + ret = ioctl(gup_fd, PIN_LONGTERM_TEST_START, &args); > + if (ret && errno == EINVAL) { > + ksft_test_result_skip("PIN_LONGTERM_TEST_START failed\n"); > + break; > + } else if (ret && errno == EFAULT) { > + ksft_test_result(!should_work, "Should have failed\n"); > + break; > + } else if (ret) { > + ksft_test_result_fail("PIN_LONGTERM_TEST_START failed\n"); > + break; > + } > + > + if (ioctl(gup_fd, PIN_LONGTERM_TEST_STOP)) > + ksft_print_msg("[INFO] PIN_LONGTERM_TEST_STOP failed\n"); > + > + /* > + * TODO: if the kernel ever supports long-term R/W pinning on > + * some previously unsupported filesystems, we might want to > + * perform some additional tests for possible data corruptions. > + */ > + ksft_test_result(should_work, "Should have worked\n"); > + break; > + } > + default: > + assert(false); > + } > + > + munmap(mem, size); > +} > + > +typedef void (*test_fn)(int fd, size_t size); > + > +static void run_with_memfd(test_fn fn, const char *desc) > +{ > + int fd; > + > + ksft_print_msg("[RUN] %s ... with memfd\n", desc); > + > + fd = memfd_create("test", 0); > + if (fd < 0) { > + ksft_test_result_fail("memfd_create() failed\n"); > + return; > + } > + > + fn(fd, pagesize); > + close(fd); > +} > + > +static void run_with_tmpfile(test_fn fn, const char *desc) > +{ > + FILE *file; > + int fd; > + > + ksft_print_msg("[RUN] %s ... with tmpfile\n", desc); > + > + file = tmpfile(); > + if (!file) { > + ksft_test_result_fail("tmpfile() failed\n"); > + return; > + } > + > + fd = fileno(file); > + if (fd < 0) { > + ksft_test_result_fail("fileno() failed\n"); > + return; > + } > + > + fn(fd, pagesize); > + fclose(file); > +} > + > +static void run_with_local_tmpfile(test_fn fn, const char *desc) > +{ > + char filename[] = __FILE__"_tmpfile_XXXXXX"; > + int fd; > + > + ksft_print_msg("[RUN] %s ... with local tmpfile\n", desc); > + > + fd = mkstemp(filename); > + if (fd < 0) { > + ksft_test_result_fail("mkstemp() failed\n"); > + return; > + } > + > + if (unlink(filename)) { > + ksft_test_result_fail("unlink() failed\n"); > + goto close; > + } > + > + fn(fd, pagesize); > +close: > + close(fd); > +} > + > +static void run_with_memfd_hugetlb(test_fn fn, const char *desc, > + size_t hugetlbsize) > +{ > + int flags = MFD_HUGETLB; > + int fd; > + > + ksft_print_msg("[RUN] %s ... with memfd hugetlb (%zu kB)\n", desc, > + hugetlbsize / 1024); > + > + flags |= __builtin_ctzll(hugetlbsize) << MFD_HUGE_SHIFT; Hm this feels a little cute :) > + > + fd = memfd_create("test", flags); > + if (fd < 0) { > + ksft_test_result_skip("memfd_create() failed\n"); > + return; > + } > + > + fn(fd, hugetlbsize); > + close(fd); > +} > + > +struct test_case { > + const char *desc; > + test_fn fn; > +}; > + > +static void test_shared_rw_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RW, true); > +} > + > +static void test_shared_rw_fast_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RW_FAST, true); > +} > + > +static void test_shared_ro_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RO, true); > +} > + > +static void test_shared_ro_fast_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RO_FAST, true); > +} > + > +static void test_private_rw_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RW, false); > +} > + > +static void test_private_rw_fast_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RW_FAST, false); > +} > + > +static void test_private_ro_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RO, false); > +} > + > +static void test_private_ro_fast_pin(int fd, size_t size) > +{ > + do_test(fd, size, TEST_TYPE_RO_FAST, false); > +} > + > +static const struct test_case test_cases[] = { > + { > + "R/W longterm GUP pin in MAP_SHARED file mapping", > + test_shared_rw_pin, > + }, > + { > + "R/W longterm GUP-fast pin in MAP_SHARED file mapping", > + test_shared_rw_fast_pin, > + }, > + { > + "R/O longterm GUP pin in MAP_SHARED file mapping", > + test_shared_ro_pin, > + }, > + { > + "R/O longterm GUP-fast pin in MAP_SHARED file mapping", > + test_shared_ro_fast_pin, > + }, > + { > + "R/W longterm GUP pin in MAP_PRIVATE file mapping", > + test_private_rw_pin, > + }, > + { > + "R/W longterm GUP-fast pin in MAP_PRIVATE file mapping", > + test_private_rw_fast_pin, > + }, > + { > + "R/O longterm GUP pin in MAP_PRIVATE file mapping", > + test_private_ro_pin, > + }, > + { > + "R/O longterm GUP-fast pin in MAP_PRIVATE file mapping", > + test_private_ro_fast_pin, > + }, > +}; > + > +static void run_test_case(struct test_case const *test_case) > +{ > + int i; > + > + run_with_memfd(test_case->fn, test_case->desc); > + run_with_tmpfile(test_case->fn, test_case->desc); > + run_with_local_tmpfile(test_case->fn, test_case->desc); > + for (i = 0; i < nr_hugetlbsizes; i++) > + run_with_memfd_hugetlb(test_case->fn, test_case->desc, > + hugetlbsizes[i]); > +} > + > +static int tests_per_test_case(void) > +{ > + return 3 + nr_hugetlbsizes; > +} > + > +int main(int argc, char **argv) > +{ > + int i, err; > + > + pagesize = getpagesize(); > + nr_hugetlbsizes = detect_hugetlb_page_sizes(hugetlbsizes, > + ARRAY_SIZE(hugetlbsizes)); > + > + ksft_print_header(); > + ksft_set_plan(ARRAY_SIZE(test_cases) * tests_per_test_case()); > + > + gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR); > + > + for (i = 0; i < ARRAY_SIZE(test_cases); i++) > + run_test_case(&test_cases[i]); > + > + err = ksft_get_fail_cnt(); > + if (err) > + ksft_exit_fail_msg("%d out of %d tests failed\n", > + err, ksft_test_num()); > + return ksft_exit_pass(); > +} > diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh > index 4893eb60d96d..b6b1eb6a8a6b 100644 > --- a/tools/testing/selftests/mm/run_vmtests.sh > +++ b/tools/testing/selftests/mm/run_vmtests.sh > @@ -24,7 +24,7 @@ separated by spaces: > - mmap > tests for mmap(2) > - gup_test > - tests for gup using gup_test interface > + tests for gup Super nitty again, but I'm guessing this means the CONFIG_GUP_TEST interface, perhaps worth keeping? > - userfaultfd > tests for userfaultfd(2) > - compaction > @@ -196,6 +196,8 @@ CATEGORY="gup_test" run_test ./gup_test -a > # Dump pages 0, 19, and 4096, using pin_user_pages: > CATEGORY="gup_test" run_test ./gup_test -ct -F 0x1 0 19 0x1000 > > +CATEGORY="gup_test" run_test ./gup_longterm > + > CATEGORY="userfaultfd" run_test ./uffd-unit-tests > uffd_stress_bin=./uffd-stress > CATEGORY="userfaultfd" run_test ${uffd_stress_bin} anon 20 16 > -- > 2.40.1 > OK this patch is really nice + well implemented, I can only point out a couple EXTREMELY nitty comments :) Thanks very much for adding a test for this, it's super useful! Therefore, Reviewed-by: Lorenzo Stoakes