[LTP] [PATCH 26/29] Hugetlb: Migrating libhugetlbfs readahead_reserve

Tarun Sahu tsahu@linux.ibm.com
Sun Oct 16 14:57:28 CEST 2022


Migrating the libhugetlbfs/testcases/readahead_reserve.c test

Test Description: readahead() on some kernels can cause the reservation
counter to get corrupted. The problem is that the patches are allocated
for the reservation but not faulted in at the time of allocation. The
counters do not get updated and effectively "leak". This test
identifies whether the kernel is vulnerable to the problem or not.
It's fixed in kernel by 'commit f2deae9d4e70
("Remove implementation of readpage from the hugetlbfs_aops")'.

Signed-off-by: Tarun Sahu <tsahu@linux.ibm.com>
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap30.c  | 120 ++++++++++++++++++
 3 files changed, 122 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap30.c

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 906acb266..76ff1a3dd 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -30,6 +30,7 @@ hugemmap26 hugemmap26
 hugemmap27 hugemmap27
 hugemmap28 hugemmap28
 hugemmap29 hugemmap29
+hugemmap30 hugemmap30
 hugemmap05_1 hugemmap05 -m
 hugemmap05_2 hugemmap05 -s
 hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index fef0a76d6..bb9720452 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -29,6 +29,7 @@
 /hugetlb/hugemmap/hugemmap27
 /hugetlb/hugemmap/hugemmap28
 /hugetlb/hugemmap/hugemmap29
+/hugetlb/hugemmap/hugemmap30
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap30.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap30.c
new file mode 100644
index 000000000..030dbb851
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap30.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * Copyright (C) 2005-2006 IBM Corporation.
+ *
+ * Test Name: Readahead Reserve
+ *
+ * Test Description: readahead() on some kernels can cause the reservation
+ * counter to get corrupted. The problem is that the patches are allocated
+ * for the reservation but not faulted in at the time of allocation. The
+ * counters do not get updated and effectively "leak". This test
+ * identifies whether the kernel is vulnerable to the problem or not.
+ * It's fixed in kernel by commit f2deae9d4e70793568ef9e85d227abb7bef5b622.
+ *
+ * HISTORY
+ *  Written by Mel Gorman & Eric B Munson
+ *
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "hugetlb.h"
+
+static char *verbose;
+static char hfile[MAXPATHLEN];
+static long hpage_size;
+static int fd = -1;
+
+static void run_test(void)
+{
+	void *p;
+	unsigned long initial_rsvd, map_rsvd, readahead_rsvd, end_rsvd;
+
+	/* Setup */
+	fd = SAFE_OPEN(hfile, O_RDWR | O_CREAT, 0600);
+	SAFE_UNLINK(hfile);
+
+	initial_rsvd = SAFE_READ_MEMINFO("HugePages_Rsvd:");
+	if (verbose)
+		tst_res(TINFO, "Reserve count before map: %lu", initial_rsvd);
+
+	/* mmap a region and record reservations */
+	p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+		 fd, 0);
+	map_rsvd = SAFE_READ_MEMINFO("HugePages_Rsvd:");
+	if (verbose)
+		tst_res(TINFO, "Reserve count after map: %lu", map_rsvd);
+
+	/* readahead the region and record reservations */
+	readahead(fd, 0, hpage_size);
+	readahead_rsvd = SAFE_READ_MEMINFO("HugePages_Rsvd:");
+	if (verbose)
+		tst_res(TINFO, "Reserve count after readahead: %lu", readahead_rsvd);
+
+	/* Write the region */
+	memset(p, 1, hpage_size);
+
+	/* Free region */
+	SAFE_MUNMAP(p, hpage_size);
+	SAFE_CLOSE(fd);
+	end_rsvd = SAFE_READ_MEMINFO("HugePages_Rsvd:");
+	if (verbose)
+		tst_res(TINFO, "Reserve count after close(): %lu\n", end_rsvd);
+
+	/* Reserve count should match initial reserve count */
+	if (end_rsvd != initial_rsvd) {
+		tst_res(TFAIL, "Reserve leaked: %lu != %lu\n", end_rsvd, initial_rsvd);
+		goto fail;
+	}
+
+	tst_res(TPASS, "Successful");
+	return;
+
+fail:
+	tst_brk(TBROK, "Once failed, No point in continuing the test");
+}
+
+static void setup(void)
+{
+	if (tst_hugepages < 1)
+		tst_brk(TCONF, "Not enough hugepages for testing.");
+
+	if (!Hopt)
+		Hopt = tst_get_tmpdir();
+	SAFE_MOUNT("none", Hopt, "hugetlbfs", 0, NULL);
+
+	snprintf(hfile, sizeof(hfile), "%s/ltp_hugetlbfile%d", Hopt, getpid());
+
+	hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024;
+}
+
+static void cleanup(void)
+{
+	if (fd >= 0)
+		SAFE_CLOSE(fd);
+	umount2(Hopt, MNT_DETACH);
+}
+
+static struct tst_test test = {
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+	.options = (struct tst_option[]) {
+		{"v", &verbose, "Turns on verbose mode"},
+		{"H:", &Hopt,   "Location of hugetlbfs, i.e.  -H /var/hugetlbfs"},
+		{"s:", &nr_opt, "Set the number of the been allocated hugepages"},
+		{}
+	},
+	.setup = setup,
+	.cleanup = cleanup,
+	.test_all = run_test,
+	.hugepages = {1, TST_REQUEST},
+};
-- 
2.31.1



More information about the ltp mailing list