All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brice Goglin <Brice.Goglin@inria.fr>
To: Christoph Lameter <cl@linux-foundation.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
	linux-mm@kvack.org, Andrew Morton <akpm@osdl.org>,
	Nathalie Furmento <nathalie.furmento@labri.fr>
Subject: [PATCH 4/5] mm: rework do_pages_move() to work on page_sized chunks
Date: Mon, 13 Oct 2008 22:22:53 +0200	[thread overview]
Message-ID: <48F3AE1D.3060208@inria.fr> (raw)
In-Reply-To: <48F3AD47.1050301@inria.fr>

Rework do_pages_move() to work by page-sized chunks of struct page_to_node
that are passed to do_move_page_to_node_array(). We now only have to
allocate a single page instead a possibly very large vmalloc area to store
all page_to_node entries.

As a result, new_page_node() will now have a very small lookup, hidding
much of the overall sys_move_pages() overhead.

Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
Signed-off-by: Nathalie Furmento <Nathalie.Furmento@labri.fr>
---
 mm/migrate.c |   79 ++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 44 insertions(+), 35 deletions(-)

diff --git a/mm/migrate.c b/mm/migrate.c
index dffc98b..175e242 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -947,41 +947,43 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
 			 const int __user *nodes,
 			 int __user *status, int flags)
 {
-	struct page_to_node *pm = NULL;
+	struct page_to_node *pm;
 	nodemask_t task_nodes;
-	int err = 0;
-	int i;
+	unsigned long chunk_nr_pages;
+	unsigned long chunk_start;
+	int err;
 
 	task_nodes = cpuset_mems_allowed(task);
 
-	/* Limit nr_pages so that the multiplication may not overflow */
-	if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) {
-		err = -E2BIG;
-		goto out;
-	}
-
-	pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node));
-	if (!pm) {
-		err = -ENOMEM;
+	err = -ENOMEM;
+	pm = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!pm)
 		goto out;
-	}
-
 	/*
-	 * Get parameters from user space and initialize the pm
-	 * array. Return various errors if the user did something wrong.
+	 * Store a chunk of page_to_node array in a page,
+	 * but keep the last one as a marker
 	 */
-	for (i = 0; i < nr_pages; i++) {
-		const void __user *p;
+	chunk_nr_pages = PAGE_SIZE/sizeof(struct page_to_node) - 1;
 
-		err = -EFAULT;
-		if (get_user(p, pages + i))
-			goto out_pm;
+	for (chunk_start = 0;
+	     chunk_start < nr_pages;
+	     chunk_start += chunk_nr_pages) {
+		int j;
+
+		if (chunk_start + chunk_nr_pages > nr_pages)
+			chunk_nr_pages = nr_pages - chunk_start;
 
-		pm[i].addr = (unsigned long)p;
-		if (nodes) {
+		/* fill the chunk pm with addrs and nodes from user-space */
+		for (j = 0; j < chunk_nr_pages; j++) {
+			const void __user *p;
 			int node;
 
-			if (get_user(node, nodes + i))
+			err = -EFAULT;
+			if (get_user(p, pages + j + chunk_start))
+				goto out_pm;
+			pm[j].addr = (unsigned long) p;
+
+			if (get_user(node, nodes + j + chunk_start))
 				goto out_pm;
 
 			err = -ENODEV;
@@ -992,22 +994,29 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
 			if (!node_isset(node, task_nodes))
 				goto out_pm;
 
-			pm[i].node = node;
-		} else
-			pm[i].node = 0;	/* anything to not match MAX_NUMNODES */
-	}
-	/* End marker */
-	pm[nr_pages].node = MAX_NUMNODES;
+			pm[j].node = node;
+		}
+
+		/* End marker for this chunk */
+		pm[chunk_nr_pages].node = MAX_NUMNODES;
+
+		/* Migrate this chunk */
+		err = do_move_page_to_node_array(mm, pm,
+						 flags & MPOL_MF_MOVE_ALL);
+		if (err < 0)
+			goto out_pm;
 
-	err = do_move_page_to_node_array(mm, pm, flags & MPOL_MF_MOVE_ALL);
-	if (err >= 0)
 		/* Return status information */
-		for (i = 0; i < nr_pages; i++)
-			if (put_user(pm[i].status, status + i))
+		for (j = 0; j < chunk_nr_pages; j++)
+			if (put_user(pm[j].status, status + j + chunk_start)) {
 				err = -EFAULT;
+				goto out_pm;
+			}
+	}
+	err = 0;
 
 out_pm:
-	vfree(pm);
+	kfree(pm);
 out:
 	return err;
 }
-- 
1.5.6.5




WARNING: multiple messages have this Message-ID (diff)
From: Brice Goglin <Brice.Goglin@inria.fr>
To: Christoph Lameter <cl@linux-foundation.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
	linux-mm@kvack.org, Andrew Morton <akpm@osdl.org>,
	Nathalie Furmento <nathalie.furmento@labri.fr>
Subject: [PATCH 4/5] mm: rework do_pages_move() to work on page_sized chunks
Date: Mon, 13 Oct 2008 22:22:53 +0200	[thread overview]
Message-ID: <48F3AE1D.3060208@inria.fr> (raw)
In-Reply-To: <48F3AD47.1050301@inria.fr>

Rework do_pages_move() to work by page-sized chunks of struct page_to_node
that are passed to do_move_page_to_node_array(). We now only have to
allocate a single page instead a possibly very large vmalloc area to store
all page_to_node entries.

As a result, new_page_node() will now have a very small lookup, hidding
much of the overall sys_move_pages() overhead.

Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
Signed-off-by: Nathalie Furmento <Nathalie.Furmento@labri.fr>
---
 mm/migrate.c |   79 ++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 44 insertions(+), 35 deletions(-)

diff --git a/mm/migrate.c b/mm/migrate.c
index dffc98b..175e242 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -947,41 +947,43 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
 			 const int __user *nodes,
 			 int __user *status, int flags)
 {
-	struct page_to_node *pm = NULL;
+	struct page_to_node *pm;
 	nodemask_t task_nodes;
-	int err = 0;
-	int i;
+	unsigned long chunk_nr_pages;
+	unsigned long chunk_start;
+	int err;
 
 	task_nodes = cpuset_mems_allowed(task);
 
-	/* Limit nr_pages so that the multiplication may not overflow */
-	if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) {
-		err = -E2BIG;
-		goto out;
-	}
-
-	pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node));
-	if (!pm) {
-		err = -ENOMEM;
+	err = -ENOMEM;
+	pm = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!pm)
 		goto out;
-	}
-
 	/*
-	 * Get parameters from user space and initialize the pm
-	 * array. Return various errors if the user did something wrong.
+	 * Store a chunk of page_to_node array in a page,
+	 * but keep the last one as a marker
 	 */
-	for (i = 0; i < nr_pages; i++) {
-		const void __user *p;
+	chunk_nr_pages = PAGE_SIZE/sizeof(struct page_to_node) - 1;
 
-		err = -EFAULT;
-		if (get_user(p, pages + i))
-			goto out_pm;
+	for (chunk_start = 0;
+	     chunk_start < nr_pages;
+	     chunk_start += chunk_nr_pages) {
+		int j;
+
+		if (chunk_start + chunk_nr_pages > nr_pages)
+			chunk_nr_pages = nr_pages - chunk_start;
 
-		pm[i].addr = (unsigned long)p;
-		if (nodes) {
+		/* fill the chunk pm with addrs and nodes from user-space */
+		for (j = 0; j < chunk_nr_pages; j++) {
+			const void __user *p;
 			int node;
 
-			if (get_user(node, nodes + i))
+			err = -EFAULT;
+			if (get_user(p, pages + j + chunk_start))
+				goto out_pm;
+			pm[j].addr = (unsigned long) p;
+
+			if (get_user(node, nodes + j + chunk_start))
 				goto out_pm;
 
 			err = -ENODEV;
@@ -992,22 +994,29 @@ static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
 			if (!node_isset(node, task_nodes))
 				goto out_pm;
 
-			pm[i].node = node;
-		} else
-			pm[i].node = 0;	/* anything to not match MAX_NUMNODES */
-	}
-	/* End marker */
-	pm[nr_pages].node = MAX_NUMNODES;
+			pm[j].node = node;
+		}
+
+		/* End marker for this chunk */
+		pm[chunk_nr_pages].node = MAX_NUMNODES;
+
+		/* Migrate this chunk */
+		err = do_move_page_to_node_array(mm, pm,
+						 flags & MPOL_MF_MOVE_ALL);
+		if (err < 0)
+			goto out_pm;
 
-	err = do_move_page_to_node_array(mm, pm, flags & MPOL_MF_MOVE_ALL);
-	if (err >= 0)
 		/* Return status information */
-		for (i = 0; i < nr_pages; i++)
-			if (put_user(pm[i].status, status + i))
+		for (j = 0; j < chunk_nr_pages; j++)
+			if (put_user(pm[j].status, status + j + chunk_start)) {
 				err = -EFAULT;
+				goto out_pm;
+			}
+	}
+	err = 0;
 
 out_pm:
-	vfree(pm);
+	kfree(pm);
 out:
 	return err;
 }
-- 
1.5.6.5



--
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>

  parent reply	other threads:[~2008-10-13 20:24 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-13 20:19 [PATCH 0/5] mm: rework sys_move_pages() to avoid vmalloc and reduce the overhead Brice Goglin
2008-10-13 20:19 ` Brice Goglin
2008-10-13 20:21 ` [PATCH 1/5] mm: stop returning -ENOENT from sys_move_pages() if nothing got migrated Brice Goglin
2008-10-13 20:21   ` Brice Goglin
2008-10-16 19:34   ` Christoph Lameter
2008-10-16 19:34     ` Christoph Lameter
2008-10-13 20:21 ` [PATCH 2/5] mm: don't vmalloc a huge page_to_node array for do_pages_stat() Brice Goglin
2008-10-13 20:21   ` Brice Goglin
2008-10-16 19:39   ` Christoph Lameter
2008-10-16 19:39     ` Christoph Lameter
2008-10-13 20:22 ` [PATCH 3/5] mm: extract do_pages_move() out of sys_move_pages() Brice Goglin
2008-10-13 20:22   ` Brice Goglin
2008-10-16 19:40   ` Christoph Lameter
2008-10-16 19:40     ` Christoph Lameter
2008-10-13 20:22 ` Brice Goglin [this message]
2008-10-13 20:22   ` [PATCH 4/5] mm: rework do_pages_move() to work on page_sized chunks Brice Goglin
2008-10-16 19:51   ` Christoph Lameter
2008-10-16 19:51     ` Christoph Lameter
2008-10-16 21:18     ` Brice Goglin
2008-10-16 21:18       ` Brice Goglin
2008-10-17 11:35     ` [RESEND][PATCH] " Brice Goglin
2008-10-17 11:35       ` Brice Goglin
2008-10-17 13:10       ` Christoph Lameter
2008-10-17 13:10         ` Christoph Lameter
2008-10-13 20:23 ` [PATCH 5/5] mm: move_pages: no need to set pp->page to ZERO_PAGE(0) by default Brice Goglin
2008-10-13 20:23   ` Brice Goglin
2008-10-16 19:42   ` Christoph Lameter
2008-10-16 19:42     ` Christoph Lameter
2008-10-14 20:53 ` [PATCH 0/5] mm: rework sys_move_pages() to avoid vmalloc and reduce the overhead Brice Goglin
2008-10-14 20:53   ` Brice Goglin

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=48F3AE1D.3060208@inria.fr \
    --to=brice.goglin@inria.fr \
    --cc=akpm@osdl.org \
    --cc=cl@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=nathalie.furmento@labri.fr \
    /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.