]> Git Repo - qemu.git/commitdiff
qmp: add block_job_cancel command
authorStefan Hajnoczi <[email protected]>
Wed, 18 Jan 2012 14:40:48 +0000 (14:40 +0000)
committerKevin Wolf <[email protected]>
Thu, 26 Jan 2012 13:49:18 +0000 (14:49 +0100)
Add block_job_cancel, which stops an active block streaming operation.
When the operation has been cancelled the new BLOCK_JOB_CANCELLED event
is emitted.

Signed-off-by: Stefan Hajnoczi <[email protected]>
Acked-by: Luiz Capitulino <[email protected]>
Signed-off-by: Kevin Wolf <[email protected]>
QMP/qmp-events.txt
blockdev.c
hmp-commands.hx
hmp.c
hmp.h
monitor.c
monitor.h
qapi-schema.json
qmp-commands.hx
trace-events

index 0cd2275c3b6a76cc01e3d0fe4753e8bcaec6ad49..06cb40483745a7956a8649845e38bdac8f5363b9 100644 (file)
@@ -293,3 +293,27 @@ Example:
                "len": 10737418240, "offset": 10737418240,
                "speed": 0 },
      "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
+
+
+BLOCK_JOB_CANCELLED
+-------------------
+
+Emitted when a block job has been cancelled.
+
+Data:
+
+- "type":     Job type ("stream" for image streaming, json-string)
+- "device":   Device name (json-string)
+- "len":      Maximum progress value (json-int)
+- "offset":   Current progress value (json-int)
+              On success this is equal to len.
+              On failure this is less than len.
+- "speed":    Rate limit, bytes per second (json-int)
+
+Example:
+
+{ "event": "BLOCK_JOB_CANCELLED",
+     "data": { "type": "stream", "device": "virtio-disk0",
+               "len": 10737418240, "offset": 134217728,
+               "speed": 0 },
+     "timestamp": { "seconds": 1267061043, "microseconds": 959568 } }
index 4c8fcdd31e36308a4039370f0b507cf57007be75..d3d6718056d8df06a6d7f5233b6756c4e9f2367c 100644 (file)
@@ -928,7 +928,11 @@ static void block_stream_cb(void *opaque, int ret)
         qdict_put(dict, "error", qstring_from_str(strerror(-ret)));
     }
 
-    monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj);
+    if (block_job_is_cancelled(bs->job)) {
+        monitor_protocol_event(QEVENT_BLOCK_JOB_CANCELLED, obj);
+    } else {
+        monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, obj);
+    }
     qobject_decref(obj);
 }
 
@@ -989,3 +993,16 @@ void qmp_block_job_set_speed(const char *device, int64_t value, Error **errp)
         error_set(errp, QERR_NOT_SUPPORTED);
     }
 }
+
+void qmp_block_job_cancel(const char *device, Error **errp)
+{
+    BlockJob *job = find_block_job(device);
+
+    if (!job) {
+        error_set(errp, QERR_DEVICE_NOT_ACTIVE, device);
+        return;
+    }
+
+    trace_qmp_block_job_cancel(job);
+    block_job_cancel(job);
+}
index 813705ee3554c3c30cb3865a3a4c668cd6e7c7de..573b8233473c99b35ad8d6460626f467c0311d0c 100644 (file)
@@ -95,6 +95,20 @@ STEXI
 @item block_job_set_stream
 @findex block_job_set_stream
 Set maximum speed for a background block operation.
+ETEXI
+
+    {
+        .name       = "block_job_cancel",
+        .args_type  = "device:B",
+        .params     = "device",
+        .help       = "stop an active block streaming operation",
+        .mhandler.cmd = hmp_block_job_cancel,
+    },
+
+STEXI
+@item block_job_cancel
+@findex block_job_cancel
+Stop an active block streaming operation.
 ETEXI
 
     {
diff --git a/hmp.c b/hmp.c
index bf3d9df88f89080045d62618b732f975ef059041..867c338788a1f407119c49e5316e269df8756489 100644 (file)
--- a/hmp.c
+++ b/hmp.c
@@ -805,3 +805,13 @@ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
 
     hmp_handle_error(mon, &error);
 }
+
+void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
+{
+    Error *error = NULL;
+    const char *device = qdict_get_str(qdict, "device");
+
+    qmp_block_job_cancel(device, &error);
+
+    hmp_handle_error(mon, &error);
+}
diff --git a/hmp.h b/hmp.h
index edd902077ee153810fb8158cfd9c4d39006d537d..eb4ca82853935d011c65368e9e270b0b0836f754 100644 (file)
--- a/hmp.h
+++ b/hmp.h
@@ -56,5 +56,6 @@ void hmp_change(Monitor *mon, const QDict *qdict);
 void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
 void hmp_block_stream(Monitor *mon, const QDict *qdict);
 void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
+void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
 
 #endif
index 3d8cbfbee36525e449bb4c554b48ca3a92795c9d..9424c31edcc552d2b0b785958e4ae84a6282e4e8 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -482,6 +482,9 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
         case QEVENT_BLOCK_JOB_COMPLETED:
             event_name = "BLOCK_JOB_COMPLETED";
             break;
+        case QEVENT_BLOCK_JOB_CANCELLED:
+            event_name = "BLOCK_JOB_CANCELLED";
+            break;
         default:
             abort();
             break;
index 34d00d107e184a4ae6409dbda19c4b6c6a6e5faa..b72ea07050b152f827b766427bc7323f71197b40 100644 (file)
--- a/monitor.h
+++ b/monitor.h
@@ -37,6 +37,7 @@ typedef enum MonitorEvent {
     QEVENT_SPICE_INITIALIZED,
     QEVENT_SPICE_DISCONNECTED,
     QEVENT_BLOCK_JOB_COMPLETED,
+    QEVENT_BLOCK_JOB_CANCELLED,
     QEVENT_MAX,
 } MonitorEvent;
 
index d9f66c67f1d600f8c4f29165b73e80018cdd5354..02c4e22571666da6b45ae5624b4e8164f479ed60 100644 (file)
 ##
 { 'command': 'block_job_set_speed',
   'data': { 'device': 'str', 'value': 'int' } }
+
+##
+# @block_job_cancel:
+#
+# Stop an active block streaming operation.
+#
+# This command returns immediately after marking the active block streaming
+# operation for cancellation.  It is an error to call this command if no
+# operation is in progress.
+#
+# The operation will cancel as soon as possible and then emit the
+# BLOCK_JOB_CANCELLED event.  Before that happens the job is still visible when
+# enumerated using query-block-jobs.
+#
+# The image file retains its backing file unless the streaming operation happens
+# to complete just as it is being cancelled.
+#
+# A new block streaming operation can be started at a later time to finish
+# copying all data from the backing file.
+#
+# @device: the device name
+#
+# Returns: Nothing on success
+#          If streaming is not active on this device, DeviceNotActive
+#          If cancellation already in progress, DeviceInUse
+#
+# Since: 1.1
+##
+{ 'command': 'block_job_cancel', 'data': { 'device': 'str' } }
index e4615ca795addec70c7c229c89a7f607b9f2f1c8..0795c5d48da4965eb3cc496f7923bc4a2964ef8e 100644 (file)
@@ -660,6 +660,12 @@ EQMP
         .mhandler.cmd_new = qmp_marshal_input_block_job_set_speed,
     },
 
+    {
+        .name       = "block_job_cancel",
+        .args_type  = "device:B",
+        .mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
+    },
+
     {
         .name       = "blockdev-snapshot-sync",
         .args_type  = "device:B,snapshot-file:s,format:s?",
index 5edba21a8912b1ad98ae5f71ed4771c16dd75a3c..ad77e0a61783c99811b543d6195522aa3507709e 100644 (file)
@@ -75,6 +75,7 @@ stream_one_iteration(void *s, int64_t sector_num, int nb_sectors, int is_allocat
 stream_start(void *bs, void *base, void *s, void *co, void *opaque) "bs %p base %p s %p co %p opaque %p"
 
 # blockdev.c
+qmp_block_job_cancel(void *job) "job %p"
 block_stream_cb(void *bs, void *job, int ret) "bs %p job %p ret %d"
 qmp_block_stream(void *bs, void *job) "bs %p job %p"
 
This page took 0.049718 seconds and 4 git commands to generate.