blob: 39d4882cdc2eb97bc7d576a4a8e61dd673b1a34e [file] [log] [blame]
/*
* perform page migration across nodes .
* Part of the code is from numactl's test code migrate_pages.c.
* Copyright (C) 2006 Silicon Graphics, Inc.
* Christoph Lameter <clameter@sgi.com>
* Copyright (C) 2010-2015 Intel Corporation
*/
#include <numaif.h>
#include <stdio.h>
#include <stdlib.h>
#include <numa.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#define PAGES_TO_MIGRATE 1024
unsigned int pagesize;
unsigned int page_count = PAGES_TO_MIGRATE;
char *pages;
void **addr;
int *status;
int *nodes;
int errors;
int nr_nodes;
struct bitmask *old_nodes;
struct bitmask *new_nodes;
void print_status(char *message, char *start_addr, int *status,
unsigned long maxnode, int desired)
{
int i;
printf("%s\n", message);
printf("---------------------------------\n");
/* get page status for each page */
for (i = 0; i < page_count; i++) {
if (get_mempolicy(&status[i], NULL, maxnode,
(unsigned long *)(start_addr + (i * pagesize)),
MPOL_F_NODE|MPOL_F_ADDR) < 0) {
perror("move_pages");
exit(1);
}
}
/* print page status for each page */
for (i = 0; i < page_count; i++) {
printf("Page %d vaddr=%p node=%d\n", i, pages + i * pagesize, status[i]);
if (((char *)pages)[ i* pagesize ] != (char) i) {
printf("*** Page content corrupted.\n");
errors++;
} else if (status[i] != desired) {
printf("Bad page state. Page %d status %d\n", i, status[i]);
exit(1);
}
}
}
int main(int argc, char **argv)
{
int i, rc;
pagesize = getpagesize();
nr_nodes = numa_max_node()+1;
old_nodes = numa_bitmask_alloc(nr_nodes);
new_nodes = numa_bitmask_alloc(nr_nodes);
numa_bitmask_setbit(old_nodes, 1);
numa_bitmask_setbit(new_nodes, 0);
/* check if atleast two nodes available for migration */
if (nr_nodes < 2) {
printf("A minimum of 2 nodes is required for this test.\n");
exit(1);
}
setbuf(stdout, NULL);
if (argc > 1)
sscanf(argv[1], "%d", &page_count);
/* Allocate pages */
if ((pages = mmap(NULL, ((pagesize + 1) * page_count), PROT_READ|PROT_WRITE,
MAP_POPULATE|MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
fprintf(stderr, "anon mmap failed: %s\n", strerror(errno));
exit(1);
}
addr = malloc(sizeof(char *) * page_count);
status = malloc(sizeof(int *) * page_count);
nodes = malloc(sizeof(int *) * page_count);
if (!addr || !status || !nodes) {
printf("Unable to allocate memory\n");
exit(1);
}
for (i = 0; i < page_count; i++) {
pages[ i * pagesize ] = (char) i;
addr[i] = pages + i * pagesize;
nodes[i] = 1;
status[i] = -123;
}
/* Move to starting node */
rc = numa_move_pages(0, page_count, addr, nodes, status, MPOL_MF_MOVE_ALL);
if (rc < 0 && errno != ENOENT) {
perror("move_pages");
exit(1);
}
/* Print page status before page migration */
print_status("Page location before migration", pages, status, old_nodes->size + 1, 1);
/* Migrate pages across nodes */
if ((rc = numa_migrate_pages(0, old_nodes, new_nodes)) < 0) {
perror("numa_migrate_pages failed");
errors++;
}
/* Print page locations after migration */
print_status("Page location after migration", pages, status, new_nodes->size + 1, 0);
/* Free allocated memory */
free(addr);
free(status);
free(nodes);
if (!errors)
printf("Test successful.\n");
else
printf("%d errors.\n", errors);
return errors > 0 ? 1 : 0;
}