[libvirt] [PATCH 2/2] qemu: add a max_core setting to qemu.conf for core dump size

Daniel P. Berrange berrange at redhat.com
Wed Mar 18 12:36:48 UTC 2015


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.
---
 src/libvirt_private.syms           |  2 ++
 src/qemu/libvirtd_qemu.aug         |  1 +
 src/qemu/qemu.conf                 | 12 ++++++++++++
 src/qemu/qemu_conf.c               |  3 +++
 src/qemu/qemu_conf.h               |  2 ++
 src/qemu/qemu_process.c            |  2 ++
 src/qemu/test_libvirtd_qemu.aug.in |  1 +
 src/util/vircommand.c              | 14 ++++++++++++++
 src/util/vircommand.h              |  1 +
 src/util/virprocess.c              | 35 +++++++++++++++++++++++++++++++++++
 src/util/virprocess.h              |  1 +
 11 files changed, 74 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ca3520d..7446357 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1240,6 +1240,7 @@ virCommandSetErrorFD;
 virCommandSetGID;
 virCommandSetInputBuffer;
 virCommandSetInputFD;
+virCommandSetMaxCoreSize;
 virCommandSetMaxFiles;
 virCommandSetMaxMemLock;
 virCommandSetMaxProcesses;
@@ -1951,6 +1952,7 @@ virProcessRunInMountNamespace;
 virProcessSchedPolicyTypeFromString;
 virProcessSchedPolicyTypeToString;
 virProcessSetAffinity;
+virProcessSetMaxCoreSize;
 virProcessSetMaxFiles;
 virProcessSetMaxMemLock;
 virProcessSetMaxProcesses;
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 62951da..029a55a 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -71,6 +71,7 @@ module Libvirtd_qemu =
                  | bool_entry "set_process_name"
                  | int_entry "max_processes"
                  | int_entry "max_files"
+                 | int_entry "max_core"
 
    let device_entry = bool_entry "mac_filter"
                  | bool_entry "relaxed_acs_check"
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 1c589a2..12e4326 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -390,6 +390,18 @@
 #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.
+#
+# By default it will inherit core limit from libvirtd, which
+# is usually set to 0 by systemd/init.
+#
+# Size is in bytes
+#max_core = 0
 
 
 # mac_filter enables MAC addressed based filtering on bridge ports.
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index bca05c9..97bb8b8 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -770,6 +770,9 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
     GET_VALUE_BOOL("set_process_name", cfg->setProcessName);
     GET_VALUE_ULONG("max_processes", cfg->maxProcesses);
     GET_VALUE_ULONG("max_files", cfg->maxFiles);
+    GET_VALUE_ULONG("max_core", cfg->maxCore);
+    if (virConfGetValue(conf, "max_core"))
+        cfg->setMaxCore = true;
 
     GET_VALUE_STR("lock_manager", cfg->lockManagerName);
 
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index cb01fb6..ac7a1bf 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -143,6 +143,8 @@ struct _virQEMUDriverConfig {
 
     int maxProcesses;
     int maxFiles;
+    bool setMaxCore;
+    unsigned long long maxCore;
 
     int maxQueuedJobs;
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 37cdb8f..995d6ef 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4731,6 +4731,8 @@ int qemuProcessStart(virConnectPtr conn,
     virCommandSetPreExecHook(cmd, qemuProcessHook, &hookData);
     virCommandSetMaxProcesses(cmd, cfg->maxProcesses);
     virCommandSetMaxFiles(cmd, cfg->maxFiles);
+    if (cfg->setMaxCore)
+        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 fc4935b..9bb3683 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -61,6 +61,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 648f5ed..1982401 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -123,6 +123,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;
@@ -686,6 +688,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);
@@ -1108,6 +1113,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 198da2f..4f2874d 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 aa00a99..02d91d9 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -825,6 +825,41 @@ 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) < 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)
+{
+    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 c812882..cd7b7a2 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);
 
 /* Callback to run code within the mount namespace tied to the given
  * pid.  This function must use only async-signal-safe functions, as
-- 
2.1.0




More information about the libvir-list mailing list