Skip to content
  • KOSAKI Motohiro's avatar
    mm: fix mbind vma merge problem · 9d8cebd4
    KOSAKI Motohiro authored
    
    
    Strangely, current mbind() doesn't merge vma with neighbor vma although it's possible.
    Unfortunately, many vma can reduce performance...
    
    This patch fixes it.
    
        reproduced program
        ----------------------------------------------------------------
         #include <numaif.h>
         #include <numa.h>
         #include <sys/mman.h>
         #include <stdio.h>
         #include <unistd.h>
         #include <stdlib.h>
         #include <string.h>
    
        static unsigned long pagesize;
    
        int main(int argc, char** argv)
        {
        	void* addr;
        	int ch;
        	int node;
        	struct bitmask *nmask = numa_allocate_nodemask();
        	int err;
        	int node_set = 0;
        	char buf[128];
    
        	while ((ch = getopt(argc, argv, "n:")) != -1){
        		switch (ch){
        		case 'n':
        			node = strtol(optarg, NULL, 0);
        			numa_bitmask_setbit(nmask, node);
        			node_set = 1;
        			break;
        		default:
        			;
        		}
        	}
        	argc -= optind;
        	argv += optind;
    
        	if (!node_set)
        		numa_bitmask_setbit(nmask, 0);
    
        	pagesize = getpagesize();
    
        	addr = mmap(NULL, pagesize*3, PROT_READ|PROT_WRITE,
        		    MAP_ANON|MAP_PRIVATE, 0, 0);
        	if (addr == MAP_FAILED)
        		perror("mmap "), exit(1);
    
        	fprintf(stderr, "pid = %d \n" "addr = %p\n", getpid(), addr);
    
        	/* make page populate */
        	memset(addr, 0, pagesize*3);
    
        	/* first mbind */
        	err = mbind(addr+pagesize, pagesize, MPOL_BIND, nmask->maskp,
        		    nmask->size, MPOL_MF_MOVE_ALL);
        	if (err)
        		error("mbind1 ");
    
        	/* second mbind */
        	err = mbind(addr, pagesize*3, MPOL_DEFAULT, NULL, 0, 0);
        	if (err)
        		error("mbind2 ");
    
        	sprintf(buf, "cat /proc/%d/maps", getpid());
        	system(buf);
    
        	return 0;
        }
        ----------------------------------------------------------------
    
    result without this patch
    
    	addr = 0x7fe26ef09000
    	[snip]
    	7fe26ef09000-7fe26ef0a000 rw-p 00000000 00:00 0
    	7fe26ef0a000-7fe26ef0b000 rw-p 00000000 00:00 0
    	7fe26ef0b000-7fe26ef0c000 rw-p 00000000 00:00 0
    	7fe26ef0c000-7fe26ef0d000 rw-p 00000000 00:00 0
    
    	=> 0x7fe26ef09000-0x7fe26ef0c000 have three vmas.
    
    result with this patch
    
    	addr = 0x7fc9ebc76000
    	[snip]
    	7fc9ebc76000-7fc9ebc7a000 rw-p 00000000 00:00 0
    	7fffbe690000-7fffbe6a5000 rw-p 00000000	00:00 0	[stack]
    
    	=> 0x7fc9ebc76000-0x7fc9ebc7a000 have only one vma.
    
    [minchan.kim@gmail.com: fix file offset passed to vma_merge()]
    Signed-off-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
    Reviewed-by: default avatarChristoph Lameter <cl@linux-foundation.org>
    Cc: Nick Piggin <nickpiggin@yahoo.com.au>
    Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
    Cc: Andrea Arcangeli <aarcange@redhat.com>
    Cc: Mel Gorman <mel@csn.ul.ie>
    Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
    Signed-off-by: default avatarMinchan Kim <minchan.kim@gmail.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    9d8cebd4