Qemu supports sizing by bytes; we shouldn't force the user to round up if they really wanted an unaligned total size. * include/libvirt/libvirt.h.in (VIR_DOMAIN_BLOCK_RESIZE_BYTES): New flag. * src/libvirt.c (virDomainBlockResize): Document it. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockResize): Take size in bytes. * src/qemu/qemu_monitor_text.c (qemuMonitorTextBlockResize): Likewise. Pass bytes, not megabytes, to monitor. * src/qemu/qemu_driver.c (qemuDomainBlockResize): Implement new flag. --- Virsh support will come later, as part of my cleanups to make virsh handle scaled integers. include/libvirt/libvirt.h.in | 10 ++++++++++ src/libvirt.c | 17 +++++++++++------ src/qemu/qemu_driver.c | 24 ++++++++++++++---------- src/qemu/qemu_monitor_json.c | 5 +++-- src/qemu/qemu_monitor_text.c | 6 +++--- 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 58c4366..b2f8f5f 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1636,6 +1636,16 @@ int virDomainBlockPeek (virDomainPtr dom, size_t size, void *buffer, unsigned int flags); + +/** + * virDomainBlockResizeFlags: + * + * Flags available for virDomainBlockResize(). + */ +typedef enum { + VIR_DOMAIN_BLOCK_RESIZE_BYTES = 1 << 0, /* size in bytes instead of KiB */ +} virDomainBlockResizeFlags; + int virDomainBlockResize (virDomainPtr dom, const char *disk, unsigned long long size, diff --git a/src/libvirt.c b/src/libvirt.c index c2e9733..d98741b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -7601,12 +7601,15 @@ error: * virDomainBlockResize: * @dom: pointer to the domain object * @disk: path to the block image, or shorthand - * @size: new size of the block image in kilobytes - * @flags: extra flags; not used yet, so callers should always pass 0 + * @size: new size of the block image, see below for unit + * @flags: bitwise-OR of virDomainBlockResizeFlags * - * Note that this call may fail if the underlying virtualization hypervisor - * does not support it. And this call requires privileged access to the - * hypervisor. + * Resize a block device of domain while the domain is running. If + * @flags is 0, then @size is in kibibytes (blocks of 1024); since + * 0.9.11, if @flags includes VIR_DOMAIN_BLOCK_RESIZE_BYTES, @size is + * in bytes instead. @size is taken directly as the new size. + * Depending on the file format, the hypervisor may round up to the + * next alignment boundary. * * The @disk parameter is either an unambiguous source name of the * block device (the <source file='...'/> sub-element, such as @@ -7615,7 +7618,9 @@ error: * can be found by calling virDomainGetXMLDesc() and inspecting * elements within //domain/devices/disk. * - * Resize a block device of domain while the domain is running. + * Note that this call may fail if the underlying virtualization hypervisor + * does not support it; this call requires privileged access to the + * hypervisor. * * Returns: 0 in case of success or -1 in case of failure. */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2afcc3f..1f57508 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7348,10 +7348,10 @@ qemuGetSchedulerParameters(virDomainPtr dom, * like LVM volumes. */ static int -qemuDomainBlockResize (virDomainPtr dom, - const char *path, - unsigned long long size, - unsigned int flags) +qemuDomainBlockResize(virDomainPtr dom, + const char *path, + unsigned long long size, + unsigned int flags) { struct qemud_driver *driver = dom->conn->privateData; virDomainObjPtr vm; @@ -7360,7 +7360,7 @@ qemuDomainBlockResize (virDomainPtr dom, char *device = NULL; virDomainDiskDefPtr disk = NULL; - virCheckFlags(0, -1); + virCheckFlags(VIR_DOMAIN_BLOCK_RESIZE_BYTES, -1); if (path[0] == '\0') { qemuReportError(VIR_ERR_INVALID_ARG, @@ -7368,11 +7368,15 @@ qemuDomainBlockResize (virDomainPtr dom, return -1; } - if (size > ULLONG_MAX / 1024) { - qemuReportError(VIR_ERR_INVALID_ARG, - _("size must be less than %llu"), - ULLONG_MAX / 1024); - return -1; + /* We prefer operating on bytes. */ + if ((flags & VIR_DOMAIN_BLOCK_RESIZE_BYTES) == 0) { + if (size > ULLONG_MAX / 1024) { + qemuReportError(VIR_ERR_INVALID_ARG, + _("size must be less than %llu"), + ULLONG_MAX / 1024); + return -1; + } + size *= 1024; } qemuDriverLock(driver); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c0f148b..dc67b4b 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1783,7 +1783,8 @@ cleanup: return ret; } -/* Return 0 on success, -1 on failure, or -2 if not supported. */ +/* Return 0 on success, -1 on failure, or -2 if not supported. Size + * is in bytes. */ int qemuMonitorJSONBlockResize(qemuMonitorPtr mon, const char *device, unsigned long long size) @@ -1794,7 +1795,7 @@ int qemuMonitorJSONBlockResize(qemuMonitorPtr mon, cmd = qemuMonitorJSONMakeCommand("block_resize", "s:device", device, - "U:size", size * 1024, + "U:size", size, NULL); if (!cmd) return -1; diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c index d6f7dac..a7ebfba 100644 --- a/src/qemu/qemu_monitor_text.c +++ b/src/qemu/qemu_monitor_text.c @@ -1097,7 +1097,8 @@ int qemuMonitorTextGetBlockExtent(qemuMonitorPtr mon ATTRIBUTE_UNUSED, return -1; } -/* Return 0 on success, -1 on failure, or -2 if not supported. */ +/* Return 0 on success, -1 on failure, or -2 if not supported. Size + * is in bytes. */ int qemuMonitorTextBlockResize(qemuMonitorPtr mon, const char *device, unsigned long long size) @@ -1106,8 +1107,7 @@ int qemuMonitorTextBlockResize(qemuMonitorPtr mon, char *reply = NULL; int ret = -1; - if (virAsprintf(&cmd, "block_resize %s %llu", - device, VIR_DIV_UP(size, 1024)) < 0) { + if (virAsprintf(&cmd, "block_resize %s %lluB", device, size) < 0) { virReportOOMError(); goto cleanup; } -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list