2018-07-16 18:42:10 +02:00
|
|
|
From 661298572a5499ccfafcd36d30d66d091a5be9b6 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Jim Fehlig <jfehlig@suse.com>
|
|
|
|
Date: Fri, 23 Mar 2018 17:41:51 -0600
|
|
|
|
Subject: [PATCH] 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>
|
|
|
|
|
|
|
|
Note: In its current form, this patch is not upstream material IMO. It uses
|
|
|
|
the unsupported libxl_qemu_monitor_command() API. Before it can be considered
|
|
|
|
upstream, we need an upstream solution in qemu and Xen. Bruce will work on
|
|
|
|
the qemu part. Once done we can consider how to do the Xen part. And only
|
|
|
|
after we have a supported blockresize API in Xen (libxl) can we consider
|
|
|
|
reworking this patch and submitting it to upstream libvirt.
|
|
|
|
|
|
|
|
---
|
|
|
|
src/libxl/libxl_driver.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
1 file changed, 91 insertions(+)
|
|
|
|
|
2018-10-03 22:24:42 +02:00
|
|
|
Index: libvirt-4.8.0/src/libxl/libxl_driver.c
|
2018-07-16 18:42:10 +02:00
|
|
|
===================================================================
|
2018-10-03 22:24:42 +02:00
|
|
|
--- libvirt-4.8.0.orig/src/libxl/libxl_driver.c
|
|
|
|
+++ libvirt-4.8.0/src/libxl/libxl_driver.c
|
|
|
|
@@ -5253,6 +5253,97 @@ libxlDomainMemoryStats(virDomainPtr dom,
|
2018-07-16 18:42:10 +02:00
|
|
|
|
|
|
|
#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)
|
|
|
|
+{
|
|
|
|
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
|
|
|
|
+ libxlDriverConfigPtr cfg;
|
|
|
|
+ virDomainObjPtr vm;
|
|
|
|
+ int ret = -1;
|
|
|
|
+ virDomainDiskDefPtr disk = NULL;
|
|
|
|
+ char *moncmd = NULL;
|
|
|
|
+ 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 (libxlDomainObjBeginJob(driver, vm, LIBXL_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);
|
|
|
|
+
|
|
|
|
+ if (virAsprintf(&moncmd, "block_resize %s %lluB", disk->dst, size) < 0)
|
|
|
|
+ goto endjob;
|
|
|
|
+
|
|
|
|
+ if (libxl_qemu_monitor_command(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:
|
|
|
|
+ libxlDomainObjEndJob(driver, vm);
|
|
|
|
+
|
|
|
|
+ cleanup:
|
|
|
|
+ VIR_FREE(moncmd);
|
|
|
|
+ VIR_FREE(monreply);
|
|
|
|
+ virDomainObjEndAPI(&vm);
|
|
|
|
+ virObjectUnref(cfg);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static int
|
|
|
|
libxlDomainGetJobInfo(virDomainPtr dom,
|
|
|
|
virDomainJobInfoPtr info)
|
2018-10-03 22:24:42 +02:00
|
|
|
@@ -6635,6 +6726,7 @@ static virHypervisorDriver libxlHypervis
|
2018-07-16 18:42:10 +02:00
|
|
|
#endif
|
|
|
|
.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 */
|