Skip to content

Commit

Permalink
[PATCH] page migration: sys_move_pages(): support moving of individua…
Browse files Browse the repository at this point in the history
…l pages

move_pages() is used to move individual pages of a process. The function can
be used to determine the location of pages and to move them onto the desired
node. move_pages() returns status information for each page.

long move_pages(pid, number_of_pages_to_move,
		addresses_of_pages[],
		nodes[] or NULL,
		status[],
		flags);

The addresses of pages is an array of void * pointing to the
pages to be moved.

The nodes array contains the node numbers that the pages should be moved
to. If a NULL is passed instead of an array then no pages are moved but
the status array is updated. The status request may be used to determine
the page state before issuing another move_pages() to move pages.

The status array will contain the state of all individual page migration
attempts when the function terminates. The status array is only valid if
move_pages() completed successfullly.

Possible page states in status[]:

0..MAX_NUMNODES	The page is now on the indicated node.

-ENOENT		Page is not present

-EACCES		Page is mapped by multiple processes and can only
		be moved if MPOL_MF_MOVE_ALL is specified.

-EPERM		The page has been mlocked by a process/driver and
		cannot be moved.

-EBUSY		Page is busy and cannot be moved. Try again later.

-EFAULT		Invalid address (no VMA or zero page).

-ENOMEM		Unable to allocate memory on target node.

-EIO		Unable to write back page. The page must be written
		back in order to move it since the page is dirty and the
		filesystem does not provide a migration function that
		would allow the moving of dirty pages.

-EINVAL		A dirty page cannot be moved. The filesystem does not provide
		a migration function and has no ability to write back pages.

The flags parameter indicates what types of pages to move:

MPOL_MF_MOVE	Move pages that are only mapped by the process.

MPOL_MF_MOVE_ALL Also move pages that are mapped by multiple processes.
		Requires sufficient capabilities.

Possible return codes from move_pages()

-ENOENT		No pages found that would require moving. All pages
		are either already on the target node, not present, had an
		invalid address or could not be moved because they were
		mapped by multiple processes.

-EINVAL		Flags other than MPOL_MF_MOVE(_ALL) specified or an attempt
		to migrate pages in a kernel thread.

-EPERM		MPOL_MF_MOVE_ALL specified without sufficient priviledges.
		or an attempt to move a process belonging to another user.

-EACCES		One of the target nodes is not allowed by the current cpuset.

-ENODEV		One of the target nodes is not online.

-ESRCH		Process does not exist.

-E2BIG		Too many pages to move.

-ENOMEM		Not enough memory to allocate control array.

-EFAULT		Parameters could not be accessed.

A test program for move_pages() may be found with the patches
on ftp.kernel.org:/pub/linux/kernel/people/christoph/pmig/patches-2.6.17-rc4-mm3

From: Christoph Lameter <[email protected]>

  Detailed results for sys_move_pages()

  Pass a pointer to an integer to get_new_page() that may be used to
  indicate where the completion status of a migration operation should be
  placed.  This allows sys_move_pags() to report back exactly what happened to
  each page.

  Wish there would be a better way to do this. Looks a bit hacky.

Signed-off-by: Christoph Lameter <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Jes Sorensen <[email protected]>
Cc: KAMEZAWA Hiroyuki <[email protected]>
Cc: Lee Schermerhorn <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Michael Kerrisk <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Christoph Lameter authored and Linus Torvalds committed Jun 23, 2006
1 parent 95a402c commit 742755a
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 25 deletions.
29 changes: 13 additions & 16 deletions Documentation/vm/page_migration
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@ a process are located. See also the numa_maps manpage in the numactl package.
Manual migration is useful if for example the scheduler has relocated
a process to a processor on a distant node. A batch scheduler or an
administrator may detect the situation and move the pages of the process
nearer to the new processor. At some point in the future we may have
some mechanism in the scheduler that will automatically move the pages.
nearer to the new processor. The kernel itself does only provide
manual page migration support. Automatic page migration may be implemented
through user space processes that move pages. A special function call
"move_pages" allows the moving of individual pages within a process.
A NUMA profiler may f.e. obtain a log showing frequent off node
accesses and may use the result to move pages to more advantageous
locations.

Larger installations usually partition the system using cpusets into
sections of nodes. Paul Jackson has equipped cpusets with the ability to
Expand Down Expand Up @@ -62,22 +67,14 @@ A. In kernel use of migrate_pages()
It also prevents the swapper or other scans to encounter
the page.

2. Generate a list of newly allocates pages. These pages will contain the
contents of the pages from the first list after page migration is
complete.
2. We need to have a function of type new_page_t that can be
passed to migrate_pages(). This function should figure out
how to allocate the correct new page given the old page.

3. The migrate_pages() function is called which attempts
to do the migration. It returns the moved pages in the
list specified as the third parameter and the failed
migrations in the fourth parameter. When the function
returns the first list will contain the pages that could still be retried.

4. The leftover pages of various types are returned
to the LRU using putback_to_lru_pages() or otherwise
disposed of. The pages will still have the refcount as
increased by isolate_lru_pages() if putback_to_lru_pages() is not
used! The kernel may want to handle the various cases of failures in
different ways.
to do the migration. It will call the function to allocate
the new page for each page that is considered for
moving.

B. How migrate_pages() works
----------------------------
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,7 @@ sys_call_table:
data8 sys_keyctl
data8 sys_ioprio_set
data8 sys_ioprio_get // 1275
data8 sys_ni_syscall
data8 sys_move_pages
data8 sys_inotify_init
data8 sys_inotify_add_watch
data8 sys_inotify_rm_watch
Expand Down
2 changes: 1 addition & 1 deletion include/asm-ia64/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@
#define __NR_keyctl 1273
#define __NR_ioprio_set 1274
#define __NR_ioprio_get 1275
/* 1276 is available for reuse (was briefly sys_set_zone_reclaim) */
#define __NR_move_pages 1276
#define __NR_inotify_init 1277
#define __NR_inotify_add_watch 1278
#define __NR_inotify_rm_watch 1279
Expand Down
2 changes: 1 addition & 1 deletion include/linux/migrate.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <linux/mm.h>

typedef struct page *new_page_t(struct page *, unsigned long private);
typedef struct page *new_page_t(struct page *, unsigned long private, int **);

#ifdef CONFIG_MIGRATION
extern int isolate_lru_page(struct page *p, struct list_head *pagelist);
Expand Down
5 changes: 5 additions & 0 deletions include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,11 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
const unsigned long __user *from,
const unsigned long __user *to);
asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
const void __user * __user *pages,
const int __user *nodes,
int __user *status,
int flags);
asmlinkage long sys_mbind(unsigned long start, unsigned long len,
unsigned long mode,
unsigned long __user *nmask,
Expand Down
1 change: 1 addition & 0 deletions kernel/sys_ni.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ cond_syscall(sys_inotify_init);
cond_syscall(sys_inotify_add_watch);
cond_syscall(sys_inotify_rm_watch);
cond_syscall(sys_migrate_pages);
cond_syscall(sys_move_pages);
cond_syscall(sys_chown16);
cond_syscall(sys_fchown16);
cond_syscall(sys_getegid16);
Expand Down
4 changes: 2 additions & 2 deletions mm/mempolicy.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
isolate_lru_page(page, pagelist);
}

static struct page *new_node_page(struct page *page, unsigned long node)
static struct page *new_node_page(struct page *page, unsigned long node, int **x)
{
return alloc_pages_node(node, GFP_HIGHUSER, 0);
}
Expand Down Expand Up @@ -698,7 +698,7 @@ int do_migrate_pages(struct mm_struct *mm,

}

static struct page *new_vma_page(struct page *page, unsigned long private)
static struct page *new_vma_page(struct page *page, unsigned long private, int **x)
{
struct vm_area_struct *vma = (struct vm_area_struct *)private;

Expand Down
Loading

0 comments on commit 742755a

Please sign in to comment.