lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 11 Jun 2013 21:22:48 -0700
From:	John Stultz <john.stultz@...aro.org>
To:	LKML <linux-kernel@...r.kernel.org>
Cc:	Minchan Kim <minchan@...nel.org>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Android Kernel Team <kernel-team@...roid.com>,
	Robert Love <rlove@...gle.com>, Mel Gorman <mel@....ul.ie>,
	Hugh Dickins <hughd@...gle.com>,
	Dave Hansen <dave@...ux.vnet.ibm.com>,
	Rik van Riel <riel@...hat.com>,
	Dmitry Adamushko <dmitry.adamushko@...il.com>,
	Dave Chinner <david@...morbit.com>, Neil Brown <neilb@...e.de>,
	Andrea Righi <andrea@...terlinux.com>,
	Andrea Arcangeli <aarcange@...hat.com>,
	"Aneesh Kumar K.V" <aneesh.kumar@...ux.vnet.ibm.com>,
	Mike Hommey <mh@...ndium.org>, Taras Glek <tglek@...illa.com>,
	Dhaval Giani <dgiani@...illa.com>, Jan Kara <jack@...e.cz>,
	KOSAKI Motohiro <kosaki.motohiro@...il.com>,
	Michel Lespinasse <walken@...gle.com>,
	"linux-mm@...ck.org" <linux-mm@...ck.org>,
	John Stultz <john.stultz@...aro.org>
Subject: [PATCH 5/8] vrange: Add new vrange(2) system call

From: Minchan Kim <minchan@...nel.org>

This patch adds new system call sys_vrange.

NAME
	vrange - Mark or unmark range of memory as volatile

SYNOPSIS
	int vrange(unsigned_long start, size_t length, int mode,
			 int *purged);

DESCRIPTION
	Applications can use vrange(2) to advise the kernel how it should
	handle paging I/O in this VM area.  The idea is to help the kernel
	discard pages of vrange instead of reclaiming when memory pressure
	happens. It means kernel doesn't discard any pages of vrange if
	there is no memory pressure.

	mode:
	VRANGE_VOLATILE
		hint to kernel so VM can discard in vrange pages when
		memory pressure happens.
	VRANGE_NONVOLATILE
		hint to kernel so VM doesn't discard vrange pages
		any more.

	If user try to access purged memory without VRANGE_NOVOLATILE call,
	he can encounter SIGBUS if the page was discarded by kernel.

	purged: Pointer to an integer which will return 1 if
	mode == VRANGE_NONVOLATILE and any page in the affected range
	was purged. If purged returns zero during a mode ==
	VRANGE_NONVOLATILE call, it means all of the pages in the range
	are intact.

RETURN VALUE
	On success vrange returns the number of bytes marked or unmarked.
	Similar to write(), it may return fewer bytes then specified
	if it ran into a problem.

	If an error is returned, no changes were made.

ERRORS
	EINVAL This error can occur for the following reasons:
		* The value length is negative or not page size units.
		* addr is not page-aligned
		* mode not a valid value.

	ENOMEM Not enough memory

	EFAULT purged pointer is invalid

Cc: Andrew Morton <akpm@...ux-foundation.org>
Cc: Android Kernel Team <kernel-team@...roid.com>
Cc: Robert Love <rlove@...gle.com>
Cc: Mel Gorman <mel@....ul.ie>
Cc: Hugh Dickins <hughd@...gle.com>
Cc: Dave Hansen <dave@...ux.vnet.ibm.com>
Cc: Rik van Riel <riel@...hat.com>
Cc: Dmitry Adamushko <dmitry.adamushko@...il.com>
Cc: Dave Chinner <david@...morbit.com>
Cc: Neil Brown <neilb@...e.de>
Cc: Andrea Righi <andrea@...terlinux.com>
Cc: Andrea Arcangeli <aarcange@...hat.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@...ux.vnet.ibm.com>
Cc: Mike Hommey <mh@...ndium.org>
Cc: Taras Glek <tglek@...illa.com>
Cc: Dhaval Giani <dgiani@...illa.com>
Cc: Jan Kara <jack@...e.cz>
Cc: KOSAKI Motohiro <kosaki.motohiro@...il.com>
Cc: Michel Lespinasse <walken@...gle.com>
Cc: Minchan Kim <minchan@...nel.org>
Cc: linux-mm@...ck.org <linux-mm@...ck.org>
Signed-off-by: Minchan Kim <minchan@...nel.org>
[jstultz: Major rework of interface and commit message]
Signed-off-by: John Stultz <john.stultz@...aro.org>
---
 arch/x86/syscalls/syscall_64.tbl       |   1 +
 include/uapi/asm-generic/mman-common.h |   3 +
 mm/vrange.c                            | 147 +++++++++++++++++++++++++++++++++
 3 files changed, 151 insertions(+)

diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index 38ae65d..dc332bd 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -320,6 +320,7 @@
 311	64	process_vm_writev	sys_process_vm_writev
 312	common	kcmp			sys_kcmp
 313	common	finit_module		sys_finit_module
+314	common	vrange			sys_vrange
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h
index 4164529..9be120b 100644
--- a/include/uapi/asm-generic/mman-common.h
+++ b/include/uapi/asm-generic/mman-common.h
@@ -66,4 +66,7 @@
 #define MAP_HUGE_SHIFT	26
 #define MAP_HUGE_MASK	0x3f
 
+#define VRANGE_VOLATILE		0	/* unpin pages so VM can discard them */
+#define VRANGE_NONVOLATILE	1	/* pin pages so VM can't discard them */
+
 #endif /* __ASM_GENERIC_MMAN_COMMON_H */
diff --git a/mm/vrange.c b/mm/vrange.c
index 5ca8853..f3c2465 100644
--- a/mm/vrange.c
+++ b/mm/vrange.c
@@ -5,6 +5,7 @@
 #include <linux/vrange.h>
 #include <linux/slab.h>
 #include <linux/mman.h>
+#include <linux/syscalls.h>
 
 static struct kmem_cache *vrange_cachep;
 
@@ -217,3 +218,149 @@ fail:
 	vrange_root_cleanup(new);
 	return -ENOMEM;
 }
+
+static ssize_t do_vrange(struct mm_struct *mm, unsigned long start_idx,
+				unsigned long end_idx, int mode, int *purged)
+{
+	struct vm_area_struct *vma;
+	unsigned long orig_start = start_idx;
+	ssize_t count = 0, ret = 0;
+
+	down_read(&mm->mmap_sem);
+
+	vma = find_vma(mm, start_idx);
+	for (;;) {
+		struct vrange_root *vroot;
+		unsigned long tmp, vstart_idx, vend_idx;
+
+		if (!vma)
+			goto out;
+
+		/* make sure start is at the front of the current vma*/
+		if (start_idx < vma->vm_start) {
+			start_idx = vma->vm_start;
+			if (start_idx > end_idx)
+				goto out;
+		}
+
+		/* bound tmp to closer of vm_end & end */
+		tmp = vma->vm_end - 1;
+		if (end_idx < tmp)
+			tmp = end_idx;
+
+		if (vma->vm_file && (vma->vm_flags & VM_SHARED)) {
+			/* Convert to file relative offsets */
+			vroot = &vma->vm_file->f_mapping->vroot;
+			vstart_idx = vma->vm_pgoff + start_idx - vma->vm_start;
+			vend_idx = vma->vm_pgoff + tmp - vma->vm_start;
+		} else {
+			vroot = &mm->vroot;
+			vstart_idx = start_idx;
+			vend_idx = tmp;
+		}
+
+		/* mark or unmark */
+		if (mode == VRANGE_VOLATILE)
+			ret = vrange_add(vroot, vstart_idx, vend_idx);
+		else if (mode == VRANGE_NONVOLATILE)
+			ret = vrange_remove(vroot, vstart_idx, vend_idx,
+						purged);
+
+		if (ret)
+			goto out;
+
+		/* update count to distance covered so far*/
+		count = tmp - orig_start;
+
+		/* move start up to the end of the vma*/
+		start_idx = vma->vm_end;
+		if (start_idx > end_idx)
+			goto out;
+		/* move to the next vma */
+		vma = vma->vm_next;
+	}
+out:
+	up_read(&mm->mmap_sem);
+
+	/* report bytes successfully marked, even if we're exiting on error */
+	if (count)
+		return count;
+
+	return ret;
+}
+
+/*
+ * The vrange(2) system call.
+ *
+ * Applications can use vrange() to advise the kernel how it should
+ * handle paging I/O in this VM area.  The idea is to help the kernel
+ * discard pages of vrange instead of swapping out when memory pressure
+ * happens. The information provided is advisory only, and can be safely
+ * disregarded by the kernel if system has enough free memory.
+ *
+ * mode values:
+ *  VRANGE_VOLATILE - hint to kernel so VM can discard vrange pages when
+ *		memory pressure happens.
+ *  VRANGE_NONVOLATILE - Removes any volatile hints previous specified in that
+ *		range.
+ *
+ * purged ptr:
+ *  Returns 1 if any page in the range being marked nonvolatile has been purged.
+ *
+ * Return values:
+ *  On success vrange returns the number of bytes marked or unmarked.
+ *  Similar to write(), it may return fewer bytes then specified if
+ *  it ran into a problem.
+ *
+ *  If an error is returned, no changes were made.
+ *
+ * Errors:
+ *  -EINVAL - start  len < 0, start is not page-aligned, start is greater
+ *		than TASK_SIZE or "mode" is not a valid value.
+ *  -ENOMEM - Short of free memory in system for successful system call.
+ *  -EFAULT - Purged pointer is invalid.
+ *  -ENOSUP - Feature not yet supported.
+ */
+SYSCALL_DEFINE4(vrange, unsigned long, start,
+		size_t, len, int, mode, int __user *, purged)
+{
+	unsigned long end;
+	struct mm_struct *mm = current->mm;
+	ssize_t ret = -EINVAL;
+	int p = 0;
+
+	if (start & ~PAGE_MASK)
+		goto out;
+
+	len &= PAGE_MASK;
+	if (!len)
+		goto out;
+
+	end = start + len;
+	if (end < start)
+		goto out;
+
+	if (start >= TASK_SIZE)
+		goto out;
+
+	if (purged) {
+		/* Test pointer is valid before making any changes */
+		if (put_user(p, purged))
+			return -EFAULT;
+	}
+
+	ret = do_vrange(mm, start, end - 1, mode, &p);
+
+	if (purged) {
+		if (put_user(p, purged)) {
+			/*
+			 * This would be bad, since we've modified volatilty
+			 * and the change in purged state would be lost.
+			 */
+			BUG();
+		}
+	}
+
+out:
+	return ret;
+}
-- 
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists