On Wed, 01 Feb 2012 08:36:41 +0530 Supriya Kannery <supri...@linux.vnet.ibm.com> wrote:
> New command "block_set_hostcache" added for dynamically changing > host pagecache setting of a block device. > > Usage: > block_set_hostcache <device> <option> > <device> = block device > <option> = on/off > > Example: > (qemu) block_set_hostcache ide0-hd0 off > > Signed-off-by: Supriya Kannery <supri...@linux.vnet.ibm.com> > > --- > block.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > block.h | 2 ++ > blockdev.c | 26 ++++++++++++++++++++++++++ > blockdev.h | 2 ++ > hmp-commands.hx | 14 ++++++++++++++ > qmp-commands.hx | 27 +++++++++++++++++++++++++++ > 6 files changed, 125 insertions(+) > > Index: qemu/block.c > =================================================================== > --- qemu.orig/block.c > +++ qemu/block.c > @@ -808,6 +808,35 @@ unlink_and_fail: > return ret; > } > > +int bdrv_reopen(BlockDriverState *bs, int bdrv_flags) > +{ > + BlockDriver *drv = bs->drv; > + int ret = 0, open_flags; > + > + /* Quiesce IO for the given block device */ > + qemu_aio_flush(); > + ret = bdrv_flush(bs); > + if (ret != 0) { > + qerror_report(QERR_DATA_SYNC_FAILED, bs->device_name); > + return ret; > + } > + open_flags = bs->open_flags; > + bdrv_close(bs); > + > + ret = bdrv_open(bs, bs->filename, bdrv_flags, drv); > + if (ret < 0) { > + /* Reopen failed. Try to open with original flags */ > + qerror_report(QERR_REOPEN_FILE_FAILED, bs->filename); OPEN_FILE_FAILED is fine. > + ret = bdrv_open(bs, bs->filename, open_flags, drv); > + if (ret < 0) { > + /* Reopen failed with orig and modified flags */ > + abort(); > + } > + } > + > + return ret; > +} > + > void bdrv_close(BlockDriverState *bs) > { > if (bs->drv) { > @@ -870,6 +899,33 @@ void bdrv_drain_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 */ > + bdrv_flags &= ~BDRV_O_CACHE_WB; > + 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 > @@ -119,6 +119,7 @@ int bdrv_parse_cache_flags(const char *m > 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_dev(BlockDriverState *bs, void *dev); > void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev); > @@ -160,6 +161,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 > @@ -1080,3 +1080,29 @@ BlockJobInfoList *qmp_query_block_jobs(E > bdrv_iterate(do_qmp_query_block_jobs_one, &prev); > return dummy.next; > } > + > + > +/* > + * Change host page cache setting while guest is running. > +*/ > +int do_block_set_hostcache(Monitor *mon, const QDict *qdict, > + QObject **ret_data) This is not a QAPI command, please read docs/writing-qmp-commands.txt to know how to write QMP commands using the QAPI. > +{ > + BlockDriverState *bs = NULL; > + int enable; > + const char *device; > + > + /* Validate device */ > + device = qdict_get_str(qdict, "device"); > + bs = bdrv_find(device); > + if (!bs) { > + qerror_report(QERR_DEVICE_NOT_FOUND, device); > + return -1; > + } > + > + /* Read hostcache setting */ > + enable = qdict_get_bool(qdict, "option"); > + return bdrv_change_hostcache(bs, enable); > + > +} > + > Index: qemu/blockdev.h > =================================================================== > --- qemu.orig/blockdev.h > +++ qemu/blockdev.h > @@ -62,4 +62,6 @@ void qmp_change_blockdev(const char *dev > bool has_format, const char *format, Error **errp); > void do_commit(Monitor *mon, const QDict *qdict); > int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data); > +int do_block_set_hostcache(Monitor *mon, const QDict *qdict, > + QObject **ret_data); > #endif > Index: qemu/hmp-commands.hx > =================================================================== > --- qemu.orig/hmp-commands.hx > +++ qemu/hmp-commands.hx > @@ -796,6 +796,20 @@ ETEXI > .mhandler.cmd_new = do_migrate, > }, > > + { > + .name = "block_set_hostcache", > + .args_type = "device:B,option:b", > + .params = "device on|off", > + .help = "Change setting of host pagecache", > + .user_print = monitor_user_noop, > + .mhandler.cmd_new = do_block_set_hostcache, > + }, > +STEXI > +@item block_set_hostcache @var{device} @var{option} > +@findex block_set_hostcache > +Change host pagecache setting of a block device while guest is running. > +ETEXI > + > > STEXI > @item migrate [-d] [-b] [-i] @var{uri} > Index: qemu/qmp-commands.hx > =================================================================== > --- qemu.orig/qmp-commands.hx > +++ qemu/qmp-commands.hx > @@ -698,7 +698,34 @@ Example: > > EQMP > > + > { > + .name = "block_set_hostcache", > + .args_type = "device:B,option:b", > + .params = "device on|off", > + .help = "Change setting of host pagecache (true|false)", > + .user_print = monitor_user_noop, > + .mhandler.cmd_new = do_block_set_hostcache, > + }, > + > +SQMP > +block_set_hostcache > +------------------- > + > +Change host pagecache setting of a block device (on|off) > + > +Arguments: > + > +- "device": the device's ID, must be unique (json-string) > +- "option": hostcache setting (json-bool) > + > +Example: > +-> { "execute": "block_set_hostcache", "arguments": { "device": "ide0-hd0", > "option": false } } > +<- { "return": {} } > + > +EQMP > + > + { > .name = "balloon", > .args_type = "value:M", > .mhandler.cmd_new = qmp_marshal_input_balloon, >