All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cyrill Gorcunov <gorcunov@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org,
	Quentin Casasnovas <quentin.casasnovas@oracle.com>,
	Vegard Nossum <vegard.nossum@oracle.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Willy Tarreau <w@1wt.eu>, Andy Lutomirski <luto@amacapital.net>,
	Kees Cook <keescook@google.com>,
	Vladimir Davydov <vdavydov@virtuozzo.com>,
	Konstantin Khlebnikov <koct9i@gmail.com>,
	Pavel Emelyanov <xemul@virtuozzo.com>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Cyrill Gorcunov <gorcunov@openvz.org>
Subject: [RFC 2/2] [RFC] selftests: vm -- Add rlimit data selftest
Date: Sun, 13 Dec 2015 23:14:20 +0300	[thread overview]
Message-ID: <20151213201646.909312009@gmail.com> (raw)

[-- Attachment #1: mm-rlimit-data-selftest --]
[-- Type: text/plain, Size: 6612 bytes --]

Just setup RLIMIT_DATA limit and play with anon memory accounting.

CC: Quentin Casasnovas <quentin.casasnovas@oracle.com>
CC: Vegard Nossum <vegard.nossum@oracle.com>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Willy Tarreau <w@1wt.eu>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Kees Cook <keescook@google.com>
CC: Vladimir Davydov <vdavydov@virtuozzo.com>
CC: Konstantin Khlebnikov <koct9i@gmail.com>
CC: Pavel Emelyanov <xemul@virtuozzo.com>
CC: Vladimir Davydov <vdavydov@virtuozzo.com>
CC: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 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@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

WARNING: multiple messages have this Message-ID (diff)
From: Cyrill Gorcunov <gorcunov@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org,
	Quentin Casasnovas <quentin.casasnovas@oracle.com>,
	Vegard Nossum <vegard.nossum@oracle.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Willy Tarreau <w@1wt.eu>, Andy Lutomirski <luto@amacapital.net>,
	Kees Cook <keescook@google.com>,
	Vladimir Davydov <vdavydov@virtuozzo.com>,
	Konstantin Khlebnikov <koct9i@gmail.com>,
	Pavel Emelyanov <xemul@virtuozzo.com>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Cyrill Gorcunov <gorcunov@openvz.org>
Subject: [RFC 2/2] [RFC] selftests: vm -- Add rlimit data selftest
Date: Sun, 13 Dec 2015 23:14:20 +0300	[thread overview]
Message-ID: <20151213201646.909312009@gmail.com> (raw)

[-- Attachment #1: mm-rlimit-data-selftest --]
[-- Type: text/plain, Size: 6387 bytes --]

Just setup RLIMIT_DATA limit and play with anon memory accounting.

CC: Quentin Casasnovas <quentin.casasnovas@oracle.com>
CC: Vegard Nossum <vegard.nossum@oracle.com>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Willy Tarreau <w@1wt.eu>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Kees Cook <keescook@google.com>
CC: Vladimir Davydov <vdavydov@virtuozzo.com>
CC: Konstantin Khlebnikov <koct9i@gmail.com>
CC: Pavel Emelyanov <xemul@virtuozzo.com>
CC: Vladimir Davydov <vdavydov@virtuozzo.com>
CC: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 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


             reply	other threads:[~2015-12-13 20:16 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-13 20:14 Cyrill Gorcunov [this message]
2015-12-13 20:14 ` [RFC 2/2] [RFC] selftests: vm -- Add rlimit data selftest Cyrill Gorcunov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151213201646.909312009@gmail.com \
    --to=gorcunov@gmail.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=gorcunov@openvz.org \
    --cc=keescook@google.com \
    --cc=koct9i@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luto@amacapital.net \
    --cc=quentin.casasnovas@oracle.com \
    --cc=torvalds@linux-foundation.org \
    --cc=vdavydov@virtuozzo.com \
    --cc=vegard.nossum@oracle.com \
    --cc=w@1wt.eu \
    --cc=xemul@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.