-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
MDEV-10814: hartmut coredump exclusions (10.1) #333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
03ef7b4
7fdbcca
8cb2014
7761699
55cf83c
a7a20db
a51a801
8a8181b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| Exclude things from core dumps (on Linux) | ||
| ========================================= | ||
|
|
||
| Movitation | ||
| ---------- | ||
|
|
||
| There are two reasons for wanting to reduce core dump size by excluding | ||
| certain memory areas from it: | ||
|
|
||
| 1. Reduce IO bandwidth and storage space requirements when dumping core | ||
|
|
||
| This reduces the time it takes to take a core dump and also makes | ||
| transfering core files easier. | ||
|
|
||
| 2. Exclude sensitive data from core dumps | ||
|
|
||
| At the same time backtrace information should remain complete and memory | ||
| regions that may be useful when doing post mortem debugging should be kept. | ||
|
|
||
| Original motivation for implementation was that very large InnoDB instances | ||
| on machines with >300GB RAM, and accordingly large innodb buffer pool, were | ||
| crashing randomly every few days, and enabling core dumps on all of them was | ||
| not an option. Also, even after we finally managed to get hold of a core | ||
| dump the file size made it very hard to get it to an environment where it | ||
| could be analyzed without causng resource issues. | ||
|
|
||
| Implementation | ||
| -------------- | ||
|
|
||
| Linux supports options to madvise(2) that control whether a certain region | ||
| should be included in core dumps (MADV_DODUMP) or should be excluded | ||
| (MADV_DONTDUMP) starting with kernel version. Such memory regions need to | ||
| be page aligned so out of the box the feature is only useful when dealing | ||
| with large enough malloc() allocations or when directly dealing with | ||
| mmap()ed or shared memory regions directly. | ||
|
|
||
| Certain memory allocations now call the new function | ||
|
|
||
| exclude_from_coredump(void *ptr, size_t size, ulonglong flagmask); | ||
|
|
||
| after successfully aquiring memory. A global variable "core_nodump" | ||
| may contain a set of memory regions to exclude. If the given flagmask | ||
| matches any of these, or if "core_nodump" has the 'magic' value "MAX", | ||
| the given memory region is marked to be excluded from core dumps using | ||
| the MADV_DONTDUMP advice. | ||
|
|
||
| So far there's only support for excluding static buffers that stay for | ||
| the entire life time of the server process. Support for memory regions | ||
| allocated on demand, like those for temporary tables or sort buffers, | ||
| or that may be resized dynamically, like the query cache, is possible | ||
| but tricky as on freeing memory regions the MADV_DONTDUMP advice has to | ||
| be removed by an explicit MADV_DODUMP madvise() for the same region. | ||
| Otherwise other later memory allocations that happen to reuse fall in | ||
| the previously excluded memory range would accidentially be excluded | ||
| from being dumped. So at the time memory is freed it is also necessary | ||
| to remove the DONTDUMP advise, and for that not only the base address | ||
| is needed but also the original allocation size. As this is not always | ||
| explicitly preserved dynamic buffers have been excluded for this first | ||
| implementation. | ||
|
|
||
|
|
||
| Configuration | ||
| ------------- | ||
|
|
||
| A new configuration variable "core_nodump" has been added that controls | ||
| which buffer types should be excluded from core dump. The variable | ||
| can't be changed dynamically at run time as exclusions happen right | ||
| after allocating memory at startup. | ||
|
|
||
| Possible values for "core_nodump" at this point are: | ||
|
|
||
| Value | Description | ||
| --------------------|------------------------------------------------------ | ||
| NONE | Default: keep current behavior that dumps everything | ||
| INNODB_POOL_BUFFER | Exclude InnoDB pool buffer instances from core dump | ||
| MYISAM_KEY_BUFFER | Exclude MyISAM key buffer(s) from core dump | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MYISAM_KEY_BUFFER is not available, why? |
||
| MAX | Apply all possible exclusion | ||
|
|
||
|
|
||
| Testing | ||
| ------- | ||
|
|
||
| A mysqld with the following minimalistic configuration | ||
|
|
||
| [mysqld] | ||
| innodb_buffer_pool_size=8G | ||
| core-file | ||
| core-nodump=NONE | ||
|
|
||
| will create a core dump of about 9GB when killed with `kill -11 $mysqld_pid`. | ||
|
|
||
| The same mysqld with INNODB_BUFFER_POOL excluded from dumps only takes | ||
| about 900M, as was to be expected with the 8GB pool being excluded: | ||
|
|
||
| [mysqld] | ||
| innodb_buffer_pool_size=8G | ||
| core-file | ||
| core-nodump=INNODB_BUFFER_POOL | ||
|
|
||
| Backtraces can be retrieved sucessfully from both core dumps with gdb | ||
| and `thread apply all bt full`. | ||
|
|
||
| As InnoDB buffer pool and Myisam key cache implementations can be considered | ||
| stable lack of those buffer contents should not affect core dump post mortem | ||
| analysis in any way. This may not be the case with new features like tablespace | ||
| encryption yet though, so core dump exclusions should be used carefully in such | ||
| contexts. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| /* | ||
| Copyright (c) 2016, 2017, MariaDB Corporation. | ||
|
|
||
| This program is free software; you can redistribute it and/or modify | ||
| it under the terms of the GNU General Public License as published by | ||
| the Free Software Foundation; version 2 of the License. | ||
|
|
||
| This program is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU General Public License for more details. | ||
|
|
||
| You should have received a copy of the GNU General Public License | ||
| along with this program; if not, write to the Free Software | ||
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ | ||
|
|
||
| /* This is the include file that should be included 'first' in every C file. */ | ||
|
|
||
| #ifndef MY_CORE_NO_DUMP_INCLUDED | ||
| #define MY_CORE_NO_DUMP_INCLUDED | ||
|
|
||
| /* | ||
| Core dump control options to exclude certain buffers from core dump files | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment indentation doesn't follow coding style: should be 2 spaces. |
||
|
|
||
| There are two motivations for excluding things from core dumps: | ||
|
|
||
| * resource utilization: stuff like the InnoDB pool buffer is rarely needed | ||
| for post mortem debugging, but on machines with large amounts of memory | ||
| just the time and file system space it takes to write a core dump can | ||
| become substantial. Large core dump sizes can also become an obstacle | ||
| when providing a core dump to a 3rd party for analysis | ||
|
|
||
| * security: certain buffers, especially the InnoDB pool buffer or the | ||
| Aria page cache, are likely to contain sensitive user data. Excluding | ||
| these from a core dump can improve data security and especially can be | ||
| a requirement for being able to pass production server core dumps to | ||
| 3rd parties for analysis | ||
| */ | ||
|
|
||
| #include <my_global.h> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we really need to include my_global.h if HAVE_MADV_DONTDUMP is not defined? |
||
|
|
||
| #ifdef HAVE_MADV_DONTDUMP | ||
|
|
||
| #include <sys/mman.h> | ||
|
|
||
| /* Core dump exclusion constants */ | ||
| #define CORE_NODUMP_NONE (0) | ||
| #define CORE_NODUMP_MAX (1 << 1) | ||
| #define CORE_NODUMP_INNODB_POOL_BUFFER (1 << 2) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why POOL_BUFFER versus commonly used BUFFER_POOL? |
||
|
|
||
| extern ulong opt_core_nodump; | ||
|
|
||
| inline void exclude_from_coredump(void *ptr, size_t size, ulong flags) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. static inline please. |
||
| { | ||
| if (opt_core_nodump & (flags | CORE_NODUMP_MAX)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to move ifdef here, so that you don't have to have #else part |
||
| madvise(ptr, size, MADV_DONTDUMP); | ||
| } | ||
| } | ||
|
|
||
| #else /* HAVE_MADV_DONTDUMP */ | ||
|
|
||
| #define exclude_from_coredump(ptr, size, flag) | ||
|
|
||
| #endif /* HAVE_MADV_DONTDUMP */ | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,8 @@ | |
| #include "opt_range.h" | ||
| #include "rpl_parallel.h" | ||
|
|
||
| #include "my_core_no_dump.h" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this include here? |
||
|
|
||
| /* | ||
| The rule for this file: everything should be 'static'. When a sys_var | ||
| variable or a function from this file is - in very rare cases - needed | ||
|
|
@@ -5356,3 +5358,17 @@ static Sys_var_ulonglong Sys_max_thread_mem( | |
| "session variable MEM_USED", SESSION_VAR(max_mem_used), | ||
| CMD_LINE(REQUIRED_ARG), VALID_RANGE(8192, ULONGLONG_MAX), | ||
| DEFAULT(LONGLONG_MAX), BLOCK_SIZE(1)); | ||
|
|
||
| #ifdef HAVE_MADV_DONTDUMP | ||
|
|
||
| /* keep list in sync with constant definitiosn in my_core_no_dump.h */ | ||
| static const char *core_nodump_names[] = { "MAX", | ||
| "INNODB_POOL_BUFFER", | ||
| NULL}; | ||
|
|
||
| static Sys_var_set Sys_core_nodump( | ||
| "core_nodump", "Things to exclude from core dumps", | ||
| GLOBAL_VAR(opt_core_nodump), CMD_LINE(REQUIRED_ARG), | ||
| core_nodump_names, DEFAULT(0)); | ||
|
|
||
| #endif /* HAVE_MADV_DONTDUMP */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -65,6 +65,9 @@ Created 11/5/1995 Heikki Tuuri | |
| #include "fil0pagecompress.h" | ||
| #include "ha_prototypes.h" | ||
|
|
||
| /* for core dump specific stuff */ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pff... such comments make little to none sense. |
||
| #include "my_core_no_dump.h" | ||
|
|
||
| /* prototypes for new functions added to ha_innodb.cc */ | ||
| trx_t* innobase_get_trx(); | ||
|
|
||
|
|
@@ -1282,6 +1285,8 @@ buf_chunk_init( | |
| } | ||
| } | ||
| #endif // HAVE_LIBNUMA | ||
| // exclude from core dumps if configured to do so | ||
| exclude_from_coredump(chunk->mem, chunk->mem_size, CORE_NODUMP_INNODB_POOL_BUFFER); | ||
|
|
||
| /* Allocate the block descriptors from | ||
| the start of the memory block. */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
acquiring