Forget to mention only x86-64 is processed in this patch.

On 06/11/14 at 08:39pm, Baoquan He wrote:
> User want to get a rough estimate of vmcore size, then they can decide
> how much storage space is reserved for vmcore dumping. This can help them
> to deploy their machines better, possibly hundreds of machines.
> 
> In this draft patch, a new configuration option is added,
>     "--vmcore-estimate"
> User can execute below command to get a dumped kcore. Since kcore is a
> elf file to map the whole memory of current kernel, it's  equal to the
> memory of crash kernel though it's not exact. Content of kcore is dynamic
> though /proc/vmcore is fixed once crash happened. But for vmcore size
> estimate, it is better enough.
> 
> sudo makedumpfile -E -d 31 --vmcore-estimate /proc/kcore /var/crash/kcore-dump
> 
> Questions:
> 1. Or we can get the dumpable page numbers only, then calculate the estimated
> vmcore size by a predifined factor if it's kdump compressed dumping. E.g if
> lzo dump, we assume the compression ratio is 45%, then the estimate size is
> equal to: (dumpable page numbers) * 4096* 45%.
> 
> This is easier but too rough, does anybody like this better compared with the
> real dumping implemented in this draft patch.
> 
> 2. If dump the /proc/kcore, there's still a bug I can't fixed. When elf dump,
> in function write_elf_header()  it will pre-calculate a num_loads_dumpfile 
> which
> is the number of program segment which will be dumped. However during dumping,
> the content of /proc/kcore is dynamic, the final num_loads_dumpfile may change
> when call write_elf_pages_cyclic/write_elf_pages(). This will cause the final
> dumped elf file has a bad file format. When you execute
> "readelf -a /var/crash/kcore-dump", you will be a little surprised.
> 
> 3. This is not a formal patch, if the final solution is decided, I will post a
> patch, maybe a patchset. If you have suggestions about the code or 
> implementation,
> please post your comment.
> 
> Signed-off-by: Baoquan He <[email protected]>
> ---
>  elf_info.c     | 136 ++++++++++++++++--
>  elf_info.h     |  17 +++
>  makedumpfile.c | 438 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++----
>  makedumpfile.h |   5 +
>  4 files changed, 560 insertions(+), 36 deletions(-)
> 
> diff --git a/elf_info.c b/elf_info.c
> index b277f69..1b05ad1 100644
> --- a/elf_info.c
> +++ b/elf_info.c
> @@ -36,16 +36,9 @@
>  
>  #define XEN_ELFNOTE_CRASH_INFO       (0x1000001)
>  
> -struct pt_load_segment {
> -     off_t                   file_offset;
> -     unsigned long long      phys_start;
> -     unsigned long long      phys_end;
> -     unsigned long long      virt_start;
> -     unsigned long long      virt_end;
> -};
>  
>  static int                   nr_cpus;             /* number of cpu */
> -static off_t                 max_file_offset;
> +off_t                        max_file_offset;
>  
>  /*
>   * File information about /proc/vmcore:
> @@ -60,9 +53,9 @@ static int                  flags_memory;
>  /*
>   * PT_LOAD information about /proc/vmcore:
>   */
> -static unsigned int          num_pt_loads;
> -static struct pt_load_segment        *pt_loads;
> -static off_t                 offset_pt_load_memory;
> +unsigned int         num_pt_loads;
> +struct pt_load_segment       *pt_loads;
> +off_t                        offset_pt_load_memory;
>  
>  /*
>   * PT_NOTE information about /proc/vmcore:
> @@ -395,7 +388,49 @@ get_pt_note_info(void)
>       return TRUE;
>  }
>  
> +#define UNINITIALIZED  ((ulong)(-1))
>  
> +#define SEEK_ERROR       (-1)
> +#define READ_ERROR       (-2)
> +int set_kcore_vmcoreinfo(uint64_t vmcoreinfo_addr, uint64_t vmcoreinfo_len)
> +{
> +     int i;
> +     ulong kvaddr;
> +     Elf64_Nhdr *note64;
> +     off_t offset;
> +     char note[MAX_SIZE_NHDR];
> +     int size_desc;
> +     off_t offset_desc;
> +
> +     offset = UNINITIALIZED;
> +     kvaddr = (ulong)vmcoreinfo_addr | PAGE_OFFSET;
> +
> +     for (i = 0; i < num_pt_loads; ++i) {
> +             struct pt_load_segment *p = &pt_loads[i];
> +             if ((kvaddr >= p->virt_start) && (kvaddr < p->virt_end)) {
> +                     offset = (off_t)(kvaddr - p->virt_start) +
> +                     (off_t)p->file_offset;
> +                     break;
> +             }
> +     }
> +
> +     if (offset == UNINITIALIZED)
> +             return SEEK_ERROR;
> +
> +        if (lseek(fd_memory, offset, SEEK_SET) != offset)
> +             perror("lseek");
> +
> +     if (read(fd_memory, note, MAX_SIZE_NHDR) != MAX_SIZE_NHDR)
> +             return READ_ERROR;
> +
> +     note64 = (Elf64_Nhdr *)note;
> +     size_desc   = note_descsz(note);
> +     offset_desc = offset + offset_note_desc(note);
> +
> +     set_vmcoreinfo(offset_desc, size_desc);
> +
> +     return 0;
> +}
>  /*
>   * External functions.
>   */
> @@ -681,6 +716,55 @@ get_elf32_ehdr(int fd, char *filename, Elf32_Ehdr *ehdr)
>       return TRUE;
>  }
>  
> +int
> +get_elf_loads(int fd, char *filename)
> +{
> +     int i, j, phnum, elf_format;
> +     Elf64_Phdr phdr;
> +
> +     /*
> +      * Check ELF64 or ELF32.
> +      */
> +     elf_format = check_elf_format(fd, filename, &phnum, &num_pt_loads);
> +     if (elf_format == ELF64)
> +             flags_memory |= MEMORY_ELF64;
> +     else if (elf_format != ELF32)
> +             return FALSE;
> +
> +     if (!num_pt_loads) {
> +             ERRMSG("Can't get the number of PT_LOAD.\n");
> +             return FALSE;
> +     }
> +
> +     /*
> +      * The below file information will be used as /proc/vmcore.
> +      */
> +     fd_memory   = fd;
> +     name_memory = filename;
> +
> +     pt_loads = calloc(sizeof(struct pt_load_segment), num_pt_loads);
> +     if (pt_loads == NULL) {
> +             ERRMSG("Can't allocate memory for the PT_LOAD. %s\n",
> +                 strerror(errno));
> +             return FALSE;
> +     }
> +     for (i = 0, j = 0; i < phnum; i++) {
> +             if (!get_phdr_memory(i, &phdr))
> +                     return FALSE;
> +
> +             if (phdr.p_type != PT_LOAD)
> +                     continue;
> +
> +             if (j >= num_pt_loads)
> +                     return FALSE;
> +             if(!dump_Elf_load(&phdr, j))
> +                     return FALSE;
> +             j++;
> +     }
> +
> +     return TRUE;
> +}
> +
>  /*
>   * Get ELF information about /proc/vmcore.
>   */
> @@ -826,6 +910,36 @@ get_phdr_memory(int index, Elf64_Phdr *phdr)
>       return TRUE;
>  }
>  
> +int
> +get_phdr_load(int index, Elf64_Phdr *phdr)
> +{
> +     Elf32_Phdr phdr32;
> +
> +     if (is_elf64_memory()) { /* ELF64 */
> +             phdr->p_type = PT_LOAD;
> +             phdr->p_vaddr = pt_loads[index].virt_start;
> +             phdr->p_paddr = pt_loads[index].phys_start;
> +             phdr->p_memsz  = pt_loads[index].phys_end - 
> pt_loads[index].phys_start;
> +             phdr->p_filesz = phdr->p_memsz;
> +             phdr->p_offset = pt_loads[index].file_offset;
> +     } else {
> +             if (!get_elf32_phdr(fd_memory, name_memory, index, &phdr32)) {
> +                     ERRMSG("Can't find Phdr %d.\n", index);
> +                     return FALSE;
> +             }
> +             memset(phdr, 0, sizeof(Elf64_Phdr));
> +             phdr->p_type   = phdr32.p_type;
> +             phdr->p_flags  = phdr32.p_flags;
> +             phdr->p_offset = phdr32.p_offset;
> +             phdr->p_vaddr  = phdr32.p_vaddr;
> +             phdr->p_paddr  = phdr32.p_paddr;
> +             phdr->p_filesz = phdr32.p_filesz;
> +             phdr->p_memsz  = phdr32.p_memsz;
> +             phdr->p_align  = phdr32.p_align;
> +     }
> +     return TRUE;
> +}
> +
>  off_t
>  get_offset_pt_load_memory(void)
>  {
> diff --git a/elf_info.h b/elf_info.h
> index 801faff..0c67d74 100644
> --- a/elf_info.h
> +++ b/elf_info.h
> @@ -27,6 +27,19 @@
>  
>  #define MAX_SIZE_NHDR        MAX(sizeof(Elf64_Nhdr), sizeof(Elf32_Nhdr))
>  
> +struct pt_load_segment {
> +     off_t                   file_offset;
> +     unsigned long long      phys_start;
> +     unsigned long long      phys_end;
> +     unsigned long long      virt_start;
> +     unsigned long long      virt_end;
> +};
> +
> +extern off_t                 max_file_offset;
> +extern unsigned int          num_pt_loads;
> +extern struct pt_load_segment        *pt_loads;
> +
> +extern off_t                 offset_pt_load_memory;
>  
>  off_t paddr_to_offset(unsigned long long paddr);
>  off_t paddr_to_offset2(unsigned long long paddr, off_t hint);
> @@ -44,11 +57,14 @@ int get_elf64_ehdr(int fd, char *filename, Elf64_Ehdr 
> *ehdr);
>  int get_elf32_ehdr(int fd, char *filename, Elf32_Ehdr *ehdr);
>  int get_elf_info(int fd, char *filename);
>  void free_elf_info(void);
> +int get_elf_loads(int fd, char *filename);
>  
>  int is_elf64_memory(void);
>  int is_xen_memory(void);
>  
>  int get_phnum_memory(void);
> +
> +int get_phdr_load(int index, Elf64_Phdr *phdr);
>  int get_phdr_memory(int index, Elf64_Phdr *phdr);
>  off_t get_offset_pt_load_memory(void);
>  int get_pt_load(int idx,
> @@ -68,6 +84,7 @@ void get_pt_note(off_t *offset, unsigned long *size);
>  int has_vmcoreinfo(void);
>  void set_vmcoreinfo(off_t offset, unsigned long size);
>  void get_vmcoreinfo(off_t *offset, unsigned long *size);
> +int set_kcore_vmcoreinfo(uint64_t vmcoreinfo_addr, uint64_t vmcoreinfo_len);
>  
>  int has_vmcoreinfo_xen(void);
>  void get_vmcoreinfo_xen(off_t *offset, unsigned long *size);
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 34db997..ac02747 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -5146,6 +5146,7 @@ create_dump_bitmap(void)
>  
>       if (info->flag_cyclic) {
>  
> +             printf("create_dump_bitmap flag_cyclic\n");
>               if (info->flag_elf_dumpfile) {
>                       if (!prepare_bitmap_buffer_cyclic())
>                               goto out;
> @@ -5189,14 +5190,23 @@ get_loads_dumpfile(void)
>  
>       initialize_2nd_bitmap(&bitmap2);
>  
> -     if (!(phnum = get_phnum_memory()))
> -             return FALSE;
> -
> -     for (i = 0; i < phnum; i++) {
> -             if (!get_phdr_memory(i, &load))
> +     if (info->flag_vmcore_estimate) {
> +             phnum = num_pt_loads;
> +     } else {
> +             if (!(phnum = get_phnum_memory()))
>                       return FALSE;
> -             if (load.p_type != PT_LOAD)
> -                     continue;
> +     }
> +
> +     for (i = 0; i < num_pt_loads; i++) {
> +             if (info->flag_vmcore_estimate) {
> +                     get_phdr_load(i , &load);
> +             } else {
> +                     if (!get_phdr_memory(i, &load))
> +                             return FALSE;
> +
> +                     if (load.p_type != PT_LOAD)
> +                             continue;
> +             }
>  
>               pfn_start = paddr_to_pfn(load.p_paddr);
>               pfn_end   = paddr_to_pfn(load.p_paddr + load.p_memsz);
> @@ -5734,17 +5744,26 @@ write_elf_pages(struct cache_data *cd_header, struct 
> cache_data *cd_page)
>       off_seg_load    = info->offset_load_dumpfile;
>       cd_page->offset = info->offset_load_dumpfile;
>  
> -     if (!(phnum = get_phnum_memory()))
> -             return FALSE;
> +     if (info->flag_vmcore_estimate) {
> +             phnum = num_pt_loads;
> +     } else { 
> +             if (!(phnum = get_phnum_memory()))
> +                     return FALSE;
> +     }
>  
>       gettimeofday(&tv_start, NULL);
>  
>       for (i = 0; i < phnum; i++) {
> -             if (!get_phdr_memory(i, &load))
> -                     return FALSE;
> +             if (info->flag_vmcore_estimate) {
> +                     memset(&load, 0, sizeof(load));
> +                     get_phdr_load(i , &load);
> +             } else {
> +                     if (!get_phdr_memory(i, &load))
> +                             return FALSE;
>  
> -             if (load.p_type != PT_LOAD)
> -                     continue;
> +                     if (load.p_type != PT_LOAD)
> +                             continue;
> +             }
>  
>               off_memory= load.p_offset;
>               paddr     = load.p_paddr;
> @@ -5923,14 +5942,24 @@ get_loads_dumpfile_cyclic(void)
>       Elf64_Phdr load;
>       struct cycle cycle = {0};
>  
> -     if (!(phnum = get_phnum_memory()))
> -             return FALSE;
> +     if (info->flag_vmcore_estimate) {
> +             phnum = num_pt_loads;
> +     } else {
> +             if (!(phnum = get_phnum_memory()))
> +                     return FALSE;
> +     }
>  
>       for (i = 0; i < phnum; i++) {
> -             if (!get_phdr_memory(i, &load))
> -                     return FALSE;
> -             if (load.p_type != PT_LOAD)
> -                     continue;
> +             if (info->flag_vmcore_estimate) {
> +                     memset(&load, 0, sizeof(load) );
> +                     get_phdr_load(i , &load);
> +             } else {
> +                     if (!get_phdr_memory(i, &load))
> +                             return FALSE;
> +
> +                     if (load.p_type != PT_LOAD)
> +                             continue;
> +             }
>  
>               pfn_start = paddr_to_pfn(load.p_paddr);
>               pfn_end = paddr_to_pfn(load.p_paddr + load.p_memsz);
> @@ -6016,17 +6045,26 @@ write_elf_pages_cyclic(struct cache_data *cd_header, 
> struct cache_data *cd_page)
>       pfn_user = pfn_free = pfn_hwpoison = 0;
>       pfn_memhole = info->max_mapnr;
>  
> -     if (!(phnum = get_phnum_memory()))
> -             return FALSE;
> +     if (info->flag_vmcore_estimate) {
> +             phnum = num_pt_loads;
> +     } else { 
> +             if (!(phnum = get_phnum_memory()))
> +                     return FALSE;
> +     }
>  
>       gettimeofday(&tv_start, NULL);
>  
>       for (i = 0; i < phnum; i++) {
> -             if (!get_phdr_memory(i, &load))
> -                     return FALSE;
> +             if (info->flag_vmcore_estimate) {
> +                     memset(&load, 0, sizeof(load));
> +                     get_phdr_load(i , &load);
> +             } else {
> +                     if (!get_phdr_memory(i, &load))
> +                             return FALSE;
>  
> -             if (load.p_type != PT_LOAD)
> -                     continue;
> +                     if (load.p_type != PT_LOAD)
> +                             continue;
> +             }
>  
>               off_memory= load.p_offset;
>               paddr = load.p_paddr;
> @@ -8929,6 +8967,13 @@ check_param_for_creating_dumpfile(int argc, char 
> *argv[])
>                */
>               info->name_memory   = argv[optind];
>  
> +     } else if ((argc == optind + 2) && info->flag_vmcore_estimate) {
> +             /*
> +              * Parameters for get the /proc/kcore to estimate
> +              * the size of dumped vmcore
> +              */
> +             info->name_memory   = argv[optind];
> +             info->name_dumpfile = argv[optind+1];
>       } else
>               return FALSE;
>  
> @@ -9011,6 +9056,332 @@ out:
>       return free_size;
>  }
>  
> +struct memory_range {
> +        unsigned long long start, end;
> +};
> +
> +#define CRASH_RESERVED_MEM_NR   8
> +static struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR];
> +static int crash_reserved_mem_nr;
> +
> +/*
> + * iomem_for_each_line()
> + *
> + * Iterate over each line in the file returned by proc_iomem(). If match is
> + * NULL or if the line matches with our match-pattern then call the
> + * callback if non-NULL.
> + *
> + * Return the number of lines matched.
> + */
> +int iomem_for_each_line(char *match,
> +                           int (*callback)(void *data,
> +                                           int nr,
> +                                           char *str,
> +                                           unsigned long base,
> +                                           unsigned long length),
> +                           void *data)
> +{
> +     const char iomem[] = "/proc/iomem";
> +     char line[MAX_LINE];
> +     FILE *fp;
> +     unsigned long long start, end, size;
> +     char *str;
> +     int consumed;
> +     int count;
> +     int nr = 0;
> +
> +     fp = fopen(iomem, "r");
> +     if (!fp) {
> +             ERRMSG("Cannot open %s\n", iomem);
> +             exit(1);
> +     }
> +
> +     while(fgets(line, sizeof(line), fp) != 0) {
> +             count = sscanf(line, "%Lx-%Lx : %n", &start, &end, &consumed);
> +             if (count != 2)
> +                     continue;
> +             str = line + consumed;
> +             size = end - start + 1;
> +             if (!match || memcmp(str, match, strlen(match)) == 0) {
> +                     if (callback
> +                         && callback(data, nr, str, start, size) < 0) {
> +                             break;
> +                     }
> +                     nr++;
> +             }
> +     }
> +
> +     fclose(fp);
> +
> +     return nr;
> +}
> +
> +static int crashkernel_mem_callback(void *data, int nr,
> +                                          char *str,
> +                                          unsigned long base,
> +                                          unsigned long length)
> +{
> +        if (nr >= CRASH_RESERVED_MEM_NR)
> +                return 1;
> +
> +        crash_reserved_mem[nr].start = base;
> +        crash_reserved_mem[nr].end   = base + length - 1;
> +        return 0;
> +}
> +
> +int is_crashkernel_mem_reserved(void)
> +{
> +        int ret;
> +
> +        ret = iomem_for_each_line("Crash kernel\n",
> +                                        crashkernel_mem_callback, NULL);
> +        crash_reserved_mem_nr = ret;
> +
> +        return !!crash_reserved_mem_nr;
> +}
> +
> +/* Returns the physical address of start of crash notes buffer for a kernel. 
> */
> +static int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len)
> +{
> +     char line[MAX_LINE];
> +     int count;
> +     FILE *fp;
> +     unsigned long long temp, temp2;
> +
> +     *addr = 0;
> +     *len = 0;
> +
> +     if (!(fp = fopen("/sys/kernel/vmcoreinfo", "r")))
> +             return -1;
> +
> +     if (!fgets(line, sizeof(line), fp))
> +             ERRMSG("Cannot parse %s: %s\n", "/sys/kernel/vmcoreinfo", 
> strerror(errno));
> +     count = sscanf(line, "%Lx %Lx", &temp, &temp2);
> +     if (count != 2)
> +             ERRMSG("Cannot parse %s: %s\n", "/sys/kernel/vmcoreinfo", 
> strerror(errno));
> +
> +     *addr = (uint64_t) temp;
> +     *len = (uint64_t) temp2;
> +
> +     fclose(fp);
> +     return 0;
> +}
> +
> +
> +static int exclude_segment(struct pt_load_segment **pt_loads, unsigned int   
> *num_pt_loads, uint64_t start, uint64_t end)
> +{
> +        int i, j, tidx = -1;
> +     unsigned long long      vstart, vend, kvstart, kvend;
> +        struct pt_load_segment temp_seg = {0};
> +     kvstart = (ulong)start | PAGE_OFFSET;
> +     kvend = (ulong)end | PAGE_OFFSET;
> +     unsigned long size;
> +
> +        for (i = 0; i < (*num_pt_loads); i++) {
> +                vstart = (*pt_loads)[i].virt_start;
> +                vend = (*pt_loads)[i].virt_end;
> +                if (kvstart <  vend && kvend > vstart) {
> +                        if (kvstart != vstart && kvend != vend) {
> +                             /* Split load segment */
> +                             temp_seg.phys_start = end +1;
> +                             temp_seg.phys_end = (*pt_loads)[i].phys_end;
> +                             temp_seg.virt_start = kvend + 1;
> +                             temp_seg.virt_end = vend;
> +                             temp_seg.file_offset = 
> (*pt_loads)[i].file_offset + temp_seg.virt_start - (*pt_loads)[i].virt_start;
> +
> +                             (*pt_loads)[i].virt_end = kvstart - 1;
> +                             (*pt_loads)[i].phys_end =  start -1;
> +
> +                             tidx = i+1;
> +                        } else if (kvstart != vstart) {
> +                             (*pt_loads)[i].phys_end = start - 1;
> +                             (*pt_loads)[i].virt_end = kvstart - 1;
> +                        } else {
> +                             (*pt_loads)[i].phys_start = end + 1;
> +                             (*pt_loads)[i].virt_start = kvend + 1;
> +                        }
> +                }
> +        }
> +        /* Insert split load segment, if any. */
> +     if (tidx >= 0) {
> +             size = (*num_pt_loads + 1) * sizeof((*pt_loads)[0]);
> +             (*pt_loads) = realloc((*pt_loads), size);
> +             if  (!(*pt_loads) ) {
> +                 ERRMSG("Cannot realloc %ld bytes: %s\n",
> +                         size + 0UL, strerror(errno));
> +                     exit(1);
> +             }
> +             for (j = (*num_pt_loads - 1); j >= tidx; j--)
> +                     (*pt_loads)[j+1] = (*pt_loads)[j];
> +             (*pt_loads)[tidx] = temp_seg;
> +             (*num_pt_loads)++;
> +        }
> +        return 0;
> +}
> +
> +static int
> +process_dump_load(struct pt_load_segment     *pls)
> +{
> +     unsigned long long paddr;
> +
> +     paddr = vaddr_to_paddr(pls->virt_start);
> +     pls->phys_start  = paddr;
> +     pls->phys_end    = paddr + (pls->virt_end - pls->virt_start);
> +     MSG("process_dump_load\n");
> +     MSG("  phys_start : %llx\n", pls->phys_start);
> +     MSG("  phys_end   : %llx\n", pls->phys_end);
> +     MSG("  virt_start : %llx\n", pls->virt_start);
> +     MSG("  virt_end   : %llx\n", pls->virt_end);
> +
> +     return TRUE;
> +}
> +
> +int get_kcore_dump_loads()
> +{
> +     struct pt_load_segment  *pls;
> +     int i, j, loads=0;
> +     unsigned long long paddr;
> +
> +     for (i = 0; i < num_pt_loads; ++i) {
> +             struct pt_load_segment *p = &pt_loads[i];
> +             if (is_vmalloc_addr(p->virt_start))
> +                     continue;
> +             loads++;
> +     }
> +
> +     pls = calloc(sizeof(struct pt_load_segment), j);
> +     if (pls == NULL) {
> +             ERRMSG("Can't allocate memory for the PT_LOAD. %s\n",
> +                 strerror(errno));
> +             return FALSE;
> +     }
> +
> +     for (i = 0, j=0; i < num_pt_loads; ++i) {
> +             struct pt_load_segment *p = &pt_loads[i];
> +             if (is_vmalloc_addr(p->virt_start))
> +                     continue;
> +             if (j >= loads)
> +                     return FALSE;
> +
> +             if (j == 0) {
> +                     offset_pt_load_memory = p->file_offset;
> +                     if (offset_pt_load_memory == 0) {
> +                             ERRMSG("Can't get the offset of page data.\n");
> +                             return FALSE;
> +                     }
> +             }
> +
> +             pls[j] = *p;
> +             process_dump_load(&pls[j]);
> +             j++;
> +     }
> +
> +     free(pt_loads);
> +     pt_loads = pls;
> +     num_pt_loads = loads;
> +
> +     for (i=0; i<crash_reserved_mem_nr; i++)
> +     {
> +             exclude_segment(&pt_loads, &num_pt_loads, 
> crash_reserved_mem[i].start, crash_reserved_mem[i].end);
> +     }
> +
> +     max_file_offset = 0;
> +     for (i = 0; i < num_pt_loads; ++i) {
> +             struct pt_load_segment *p = &pt_loads[i];
> +             max_file_offset = MAX(max_file_offset,
> +                                   p->file_offset + p->phys_end - 
> p->phys_start);
> +     }
> +
> +     for (i = 0; i < num_pt_loads; ++i) {
> +             struct pt_load_segment *p = &pt_loads[i];
> +             MSG("LOAD (%d)\n", i);
> +             MSG("  phys_start : %llx\n", p->phys_start);
> +             MSG("  phys_end   : %llx\n", p->phys_end);
> +             MSG("  virt_start : %llx\n", p->virt_start);
> +             MSG("  virt_end   : %llx\n", p->virt_end);
> +     }
> +
> +     return TRUE;
> +}
> +
> +int get_page_offset()
> +{
> +     struct utsname utsname;
> +     if (uname(&utsname)) {
> +             ERRMSG("Cannot get name and information about current kernel : 
> %s", strerror(errno));
> +             return FALSE;
> +     }
> +
> +     info->kernel_version = get_kernel_version(utsname.release);
> +     get_versiondep_info_x86_64();
> +     return TRUE;
> +}
> +
> +int vmcore_estimate(void)
> +{
> +     uint64_t vmcoreinfo_addr, vmcoreinfo_len;
> +     int num_retry, status;
> +
> +     if (!is_crashkernel_mem_reserved()) {
> +             ERRMSG("No memory is reserved for crashkenrel!\n");
> +             exit(1);
> +     }
> +
> +     get_page_offset();
> +
> +#if 1
> +     if (!open_dump_memory())
> +             return FALSE;
> +#endif
> +
> +     if (info->flag_vmcore_estimate) {
> +             if (!get_elf_loads(info->fd_memory, info->name_memory))
> +                     return FALSE;
> +     }
> +
> +     if (get_kernel_vmcoreinfo(&vmcoreinfo_addr, &vmcoreinfo_len))
> +             return FALSE;
> +
> +     if (set_kcore_vmcoreinfo(vmcoreinfo_addr, vmcoreinfo_len))
> +             return FALSE;
> +
> +     if (!get_kcore_dump_loads())
> +             return FALSE;
> +
> +#if 1
> +     if (!initial())
> +             return FALSE;
> +#endif
> +
> +retry:
> +     if (!create_dump_bitmap())
> +             return FALSE;
> +
> +     if ((status = writeout_dumpfile()) == FALSE)
> +             return FALSE;
> +
> +     if (status == NOSPACE) {
> +             /*
> +              * If specifying the other dump_level, makedumpfile tries
> +              * to create a dumpfile with it again.
> +              */
> +             num_retry++;
> +             if ((info->dump_level = get_next_dump_level(num_retry)) < 0)
> +                     return FALSE;
> +             MSG("Retry to create a dumpfile by dump_level(%d).\n",
> +                 info->dump_level);
> +             if (!delete_dumpfile())
> +                     return FALSE;
> +             goto retry;
> +     }
> +     print_report();
> +
> +     clear_filter_info();
> +     if (!close_files_for_creating_dumpfile())
> +             return FALSE;
> +
> +     return TRUE;
> +}
>  
>  /*
>   * Choose the lesser value of the two below as the size of cyclic buffer.
> @@ -9063,6 +9434,7 @@ static struct option longopts[] = {
>       {"cyclic-buffer", required_argument, NULL, OPT_CYCLIC_BUFFER},
>       {"eppic", required_argument, NULL, OPT_EPPIC},
>       {"non-mmap", no_argument, NULL, OPT_NON_MMAP},
> +     {"vmcore-estimate", no_argument, NULL, OPT_VMCORE_ESTIMATE},
>       {0, 0, 0, 0}
>  };
>  
> @@ -9154,6 +9526,9 @@ main(int argc, char *argv[])
>               case OPT_DUMP_DMESG:
>                       info->flag_dmesg = 1;
>                       break;
> +             case OPT_VMCORE_ESTIMATE:
> +                     info->flag_vmcore_estimate = 1;
> +                     break;
>               case OPT_COMPRESS_SNAPPY:
>                       info->flag_compress = DUMP_DH_COMPRESSED_SNAPPY;
>                       break;
> @@ -9294,6 +9669,19 @@ main(int argc, char *argv[])
>  
>               MSG("\n");
>               MSG("The dmesg log is saved to %s.\n", info->name_dumpfile);
> +     } else if (info->flag_vmcore_estimate) {
> +#if 1
> +             if (!check_param_for_creating_dumpfile(argc, argv)) {
> +                     MSG("Commandline parameter is invalid.\n");
> +                     MSG("Try `makedumpfile --help' for more 
> information.\n");
> +                     goto out;
> +             }
> +#endif
> +             if (!vmcore_estimate())
> +                     goto out;
> +
> +             MSG("\n");
> +             MSG("vmcore size estimate successfully.\n");
>       } else {
>               if (!check_param_for_creating_dumpfile(argc, argv)) {
>                       MSG("Commandline parameter is invalid.\n");
> diff --git a/makedumpfile.h b/makedumpfile.h
> index 9402f05..c401337 100644
> --- a/makedumpfile.h
> +++ b/makedumpfile.h
> @@ -216,6 +216,9 @@ isAnon(unsigned long mapping)
>  #define FILENAME_STDOUT              "STDOUT"
>  #define MAP_REGION           (4096*1024)
>  
> +#define MAX_LINE     160
> +
> +
>  /*
>   * Minimam vmcore has 2 ProgramHeaderTables(PT_NOTE and PT_LOAD).
>   */
> @@ -910,6 +913,7 @@ struct DumpInfo {
>       int             flag_force;          /* overwrite existing stuff */
>       int             flag_exclude_xen_dom;/* exclude Domain-U from xen-kdump 
> */
>       int             flag_dmesg;          /* dump the dmesg log out of the 
> vmcore file */
> +     int             flag_vmcore_estimate;          /* estimate the size  of 
> vmcore in current system */
>       int             flag_use_printk_log; /* did we read printk_log symbol 
> name? */
>       int             flag_nospace;        /* the flag of "No space on 
> device" error */
>       int             flag_vmemmap;        /* kernel supports vmemmap address 
> space */
> @@ -1764,6 +1768,7 @@ struct elf_prstatus {
>  #define OPT_CYCLIC_BUFFER       OPT_START+11
>  #define OPT_EPPIC               OPT_START+12
>  #define OPT_NON_MMAP            OPT_START+13
> +#define OPT_VMCORE_ESTIMATE            OPT_START+14
>  
>  /*
>   * Function Prototype.
> -- 
> 1.8.5.3
> 
> 
> _______________________________________________
> kexec mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to