[RFC 2/2] [RFC] selftests: vm -- Add rlimit data selftest

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Just setup RLIMIT_DATA limit and play with anon memory accounting.

CC: Quentin Casasnovas <quentin.casasnovas@xxxxxxxxxx>
CC: Vegard Nossum <vegard.nossum@xxxxxxxxxx>
CC: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
CC: Willy Tarreau <w@xxxxxx>
CC: Andy Lutomirski <luto@xxxxxxxxxxxxxx>
CC: Kees Cook <keescook@xxxxxxxxxx>
CC: Vladimir Davydov <vdavydov@xxxxxxxxxxxxx>
CC: Konstantin Khlebnikov <koct9i@xxxxxxxxx>
CC: Pavel Emelyanov <xemul@xxxxxxxxxxxxx>
CC: Vladimir Davydov <vdavydov@xxxxxxxxxxxxx>
CC: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
Signed-off-by: Cyrill Gorcunov <gorcunov@xxxxxxxxxx>
---
 tools/testing/selftests/vm/Makefile      |    1 
 tools/testing/selftests/vm/rlimit-data.c |  201 +++++++++++++++++++++++++++++++
 tools/testing/selftests/vm/run_vmtests   |    4 
 3 files changed, 204 insertions(+), 2 deletions(-)

Index: linux-ml.git/tools/testing/selftests/vm/Makefile
===================================================================
--- linux-ml.git.orig/tools/testing/selftests/vm/Makefile
+++ linux-ml.git/tools/testing/selftests/vm/Makefile
@@ -10,6 +10,7 @@ BINARIES += on-fault-limit
 BINARIES += thuge-gen
 BINARIES += transhuge-stress
 BINARIES += userfaultfd
+BINARIES += rlimit-data
 
 all: $(BINARIES)
 %: %.c
Index: linux-ml.git/tools/testing/selftests/vm/rlimit-data.c
===================================================================
--- /dev/null
+++ linux-ml.git/tools/testing/selftests/vm/rlimit-data.c
@@ -0,0 +1,201 @@
+/*
+ * rlimit-data:
+ *
+ * Test that RLIMIT_DATA accounts anonymous
+ * memory correctly.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+
+#define pr_info(fmt, ...)					\
+	fprintf(stdout, fmt, ##__VA_ARGS__)
+#define pr_err(fmt, ...)					\
+	fprintf(stderr, "ERROR: " fmt, ##__VA_ARGS__)
+#define pr_perror(fmt, ...)					\
+	fprintf(stderr, "ERROR: " fmt ": %s\n", ##__VA_ARGS__,	\
+		strerror(errno))
+
+#define mmap_anon(__addr, __size)				\
+	mmap(__addr, __size, PROT_READ | PROT_WRITE,		\
+		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
+
+static const char self_status_path[] = "/proc/self/status";
+static int fd_status = -1;
+static size_t page_size;
+
+static const char tplt[] = "VmAnon:";
+static const size_t tplt_len = sizeof(tplt) - 1;
+
+static int get_self_anon_vm(int fd, unsigned long *npages)
+{
+	FILE *f = fdopen(fd, "r");
+	bool found = false;
+	char buf[1024];
+
+	if (!f) {
+		pr_perror("Can't open status");
+		return -1;
+	}
+
+	setbuffer(f, NULL, 0);
+	rewind(f);
+	while (fgets(buf, sizeof(buf), f)) {
+		if (strncmp(buf, tplt, tplt_len))
+			continue;
+		*npages = (atol(&buf[tplt_len + 1]) << 10) / page_size;
+		found = true;
+		break;
+	}
+
+	if (!found)
+		pr_err("No data found in status\n");
+	return found ? 0 : -1;
+}
+
+int main(int argc, char *argv[])
+{
+	unsigned long npages_cur = 0, npages_new = 0;
+	unsigned long npages_init = 0;
+	int ret = 1, match;
+	struct rlimit lim;
+
+	void *mem, *mem_new;
+	size_t size;
+
+	size_t shmem_size;
+	void *shmem;
+
+	page_size = getpagesize();
+
+	if (getrlimit(RLIMIT_DATA, &lim)) {
+		pr_perror("Can't get rlimit data");
+		return 1;
+	}
+
+	fd_status = open(self_status_path, O_RDONLY);
+	if (fd_status < 0) {
+		pr_perror("Can't open %s", self_status_path);
+		return 1;
+	}
+
+	if (get_self_anon_vm(fd_status, &npages_init))
+		goto err;
+	pr_info("Initial anon pages %lu\n", npages_init);
+
+	/*
+	 * Map first chunk.
+	 */
+	size = page_size * 10;
+	mem = mmap_anon(NULL, size);
+	if (mem == MAP_FAILED) {
+		pr_perror("Can't map first chunk");
+		goto err;
+	}
+	if (get_self_anon_vm(fd_status, &npages_cur))
+		goto err;
+	pr_info("Mapped %zu bytes %lu pages, parsed %lu\n",
+		size, size / page_size, npages_cur);
+
+	if (npages_cur <= (npages_init + 10)) {
+		pr_err("Parsed number of pages is too small\n");
+		goto err;
+	}
+
+	/*
+	 * Allow up to more 80K of anon data.
+	 */
+	lim.rlim_cur = (80 << 10) + npages_init * page_size;
+	lim.rlim_max = RLIM_INFINITY;
+	if (setrlimit(RLIMIT_DATA, &lim)) {
+		pr_perror("Can't setup limit to %lu bytes",
+			  (unsigned long)lim.rlim_cur);
+		goto err;
+	}
+
+	/*
+	 * This one should fail.
+	 */
+	mem_new = mmap_anon(NULL, lim.rlim_cur);
+	if (mem_new != MAP_FAILED) {
+		pr_err("RLIMIT_DATA didn't catch the overrflow\n");
+		goto err;
+	}
+
+	/*
+	 * Shrink it.
+	 */
+	mem_new = mremap(mem, size, size / 2, MREMAP_MAYMOVE);
+	if (!mem_new) {
+		pr_perror("Can't shrink memory");
+		goto err;
+	}
+	size /= 2;
+	mem = mem_new;
+
+	if (get_self_anon_vm(fd_status, &npages_cur))
+		goto err;
+	pr_info("Remapped %zu bytes %lu pages, parsed %lu\n",
+		size, size / page_size, npages_cur);
+
+	if (npages_cur <= (npages_init + 5)) {
+		pr_err("Parsed number of pages is too small\n");
+		goto err;
+	}
+
+	/*
+	 * Test via sbrk.
+	 */
+	mem_new = sbrk(0);
+	pr_info("Current brk %p\n", sbrk(0));
+	mem_new = sbrk(page_size);
+	if (mem_new != (void *)-1) {
+		if (get_self_anon_vm(fd_status, &npages_cur))
+			goto err;
+
+		/*
+		 * Allow up to two pages.
+		 */
+		lim.rlim_cur = (npages_cur + 3) * page_size;
+		lim.rlim_max = RLIM_INFINITY;
+		if (setrlimit(RLIMIT_DATA, &lim)) {
+			pr_perror("Can't setup limit to %lu bytes",
+				  (unsigned long)lim.rlim_cur);
+			goto err;
+		}
+
+		pr_info("Allocating 3 pages, must pass...");
+		mem_new = sbrk(page_size * 3);
+		if (mem_new == (void *)-1) {
+			pr_err("Can't allocate pages while should\n");
+			goto err;
+		} else
+			pr_info("OK\n");
+
+		pr_info("Allocating 1 pages, must fail...");
+		mem_new = sbrk(page_size);
+		if (mem_new != (void *)-1) {
+			pr_err("Allocated page while should not\n");
+			goto err;
+		} else
+			pr_info("OK\n");
+	}
+
+	ret = 0;
+err:
+	if (mem)
+		munmap(mem, size);
+	close(fd_status);
+	return ret;
+}
Index: linux-ml.git/tools/testing/selftests/vm/run_vmtests
===================================================================
--- linux-ml.git.orig/tools/testing/selftests/vm/run_vmtests
+++ linux-ml.git/tools/testing/selftests/vm/run_vmtests
@@ -131,9 +131,9 @@ else
 fi
 
 echo "--------------------"
-echo "running mlock2-tests"
+echo "running rlimit-data"
 echo "--------------------"
-./mlock2-tests
+./rlimit-data
 if [ $? -ne 0 ]; then
 	echo "[FAIL]"
 	exitcode=1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]