On Wed, Dec 13, 2006 at 06:12:17PM +0530, Sachin P. Sant wrote:
> Horms wrote:
> >>I will rediff them with all these patches applied and then send you the
> >>patches.
> >>    
> >
> >Ok, that sounds perfect.
> >
> >I have pushed my changes into kexec-tools-testing now,
> >that is all of them except the last one.
> >  
> kexec tools for ppc64 uses static arrays [of length MAX_MEMORY_RANGES]
> to store data related to memory regions. This used to eat up lot's of memory. 
> There were some instances where more memory regions existed, which made kexec 
> tools unusable on those machines. The following patch
> gets rid of MAX_MEMORY_RANGES macro and uses dynamic memory allocation
> for the above mentioned structures.
> 
> Please review.

Hi Sachin,

I took a quick look over this. And it seems to be fine.
I've put some minor comments inline.

> Thanks
> -Sachin
> 
> Signed-off-by : Sachin Sant <[EMAIL PROTECTED]>
> ---
> 
> 
> 
> 
> 

> * kexec tools for ppc64 uses static arrays [of length MAX_MEMORY_RANGES] to
> * store data related to memory regions. This used to eat up lot's of memory.
> * There were some instances where more memory regions existed, which made
> * kexec tools unusable on those machines. The following patch gets rid of
> * MAX_MEMORY_RANGES macro and uses dynamic memory allocation for the
> * above mentioned structures.
> 
> Signed-off-by : Sachin Sant <[EMAIL PROTECTED]>
> ---
> 
> diff -Naurp hormsgittree/kexec/arch/ppc64/crashdump-ppc64.c 
> hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/crashdump-ppc64.c
> --- hormsgittree/kexec/arch/ppc64/crashdump-ppc64.c   2006-12-05 
> 17:08:18.000000000 +0530
> +++ hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/crashdump-ppc64.c     
> 2006-12-13 11:35:23.000000000 +0530
> @@ -62,7 +62,10 @@ extern struct arch_options_t arch_option
>  /* Stores a sorted list of RAM memory ranges for which to create elf headers.
>   * A separate program header is created for backup region
>   */
> -static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
> +static struct memory_range *crash_memory_range;

I think that crash_memory_range needs to be initialised to NULL here.
Otherwise the err check in get_crash_memory_ranges() may be bogus.

> +/* Define a variable to replace the CRASH_MAX_MEMORY_RANGES macro */
> +static int crash_max_memory_ranges;
>  
>  /*
>   * Used to save various memory ranges/regions needed for the captured
> @@ -105,6 +108,15 @@ static int get_crash_memory_ranges(struc
>       int i, n;
>       unsigned long long start, end, cstart, cend;
>  
> +     crash_max_memory_ranges = max_memory_ranges + 6;
> +
> +     crash_memory_range = (struct memory_range *) malloc(
> +             (sizeof(struct memory_range) * (crash_max_memory_ranges)));
> +     if (crash_memory_range == NULL) {
> +             fprintf(stderr, "Memory allocation for crash memory range 
> failed\n");

Can you make this <= 80col wide? I think it is just a little over.

> +             return -1;
> +     }
> +
>       /* create a separate program header for the backup region */
>       crash_memory_range[0].start = BACKUP_SRC_START;
>       crash_memory_range[0].end = BACKUP_SRC_END;
> @@ -113,7 +125,7 @@ static int get_crash_memory_ranges(struc
>  
>       if ((dir = opendir(device_tree)) == NULL) {
>               perror(device_tree);
> -             return -1;
> +             goto err;
>       }
>       while ((dentry = readdir(dir)) != NULL) {
>               if (strncmp(dentry->d_name, "memory@", 7))
> @@ -123,7 +135,7 @@ static int get_crash_memory_ranges(struc
>               if ((dmem = opendir(fname)) == NULL) {
>                       perror(fname);
>                       closedir(dir);
> -                     return -1;
> +                     goto err;
>               }
>               while ((mentry = readdir(dmem)) != NULL) {
>                       if (strcmp(mentry->d_name, "reg"))
> @@ -133,21 +145,21 @@ static int get_crash_memory_ranges(struc
>                               perror(fname);
>                               closedir(dmem);
>                               closedir(dir);
> -                             return -1;
> +                             goto err;
>                       }
>                       if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
>                               perror(fname);
>                               fclose(file);
>                               closedir(dmem);
>                               closedir(dir);
> -                             return -1;
> +                             goto err;
>                       }
> -                     if (memory_ranges >= MAX_MEMORY_RANGES) {
> +                     if (memory_ranges >= max_memory_ranges) {
>                               /* No space to insert another element. */
>                               fprintf(stderr,
>                                       "Error: Number of crash memory ranges"
>                                       " excedeed the max limit\n");
> -                             return -1;
> +                             goto err;
>                       }
>  
>                       start = ((unsigned long long *)buf)[0];
> @@ -228,6 +240,11 @@ static int get_crash_memory_ranges(struc
>       }
>  #endif
>       return 0;
> +
> +err:
> +     if (crash_memory_range)
> +             free(crash_memory_range);
> +     return -1;
>  }
>  
>  /* Converts unsigned long to ascii string. */
> diff -Naurp hormsgittree/kexec/arch/ppc64/crashdump-ppc64.h 
> hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/crashdump-ppc64.h
> --- hormsgittree/kexec/arch/ppc64/crashdump-ppc64.h   2006-12-05 
> 17:08:18.000000000 +0530
> +++ hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/crashdump-ppc64.h     
> 2006-12-13 11:26:40.000000000 +0530
> @@ -13,8 +13,6 @@ void add_usable_mem_rgns(unsigned long l
>  #define __pa(x)         ((unsigned long)(x)-PAGE_OFFSET)
>  #define MAXMEM          (-KERNELBASE-VMALLOCBASE)
>  
> -#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 6)
> -
>  #define COMMAND_LINE_SIZE       512 /* from kernel */
>  /* Backup Region, First 64K of System RAM. */
>  #define BACKUP_SRC_START    0x0000
> diff -Naurp hormsgittree/kexec/arch/ppc64/fs2dt.c 
> hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/fs2dt.c
> --- hormsgittree/kexec/arch/ppc64/fs2dt.c     2006-12-13 11:23:25.000000000 
> +0530
> +++ hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/fs2dt.c       2006-12-13 
> 17:29:26.000000000 +0530
> @@ -36,6 +36,7 @@
>  #define NAMESPACE 16384              /* max bytes for property names */
>  #define TREEWORDS 65536              /* max 32 bit words for property values 
> */
>  #define MEMRESERVE 256               /* max number of reserved memory blocks 
> */
> +#define MAX_MEMORY_RANGES 1024
>  
>  static char pathname[MAXPATH], *pathstart;
>  static char propnames[NAMESPACE] = { 0 };
> diff -Naurp hormsgittree/kexec/arch/ppc64/kexec-ppc64.c 
> hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/kexec-ppc64.c
> --- hormsgittree/kexec/arch/ppc64/kexec-ppc64.c       2006-12-13 
> 11:25:48.000000000 +0530
> +++ hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/kexec-ppc64.c 2006-12-13 
> 11:29:24.000000000 +0530
> @@ -20,6 +20,7 @@
>  
>  #include <stddef.h>
>  #include <stdio.h>
> +#include <stdlib.h>
>  #include <errno.h>
>  #include <stdint.h>
>  #include <string.h>
> @@ -34,17 +35,83 @@
>  #include "crashdump-ppc64.h"
>  #include <arch/options.h>
>  
> -static struct exclude_range exclude_range[MAX_MEMORY_RANGES];
> +static struct exclude_range *exclude_range;
> +static struct memory_range *memory_range;
> +static struct memory_range *base_memory_range;

I think that memory_range, base_memory_range and exclude_range all
need to be initialised to NULL here. Otherwise the checks
in cleanup_memory_ranges() may be bogus.

>  static unsigned long long rmo_top;
> -static struct memory_range memory_range[MAX_MEMORY_RANGES];
> -static struct memory_range base_memory_range[MAX_MEMORY_RANGES];
>  unsigned long long memory_max = 0;
>  static int nr_memory_ranges, nr_exclude_ranges;
>  unsigned long long crash_base, crash_size;
>  unsigned int rtas_base, rtas_size;
> +int max_memory_ranges;
>  
>  static int sort_base_ranges();
>  
> +
> +static void cleanup_memory_ranges()
> +{
> +     if (memory_range)
> +             free(memory_range);
> +     if (base_memory_range)
> +             free(base_memory_range);
> +     if (exclude_range)
> +             free(exclude_range);
> +     if (usablemem_rgns.ranges)
> +             free(usablemem_rgns.ranges);
> +}

Should this function set any freed pointers to NULL ?

> +
> +/*
> + * Allocate memory for various data structures used to hold
> + * values of different memory ranges
> + */
> +static int alloc_memory_ranges()
> +{
> +     memory_range = (struct memory_range *) malloc(
> +             (sizeof(struct memory_range) * max_memory_ranges));
> +     base_memory_range = (struct memory_range *) malloc(
> +             (sizeof(struct memory_range) * max_memory_ranges));
> +     exclude_range = (struct exclude_range *) malloc(
> +             (sizeof(struct exclude_range) * max_memory_ranges));
> +     usablemem_rgns.ranges = (struct exclude_range *) malloc(
> +             (sizeof(struct exclude_range) * max_memory_ranges));
> +     if ((memory_range == NULL) ||
> +         (base_memory_range == NULL) ||
> +         (exclude_range == NULL) ||
> +         (usablemem_rgns.ranges == NULL)) {

I personally prefer the following
        if (!memory_range || !base_memory_range || !exclude_range ||
            !usablemem_rgns.ranges)

Actually, I really prefer doing the error check after each malloc(),
but thats just me.

> +             fprintf(stderr, "Memory allocation for memory range structure 
> failed\n");

Can you make this <= 80col wide? I think it is just a little over.

> +             cleanup_memory_ranges();
> +             return -1;
> +     }
> +
> +     return 0;
> +}
> +
> +/*
> + * Count the memory@ nodes under /proc/device-tree and populate the
> + * max_memory_ranges variable. This variable replaces MAX_MEMORY_RANGES
> + * macro used earlier.
> + */
> +static int count_memory_ranges()
> +{
> +     char device_tree[256] = "/proc/device-tree/";
> +     struct dirent *dentry;
> +     DIR *dir;
> +
> +     if ((dir = opendir(device_tree)) == NULL) {
> +             perror(device_tree);
> +             return -1;
> +     }
> +
> +     while ((dentry = readdir(dir)) != NULL) {
> +             if (strncmp(dentry->d_name, "memory@", 7))
> +                     continue;
> +             max_memory_ranges++;
> +     }
> +     closedir(dir);
> +
> +     return 0;
> +}
> +
>  /* Get base memory ranges */
>  static int get_base_ranges()
>  {
> @@ -88,7 +155,7 @@ static int get_base_ranges()
>                               closedir(dir);
>                               return -1;
>                       }
> -                     if (local_memory_ranges >= MAX_MEMORY_RANGES) {
> +                     if (local_memory_ranges >= max_memory_ranges) {
>                               fclose(file);
>                               break;
>                       }
> @@ -447,8 +514,10 @@ int setup_memory_ranges(unsigned long ke
>        * nodes. Build list of ranges to be excluded from valid memory
>        */
>  
> -     get_base_ranges();
> -     get_devtree_details(kexec_flags);
> +     if (get_base_ranges())
> +             goto out;
> +     if (get_devtree_details(kexec_flags))
> +             goto out;
>  
>       for (i = 0; i < nr_exclude_ranges; i++) {
>               /* If first exclude range does not start with 0, include the
> @@ -511,12 +580,21 @@ int setup_memory_ranges(unsigned long ke
>               fprintf(stderr, "setup_memory_ranges memory_range[%d] 
> start:%lx, end:%lx\n", k, memory_range[k].start, memory_range[k].end);
>  #endif
>       return 0;
> +
> +out:
> +     cleanup_memory_ranges();
> +     return -1;
>  }
>  
>  /* Return a list of valid memory ranges */
>  int get_memory_ranges(struct memory_range **range, int *ranges,
>                       unsigned long kexec_flags)
>  {
> +     if (count_memory_ranges())
> +             return -1;
> +     if (alloc_memory_ranges())
> +             return -1;
> +
>       setup_memory_ranges(kexec_flags);
>       *range = memory_range;
>       *ranges = nr_memory_ranges;
> diff -Naurp hormsgittree/kexec/arch/ppc64/kexec-ppc64.h 
> hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/kexec-ppc64.h
> --- hormsgittree/kexec/arch/ppc64/kexec-ppc64.h       2006-12-13 
> 11:25:48.000000000 +0530
> +++ hormsgittree-dyn-mem-alloc/kexec/arch/ppc64/kexec-ppc64.h 2006-12-13 
> 11:43:00.000000000 +0530
> @@ -1,8 +1,6 @@
>  #ifndef KEXEC_PPC64_H
>  #define KEXEC_PPC64_H
>  
> -#define MAX_MEMORY_RANGES 1024 /* TO FIX - needs to be dynamically set */
> -
>  #define MAXBYTES 128
>  #define MAX_LINE 160
>  #define CORE_TYPE_ELF32 1
> @@ -17,6 +15,8 @@ void elf_ppc64_usage(void);
>  void reserve(unsigned long long where, unsigned long long length);
>  
>  extern unsigned long initrd_base, initrd_size;
> +extern int max_memory_ranges;
> +
>  /* boot block version 2 as defined by the linux kernel */
>  struct bootblock {
>       unsigned magic,
> @@ -39,7 +39,9 @@ struct exclude_range {
>  
>  typedef struct mem_rgns {
>          unsigned int size;
> -        struct exclude_range ranges[MAX_MEMORY_RANGES];
> +        struct exclude_range *ranges;
>  } mem_rgns_t;

> +extern mem_rgns_t usablemem_rgns;

usablemem_rgns.ranges needs to be initialised to NULL somehow.
Perhaps you could just change the declaration (wherever that is)
to mem_rgns_t usablemem_rgns = { 0, NULL }; I think that would work.

> +
>  #endif /* KEXEC_PPC64_H */


-- 
Horms
  H: http://www.vergenet.net/~horms/
  W: http://www.valinux.co.jp/en/

_______________________________________________
fastboot mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/fastboot

Reply via email to