From 4e83dfecc62f282d364b446ce77c8afad9ba29fa Mon Sep 17 00:00:00 2001 From: Jeffrey Cody Date: Wed, 21 Mar 2012 21:54:33 +0100 Subject: [PATCH 06/55] Revert "qmp: add block_stream command" RH-Author: Jeffrey Cody Message-id: Patchwork-id: 38856 O-Subject: [RHEL6.3 qemu-kvm PATCH v8 06/54] Revert "qmp: add block_stream command" Bugzilla: 582475 RH-Acked-by: Paolo Bonzini RH-Acked-by: Marcelo Tosatti RH-Acked-by: Kevin Wolf From: Stefan Hajnoczi This reverts commit 23dc821a5318f6cd2c6f8f0071c2dbd6638a4812. Signed-off-by: Stefan Hajnoczi Signed-off-by: Anthony Liguori Signed-off-by: Jeff Cody --- blockdev.c | 139 ------------------------------------------------------- blockdev.h | 1 - monitor.c | 3 - monitor.h | 1 - qemu-monitor.hx | 69 --------------------------- qerror.c | 8 --- qerror.h | 6 -- 7 files changed, 0 insertions(+), 227 deletions(-) Signed-off-by: Michal Novotny --- blockdev.c | 139 ------------------------------------------------------- blockdev.h | 1 - monitor.c | 3 - monitor.h | 1 - qemu-monitor.hx | 69 --------------------------- qerror.c | 8 --- qerror.h | 6 -- 7 files changed, 0 insertions(+), 227 deletions(-) diff --git a/blockdev.c b/blockdev.c index f8c1111..402cd40 100644 --- a/blockdev.c +++ b/blockdev.c @@ -15,7 +15,6 @@ #include "qemu-config.h" #include "sysemu.h" #include "block_int.h" -#include "qjson.h" #include "qmp-commands.h" struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); @@ -52,137 +51,6 @@ static const int if_max_devs[IF_COUNT] = { [IF_SCSI] = 7, }; -typedef struct StreamState { - int64_t offset; /* current position in block device */ - BlockDriverState *bs; - QEMUTimer *timer; - QLIST_ENTRY(StreamState) list; -} StreamState; - -static QLIST_HEAD(, StreamState) block_streams = - QLIST_HEAD_INITIALIZER(block_streams); - -static QObject *stream_get_qobject(StreamState *s) -{ - const char *name = bdrv_get_device_name(s->bs); - int64_t len = bdrv_getlength(s->bs); - - return qobject_from_jsonf("{ 'device': %s, 'type': 'stream', " - "'offset': %" PRId64 ", 'len': %" PRId64 ", " - "'speed': %" PRId64 " }", - name, s->offset, len, (int64_t)0); -} - -static void stream_mon_event(StreamState *s, int ret) -{ - QObject *data = stream_get_qobject(s); - - if (ret < 0) { - QDict *qdict = qobject_to_qdict(data); - - qdict_put(qdict, "error", qstring_from_str(strerror(-ret))); - } - - monitor_protocol_event(QEVENT_BLOCK_JOB_COMPLETED, data); - qobject_decref(data); -} - -static void stream_free(StreamState *s) -{ - QLIST_REMOVE(s, list); - - bdrv_set_in_use(s->bs, 0); - qemu_del_timer(s->timer); - qemu_free_timer(s->timer); - qemu_free(s); -} - -static void stream_complete(StreamState *s, int ret) -{ - stream_mon_event(s, ret); - stream_free(s); -} - -static void stream_cb(void *opaque, int nb_sectors) -{ - StreamState *s = opaque; - - if (nb_sectors < 0) { - stream_complete(s, nb_sectors); - return; - } - - s->offset += nb_sectors * BDRV_SECTOR_SIZE; - - if (s->offset == bdrv_getlength(s->bs)) { - bdrv_change_backing_file(s->bs, NULL, NULL); - stream_complete(s, 0); - } else { - qemu_mod_timer(s->timer, qemu_get_clock(rt_clock)); - } -} - -/* We can't call bdrv_aio_stream() directly from the callback because that - * makes qemu_aio_flush() not complete until the streaming is completed. - * By delaying with a timer, we give qemu_aio_flush() a chance to complete. - */ -static void stream_next_iteration(void *opaque) -{ - StreamState *s = opaque; - - bdrv_aio_copy_backing(s->bs, s->offset / BDRV_SECTOR_SIZE, stream_cb, s); -} - -static StreamState *stream_find(const char *device) -{ - StreamState *s; - - QLIST_FOREACH(s, &block_streams, list) { - if (strcmp(bdrv_get_device_name(s->bs), device) == 0) { - return s; - } - } - return NULL; -} - -static StreamState *stream_start(const char *device) -{ - StreamState *s; - BlockDriverAIOCB *acb; - BlockDriverState *bs; - - s = stream_find(device); - if (s) { - qerror_report(QERR_DEVICE_IN_USE, device); - return NULL; - } - - bs = bdrv_find(device); - if (!bs) { - qerror_report(QERR_DEVICE_NOT_FOUND, device); - return NULL; - } - if (bdrv_in_use(bs)) { - qerror_report(QERR_DEVICE_IN_USE, device); - return NULL; - } - bdrv_set_in_use(bs, 1); - - s = qemu_mallocz(sizeof(*s)); - s->bs = bs; - s->timer = qemu_new_timer(rt_clock, stream_next_iteration, s); - QLIST_INSERT_HEAD(&block_streams, s, list); - - acb = bdrv_aio_copy_backing(s->bs, s->offset / BDRV_SECTOR_SIZE, - stream_cb, s); - if (acb == NULL) { - stream_free(s); - qerror_report(QERR_NOT_SUPPORTED); - return NULL; - } - return s; -} - /* * We automatically delete the drive when a device using it gets * unplugged. Questionable feature, but we can't just drop it. @@ -966,13 +834,6 @@ exit: } #endif -int do_block_stream(Monitor *mon, const QDict *params, QObject **ret_data) -{ - const char *device = qdict_get_str(params, "device"); - - return stream_start(device) ? 0 : -1; -} - static int eject_device(Monitor *mon, BlockDriverState *bs, int force) { if (!bdrv_dev_has_removable_media(bs)) { diff --git a/blockdev.h b/blockdev.h index 5a6d9fc..171401c 100644 --- a/blockdev.h +++ b/blockdev.h @@ -71,6 +71,5 @@ int do_change_block(Monitor *mon, const char *device, const char *filename, const char *fmt); int simple_drive_add(Monitor *mon, const QDict *qdict, QObject **ret_data); int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); -int do_block_stream(Monitor *mon, const QDict *params, QObject **ret_data); #endif diff --git a/monitor.c b/monitor.c index 9930635..b714e99 100644 --- a/monitor.c +++ b/monitor.c @@ -484,9 +484,6 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) case QEVENT_RH_SPICE_DISCONNECTED: event_name = RFQDN_REDHAT "SPICE_DISCONNECTED"; break; - case QEVENT_BLOCK_JOB_COMPLETED: - event_name = "BLOCK_JOB_COMPLETED"; - break; case QEVENT_SUSPEND: event_name = "SUSPEND"; break; diff --git a/monitor.h b/monitor.h index 8db2523..b4481cf 100644 --- a/monitor.h +++ b/monitor.h @@ -41,7 +41,6 @@ typedef enum MonitorEvent { QEVENT_DEVICE_TRAY_MOVED, QEVENT_RH_SPICE_INITIALIZED, QEVENT_RH_SPICE_DISCONNECTED, - QEVENT_BLOCK_JOB_COMPLETED, QEVENT_SUSPEND, QEVENT_WAKEUP, QEVENT_MAX, diff --git a/qemu-monitor.hx b/qemu-monitor.hx index b974542..07d8739 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -99,75 +99,6 @@ Commit changes to the disk images (if -snapshot is used) or backing files. ETEXI { - .name = "block_stream", - .args_type = "device:B", - .params = "device", - .help = "Copy data from a backing file into a block device", - .user_print = monitor_user_noop, - .mhandler.cmd_new = do_block_stream, - }, - -STEXI -@item block_stream -@findex block_stream -Copy data from a backing file into a block device. -ETEXI -SQMP - -Copy data from a backing file into a block device. - -The block streaming operation is performed in the background until the entire -backing file has been copied. This command returns immediately once streaming -has started. The status of ongoing block streaming operations can be checked -with query-block-jobs. The operation can be stopped before it has completed -using the block_job_cancel command. - -If a base file is specified then sectors are not copied from that base file and -its backing chain. When streaming completes the image file will have the base -file as its backing file. This can be used to stream a subset of the backing -file chain instead of flattening the entire image. - -On successful completion the image file is updated to drop the backing file. - -Arguments: - -- device: device name (json-string) -- base: common backing file (json-string, optional) - -Errors: - -DeviceInUse: streaming is already active on this device -DeviceNotFound: device name is invalid -NotSupported: image streaming is not supported by this device - -Events: - -On completion the BLOCK_JOB_COMPLETED event is raised with the following -fields: - -- type: job type ("stream" for image streaming, json-string) -- device: device name (json-string) -- end: maximum progress value (json-int) -- position: current progress value (json-int) -- speed: rate limit, bytes per second (json-int) -- error: error message (json-string, only on error) - -The completion event is raised both on success and on failure. On -success position is equal to end. On failure position and end can be -used to indicate at which point the operation failed. - -On failure the error field contains a human-readable error message. There are -no semantics other than that streaming has failed and clients should not try -to interpret the error string. - -Examples: - --> { "execute": "block_stream", "arguments": { "device": "virtio0" } } -<- { "return": {} } - -EQMP - - { .name = "q|quit", .args_type = "", .params = "", diff --git a/qerror.c b/qerror.c index 5261552..29d6577 100644 --- a/qerror.c +++ b/qerror.c @@ -174,10 +174,6 @@ static const QErrorStringTable qerror_table[] = { .desc = "No '%(bus)' bus found for device '%(device)'", }, { - .error_fmt = QERR_NOT_SUPPORTED, - .desc = "Operation is not supported", - }, - { .error_fmt = QERR_OPEN_FILE_FAILED, .desc = "Could not open '%(filename)'", }, @@ -246,10 +242,6 @@ static const QErrorStringTable qerror_table[] = { .error_fmt = QERR_QGA_COMMAND_FAILED, .desc = "Guest agent command failed, error was '%(message)'", }, - { - .error_fmt = QERR_STREAMING_ERROR, - .desc = "An error occurred during streaming: %(msg)", - }, {} }; diff --git a/qerror.h b/qerror.h index bff2b8e..27de1da 100644 --- a/qerror.h +++ b/qerror.h @@ -152,9 +152,6 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_NO_BUS_FOR_DEVICE \ "{ 'class': 'NoBusForDevice', 'data': { 'device': %s, 'bus': %s } }" -#define QERR_NOT_SUPPORTED \ - "{ 'class': 'NotSupported', 'data': {} }" - #define QERR_OPEN_FILE_FAILED \ "{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }" @@ -200,9 +197,6 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_VNC_SERVER_FAILED \ "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }" -#define QERR_STREAMING_ERROR \ - "{ 'class': 'StreamingError', 'data': { 'msg': %s } }" - #define QERR_QGA_LOGGING_FAILED \ "{ 'class': 'QgaLoggingFailed', 'data': {} }" -- 1.7.7.6