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",
