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