• K
    coredump_filter: add hugepage dumping · e575f111
    KOSAKI Motohiro 提交于
    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: NKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
    Reviewed-by: NKawai 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: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    e575f111
binfmt_elf.c 53.9 KB