From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:38546) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QjRBT-0007dJ-7c for qemu-devel@nongnu.org; Wed, 20 Jul 2011 03:27:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QjRBR-0006TP-I7 for qemu-devel@nongnu.org; Wed, 20 Jul 2011 03:27:07 -0400 Received: from e23smtp06.au.ibm.com ([202.81.31.148]:37775) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QjRBQ-0006Sf-F4 for qemu-devel@nongnu.org; Wed, 20 Jul 2011 03:27:05 -0400 Received: from d23relay04.au.ibm.com (d23relay04.au.ibm.com [202.81.31.246]) by e23smtp06.au.ibm.com (8.14.4/8.13.1) with ESMTP id p6K7Q808017342 for ; Wed, 20 Jul 2011 17:26:08 +1000 Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay04.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p6K7QN35864420 for ; Wed, 20 Jul 2011 17:26:23 +1000 Received: from d23av02.au.ibm.com (loopback [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p6K7Qrqg027612 for ; Wed, 20 Jul 2011 17:26:53 +1000 Message-ID: <4E268600.6060401@in.ibm.com> Date: Wed, 20 Jul 2011 13:08:40 +0530 From: Supriya Kannery MIME-Version: 1.0 References: <20110704104237.28170.97021.sendpatchset@skannery> <20110704104320.28170.29248.sendpatchset@skannery> <4E12ED9A.7070805@in.ibm.com> <4E1D9879.8060009@in.ibm.com> In-Reply-To: <4E1D9879.8060009@in.ibm.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [V4 Patch 3/4 - Updated]Qemu: Command "block_set" for dynamic block params change List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Stefan Hajnoczi Cc: Kevin Wolf , qemu-devel@nongnu.org, Christoph Hellwig On 07/13/2011 06:37 PM, Supriya Kannery wrote: > Updated "block_set" command to accept multiple -drive parameters. > Also, added code for re-opening of device file with original flags, > incase opening file using changed hostcache setting fails. > > ---------------------------------------------------------------------- > New command "block_set" added for dynamically changing any of the block > device parameters. For now, dynamic setting of hostcache params using this > command is implemented. Other block device parameters, can be integrated > in similar lines. > > Signed-off-by: Supriya Kannery > > --- > block.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > block.h | 2 + > blockdev.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > blockdev.h | 1 > hmp-commands.hx | 14 +++++++++++++ > qemu-config.c | 13 ++++++++++++ > qemu-option.c | 25 +++++++++++++++++++++++ > qemu-option.h | 2 + > qmp-commands.hx | 28 ++++++++++++++++++++++++++ > 9 files changed, 205 insertions(+) > > Index: qemu/block.c > =================================================================== > --- qemu.orig/block.c > +++ qemu/block.c > @@ -651,6 +651,40 @@ unlink_and_fail: > return ret; > } > > +int bdrv_reopen(BlockDriverState *bs, int bdrv_flags) > +{ > + BlockDriver *drv = bs->drv; > + int ret = 0; > + > + /* Quiesce IO for the given block device */ > + qemu_aio_flush(); > + if (bdrv_flush(bs)) { > + qerror_report(QERR_DATA_SYNC_FAILED, bs->device_name); > + return ret; > + } > + bdrv_close(bs); > + > + > + ret = bdrv_open(bs, bs->filename, bdrv_flags, drv); > + if (ret < 0) { > + /* Reopen failed. Try to open with original flags */ > + error_report("Opening file with changed flags..."); > + qerror_report(QERR_REOPEN_FILE_FAILED, bs->filename); > + > + ret = bdrv_open(bs, bs->filename, bs->open_flags, drv); > + if (ret < 0) { > + /* > + * Reopen failed with orig and modified flags > + */ > + error_report("Opening file with original flags..."); > + qerror_report(QERR_REOPEN_FILE_FAILED, bs->filename); > + abort(); > + } > + } > + > + return ret; > +} > + > void bdrv_close(BlockDriverState *bs) > { > if (bs->drv) { > @@ -691,6 +725,32 @@ void bdrv_close_all(void) > } > } > > +int bdrv_change_hostcache(BlockDriverState *bs, bool enable_host_cache) > +{ > + int bdrv_flags = bs->open_flags; > + > + /* set hostcache flags (without changing WCE/flush bits) */ > + if (enable_host_cache) { > + bdrv_flags &= ~BDRV_O_NOCACHE; > + } else { > + bdrv_flags |= BDRV_O_NOCACHE; > + } > + > + /* If no change in flags, no need to reopen */ > + if (bdrv_flags == bs->open_flags) { > + return 0; > + } > + > + if (bdrv_is_inserted(bs)) { > + /* Reopen file with changed set of flags */ > + return bdrv_reopen(bs, bdrv_flags); > + } else { > + /* Save hostcache change for future use */ > + bs->open_flags = bdrv_flags; > + return 0; > + } > +} > + > /* make a BlockDriverState anonymous by removing from bdrv_state list. > Also, NULL terminate the device_name to prevent double remove */ > void bdrv_make_anon(BlockDriverState *bs) > Index: qemu/block.h > =================================================================== > --- qemu.orig/block.h > +++ qemu/block.h > @@ -71,6 +71,7 @@ void bdrv_delete(BlockDriverState *bs); > int bdrv_file_open(BlockDriverState **pbs, const char *filename, int > flags); > int bdrv_open(BlockDriverState *bs, const char *filename, int flags, > BlockDriver *drv); > +int bdrv_reopen(BlockDriverState *bs, int bdrv_flags); > void bdrv_close(BlockDriverState *bs); > int bdrv_attach(BlockDriverState *bs, DeviceState *qdev); > void bdrv_detach(BlockDriverState *bs, DeviceState *qdev); > @@ -96,6 +97,7 @@ void bdrv_commit_all(void); > int bdrv_change_backing_file(BlockDriverState *bs, > const char *backing_file, const char *backing_fmt); > void bdrv_register(BlockDriver *bdrv); > +int bdrv_change_hostcache(BlockDriverState *bs, bool enable_host_cache); > > > typedef struct BdrvCheckResult { > Index: qemu/blockdev.c > =================================================================== > --- qemu.orig/blockdev.c > +++ qemu/blockdev.c > @@ -793,3 +793,63 @@ int do_block_resize(Monitor *mon, const > > return 0; > } > + > + > +/* > + * Handle changes to block device settings, like hostcache, > + * while guest is running. > +*/ > +int do_block_set(Monitor *mon, const QDict *qdict, QObject **ret_data) > +{ > + BlockDriverState *bs = NULL; > + QemuOpts *opts; > + int enable; > + const char *device, *driver; > + int ret; > + > + /* Validate device */ > + device = qdict_get_str(qdict, "device"); > + bs = bdrv_find(device); > + if (!bs) { > + qerror_report(QERR_DEVICE_NOT_FOUND, device); > + return -1; > + } > + > + opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict); > + if (opts == NULL) { > + return -1; > + } > + > + /* If input not in "param=value" format, display error */ > + driver = qemu_opt_get(opts, "driver"); > + if (driver != NULL) { > + error_report("Invalid parameter %s", driver); > + return -1; > + } > + > + /* Before validating parameters, remove "device" option */ > + ret = qemu_opt_delete(opts, "device"); > + if (ret == 1) { > + error_report("Specify parameter to be changed"); > + error_report("Usage: block_set device [prop=value][,...]"); > + return 0; > + } > + > + /* Validate parameters with "-drive" parameter list */ > + ret = qemu_validate_opts(opts, "drive"); > + if (ret == -1) { > + return -1; > + } > + > + /* Check for 'hostcache' parameter */ > + enable = qemu_opt_get_bool(opts, "hostcache", -1); > + if (enable != -1) { > + return bdrv_change_hostcache(bs, enable); > + } else { > + error_report("Specify 'hostcache=on/off'"); > + } > + > + return 0; > + > +} > + > Index: qemu/blockdev.h > =================================================================== > --- qemu.orig/blockdev.h > +++ qemu/blockdev.h > @@ -65,5 +65,6 @@ int do_change_block(Monitor *mon, const > int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); > int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject > **ret_data); > int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data); > +int do_block_set(Monitor *mon, const QDict *qdict, QObject **ret_data); > > #endif > Index: qemu/hmp-commands.hx > =================================================================== > --- qemu.orig/hmp-commands.hx > +++ qemu/hmp-commands.hx > @@ -70,6 +70,20 @@ but should be used with extreme caution. > resizes image files, it can not resize block devices like LVM volumes. > ETEXI > > + { > + .name = "block_set", > + .args_type = "device:B,device:O", > + .params = "device [prop=value][,...]", > + .help = "Change block device parameters [hostcache=on/off]", > + .user_print = monitor_user_noop, > + .mhandler.cmd_new = do_block_set, > + }, > +STEXI > +@item block_set @var{config} > +@findex block_set > +Change block device parameters (eg: hostcache=on/off) while guest is > running. > +ETEXI > + > > { > .name = "eject", > Index: qemu/qemu-config.c > =================================================================== > --- qemu.orig/qemu-config.c > +++ qemu/qemu-config.c > @@ -506,6 +506,19 @@ QemuOptsList *qemu_find_opts(const char > return find_list(vm_config_groups, group); > } > > +/* Validate given opts list with that of defined vm_group */ > +int qemu_validate_opts(QemuOpts *opts, const char *group) > +{ > + QemuOptsList *vm_group; > + > + vm_group = qemu_find_opts(group); > + if (vm_group == NULL) { > + return -1; > + } > + > + return qemu_opts_validate(opts, &vm_group->desc[0]); > +} > + > void qemu_add_opts(QemuOptsList *list) > { > int entries, i; > Index: qemu/qemu-option.c > =================================================================== > --- qemu.orig/qemu-option.c > +++ qemu/qemu-option.c > @@ -599,6 +599,31 @@ static void qemu_opt_del(QemuOpt *opt) > qemu_free(opt); > } > > +/* > + * Delete specified parameter with name "name" from opts > + * Return > + * 0 - Deletion Successful > + * -1 - Param doesn't exist in opts > + * 1 - Deletion Successful and opts is empty. > +*/ > + > +int qemu_opt_delete(QemuOpts *opts, const char *name) > +{ > + QemuOpt *opt = qemu_opt_find(opts, name); > + if (opt == NULL) { > + return -1; > + } > + > + qemu_opt_del(opt); > + > + if ((&opts->head)->tqh_first == NULL) { > + /* opt queue is empty */ > + return 1; > + } > + > + return 0; > +} > + > int qemu_opt_set(QemuOpts *opts, const char *name, const char *value) > { > QemuOpt *opt; > Index: qemu/qemu-option.h > =================================================================== > --- qemu.orig/qemu-option.h > +++ qemu/qemu-option.h > @@ -121,6 +121,7 @@ int qemu_opts_set(QemuOptsList *list, co > const char *name, const char *value); > const char *qemu_opts_id(QemuOpts *opts); > void qemu_opts_del(QemuOpts *opts); > +int qemu_opt_delete(QemuOpts *opts, const char *name); > int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc); > int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char > *firstname); > QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int > permit_abbrev); > @@ -131,5 +132,6 @@ typedef int (*qemu_opts_loopfunc)(QemuOp > int qemu_opts_print(QemuOpts *opts, void *dummy); > int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void > *opaque, > int abort_on_failure); > +int qemu_validate_opts(QemuOpts *opts, const char *id); > > #endif > Index: qemu/qmp-commands.hx > =================================================================== > --- qemu.orig/qmp-commands.hx > +++ qemu/qmp-commands.hx > @@ -693,7 +693,35 @@ Example: > > EQMP > > + > { > + .name = "block_set", > + .args_type = "device:B,device:O", > + .params = "device [prop=value][,...]", > + .help = "Change block device parameters [hostcache=on/off]", > + .user_print = monitor_user_noop, > + .mhandler.cmd_new = do_block_set, > + }, > + > +SQMP > +block_set > +--------- > + > +Change various block device parameters (eg: hostcache=on/off) > + > +Arguments: > + > +- "device": the device's ID, must be unique (json-string) > +- device parameters to be changed (eg: "hostcache": "off") > + > +Example: > + > +-> { "execute": "block_set", "arguments": { "device": "ide0-hd0", > "hostcache": "off"} } > +<- { "return": {} } > + > +EQMP > + > + { > .name = "balloon", > .args_type = "value:M", > .params = "target", > Please review..