/* * 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 * Copyright (C) 2010-2015 Intel Corporation */ #include #include #include #include #include #include #include #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; }