File 0001-libxl-add-support-for-BlockResize-API.patch of Package libvirt.29828

From 914c37ca3f0af956e69179d49e87e8390560c2b3 Mon Sep 17 00:00:00 2001
From: Jim Fehlig <jfehlig@suse.com>
Date: Tue, 5 Jul 2022 11:36:37 -0600
Subject: libxl: add support for BlockResize API

Add support in the libxl driver for the BlockResize API. Use libxl's
libxl_qemu_monitor_command API to issue the block_resize command to qemu.

Signed-off-by: Jim Fehlig <jfehlig@suse.com>
---
 src/libxl/libxl_api_wrapper.h | 15 ++++++
 src/libxl/libxl_driver.c      | 90 +++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+)

Index: libvirt-9.0.0/src/libxl/libxl_api_wrapper.h
===================================================================
--- libvirt-9.0.0.orig/src/libxl/libxl_api_wrapper.h
+++ libvirt-9.0.0/src/libxl/libxl_api_wrapper.h
@@ -215,3 +215,18 @@ libxlSetMemoryTargetWrapper(libxl_ctx *c
 
     return ret;
 }
+
+static inline int
+libxlQemuMonitorCommandWrapper(libxl_ctx *ctx, uint32_t domid,
+                               const char *command_line, char **output)
+{
+    int ret;
+
+#if LIBXL_API_VERSION < 0x041300
+    ret = libxl_qemu_monitor_command(ctx, domid, command_line, output);
+#else
+    ret = libxl_qemu_monitor_command(ctx, domid, command_line, output, NULL);
+#endif
+
+    return ret;
+}
Index: libvirt-9.0.0/src/libxl/libxl_driver.c
===================================================================
--- libvirt-9.0.0.orig/src/libxl/libxl_driver.c
+++ libvirt-9.0.0/src/libxl/libxl_driver.c
@@ -5257,6 +5257,95 @@ libxlDomainMemoryStats(virDomainPtr dom,
 
 #undef LIBXL_SET_MEMSTAT
 
+/**
+ * Resize a block device while a guest is running. Resize to a lower size
+ * is supported, but should be used with extreme caution.  Note that it
+ * only supports to resize image files, it can't resize block devices
+ * like LVM volumes.
+ */
+static int
+libxlDomainBlockResize(virDomainPtr dom,
+                       const char *path,
+                       unsigned long long size,
+                       unsigned int flags)
+{
+    libxlDriverPrivate *driver = dom->conn->privateData;
+    libxlDriverConfig *cfg;
+    virDomainObj *vm;
+    int ret = -1;
+    virDomainDiskDef *disk = NULL;
+    g_autofree char *moncmd = NULL;
+    g_autofree char *monreply = NULL;
+
+    virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1);
+
+    if (path[0] == '\0') {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       "%s", _("empty path"));
+        return -1;
+    }
+
+    /* We prefer operating on bytes.  */
+    if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) {
+        if (size > ULLONG_MAX / 1024) {
+            virReportError(VIR_ERR_OVERFLOW,
+                           _("size must be less than %llu"),
+                           ULLONG_MAX / 1024);
+            return -1;
+        }
+        size *= 1024;
+    }
+
+    cfg = libxlDriverConfigGet(driver);
+    if (!(vm = libxlDomObjFromDomain(dom)))
+        goto cleanup;
+
+    if (virDomainBlockResizeEnsureACL(dom->conn, vm->def) < 0)
+        goto cleanup;
+
+    if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (!virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       "%s", _("domain is not running"));
+        goto endjob;
+    }
+
+    if (!(disk = virDomainDiskByName(vm->def, path, false))) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("invalid path: %s"), path);
+        goto endjob;
+    }
+
+    /* qcow2 and qed must be sized on 512 byte blocks/sectors,
+     * so adjust size if necessary to round up.
+     */
+    if (disk->src->format == VIR_STORAGE_FILE_QCOW2 ||
+        disk->src->format == VIR_STORAGE_FILE_QED)
+        size = VIR_ROUND_UP(size, 512);
+
+    moncmd = g_strdup_printf("block_resize %s %lluB", disk->dst, size);
+
+    if (libxlQemuMonitorCommandWrapper(cfg->ctx, vm->def->id,
+                                       moncmd, &monreply) != 0) {
+        virReportError(VIR_ERR_OPERATION_FAILED,
+                       _("block_resize command failed for device '%s' on domain '%d'"),
+                       disk->dst, vm->def->id);
+        goto endjob;
+    }
+
+    ret = 0;
+
+ endjob:
+    virDomainObjEndJob(vm);
+
+ cleanup:
+    virDomainObjEndAPI(&vm);
+    virObjectUnref(cfg);
+    return ret;
+}
+
 static int
 libxlDomainGetJobInfo(virDomainPtr dom,
                       virDomainJobInfoPtr info)
@@ -6577,6 +6666,7 @@ static virHypervisorDriver libxlHypervis
     .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
     .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
     .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
+    .domainBlockResize = libxlDomainBlockResize, /* 4.2.0 */
     .domainGetJobInfo = libxlDomainGetJobInfo, /* 1.3.1 */
     .domainGetJobStats = libxlDomainGetJobStats, /* 1.3.1 */
     .domainMemoryStats = libxlDomainMemoryStats, /* 1.3.0 */
openSUSE Build Service is sponsored by