Monitor commands "hostcache_set" and "hostcache_get" added for dynamic host cache change and display of host cache setting respectively.
Signed-off-by: Supriya Kannery <supri...@in.ibm.com> --- block.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ block.h | 2 ++ blockdev.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ blockdev.h | 2 ++ hmp-commands.hx | 29 +++++++++++++++++++++++++++++ qmp-commands.hx | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 184 insertions(+) Index: qemu/hmp-commands.hx =================================================================== --- qemu.orig/hmp-commands.hx +++ qemu/hmp-commands.hx @@ -70,6 +70,35 @@ but should be used with extreme caution. resizes image files, it can not resize block devices like LVM volumes. ETEXI + { + .name = "hostcache_get", + .args_type = "device:B", + .params = "device", + .help = "retrieve host cache settings for device", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_hostcache_get, + }, + +STEXI +@item hostcache_get +@findex hostcache_get +Display host cache settings for a block device while guest is running. +ETEXI + + { + .name = "hostcache_set", + .args_type = "device:B,hostcache:s", + .params = "device hostcache", + .help = "change host cache setting for device", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_hostcache_set, + }, + +STEXI +@item hostcache_set +@findex hostcache_set +Change host cache options for a block device while guest is running. +ETEXI { .name = "eject", Index: qemu/block.c =================================================================== --- qemu.orig/block.c +++ qemu/block.c @@ -657,6 +657,34 @@ unlink_and_fail: return ret; } +int bdrv_reopen(BlockDriverState *bs, int bdrv_flags) +{ + BlockDriver *drv = bs->drv; + int ret = 0; + + /* No need to reopen as no change in flags */ + if (bdrv_flags == bs->open_flags) { + return 0; + } + + /* Quiesce IO for the given block device */ + qemu_aio_flush(); + bdrv_flush(bs); + + bdrv_close(bs); + ret = bdrv_open(bs, bs->filename, bdrv_flags, drv); + + /* + * A failed attempt to reopen the image file must lead to 'abort()' + */ + if (ret != 0) { + qerror_report(QERR_REOPEN_FILE_FAILED, bs->filename); + abort(); + } + + return ret; +} + void bdrv_close(BlockDriverState *bs) { if (bs->drv) { @@ -3049,3 +3077,23 @@ out: return ret; } + +int bdrv_change_hostcache(BlockDriverState *bs, bool enable_host_cache) +{ + int bdrv_flags = bs->open_flags; + + /* No change in existing hostcache setting */ + if(!enable_host_cache == (bdrv_flags & BDRV_O_NOCACHE)) { + return -1; + } + + /* set hostcache flags (without changing WCE/flush bits) */ + if(!enable_host_cache) { + bdrv_flags |= BDRV_O_NOCACHE; + } else { + bdrv_flags &= ~BDRV_O_NOCACHE; + } + + /* Reopen file with changed set of flags */ + return(bdrv_reopen(bs, bdrv_flags)); +} Index: qemu/blockdev.c =================================================================== --- qemu.orig/blockdev.c +++ qemu/blockdev.c @@ -796,3 +796,51 @@ int do_block_resize(Monitor *mon, const return 0; } + +int do_hostcache_get(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *device = qdict_get_str(qdict, "device"); + BlockDriverState *bs; + + bs = bdrv_find(device); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, device); + return -1; + } + + monitor_printf(mon, "%s:", device); + + if (bs->open_flags & BDRV_O_NOCACHE) { + monitor_printf(mon, " hostcache=off\n"); + } else { + monitor_printf(mon, " hostcache=on\n"); + } + + return 0; +} + +int do_hostcache_set(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *hostcache = qdict_get_str(qdict, "hostcache"); + BlockDriverState *bs; + bool enable_host_cache = 0; + + bs = bdrv_find(device); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, device); + return -1; + } + + /* cache change applicable only if device inserted */ + if (bdrv_is_inserted(bs)) { + if (!strcmp(hostcache,"on")) + enable_host_cache = 1; + else + enable_host_cache = 0; + return(bdrv_change_hostcache(bs, enable_host_cache)); + } else { + qerror_report(QERR_DEVICE_NOT_INSERTED, device); + return -1; + } +} 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.h =================================================================== --- qemu.orig/blockdev.h +++ qemu/blockdev.h @@ -64,5 +64,7 @@ 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_hostcache_get(Monitor *mon, const QDict *qdict, QObject **ret_data); +int do_hostcache_set(Monitor *mon, const QDict *qdict, QObject **ret_data); #endif Index: qemu/qmp-commands.hx =================================================================== --- qemu.orig/qmp-commands.hx +++ qemu/qmp-commands.hx @@ -664,6 +664,61 @@ Example: -> { "execute": "block_resize", "arguments": { "device": "scratch", "size": 1073741824 } } <- { "return": {} } + +EQMP + + { + .name = "hostcache_get", + .args_type = "device:B", + .params = "device", + .help = "retrieve host cache settings for device", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_hostcache_get, + }, +SQMP +cache_get +--------- + +Retrieve host page cache setting while a guest is running. + +Arguments: + +- "device": the device's ID, must be unique (json-string) + +Example: + +-> { "execute": "hostcache_set", "arguments": { "device": "ide0-hd0" } } +<- { "return": {} } + + +EQMP + + { + .name = "hostcache_set", + .args_type = "device:B,cache:s", + .params = "device cache", + .help = "change hostcache setting for device", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_hostcache_set, + }, + +SQMP +hostcache_set +------------- + +Change host page cache setting while a guest is running. + +Arguments: + +- "device": the device's ID, must be unique (json-string) +- "cache": host cache value "off" or "on" (json-string) + +Example: + +-> { "execute": "hostcache_set", "arguments": { "device": "ide0-hd0", "cache": "on" } } +<- { "return": {} } + + EQMP {