]> xenbits.xensource.com Git - qemu-upstream-4.6-testing.git/commitdiff
block: add 'speed' optional parameter to block-stream
authorStefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Wed, 25 Apr 2012 15:51:03 +0000 (16:51 +0100)
committerLuiz Capitulino <lcapitulino@redhat.com>
Fri, 27 Apr 2012 14:44:50 +0000 (11:44 -0300)
Allow streaming operations to be started with an initial speed limit.
This eliminates the window of time between starting streaming and
issuing block-job-set-speed.  Users should use the new optional 'speed'
parameter instead so that speed limits are in effect immediately when
the job starts.

Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Acked-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
block.c
block/stream.c
block_int.h
blockdev.c
hmp-commands.hx
hmp.c
qapi-schema.json
qmp-commands.hx

diff --git a/block.c b/block.c
index 1ab6e525c2634791433048c50fd7fbcc8aacf217..43c794c4d7816ee41a609c556761fed0c119b487 100644 (file)
--- a/block.c
+++ b/block.c
@@ -4083,8 +4083,8 @@ out:
 }
 
 void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
-                       BlockDriverCompletionFunc *cb, void *opaque,
-                       Error **errp)
+                       int64_t speed, BlockDriverCompletionFunc *cb,
+                       void *opaque, Error **errp)
 {
     BlockJob *job;
 
@@ -4100,6 +4100,20 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
     job->cb            = cb;
     job->opaque        = opaque;
     bs->job = job;
+
+    /* Only set speed when necessary to avoid NotSupported error */
+    if (speed != 0) {
+        Error *local_err = NULL;
+
+        block_job_set_speed(job, speed, &local_err);
+        if (error_is_set(&local_err)) {
+            bs->job = NULL;
+            g_free(job);
+            bdrv_set_in_use(bs, 0);
+            error_propagate(errp, local_err);
+            return NULL;
+        }
+    }
     return job;
 }
 
index b66242a7b8fed1274f081624da268168b44e5433..6724af2764fa6c9e0183fa810db33c200d9a9d8c 100644 (file)
@@ -281,13 +281,14 @@ static BlockJobType stream_job_type = {
 };
 
 void stream_start(BlockDriverState *bs, BlockDriverState *base,
-                  const char *base_id, BlockDriverCompletionFunc *cb,
+                  const char *base_id, int64_t speed,
+                  BlockDriverCompletionFunc *cb,
                   void *opaque, Error **errp)
 {
     StreamBlockJob *s;
     Coroutine *co;
 
-    s = block_job_create(&stream_job_type, bs, cb, opaque, errp);
+    s = block_job_create(&stream_job_type, bs, speed, cb, opaque, errp);
     if (!s) {
         return;
     }
index 624b2e634cc2751ce1aeede8f135051457cefa77..086832aab91165e9719c29e7272f2aee64cbe760 100644 (file)
@@ -344,6 +344,7 @@ int is_windows_drive(const char *filename);
  * block_job_create:
  * @job_type: The class object for the newly-created job.
  * @bs: The block
+ * @speed: The maximum speed, in bytes per second, or 0 for unlimited.
  * @cb: Completion function for the job.
  * @opaque: Opaque pointer value passed to @cb.
  * @errp: Error object.
@@ -358,8 +359,8 @@ int is_windows_drive(const char *filename);
  * called from a wrapper that is specific to the job type.
  */
 void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
-                       BlockDriverCompletionFunc *cb, void *opaque,
-                       Error **errp);
+                       int64_t speed, BlockDriverCompletionFunc *cb,
+                       void *opaque, Error **errp);
 
 /**
  * block_job_complete:
@@ -418,6 +419,7 @@ void block_job_cancel_sync(BlockJob *job);
  * flatten the whole backing file chain onto @bs.
  * @base_id: The file name that will be written to @bs as the new
  * backing file if the job completes.  Ignored if @base is %NULL.
+ * @speed: The maximum speed, in bytes per second, or 0 for unlimited.
  * @cb: Completion function for the job.
  * @opaque: Opaque pointer value passed to @cb.
  * @errp: Error object.
@@ -429,7 +431,8 @@ void block_job_cancel_sync(BlockJob *job);
  * @base_id in the written image and to @base in the live BlockDriverState.
  */
 void stream_start(BlockDriverState *bs, BlockDriverState *base,
-                  const char *base_id, BlockDriverCompletionFunc *cb,
+                  const char *base_id, int64_t speed,
+                  BlockDriverCompletionFunc *cb,
                   void *opaque, Error **errp);
 
 #endif /* BLOCK_INT_H */
index 80b62c3b29cd2b54c1016c9fcbb70635c479d1f4..d25ffea9269ec6c6b24b97b77de0094fa60a2ec3 100644 (file)
@@ -1091,7 +1091,8 @@ static void block_stream_cb(void *opaque, int ret)
 }
 
 void qmp_block_stream(const char *device, bool has_base,
-                      const char *base, Error **errp)
+                      const char *base, bool has_speed,
+                      int64_t speed, Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *base_bs = NULL;
@@ -1111,7 +1112,8 @@ void qmp_block_stream(const char *device, bool has_base,
         }
     }
 
-    stream_start(bs, base_bs, base, block_stream_cb, bs, &local_err);
+    stream_start(bs, base_bs, base, has_speed ? speed : 0,
+                 block_stream_cb, bs, &local_err);
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
         return;
index 8a929f096756d1c97214766704592a973660e2af..18cb415ac442680cd0d63d6335656c3f637f1494 100644 (file)
@@ -71,8 +71,8 @@ ETEXI
 
     {
         .name       = "block_stream",
-        .args_type  = "device:B,base:s?",
-        .params     = "device [base]",
+        .args_type  = "device:B,speed:o?,base:s?",
+        .params     = "device [speed [base]]",
         .help       = "copy data from a backing file into a block device",
         .mhandler.cmd = hmp_block_stream,
     },
diff --git a/hmp.c b/hmp.c
index f3e5163f1e4e0d98d91877aa85f1f8469336eb26..eb96618e1ed2dcfabd0094ee8df46280864c1cfb 100644 (file)
--- a/hmp.c
+++ b/hmp.c
@@ -835,8 +835,10 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
     Error *error = NULL;
     const char *device = qdict_get_str(qdict, "device");
     const char *base = qdict_get_try_str(qdict, "base");
+    int64_t speed = qdict_get_try_int(qdict, "speed", 0);
 
-    qmp_block_stream(device, base != NULL, base, &error);
+    qmp_block_stream(device, base != NULL, base,
+                     qdict_haskey(qdict, "speed"), speed, &error);
 
     hmp_handle_error(mon, &error);
 }
index d56fcb639bea0fa7ecc24331400d1f336d698d6c..9193fb996816e861a8b66e4fb6380184c62ca027 100644 (file)
 #
 # @base:   #optional the common backing file name
 #
+# @speed:  #optional the maximum speed, in bytes per second
+#
 # Returns: Nothing on success
 #          If streaming is already active on this device, DeviceInUse
 #          If @device does not exist, DeviceNotFound
 #          If image streaming is not supported by this device, NotSupported
 #          If @base does not exist, BaseNotFound
+#          If @speed is invalid, InvalidParameter
 #
 # Since: 1.1
 ##
-{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str' } }
+{ 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str',
+                                       '*speed': 'int' } }
 
 ##
 # @block-job-set-speed:
 #
 # @device: the device name
 #
-# @speed:  the maximum speed, in bytes per second
+# @speed:  the maximum speed, in bytes per second, or 0 for unlimited.
+#          Defaults to 0.
 #
 # Returns: Nothing on success
 #          If the job type does not support throttling, NotSupported
index b07ed59ccc34f113ee4b0afac5ebbcf584886896..c810c74c117d470ff1a06f963bb270673e37f24a 100644 (file)
@@ -688,7 +688,7 @@ EQMP
 
     {
         .name       = "block-stream",
-        .args_type  = "device:B,base:s?",
+        .args_type  = "device:B,base:s?,speed:o?",
         .mhandler.cmd_new = qmp_marshal_input_block_stream,
     },