Currently the QEMU processes inherit their core dump rlimit
from libvirtd, which is really suboptimal. This change allows
their limit to be directly controller from qemu.conf instead.
---
Changed in v2:
- Allow use of string "unlimited"
src/libvirt_private.syms | 2 ++
src/qemu/libvirtd_qemu.aug | 1 +
src/qemu/qemu.conf | 16 +++++++++++++++-
src/qemu/qemu_conf.c | 17 +++++++++++++++++
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_process.c | 1 +
src/qemu/test_libvirtd_qemu.aug.in | 1 +
src/util/vircommand.c | 14 ++++++++++++++
src/util/vircommand.h | 1 +
src/util/virprocess.c | 36 ++++++++++++++++++++++++++++++++++++
src/util/virprocess.h | 1 +
11 files changed, 90 insertions(+), 1 deletion(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 597ce5f..773d935 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1371,6 +1371,7 @@ virCommandSetErrorFD;
virCommandSetGID;
virCommandSetInputBuffer;
virCommandSetInputFD;
+virCommandSetMaxCoreSize;
virCommandSetMaxFiles;
virCommandSetMaxMemLock;
virCommandSetMaxProcesses;
@@ -2180,6 +2181,7 @@ virProcessRunInMountNamespace;
virProcessSchedPolicyTypeFromString;
virProcessSchedPolicyTypeToString;
virProcessSetAffinity;
+virProcessSetMaxCoreSize;
virProcessSetMaxFiles;
virProcessSetMaxMemLock;
virProcessSetMaxProcesses;
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 8bc23ba..a8edc2b 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -72,6 +72,7 @@ module Libvirtd_qemu =
| bool_entry "set_process_name"
| int_entry "max_processes"
| int_entry "max_files"
+ | int_entry "max_core"
| str_entry "stdio_handler"
let device_entry = bool_entry "mac_filter"
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 7964273..fac33ec 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -401,7 +401,21 @@
#max_processes = 0
#max_files = 0
-
+# If max_core is set to a positive integer, then QEMU will be
+# permitted to create core dumps when it crashes, provided its
+# RAM size is smaller than the limit set. Be warned that the
+# core dump will include a full copy of the guest RAM, so if
+# the largest guest is 32 GB in size, the max_core limit will
+# have to be at least 33/34 GB to allow enough overhead.
+#
+# As a special case it can be set to the string "unlimited" to
+# to allow arbitrarily sized core dumps.
+#
+# By default the core dump size is set to 0 disabling all dumps
+#
+# Size is in bytes or string "unlimited"
+#max_core = 0
+#max_core = "unlimited"
# mac_filter enables MAC addressed based filtering on bridge ports.
# This currently requires ebtables to be installed.
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index fa9d65e..45d039c 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -393,6 +393,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
char **controllers = NULL;
char **hugetlbfs = NULL;
char **nvram = NULL;
+ char *corestr = NULL;
/* Just check the file is readable before opening it, otherwise
* libvirt emits an error.
@@ -633,6 +634,21 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
if (virConfGetValueUInt(conf, "max_files", &cfg->maxFiles) < 0)
goto cleanup;
+ if (virConfGetValueType(conf, "max_core") == VIR_CONF_STRING) {
+ if (virConfGetValueString(conf, "max_core", &corestr) < 0)
+ goto cleanup;
+ if (STREQ(corestr, "unlimited")) {
+ cfg->maxCore = ULLONG_MAX;
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown core size '%s'"),
+ corestr);
+ goto cleanup;
+ }
+ } else if (virConfGetValueULLong(conf, "max_core", &cfg->maxCore)
< 0) {
+ goto cleanup;
+ }
+
if (virConfGetValueString(conf, "lock_manager",
&cfg->lockManagerName) < 0)
goto cleanup;
if (virConfGetValueString(conf, "stdio_handler", &stdioHandler) <
0)
@@ -715,6 +731,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
virStringFreeList(controllers);
virStringFreeList(hugetlbfs);
virStringFreeList(nvram);
+ VIR_FREE(corestr);
VIR_FREE(user);
VIR_FREE(group);
virConfFree(conf);
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 510cd9a..b730202 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -148,6 +148,7 @@ struct _virQEMUDriverConfig {
unsigned int maxProcesses;
unsigned int maxFiles;
+ unsigned long long maxCore;
unsigned int maxQueuedJobs;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4adb14e..a7cbd59 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5069,6 +5069,7 @@ qemuProcessLaunch(virConnectPtr conn,
virCommandSetPreExecHook(cmd, qemuProcessHook, &hookData);
virCommandSetMaxProcesses(cmd, cfg->maxProcesses);
virCommandSetMaxFiles(cmd, cfg->maxFiles);
+ virCommandSetMaxCoreSize(cmd, cfg->maxCore);
virCommandSetUmask(cmd, 0x002);
VIR_DEBUG("Setting up security labelling");
diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
index c4d4f19..c3d6da5 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -62,6 +62,7 @@ module Test_libvirtd_qemu =
{ "set_process_name" = "1" }
{ "max_processes" = "0" }
{ "max_files" = "0" }
+{ "max_core" = "0" }
{ "mac_filter" = "1" }
{ "relaxed_acs_check" = "1" }
{ "allow_disk_format_probing" = "1" }
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index f5bd7af..6baa37a 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -124,6 +124,8 @@ struct _virCommand {
unsigned long long maxMemLock;
unsigned int maxProcesses;
unsigned int maxFiles;
+ bool setMaxCore;
+ unsigned long long maxCore;
uid_t uid;
gid_t gid;
@@ -687,6 +689,9 @@ virExec(virCommandPtr cmd)
goto fork_error;
if (virProcessSetMaxFiles(0, cmd->maxFiles) < 0)
goto fork_error;
+ if (cmd->setMaxCore &&
+ virProcessSetMaxCoreSize(0, cmd->maxCore) < 0)
+ goto fork_error;
if (cmd->hook) {
VIR_DEBUG("Run hook %p %p", cmd->hook, cmd->opaque);
@@ -1105,6 +1110,15 @@ virCommandSetMaxFiles(virCommandPtr cmd, unsigned int files)
cmd->maxFiles = files;
}
+void virCommandSetMaxCoreSize(virCommandPtr cmd, unsigned long long bytes)
+{
+ if (!cmd || cmd->has_error)
+ return;
+
+ cmd->maxCore = bytes;
+ cmd->setMaxCore = true;
+}
+
void virCommandSetUmask(virCommandPtr cmd, int mask)
{
if (!cmd || cmd->has_error)
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index 44818ef..99dcdeb 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -75,6 +75,7 @@ void virCommandSetUID(virCommandPtr cmd, uid_t uid);
void virCommandSetMaxMemLock(virCommandPtr cmd, unsigned long long bytes);
void virCommandSetMaxProcesses(virCommandPtr cmd, unsigned int procs);
void virCommandSetMaxFiles(virCommandPtr cmd, unsigned int files);
+void virCommandSetMaxCoreSize(virCommandPtr cmd, unsigned long long bytes);
void virCommandSetUmask(virCommandPtr cmd, int umask);
void virCommandClearCaps(virCommandPtr cmd);
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 09dd3c9..2b71445 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -914,6 +914,42 @@ virProcessSetMaxFiles(pid_t pid ATTRIBUTE_UNUSED, unsigned int
files)
}
#endif /* ! (HAVE_SETRLIMIT && defined(RLIMIT_NOFILE)) */
+#if HAVE_SETRLIMIT && defined(RLIMIT_CORE)
+int
+virProcessSetMaxCoreSize(pid_t pid, unsigned long long bytes)
+{
+ struct rlimit rlim;
+
+ rlim.rlim_cur = rlim.rlim_max = bytes;
+ if (pid == 0) {
+ if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
+ virReportSystemError(errno,
+ _("cannot limit core file size to %llu"),
+ bytes);
+ return -1;
+ }
+ } else {
+ if (virProcessPrLimit(pid, RLIMIT_CORE, &rlim, NULL) < 0) {
+ virReportSystemError(errno,
+ _("cannot limit core file size "
+ "of process %lld to %llu"),
+ (long long int)pid, bytes);
+ return -1;
+ }
+ }
+ return 0;
+}
+#else /* ! (HAVE_SETRLIMIT && defined(RLIMIT_CORE)) */
+int
+virProcessSetMaxCoreSize(pid_t pid ATTRIBUTE_UNUSED,
+ unsigned long long bytes ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s", _("Not supported on this
platform"));
+ return -1;
+}
+#endif /* ! (HAVE_SETRLIMIT && defined(RLIMIT_CORE)) */
+
+
#ifdef __linux__
/*
* Port of code from polkitunixprocess.c under terms
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index a7a1fe9..04e9802 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -75,6 +75,7 @@ int virProcessSetNamespaces(size_t nfdlist,
int virProcessSetMaxMemLock(pid_t pid, unsigned long long bytes);
int virProcessSetMaxProcesses(pid_t pid, unsigned int procs);
int virProcessSetMaxFiles(pid_t pid, unsigned int files);
+int virProcessSetMaxCoreSize(pid_t pid, unsigned long long bytes);
int virProcessGetMaxMemLock(pid_t pid, unsigned long long *bytes);
--
2.7.4