• KOSAKI Motohiro's avatar
    coredump_filter: add hugepage dumping · e575f111
    KOSAKI Motohiro authored
    Presently hugepage's vma has a VM_RESERVED flag in order not to be
    swapped.  But a VM_RESERVED vma isn't core dumped because this flag is
    often used for some kernel vmas (e.g.  vmalloc, sound related).
    
    Thus hugepages are never dumped and it can't be debugged easily.  Many
    developers want hugepages to be included into core-dump.
    
    However, We can't read generic VM_RESERVED area because this area is often
    IO mapping area.  then these area reading may change device state.  it is
    definitly undesiable side-effect.
    
    So adding a hugepage specific bit to the coredump filter is better.  It
    will be able to hugepage core dumping and doesn't cause any side-effect to
    any i/o devices.
    
    In additional, libhugetlb use hugetlb private mapping pages as anonymous
    page.  Then, hugepage private mapping pages should be core dumped by
    default.
    
    Then, /proc/[pid]/core_dump_filter has two new bits.
    
     - bit 5 mean hugetlb private mapping pages are dumped or not. (default: yes)
     - bit 6 mean hugetlb shared mapping pages are dumped or not.  (default: no)
    
    I tested by following method.
    
    % ulimit -c unlimited
    % ./crash_hugepage  50
    % ./crash_hugepage  50  -p
    % ls -lh
    % gdb ./crash_hugepage core
    %
    % echo 0x43 > /proc/self/coredump_filter
    % ./crash_hugepage  50
    % ./crash_hugepage  50  -p
    % ls -lh
    % gdb ./crash_hugepage core
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <string.h>
    
    #include "hugetlbfs.h"
    
    int main(int argc, char** argv){
    	char* p;
    	int ch;
    	int mmap_flags = MAP_SHARED;
    	int fd;
    	int nr_pages;
    
    	while((ch = getopt(argc, argv, "p")) != -1) {
    		switch (ch) {
    		case 'p':
    			mmap_flags &= ~MAP_SHARED;
    			mmap_flags |= MAP_PRIVATE;
    			break;
    		default:
    			/* nothing*/
    			break;
    		}
    	}
    	argc -= optind;
    	argv += optind;
    
    	if (argc == 0){
    		printf("need # of pages\n");
    		exit(1);
    	}
    
    	nr_pages = atoi(argv[0]);
    	if (nr_pages < 2) {
    		printf("nr_pages must >2\n");
    		exit(1);
    	}
    
    	fd = hugetlbfs_unlinked_fd();
    	p = mmap(NULL, nr_pages * gethugepagesize(),
    		 PROT_READ|PROT_WRITE, mmap_flags, fd, 0);
    
    	sleep(2);
    
    	*(p + gethugepagesize()) = 1; /* COW */
    	sleep(2);
    
    	/* crash! */
    	*(int*)0 = 1;
    
    	return 0;
    }
    Signed-off-by: default avatarKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
    Reviewed-by: default avatarKawai Hidehiro <hidehiro.kawai.ez@hitachi.com>
    Cc: Hugh Dickins <hugh@veritas.com>
    Cc: William Irwin <wli@holomorphy.com>
    Cc: Adam Litke <agl@us.ibm.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    e575f111
binfmt_elf.c 53.9 KB