Commit afa9cb75 authored by Monty's avatar Monty

Fixed overrun in key cache if one tried to allocate a key cache

of more than 45G with a key_cache_block_size of 1024 or less.

The problem was that some of the arguments to my_multi_malloc() got to be
more than 4G.

Fix:
- Inntroduced my_multi_malloc_large() that can handle big regions.
- Changed MyISAM and Aria key caches to use my_multi_malloc_large().

I didn't change the default my_multi_malloc() as this would be a too big
patch and we don't allocate 4G blocks anywhere else.
parent 04037907
...@@ -168,6 +168,7 @@ extern void set_malloc_size_cb(MALLOC_SIZE_CB func); ...@@ -168,6 +168,7 @@ extern void set_malloc_size_cb(MALLOC_SIZE_CB func);
/* defines when allocating data */ /* defines when allocating data */
extern void *my_malloc(size_t Size,myf MyFlags); extern void *my_malloc(size_t Size,myf MyFlags);
extern void *my_multi_malloc(myf MyFlags, ...); extern void *my_multi_malloc(myf MyFlags, ...);
extern void *my_multi_malloc_large(myf MyFlags, ...);
extern void *my_realloc(void *oldpoint, size_t Size, myf MyFlags); extern void *my_realloc(void *oldpoint, size_t Size, myf MyFlags);
extern void my_free(void *ptr); extern void my_free(void *ptr);
extern void *my_memdup(const void *from,size_t length,myf MyFlags); extern void *my_memdup(const void *from,size_t length,myf MyFlags);
......
...@@ -552,16 +552,20 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -552,16 +552,20 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
Allocate memory for blocks, hash_links and hash entries; Allocate memory for blocks, hash_links and hash entries;
For each block 2 hash links are allocated For each block 2 hash links are allocated
*/ */
if (my_multi_malloc(MYF(MY_ZEROFILL), if (my_multi_malloc_large(MYF(MY_ZEROFILL),
&keycache->block_root, blocks * sizeof(BLOCK_LINK), &keycache->block_root,
(ulonglong) (blocks * sizeof(BLOCK_LINK)),
&keycache->hash_root, &keycache->hash_root,
sizeof(HASH_LINK*) * keycache->hash_entries, (ulonglong) (sizeof(HASH_LINK*) *
keycache->hash_entries),
&keycache->hash_link_root, &keycache->hash_link_root,
hash_links * sizeof(HASH_LINK), (ulonglong) (hash_links * sizeof(HASH_LINK)),
&keycache->changed_blocks, &keycache->changed_blocks,
sizeof(BLOCK_LINK*) * changed_blocks_hash_size, (ulonglong) (sizeof(BLOCK_LINK*) *
changed_blocks_hash_size),
&keycache->file_blocks, &keycache->file_blocks,
sizeof(BLOCK_LINK*) * changed_blocks_hash_size, (ulonglong) (sizeof(BLOCK_LINK*) *
changed_blocks_hash_size),
NullS)) NullS))
break; break;
my_large_free(keycache->block_mem); my_large_free(keycache->block_mem);
......
...@@ -62,3 +62,47 @@ void* my_multi_malloc(myf myFlags, ...) ...@@ -62,3 +62,47 @@ void* my_multi_malloc(myf myFlags, ...)
va_end(args); va_end(args);
DBUG_RETURN((void*) start); DBUG_RETURN((void*) start);
} }
/*
Same as my_multi_malloc, but each entry can be over 4G
SYNOPSIS
my_multi_malloc()
myFlags Flags
ptr1, length1 Multiple arguments terminated by null ptr
ptr2, length2 ...
...
NULL
*/
void *my_multi_malloc_large(myf myFlags, ...)
{
va_list args;
char **ptr,*start,*res;
size_t tot_length,length;
DBUG_ENTER("my_multi_malloc");
va_start(args,myFlags);
tot_length=0;
while ((ptr=va_arg(args, char **)))
{
length=va_arg(args,ulonglong);
tot_length+=ALIGN_SIZE(length);
}
va_end(args);
if (!(start=(char *) my_malloc(tot_length, myFlags)))
DBUG_RETURN(0); /* purecov: inspected */
va_start(args,myFlags);
res=start;
while ((ptr=va_arg(args, char **)))
{
*ptr=res;
length=va_arg(args,ulonglong);
res+=ALIGN_SIZE(length);
}
va_end(args);
DBUG_RETURN((void*) start);
}
...@@ -829,16 +829,22 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, ...@@ -829,16 +829,22 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem,
Allocate memory for blocks, hash_links and hash entries; Allocate memory for blocks, hash_links and hash entries;
For each block 2 hash links are allocated For each block 2 hash links are allocated
*/ */
if (my_multi_malloc(MYF(MY_ZEROFILL), if (my_multi_malloc_large(MYF(MY_ZEROFILL),
&pagecache->block_root, blocks * sizeof(PAGECACHE_BLOCK_LINK), &pagecache->block_root,
(ulonglong) (blocks *
sizeof(PAGECACHE_BLOCK_LINK)),
&pagecache->hash_root, &pagecache->hash_root,
sizeof(PAGECACHE_HASH_LINK*) * pagecache->hash_entries, (ulonglong) (sizeof(PAGECACHE_HASH_LINK*) *
pagecache->hash_entries),
&pagecache->hash_link_root, &pagecache->hash_link_root,
hash_links * sizeof(PAGECACHE_HASH_LINK), (ulonglong) (hash_links *
sizeof(PAGECACHE_HASH_LINK)),
&pagecache->changed_blocks, &pagecache->changed_blocks,
sizeof(PAGECACHE_BLOCK_LINK*) * changed_blocks_hash_size, (ulonglong) (sizeof(PAGECACHE_BLOCK_LINK*) *
changed_blocks_hash_size),
&pagecache->file_blocks, &pagecache->file_blocks,
sizeof(PAGECACHE_BLOCK_LINK*) * changed_blocks_hash_size, (ulonglong) (sizeof(PAGECACHE_BLOCK_LINK*) *
changed_blocks_hash_size),
NullS)) NullS))
break; break;
my_large_free(pagecache->block_mem); my_large_free(pagecache->block_mem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment