On Tue, Aug 11, 2026 at 11:24:57AM +0200, Denis V. Lunev via Devel wrote:
Each on_crash or watchdog-triggered dump writes a full memory dump into auto_dump_path. A guest that keeps crashing and restarting (or crashing and getting destroyed, then respawned by the mgmt app) can fill the disk one dump at a time, with nothing to stop it.
Add auto_dump_max_size (qemu.conf), parsed via virConfGetValueBytes() so it takes a plain byte count or a size with a unit suffix (e.g. "10GiB"). After a dump is written, the oldest dumps under auto_dump_path are removed until the total fits the configured quota. The dump that was just written is always kept by identity, not by sort position: mtime is only second-granularity, so two dumps written the same second would otherwise make the eviction order between them arbitrary and could delete the one just written instead of an older one. Defaults to 0, which keeps every dump forever, as before.
Only files named the way getAutoDumpPath() names them count toward the quota, and nothing is pruned when the dump itself failed.
libvirtd_qemu.aug gains a matching entry; its quoted branch requires a unit suffix, as one matching a bare number would overlap the integer branch.
Signed-off-by: Denis V. Lunev <den@openvz.org> --- NEWS.rst | 7 ++ src/qemu/libvirtd_qemu.aug | 4 + src/qemu/qemu.conf.in | 17 ++++ src/qemu/qemu_conf.c | 2 + src/qemu/qemu_conf.h | 1 + src/qemu/qemu_driver.c | 130 +++++++++++++++++++++++++++++ src/qemu/test_libvirtd_qemu.aug.in | 1 + 7 files changed, 162 insertions(+)
+static void +qemuPruneAutoDumpPath(virQEMUDriverConfig *cfg, + const char *keep) +{ + g_autoptr(DIR) dir = NULL; + struct dirent *entry; + g_autoptr(GPtrArray) files = NULL; + unsigned long long total = 0; + size_t i; + int rc; + + if (cfg->autoDumpMaxSize == 0) + return; + + if (virDirOpenQuiet(&dir, cfg->autoDumpPath) < 0) + return; + + files = g_ptr_array_new_with_free_func(qemuAutoDumpFileFree); + + while ((rc = virDirRead(dir, &entry, NULL)) > 0) { + g_autofree char *path = g_strdup_printf("%s/%s", cfg->autoDumpPath, + entry->d_name); + GStatBuf sb; + qemuAutoDumpFile *file; + + if (!qemuIsAutoDumpFileName(entry->d_name)) + continue; + + if (g_stat(path, &sb) < 0 || !S_ISREG(sb.st_mode)) + continue; + + total += sb.st_size;
'st_size' is counting logical file size. I think we probably want to instead count allocated file size (total += sb.st_blocks * sb.st_blksize) so that we don't over-count if files happen to be sparse. I was wondernig if we should be concerned about overflowing 'total', but as long as we count allocated size, not logical size I think we'll be safe enough from overflow.
+ + if (STREQ(path, keep)) + continue; + + file = g_new0(qemuAutoDumpFile, 1); + file->path = g_steal_pointer(&path); + file->size = sb.st_size; + file->mtime = sb.st_mtime; + + g_ptr_array_add(files, file); + } + + if (rc < 0) + return; + + g_ptr_array_sort(files, qemuAutoDumpFileCompare); + + for (i = 0; i < files->len && total > cfg->autoDumpMaxSize; i++) { + qemuAutoDumpFile *file = g_ptr_array_index(files, i); + + if (unlink(file->path) < 0 && errno != ENOENT) { + VIR_WARN("Failed to prune old dump %s: %s", + file->path, g_strerror(errno)); + continue; + } + + VIR_DEBUG("Pruned old dump %s to satisfy auto_dump_max_size quota", + file->path); + total -= file->size; + } +} + + static void processWatchdogEvent(virQEMUDriver *driver, virDomainObj *vm, @@ -3589,6 +3715,8 @@ processWatchdogEvent(virQEMUDriver *driver, qemuDomainGetAutoDumpFormat(vm))) < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); + else + qemuPruneAutoDumpPath(cfg, dumpfile);
ret = qemuProcessStartCPUs(driver, vm, VIR_DOMAIN_RUNNING_UNPAUSED, @@ -3624,6 +3752,8 @@ doCoreDumpToAutoDumpPath(virQEMUDriver *driver, qemuDomainGetAutoDumpFormat(vm))) < 0) virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Dump failed")); + else + qemuPruneAutoDumpPath(cfg, dumpfile); return ret; }
diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index c4cf9cf634..c97d8d7081 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -83,6 +83,7 @@ module Test_libvirtd_qemu = { "snapshot_image_format" = "raw" } { "auto_dump_path" = "/var/lib/libvirt/qemu/dump" } { "auto_dump_bypass_cache" = "0" } +{ "auto_dump_max_size" = "10GiB" } { "auto_start_bypass_cache" = "0" } { "auto_start_delay" = "0" } { "auto_shutdown_try_save" = "persistent" } -- 2.53.0
With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|