diff options
author | Monty <monty@mariadb.org> | 2015-08-13 01:27:23 +0300 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2015-08-13 01:27:23 +0300 |
commit | afa9cb7519fcb73d546bba45d3baa7b157926084 (patch) | |
tree | e207ab7924f79ce56c822cf2f6b76f2ff9fe925a | |
parent | 0403790722e3941779ccea26e85fcd818e2320b5 (diff) | |
download | mariadb-git-afa9cb7519fcb73d546bba45d3baa7b157926084.tar.gz |
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.
-rw-r--r-- | include/my_sys.h | 1 | ||||
-rw-r--r-- | mysys/mf_keycache.c | 26 | ||||
-rw-r--r-- | mysys/mulalloc.c | 44 | ||||
-rw-r--r-- | storage/maria/ma_pagecache.c | 28 |
4 files changed, 77 insertions, 22 deletions
diff --git a/include/my_sys.h b/include/my_sys.h index 9913ee8c79b..741116a1dd5 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -168,6 +168,7 @@ extern void set_malloc_size_cb(MALLOC_SIZE_CB func); /* defines when allocating data */ extern void *my_malloc(size_t Size,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_free(void *ptr); extern void *my_memdup(const void *from,size_t length,myf MyFlags); diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 0faba93c0a3..16ac749fa09 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -552,17 +552,21 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, Allocate memory for blocks, hash_links and hash entries; For each block 2 hash links are allocated */ - if (my_multi_malloc(MYF(MY_ZEROFILL), - &keycache->block_root, blocks * sizeof(BLOCK_LINK), - &keycache->hash_root, - sizeof(HASH_LINK*) * keycache->hash_entries, - &keycache->hash_link_root, - hash_links * sizeof(HASH_LINK), - &keycache->changed_blocks, - sizeof(BLOCK_LINK*) * changed_blocks_hash_size, - &keycache->file_blocks, - sizeof(BLOCK_LINK*) * changed_blocks_hash_size, - NullS)) + if (my_multi_malloc_large(MYF(MY_ZEROFILL), + &keycache->block_root, + (ulonglong) (blocks * sizeof(BLOCK_LINK)), + &keycache->hash_root, + (ulonglong) (sizeof(HASH_LINK*) * + keycache->hash_entries), + &keycache->hash_link_root, + (ulonglong) (hash_links * sizeof(HASH_LINK)), + &keycache->changed_blocks, + (ulonglong) (sizeof(BLOCK_LINK*) * + changed_blocks_hash_size), + &keycache->file_blocks, + (ulonglong) (sizeof(BLOCK_LINK*) * + changed_blocks_hash_size), + NullS)) break; my_large_free(keycache->block_mem); keycache->block_mem= 0; diff --git a/mysys/mulalloc.c b/mysys/mulalloc.c index 9384ed744ad..fceecdc1dc7 100644 --- a/mysys/mulalloc.c +++ b/mysys/mulalloc.c @@ -62,3 +62,47 @@ void* my_multi_malloc(myf myFlags, ...) va_end(args); 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); +} diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index ac66fdf6c57..b2b39598eab 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -829,17 +829,23 @@ ulong init_pagecache(PAGECACHE *pagecache, size_t use_mem, Allocate memory for blocks, hash_links and hash entries; For each block 2 hash links are allocated */ - if (my_multi_malloc(MYF(MY_ZEROFILL), - &pagecache->block_root, blocks * sizeof(PAGECACHE_BLOCK_LINK), - &pagecache->hash_root, - sizeof(PAGECACHE_HASH_LINK*) * pagecache->hash_entries, - &pagecache->hash_link_root, - hash_links * sizeof(PAGECACHE_HASH_LINK), - &pagecache->changed_blocks, - sizeof(PAGECACHE_BLOCK_LINK*) * changed_blocks_hash_size, - &pagecache->file_blocks, - sizeof(PAGECACHE_BLOCK_LINK*) * changed_blocks_hash_size, - NullS)) + if (my_multi_malloc_large(MYF(MY_ZEROFILL), + &pagecache->block_root, + (ulonglong) (blocks * + sizeof(PAGECACHE_BLOCK_LINK)), + &pagecache->hash_root, + (ulonglong) (sizeof(PAGECACHE_HASH_LINK*) * + pagecache->hash_entries), + &pagecache->hash_link_root, + (ulonglong) (hash_links * + sizeof(PAGECACHE_HASH_LINK)), + &pagecache->changed_blocks, + (ulonglong) (sizeof(PAGECACHE_BLOCK_LINK*) * + changed_blocks_hash_size), + &pagecache->file_blocks, + (ulonglong) (sizeof(PAGECACHE_BLOCK_LINK*) * + changed_blocks_hash_size), + NullS)) break; my_large_free(pagecache->block_mem); pagecache->block_mem= 0; |