Skip to content
  • Hugh Dickins's avatar
    mm: use clear_page_mlock() in page_remove_rmap() · e6c509f8
    Hugh Dickins authored
    
    
    We had thought that pages could no longer get freed while still marked as
    mlocked; but Johannes Weiner posted this program to demonstrate that
    truncating an mlocked private file mapping containing COWed pages is still
    mishandled:
    
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    int main(void)
    {
    	char *map;
    	int fd;
    
    	system("grep mlockfreed /proc/vmstat");
    	fd = open("chigurh", O_CREAT|O_EXCL|O_RDWR);
    	unlink("chigurh");
    	ftruncate(fd, 4096);
    	map = mmap(NULL, 4096, PROT_WRITE, MAP_PRIVATE, fd, 0);
    	map[0] = 11;
    	mlock(map, sizeof(fd));
    	ftruncate(fd, 0);
    	close(fd);
    	munlock(map, sizeof(fd));
    	munmap(map, 4096);
    	system("grep mlockfreed /proc/vmstat");
    	return 0;
    }
    
    The anon COWed pages are not caught by truncation's clear_page_mlock() of
    the pagecache pages; but unmap_mapping_range() unmaps them, so we ought to
    look out for them there in page_remove_rmap().  Indeed, why should
    truncation or invalidation be doing the clear_page_mlock() when removing
    from pagecache?  mlock is a property of mapping in userspace, not a
    property of pagecache: an mlocked unmapped page is nonsensical.
    
    Reported-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
    Signed-off-by: default avatarHugh Dickins <hughd@google.com>
    Cc: Mel Gorman <mel@csn.ul.ie>
    Cc: Rik van Riel <riel@redhat.com>
    Cc: Michel Lespinasse <walken@google.com>
    Cc: Ying Han <yinghan@google.com>
    Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    e6c509f8