Index: kern/disk.c =================================================================== --- kern/disk.c (revision 2021) +++ kern/disk.c (working copy) @@ -41,7 +41,8 @@ struct grub_disk_cache int lock; }; -static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; +static struct grub_disk_cache *grub_disk_cache_table = 0; +static int grub_disk_cache_num = 0; void (*grub_disk_firmware_fini) (void); int grub_disk_firmware_is_tainted; @@ -68,7 +69,7 @@ grub_disk_cache_get_index (unsigned long dev_id, u { return ((dev_id * 524287UL + disk_id * 2606459UL + ((unsigned) (sector >> GRUB_DISK_CACHE_BITS))) - % GRUB_DISK_CACHE_NUM); + % grub_disk_cache_num); } static void @@ -78,6 +79,9 @@ grub_disk_cache_invalidate (unsigned long dev_id, unsigned index; struct grub_disk_cache *cache; + if (!grub_disk_cache_table) + return; + sector &= ~(GRUB_DISK_CACHE_SIZE - 1); index = grub_disk_cache_get_index (dev_id, disk_id, sector); cache = grub_disk_cache_table + index; @@ -97,7 +101,10 @@ grub_disk_cache_invalidate_all (void) { unsigned i; - for (i = 0; i < GRUB_DISK_CACHE_NUM; i++) + if (!grub_disk_cache_table) + return; + + for (i = 0; i < grub_disk_cache_num; i++) { struct grub_disk_cache *cache = grub_disk_cache_table + i; @@ -116,6 +123,14 @@ grub_disk_cache_fetch (unsigned long dev_id, unsig struct grub_disk_cache *cache; unsigned index; + if (!grub_disk_cache_table) + { +#if 0 + grub_disk_cache_misses++; +#endif + return 0; + } + index = grub_disk_cache_get_index (dev_id, disk_id, sector); cache = grub_disk_cache_table + index; @@ -143,6 +158,9 @@ grub_disk_cache_unlock (unsigned long dev_id, unsi struct grub_disk_cache *cache; unsigned index; + if (!grub_disk_cache_table) + return ; + index = grub_disk_cache_get_index (dev_id, disk_id, sector); cache = grub_disk_cache_table + index; @@ -157,7 +175,24 @@ grub_disk_cache_store (unsigned long dev_id, unsig { unsigned index; struct grub_disk_cache *cache; - + + if (!grub_disk_cache_table) + { +#ifdef GRUB_UTIL + grub_disk_cache_num = GRUB_UTIL_CACHE_NUM; +#else + grub_disk_cache_num = grub_mm_get_free () / GRUB_DISK_CACHE_DIVIDE; +#endif + grub_disk_cache_table = (struct grub_disk_cache *) + grub_malloc (grub_disk_cache_num * sizeof (struct grub_disk_cache)); + grub_memset (grub_disk_cache_table, 0, + grub_disk_cache_num * sizeof (struct grub_disk_cache)); + } + + if (!grub_disk_cache_table) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "couldn't allocate space for cache index"); + grub_disk_cache_invalidate (dev_id, disk_id, sector); index = grub_disk_cache_get_index (dev_id, disk_id, sector); Index: kern/mm.c =================================================================== --- kern/mm.c (revision 2021) +++ kern/mm.c (working copy) @@ -449,6 +449,33 @@ grub_realloc (void *ptr, grub_size_t size) return q; } +grub_size_t +grub_mm_get_free (void) +{ + grub_mm_region_t r; + grub_size_t ret = 0; + + for (r = base; r; r = r->next) + { + grub_mm_header_t p; + + /* Follow the free list. */ + p = r->first; + do + { + if (p->magic != GRUB_MM_FREE_MAGIC) + grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic); + + ret += p->size << GRUB_MM_ALIGN_LOG2; + p = p->next; + } + while (p != r->first); + } + + return ret; +} + + #ifdef MM_DEBUG int grub_mm_debug = 0; Index: include/grub/disk.h =================================================================== --- include/grub/disk.h (revision 2021) +++ include/grub/disk.h (working copy) @@ -129,9 +129,14 @@ typedef struct grub_disk_memberlist *grub_disk_mem #define GRUB_DISK_SECTOR_SIZE 0x200 #define GRUB_DISK_SECTOR_BITS 9 -/* The maximum number of disk caches. */ -#define GRUB_DISK_CACHE_NUM 1021 +/* Allocate one cache entry per N bytes. + By default use up to one quarter of memory available for allocation */ +#define GRUB_DISK_CACHE_DIVIDE 16536 +/* On grub-util we can't know the available memory size and since host OS + already caches data we don't need a big cache*/ +#define GRUB_UTIL_CACHE_NUM 100 + /* The size of a disk cache in sector units. */ #define GRUB_DISK_CACHE_SIZE 8 #define GRUB_DISK_CACHE_BITS 3 Index: include/grub/mm.h =================================================================== --- include/grub/mm.h (revision 2021) +++ include/grub/mm.h (working copy) @@ -33,6 +33,7 @@ void *EXPORT_FUNC(grub_malloc) (grub_size_t size); void EXPORT_FUNC(grub_free) (void *ptr); void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size); void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size); +grub_size_t EXPORT_FUNC(grub_mm_get_free) (void); /* For debugging. */ #if defined(MM_DEBUG) && !defined(GRUB_UTIL) Index: ChangeLog =================================================================== --- ChangeLog (revision 2021) +++ ChangeLog (working copy) @@ -1,3 +1,17 @@ +2009-03-07 Vladimir Serbinenko + + Dynamic cache allocation + + * kern/disk.c (grub_disk_cache_table): changed declaration as pointer + instead of array. All users updated + * include/grub/disk.h (GRUB_DISK_CACHE_NUM): changed to ... + (grub_disk_cache_num): ... a variable. All users updated + * kern/disk.c (grub_disk_cache_store): allocate cache index + * kern/mm.c (grub_mm_get_free): new function + * include/grub/disk.h (GRUB_DISK_CACHE_DIVIDE): new declaration + (GRUB_UTIL_CACHE_NUM): likewise + * include/grub/mm.h (grub_mm_get_free): likewise + 2009-03-07 Bean * loader/i386/efi/linux.c (grub_rescue_cmd_initrd): Fix a bug in initrd