Index: qemu/block.c
===================================================================
--- qemu.orig/block.c
+++ qemu/block.c
@@ -651,6 +651,34 @@ 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();
+    if (bdrv_flush(bs)) {
+        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);
+        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) {
@@ -691,6 +719,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);
@@ -97,6 +98,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,64 @@ 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;
+    char usage[50];
+
+    /* 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) {
+        qerror_report(QERR_INVALID_PARAMETER, driver);
+        return -1;
+    }
+
+    /* Before validating parameters, remove "device" option */
+    ret = qemu_opt_delete(opts, "device");
+    if (ret == 1) {
+        strcpy(usage,"block_set device [prop=value][,...]");
+        qerror_report(QERR_INCORRECT_COMMAND_SYNTAX, usage);
+        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 {
+        qerror_report(QERR_INVALID_PARAMETER_VALUE, "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
@@ -517,6 +517,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
@@ -727,7 +727,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",
