]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: add a max_core setting to qemu.conf for core dump size
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 18 Mar 2015 11:14:55 +0000 (11:14 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 6 Sep 2016 12:08:30 +0000 (13:08 +0100)
Currently the QEMU processes inherit their core dump rlimit
from libvirtd, which is really suboptimal. This change allows
their limit to be directly controlled from qemu.conf instead.

src/libvirt_private.syms
src/qemu/libvirtd_qemu.aug
src/qemu/qemu.conf
src/qemu/qemu_conf.c
src/qemu/qemu_conf.h
src/qemu/qemu_process.c
src/qemu/test_libvirtd_qemu.aug.in
src/util/vircommand.c
src/util/vircommand.h
src/util/virprocess.c
src/util/virprocess.h

index d62c74c39e8ce9b3d449bbe75825cb86d44c3a22..a5fa30562f0c4c82d7e7f89bd4a51fa3455f9ad3 100644 (file)
@@ -1392,6 +1392,7 @@ virCommandSetErrorFD;
 virCommandSetGID;
 virCommandSetInputBuffer;
 virCommandSetInputFD;
+virCommandSetMaxCoreSize;
 virCommandSetMaxFiles;
 virCommandSetMaxMemLock;
 virCommandSetMaxProcesses;
@@ -2203,6 +2204,7 @@ virProcessRunInMountNamespace;
 virProcessSchedPolicyTypeFromString;
 virProcessSchedPolicyTypeToString;
 virProcessSetAffinity;
+virProcessSetMaxCoreSize;
 virProcessSetMaxFiles;
 virProcessSetMaxMemLock;
 virProcessSetMaxProcesses;
index 8bc23baa666641f8493b810eecb473b273aa46a9..9ec82508409486b31273474baa16e56968a7aa44 100644 (file)
@@ -22,6 +22,9 @@ module Libvirtd_qemu =
    let int_entry       (kw:string) = [ key kw . value_sep . int_val ]
    let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
 
+   let unlimited_val =  del /\"/ "\"" . store /unlimited/ . del /\"/ "\""
+   let limits_entry (kw:string) = [ key kw . value_sep . unlimited_val ] |  [ key kw . value_sep . int_val ]
+
 
    (* Config entry grouped by function - same order as example config *)
    let vnc_entry = str_entry "vnc_listen"
@@ -72,6 +75,7 @@ module Libvirtd_qemu =
                  | bool_entry "set_process_name"
                  | int_entry "max_processes"
                  | int_entry "max_files"
+                 | limits_entry "max_core"
                  | str_entry "stdio_handler"
 
    let device_entry = bool_entry "mac_filter"
index 20bfb745a59f3eb401be7058bbcc2d78f353dcb1..b1ece732c98d9ed0f91e877a5c178bbfe8526ce6 100644 (file)
 #max_processes = 0
 #max_files = 0
 
-
+# If max_core is set to a non-zero 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, unless it has been disabled via the guest XML by
+# setting:
+#
+#   <memory dumpcore="off">...guest ram...</memory>
+#
+# If guest RAM is to be included, ensure the max_core limit
+# is set to at least the size of the largest expected guest
+# plus another 1GB for any QEMU host side memory mappings.
+#
+# 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 a positive integer specifying bytes or the
+# string "unlimited"
+#
+#max_core = "unlimited"
 
 # mac_filter enables MAC addressed based filtering on bridge ports.
 # This currently requires ebtables to be installed.
index 7b971f14ff9df9c2e4c1ef0010839c10c60eed4e..b3db22c0451055dcbaa58638320252b0581352ac 100644 (file)
@@ -398,6 +398,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.
@@ -638,6 +639,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)
@@ -720,6 +736,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
     virStringFreeList(controllers);
     virStringFreeList(hugetlbfs);
     virStringFreeList(nvram);
+    VIR_FREE(corestr);
     VIR_FREE(user);
     VIR_FREE(group);
     virConfFree(conf);
index 510cd9a54145e21f3c64a41e2c5252ef33c10297..b730202c5e436807db1357a817b924d0c6b0cbd3 100644 (file)
@@ -148,6 +148,7 @@ struct _virQEMUDriverConfig {
 
     unsigned int maxProcesses;
     unsigned int maxFiles;
+    unsigned long long maxCore;
 
     unsigned int maxQueuedJobs;
 
index b10b05359d236f1cbd95ec0da3a88e1a2cc71983..ec6b547c85518e9321d1bbffc48fe2d90d491de8 100644 (file)
@@ -5269,6 +5269,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");
index 99bf90f26d25c3a7a229f989a65e449121b503bd..1d3c0b73a6cee20e63f53755e662b44bc1e000d3 100644 (file)
@@ -62,6 +62,7 @@ module Test_libvirtd_qemu =
 { "set_process_name" = "1" }
 { "max_processes" = "0" }
 { "max_files" = "0" }
+{ "max_core" = "unlimited" }
 { "mac_filter" = "1" }
 { "relaxed_acs_check" = "1" }
 { "allow_disk_format_probing" = "1" }
index 3c67c907aada1ffcc9fe495cb03be1d30ba114d2..2a59bd1a4112f1cb2ee99d7edcb2bfa1e102a081 100644 (file)
@@ -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)
index 44818efe2ab2125b2457dda0eb3605a7e0b499c3..99dcdeb541a7e97f3b922a25a47a93ac09d4729a 100644 (file)
@@ -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);
index 09dd3c90f47181a88a8f33f72a87cc2a629d787f..8b9f9c5d609a8aa75a71c8d77f9ed31c727edf34 100644 (file)
@@ -914,6 +914,45 @@ 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)
+{
+    if (bytes == 0)
+        return 0;
+
+    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
index a7a1fe9200ca91140c174aa6bc3cbb97beaa3482..04e9802aa688eea4bfa4927754df5bce6a1a223a 100644 (file)
@@ -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);