Re: [libvirt] [PATCHv2 02/15] blockjob: wire up qemu async virDomainBlockJobAbort

2012-04-06 Thread Adam Litke
On Thu, Apr 05, 2012 at 10:36:48PM -0600, Eric Blake wrote:
 From: Adam Litke a...@us.ibm.com
 
 Without the VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag, libvirt will internally 
 poll
 using qemu's query-block-jobs API and will not return until the operation 
 has
 been completed.  API users are advised that this operation is unbounded and
 further interaction with the domain during this period may block.  Future
 patches may refactor things to allow other queries in parallel with this
 polling.  Unfortunately, there's no good way to tell if qemu will emit the
 new event, so this implementation always polls to deal with older qemu.
 
 Signed-off-by: Adam Litke a...@us.ibm.com
 Cc: Stefan Hajnoczi stefa...@gmail.com
 Signed-off-by: Eric Blake ebl...@redhat.com

Tested-by: Adam Litke a...@us.ibm.com

 ---
  src/qemu/qemu_driver.c |   55 +--
  1 files changed, 48 insertions(+), 7 deletions(-)
 
 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
 index 0456b34..455fa30 100644
 --- a/src/qemu/qemu_driver.c
 +++ b/src/qemu/qemu_driver.c
 @@ -11602,7 +11602,7 @@ cleanup:
  static int
  qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base,
 unsigned long bandwidth, virDomainBlockJobInfoPtr 
 info,
 -   int mode)
 +   int mode, unsigned int flags)
  {
  struct qemud_driver *driver = dom-conn-privateData;
  virDomainObjPtr vm = NULL;
 @@ -11644,6 +11644,45 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char 
 *path, const char *base,
  ret = qemuMonitorBlockJob(priv-mon, device, base, bandwidth, info, 
 mode);
  qemuDomainObjExitMonitorWithDriver(driver, vm);
 
 +/* Qemu provides asynchronous block job cancellation, but without
 + * the VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag libvirt guarantees a
 + * synchronous operation.  Provide this behavior by waiting here,
 + * so we don't get confused by newly scheduled block jobs.
 + */
 +if (ret == 0  mode == BLOCK_JOB_ABORT 
 +!(flags  VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)) {
 +ret = 1;
 +while (1) {
 +/* Poll every 50ms */
 +struct timespec ts = { .tv_sec = 0,
 +   .tv_nsec = 50 * 1000 * 1000ull };
 +virDomainBlockJobInfo dummy;
 +
 +qemuDomainObjEnterMonitorWithDriver(driver, vm);
 +ret = qemuMonitorBlockJob(priv-mon, device, NULL, 0, dummy,
 +  BLOCK_JOB_INFO);
 +qemuDomainObjExitMonitorWithDriver(driver, vm);
 +
 +if (ret = 0)
 +break;
 +
 +virDomainObjUnlock(vm);
 +qemuDriverUnlock(driver);
 +
 +nanosleep(ts, NULL);
 +
 +qemuDriverLock(driver);
 +virDomainObjLock(vm);
 +
 +if (!virDomainObjIsActive(vm)) {
 +qemuReportError(VIR_ERR_OPERATION_INVALID, %s,
 +_(domain is not running));
 +ret = -1;
 +break;
 +}
 +}
 +}
 +
  endjob:
  if (qemuDomainObjEndJob(driver, vm) == 0) {
  vm = NULL;
 @@ -11661,8 +11700,9 @@ cleanup:
  static int
  qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int 
 flags)
  {
 -virCheckFlags(0, -1);
 -return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT);
 +virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC, -1);
 +return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT,
 +  flags);
  }
 
  static int
 @@ -11670,7 +11710,8 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const 
 char *path,
 virDomainBlockJobInfoPtr info, unsigned int flags)
  {
  virCheckFlags(0, -1);
 -return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO);
 +return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO,
 +  flags);
  }
 
  static int
 @@ -11679,7 +11720,7 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom, const 
 char *path,
  {
  virCheckFlags(0, -1);
  return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
 -  BLOCK_JOB_SPEED);
 +  BLOCK_JOB_SPEED, flags);
  }
 
  static int
 @@ -11690,10 +11731,10 @@ qemuDomainBlockRebase(virDomainPtr dom, const char 
 *path, const char *base,
 
  virCheckFlags(0, -1);
  ret = qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL,
 - BLOCK_JOB_PULL);
 + BLOCK_JOB_PULL, flags);
  if (ret == 0  bandwidth != 0)
  ret = qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
 - BLOCK_JOB_SPEED);
 + BLOCK_JOB_SPEED, flags);
  return ret;
  }
 
 -- 
 

[libvirt] [PATCHv2 02/15] blockjob: wire up qemu async virDomainBlockJobAbort

2012-04-05 Thread Eric Blake
From: Adam Litke a...@us.ibm.com

Without the VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag, libvirt will internally poll
using qemu's query-block-jobs API and will not return until the operation has
been completed.  API users are advised that this operation is unbounded and
further interaction with the domain during this period may block.  Future
patches may refactor things to allow other queries in parallel with this
polling.  Unfortunately, there's no good way to tell if qemu will emit the
new event, so this implementation always polls to deal with older qemu.

Signed-off-by: Adam Litke a...@us.ibm.com
Cc: Stefan Hajnoczi stefa...@gmail.com
Signed-off-by: Eric Blake ebl...@redhat.com
---
 src/qemu/qemu_driver.c |   55 +--
 1 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0456b34..455fa30 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11602,7 +11602,7 @@ cleanup:
 static int
 qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base,
unsigned long bandwidth, virDomainBlockJobInfoPtr info,
-   int mode)
+   int mode, unsigned int flags)
 {
 struct qemud_driver *driver = dom-conn-privateData;
 virDomainObjPtr vm = NULL;
@@ -11644,6 +11644,45 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char 
*path, const char *base,
 ret = qemuMonitorBlockJob(priv-mon, device, base, bandwidth, info, mode);
 qemuDomainObjExitMonitorWithDriver(driver, vm);

+/* Qemu provides asynchronous block job cancellation, but without
+ * the VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag libvirt guarantees a
+ * synchronous operation.  Provide this behavior by waiting here,
+ * so we don't get confused by newly scheduled block jobs.
+ */
+if (ret == 0  mode == BLOCK_JOB_ABORT 
+!(flags  VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC)) {
+ret = 1;
+while (1) {
+/* Poll every 50ms */
+struct timespec ts = { .tv_sec = 0,
+   .tv_nsec = 50 * 1000 * 1000ull };
+virDomainBlockJobInfo dummy;
+
+qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ret = qemuMonitorBlockJob(priv-mon, device, NULL, 0, dummy,
+  BLOCK_JOB_INFO);
+qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+if (ret = 0)
+break;
+
+virDomainObjUnlock(vm);
+qemuDriverUnlock(driver);
+
+nanosleep(ts, NULL);
+
+qemuDriverLock(driver);
+virDomainObjLock(vm);
+
+if (!virDomainObjIsActive(vm)) {
+qemuReportError(VIR_ERR_OPERATION_INVALID, %s,
+_(domain is not running));
+ret = -1;
+break;
+}
+}
+}
+
 endjob:
 if (qemuDomainObjEndJob(driver, vm) == 0) {
 vm = NULL;
@@ -11661,8 +11700,9 @@ cleanup:
 static int
 qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags)
 {
-virCheckFlags(0, -1);
-return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT);
+virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC, -1);
+return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT,
+  flags);
 }

 static int
@@ -11670,7 +11710,8 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char 
*path,
virDomainBlockJobInfoPtr info, unsigned int flags)
 {
 virCheckFlags(0, -1);
-return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO);
+return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO,
+  flags);
 }

 static int
@@ -11679,7 +11720,7 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char 
*path,
 {
 virCheckFlags(0, -1);
 return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
-  BLOCK_JOB_SPEED);
+  BLOCK_JOB_SPEED, flags);
 }

 static int
@@ -11690,10 +11731,10 @@ qemuDomainBlockRebase(virDomainPtr dom, const char 
*path, const char *base,

 virCheckFlags(0, -1);
 ret = qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL,
- BLOCK_JOB_PULL);
+ BLOCK_JOB_PULL, flags);
 if (ret == 0  bandwidth != 0)
 ret = qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL,
- BLOCK_JOB_SPEED);
+ BLOCK_JOB_SPEED, flags);
 return ret;
 }

-- 
1.7.7.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list