summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2015-08-13 01:27:23 +0300
committerMonty <monty@mariadb.org>2015-08-13 01:27:23 +0300
commitafa9cb7519fcb73d546bba45d3baa7b157926084 (patch)
treee207ab7924f79ce56c822cf2f6b76f2ff9fe925a
parent0403790722e3941779ccea26e85fcd818e2320b5 (diff)
downloadmariadb-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.h1
-rw-r--r--mysys/mf_keycache.c26
-rw-r--r--mysys/mulalloc.c44
-rw-r--r--storage/maria/ma_pagecache.c28
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;