diff options
author | Sachin P. Sant <sachinp@in.ibm.com> | 2006-12-14 15:08:29 +0530 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2006-12-15 15:24:59 +0900 |
commit | bac7bfac708e63f9e974b742aad79e08e43f7cb5 (patch) | |
tree | e01c8bbea797d72b9d275b7fb1f9a4a848034c51 | |
parent | d4bd5d52f7d1e702c11a9e8070d74de2aaead7af (diff) |
Dynamic memory allocation : ppc64 kexec tools Cleanup
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 <sachinp@in.ibm.com>
Removed trailing whitespace
Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r-- | kexec/arch/ppc64/crashdump-ppc64.c | 33 | ||||
-rw-r--r-- | kexec/arch/ppc64/crashdump-ppc64.h | 2 | ||||
-rw-r--r-- | kexec/arch/ppc64/fs2dt.c | 1 | ||||
-rw-r--r-- | kexec/arch/ppc64/kexec-ppc64.c | 99 | ||||
-rw-r--r-- | kexec/arch/ppc64/kexec-ppc64.h | 8 |
5 files changed, 124 insertions, 19 deletions
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c index e84aee1..00740dc 100644 --- a/kexec/arch/ppc64/crashdump-ppc64.c +++ b/kexec/arch/ppc64/crashdump-ppc64.c @@ -62,13 +62,16 @@ extern struct arch_options_t arch_options; /* 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 = NULL; + +/* 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 * kernel to boot. (lime memmap= option in other archs) */ -mem_rgns_t usablemem_rgns = {0, }; +mem_rgns_t usablemem_rgns = {0, NULL}; /* * To store the memory size of the first kernel and this value will be @@ -105,6 +108,15 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges) 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) { + fprintf(stderr, "Allocation for crash memory range failed\n"); + 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(struct memory_range **range, int *ranges) 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(struct memory_range **range, int *ranges) 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(struct memory_range **range, int *ranges) 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(struct memory_range **range, int *ranges) } #endif return 0; + +err: + if (crash_memory_range) + free(crash_memory_range); + return -1; } /* Converts unsigned long to ascii string. */ diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h index 209f6da..db44df2 100644 --- a/kexec/arch/ppc64/crashdump-ppc64.h +++ b/kexec/arch/ppc64/crashdump-ppc64.h @@ -13,8 +13,6 @@ void add_usable_mem_rgns(unsigned long long base, unsigned long long size); #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 --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c index 7c07e19..61a3638 100644 --- a/kexec/arch/ppc64/fs2dt.c +++ b/kexec/arch/ppc64/fs2dt.c @@ -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 --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c index fdd5385..592a4d6 100644 --- a/kexec/arch/ppc64/kexec-ppc64.c +++ b/kexec/arch/ppc64/kexec-ppc64.c @@ -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,92 @@ #include "crashdump-ppc64.h" #include <arch/options.h> -static struct exclude_range exclude_range[MAX_MEMORY_RANGES]; +static struct exclude_range *exclude_range = NULL; +static struct memory_range *memory_range = NULL; +static struct memory_range *base_memory_range = NULL; 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); +} + +/* + * 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)); + if (!memory_range) + goto err1; + + base_memory_range = (struct memory_range *) malloc( + (sizeof(struct memory_range) * max_memory_ranges)); + if (!base_memory_range) + goto err1; + + exclude_range = (struct exclude_range *) malloc( + (sizeof(struct exclude_range) * max_memory_ranges)); + if (!exclude_range) + goto err1; + + usablemem_rgns.ranges = (struct exclude_range *) malloc( + (sizeof(struct exclude_range) * max_memory_ranges)); + if (!(usablemem_rgns.ranges)) + goto err1; + + return 0; + +err1: + fprintf(stderr, "memory range structure allocation failure\n"); + cleanup_memory_ranges(); + return -1; + +} + +/* + * 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 +164,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 +523,10 @@ int setup_memory_ranges(unsigned long kexec_flags) * 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 +589,21 @@ int setup_memory_ranges(unsigned long kexec_flags) 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 --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h index c74c95c..9776cb1 100644 --- a/kexec/arch/ppc64/kexec-ppc64.h +++ b/kexec/arch/ppc64/kexec-ppc64.h @@ -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; + #endif /* KEXEC_PPC64_H */ |