Commit 97713a3a authored by David Hildenbrand's avatar David Hildenbrand Committed by Andrew Morton
Browse files

selftests/vm: cow: R/O long-term pinning reliability tests for non-anon pages

Let's test whether R/O long-term pinning is reliable for non-anonymous
memory: when R/O long-term pinning a page, the expectation is that we
break COW early before pinning, such that actual write access via the
page tables won't break COW later and end up replacing the R/O-pinned
page in the page table.

Consequently, R/O long-term pinning in private mappings would only target
exclusive anonymous pages.

For now, all tests fail:
	# [RUN] R/O longterm GUP pin ... with shared zeropage
	not ok 151 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP pin ... with memfd
	not ok 152 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP pin ... with tmpfile
	not ok 153 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP pin ... with huge zeropage
	not ok 154 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP pin ... with memfd hugetlb (2048 kB)
	not ok 155 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP pin ... with memfd hugetlb (1048576 kB)
	not ok 156 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP-fast pin ... with shared zeropage
	not ok 157 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP-fast pin ... with memfd
	not ok 158 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP-fast pin ... with tmpfile
	not ok 159 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP-fast pin ... with huge zeropage
	not ok 160 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP-fast pin ... with memfd hugetlb (2048 kB)
	not ok 161 Longterm R/O pin is reliable
	# [RUN] R/O longterm GUP-fast pin ... with memfd hugetlb (1048576 kB)
	not ok 162 Longterm R/O pin is reliable

Link: https://lkml.kernel.org/r/20221116102659.70287-4-david@redhat.com


Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent f8664f3c
Loading
Loading
Loading
Loading
+27 −1
Original line number Original line Diff line number Diff line
@@ -561,6 +561,7 @@ static void test_iouring_fork(char *mem, size_t size)
#endif /* LOCAL_CONFIG_HAVE_LIBURING */
#endif /* LOCAL_CONFIG_HAVE_LIBURING */


enum ro_pin_test {
enum ro_pin_test {
	RO_PIN_TEST,
	RO_PIN_TEST_SHARED,
	RO_PIN_TEST_SHARED,
	RO_PIN_TEST_PREVIOUSLY_SHARED,
	RO_PIN_TEST_PREVIOUSLY_SHARED,
	RO_PIN_TEST_RO_EXCLUSIVE,
	RO_PIN_TEST_RO_EXCLUSIVE,
@@ -593,6 +594,8 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,
	}
	}


	switch (test) {
	switch (test) {
	case RO_PIN_TEST:
		break;
	case RO_PIN_TEST_SHARED:
	case RO_PIN_TEST_SHARED:
	case RO_PIN_TEST_PREVIOUSLY_SHARED:
	case RO_PIN_TEST_PREVIOUSLY_SHARED:
		/*
		/*
@@ -1193,6 +1196,16 @@ static void test_cow(char *mem, const char *smem, size_t size)
	free(old);
	free(old);
}
}


static void test_ro_pin(char *mem, const char *smem, size_t size)
{
	do_test_ro_pin(mem, size, RO_PIN_TEST, false);
}

static void test_ro_fast_pin(char *mem, const char *smem, size_t size)
{
	do_test_ro_pin(mem, size, RO_PIN_TEST, true);
}

static void run_with_zeropage(non_anon_test_fn fn, const char *desc)
static void run_with_zeropage(non_anon_test_fn fn, const char *desc)
{
{
	char *mem, *smem, tmp;
	char *mem, *smem, tmp;
@@ -1433,7 +1446,7 @@ struct non_anon_test_case {
};
};


/*
/*
 * Test cases that target any pages in private mappings that are non anonymous:
 * Test cases that target any pages in private mappings that are not anonymous:
 * pages that may get shared via COW ndependent of fork(). This includes
 * pages that may get shared via COW ndependent of fork(). This includes
 * the shared zeropage(s), pagecache pages, ...
 * the shared zeropage(s), pagecache pages, ...
 */
 */
@@ -1446,6 +1459,19 @@ static const struct non_anon_test_case non_anon_test_cases[] = {
		"Basic COW",
		"Basic COW",
		test_cow,
		test_cow,
	},
	},
	/*
	 * Take a R/O longterm pin. When modifying the page via the page table,
	 * the page content change must be visible via the pin.
	 */
	{
		"R/O longterm GUP pin",
		test_ro_pin,
	},
	/* Same as above, but using GUP-fast. */
	{
		"R/O longterm GUP-fast pin",
		test_ro_fast_pin,
	},
};
};


static void run_non_anon_test_case(struct non_anon_test_case const *test_case)
static void run_non_anon_test_case(struct non_anon_test_case const *test_case)