VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT = 1 << 1,
} virDomainBlockJobAbortFlags;
+int virDomainBlockJobAbort(virDomainPtr dom, const char *disk,
+ unsigned int flags);
+
+/* Flags for use with virDomainGetBlockJobInfo */
+typedef enum {
+ VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES = 1 << 0, /* bandwidth in bytes/s
+ instead of MiB/s */
+} virDomainBlockJobInfoFlags;
+
/* An iterator for monitoring block job operations */
typedef unsigned long long virDomainBlockJobCursor;
typedef struct _virDomainBlockJobInfo virDomainBlockJobInfo;
struct _virDomainBlockJobInfo {
int type; /* virDomainBlockJobType */
- unsigned long bandwidth;
+ unsigned long bandwidth; /* either bytes/s or MiB/s, according to flags */
+
/*
* The following fields provide an indication of block job progress. @cur
* indicates the current position and will be between 0 and @end. @end is
};
typedef virDomainBlockJobInfo *virDomainBlockJobInfoPtr;
-int virDomainBlockJobAbort(virDomainPtr dom, const char *disk,
- unsigned int flags);
-int virDomainGetBlockJobInfo(virDomainPtr dom, const char *disk,
- virDomainBlockJobInfoPtr info,
- unsigned int flags);
+int virDomainGetBlockJobInfo(virDomainPtr dom, const char *disk,
+ virDomainBlockJobInfoPtr info,
+ unsigned int flags);
+
int virDomainBlockJobSetSpeed(virDomainPtr dom, const char *disk,
unsigned long bandwidth, unsigned int flags);
* the maximum bandwidth in bytes/s, and is used while getting the
* copy operation into the mirrored phase, with a type of ullong. For
* compatibility with virDomainBlockJobSetSpeed(), values larger than
- * 2^52 bytes/sec (a 32-bit MiB/s value) may be rejected due to
- * overflow considerations, and hypervisors may further restrict the
- * set of valid values. Specifying 0 is the same as omitting this
- * parameter, to request no bandwidth limiting. Some hypervisors may
- * lack support for this parameter, while still allowing a subsequent
- * change of bandwidth via virDomainBlockJobSetSpeed(). The actual
- * speed can be determined with virDomainGetBlockJobInfo().
+ * 2^52 bytes/sec (a 32-bit MiB/s value) may be rejected on input due
+ * to overflow considerations (but do you really have an interface
+ * with that much bandwidth?), and values larger than 2^31 bytes/sec
+ * may cause overflow problems if queried in bytes/sec. Hypervisors
+ * may further restrict the set of valid values. Specifying 0 is the
+ * same as omitting this parameter, to request no bandwidth limiting.
+ * Some hypervisors may lack support for this parameter, while still
+ * allowing a subsequent change of bandwidth via
+ * virDomainBlockJobSetSpeed(). The actual speed can be determined
+ * with virDomainGetBlockJobInfo().
*/
#define VIR_DOMAIN_BLOCK_COPY_BANDWIDTH "bandwidth"
* @dom: pointer to domain object
* @disk: path to the block device, or device shorthand
* @info: pointer to a virDomainBlockJobInfo structure
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise-OR of virDomainBlockJobInfoFlags
*
* Request block job information for the given disk. If an operation is active
- * @info will be updated with the current progress.
+ * @info will be updated with the current progress. The units used for the
+ * bandwidth field of @info depends on @flags. If @flags includes
+ * VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, bandwidth is in bytes/second
+ * (although this mode can risk failure due to overflow, depending on both
+ * client and server word size); otherwise, the value is rounded up to MiB/s.
*
* The @disk parameter is either an unambiguous source name of the
* block device (the <source file='...'/> sub-element, such as
/* Probe the status, if needed. */
if (!disk->mirrorState) {
qemuDomainObjEnterMonitor(driver, vm);
- rc = qemuMonitorBlockJobInfo(priv->mon, device, &info);
+ rc = qemuMonitorBlockJobInfo(priv->mon, device, &info, NULL);
qemuDomainObjExitMonitor(driver, vm);
if (rc < 0)
goto cleanup;
virDomainBlockJobInfo dummy;
qemuDomainObjEnterMonitor(driver, vm);
- ret = qemuMonitorBlockJobInfo(priv->mon, device, &dummy);
+ ret = qemuMonitorBlockJobInfo(priv->mon, device, &dummy, NULL);
qemuDomainObjExitMonitor(driver, vm);
if (ret <= 0)
int idx;
virDomainDiskDefPtr disk;
int ret = -1;
+ unsigned long long bandwidth;
- virCheckFlags(0, -1);
+ virCheckFlags(VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES, -1);
if (!(vm = qemuDomObjFromDomain(dom)))
return -1;
disk = vm->def->disks[idx];
qemuDomainObjEnterMonitor(driver, vm);
- ret = qemuMonitorBlockJobInfo(priv->mon, device, info);
+ ret = qemuMonitorBlockJobInfo(priv->mon, device, info, &bandwidth);
qemuDomainObjExitMonitor(driver, vm);
if (ret < 0)
goto endjob;
if (info->type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT &&
disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT)
info->type = disk->mirrorJob;
+ if (bandwidth) {
+ if (!(flags & VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES))
+ bandwidth = VIR_DIV_UP(bandwidth, 1024 * 1024);
+ info->bandwidth = bandwidth;
+ if (info->bandwidth != bandwidth) {
+ virReportError(VIR_ERR_OVERFLOW,
+ _("bandwidth %llu cannot be represented in result"),
+ bandwidth);
+ goto endjob;
+ }
+ }
/* Snoop block copy operations, so future cancel operations can
* avoid checking if pivot is safe. Save the change to XML, but
_("canceled by client"));
goto error;
}
- mon_ret = qemuMonitorBlockJobInfo(priv->mon, diskAlias, &info);
+ mon_ret = qemuMonitorBlockJobInfo(priv->mon, diskAlias, &info,
+ NULL);
qemuDomainObjExitMonitor(driver, vm);
if (mon_ret < 0)
int
qemuMonitorBlockJobInfo(qemuMonitorPtr mon,
const char *device,
- virDomainBlockJobInfoPtr info)
+ virDomainBlockJobInfoPtr info,
+ unsigned long long *bandwidth)
{
int ret = -1;
- VIR_DEBUG("mon=%p, device=%s, info=%p", mon, device, info);
+ VIR_DEBUG("mon=%p, device=%s, info=%p, bandwidth=%p",
+ mon, device, info, bandwidth);
if (mon->json)
- ret = qemuMonitorJSONBlockJobInfo(mon, device, info);
+ ret = qemuMonitorJSONBlockJobInfo(mon, device, info, bandwidth);
else
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("block jobs require JSON monitor"));
int qemuMonitorBlockJobInfo(qemuMonitorPtr mon,
const char *device,
- virDomainBlockJobInfoPtr info)
+ virDomainBlockJobInfoPtr info,
+ unsigned long long *bandwidth)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
return ret;
}
-/* Returns -1 on error, 0 if not the right device, 1 if info was populated. */
+/* Returns -1 on error, 0 if not the right device, 1 if info was
+ * populated. However, rather than populate info->bandwidth (which
+ * might overflow on 32-bit machines), bandwidth is tracked optionally
+ * on the side. */
static int
qemuMonitorJSONGetBlockJobInfoOne(virJSONValuePtr entry,
const char *device,
- virDomainBlockJobInfoPtr info)
+ virDomainBlockJobInfoPtr info,
+ unsigned long long *bandwidth)
{
const char *this_dev;
const char *type;
- unsigned long long speed_bytes;
if ((this_dev = virJSONValueObjectGetString(entry, "device")) == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
else
info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
- if (virJSONValueObjectGetNumberUlong(entry, "speed", &speed_bytes) < 0) {
+ if (bandwidth &&
+ virJSONValueObjectGetNumberUlong(entry, "speed", bandwidth) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("entry was missing 'speed'"));
return -1;
}
- info->bandwidth = speed_bytes / 1024ULL / 1024ULL;
if (virJSONValueObjectGetNumberUlong(entry, "offset", &info->cur) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
int
qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon,
const char *device,
- virDomainBlockJobInfoPtr info)
+ virDomainBlockJobInfoPtr info,
+ unsigned long long *bandwidth)
{
virJSONValuePtr cmd = NULL;
virJSONValuePtr reply = NULL;
ret = -1;
goto cleanup;
}
- ret = qemuMonitorJSONGetBlockJobInfoOne(entry, device, info);
+ ret = qemuMonitorJSONGetBlockJobInfoOne(entry, device, info,
+ bandwidth);
}
cleanup:
int qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon,
const char *device,
- virDomainBlockJobInfoPtr info)
+ virDomainBlockJobInfoPtr info,
+ unsigned long long *bandwidth)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuMonitorJSONSetLink(qemuMonitorPtr mon,