Merge remote-tracking branch 'kwolf/for-anthony' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Fri, 5 Oct 2012 00:53:50 +0000 (19:53 -0500)
committerAnthony Liguori <aliguori@us.ibm.com>
Fri, 5 Oct 2012 00:53:50 +0000 (19:53 -0500)
* kwolf/for-anthony: (30 commits)
  qemu-iotests: add tests for streaming error handling
  qemu-iotests: map underscore to dash in QMP argument names
  blkdebug: process all set_state rules in the old state
  stream: add on-error argument
  block: introduce block job error
  iostatus: reorganize io error code
  iostatus: change is_read to a bool
  iostatus: move BlockdevOnError declaration to QAPI
  iostatus: rename BlockErrorAction, BlockQMPEventAction
  qemu-iotests: add test for pausing a streaming operation
  qmp: add block-job-pause and block-job-resume
  block: add support for job pause/resume
  qmp: add 'busy' member to BlockJobInfo
  block: add block_job_query
  block: move job APIs to separate files
  block: fix documentation of block_job_cancel_sync
  qerror/block: introduce QERR_BLOCK_JOB_NOT_ACTIVE
  qemu-iotests: add initial tests for live block commit
  QAPI: add command for live block commit, 'block-commit'
  block: helper function, to find the base image of a chain
  ...

1  2 
configure
hmp-commands.hx
hmp.c
monitor.c
monitor.h
qapi-schema.json
qmp-commands.hx

diff --combined configure
index c5e5bb2e81f693518d8a5bb58165ccb47abc0be5,72d4b0d989e44b23fb9d69edca1b7d40685fcd62..e58846d5e242a4763be782f6573e24a9c527a817
+++ b/configure
@@@ -219,6 -219,7 +219,7 @@@ want_tools="yes
  libiscsi=""
  coroutine=""
  seccomp=""
+ glusterfs=""
  
  # parse CC options first
  for opt do
@@@ -856,6 -857,10 +857,10 @@@ for opt d
    ;;
    --disable-seccomp) seccomp="no"
    ;;
+   --disable-glusterfs) glusterfs="no"
+   ;;
+   --enable-glusterfs) glusterfs="yes"
+   ;;
    *) echo "ERROR: unknown option $opt"; show_help="yes"
    ;;
    esac
@@@ -1128,6 -1133,8 +1133,8 @@@ echo "  --disable-seccomp        disabl
  echo "  --enable-seccomp         enables seccomp support"
  echo "  --with-coroutine=BACKEND coroutine backend. Supported options:"
  echo "                           gthread, ucontext, sigaltstack, windows"
+ echo "  --enable-glusterfs       enable GlusterFS backend"
+ echo "  --disable-glusterfs      disable GlusterFS backend"
  echo ""
  echo "NOTE: The object files are built at the place where configure is launched"
  exit 1
    fi
  fi
  
+ ##########################################
+ # glusterfs probe
+ if test "$glusterfs" != "no" ; then
+   cat > $TMPC <<EOF
+ #include <glusterfs/api/glfs.h>
+ int main(void) {
+     (void) glfs_new("volume");
+     return 0;
+ }
+ EOF
+   glusterfs_libs="-lgfapi -lgfrpc -lgfxdr"
+   if compile_prog "" "$glusterfs_libs" ; then
+     glusterfs=yes
+     libs_tools="$glusterfs_libs $libs_tools"
+     libs_softmmu="$glusterfs_libs $libs_softmmu"
+   else
+     if test "$glusterfs" = "yes" ; then
+       feature_not_found "GlusterFS backend support"
+     fi
+     glusterfs=no
+   fi
+ fi
  #
  # Check for xxxat() functions when we are building linux-user
  # emulator.  This is done because older glibc versions don't
  
  # check for usbredirparser for usb network redirection support
  if test "$usb_redir" != "no" ; then
 -    if $pkg_config --atleast-version=0.5 libusbredirparser >/dev/null 2>&1 ; then
 +    if $pkg_config --atleast-version=0.5 libusbredirparser-0.5 >/dev/null 2>&1 ; then
          usb_redir="yes"
 -        usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
 -        usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
 +        usb_redir_cflags=$($pkg_config --cflags libusbredirparser-0.5 2>/dev/null)
 +        usb_redir_libs=$($pkg_config --libs libusbredirparser-0.5 2>/dev/null)
          QEMU_CFLAGS="$QEMU_CFLAGS $usb_redir_cflags"
          libs_softmmu="$libs_softmmu $usb_redir_libs"
      else
@@@ -3170,6 -3200,7 +3200,7 @@@ echo "libiscsi support  $libiscsi
  echo "build guest agent $guest_agent"
  echo "seccomp support   $seccomp"
  echo "coroutine backend $coroutine_backend"
+ echo "GlusterFS support $glusterfs"
  
  if test "$sdl_too_old" = "yes"; then
  echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@@ -3516,6 -3547,10 +3547,10 @@@ if test "$has_environ" = "yes" ; the
    echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
  fi
  
+ if test "$glusterfs" = "yes" ; then
+   echo "CONFIG_GLUSTERFS=y" >> $config_host_mak
+ fi
  # USB host support
  case "$usb" in
  linux)
@@@ -3694,6 -3729,7 +3729,6 @@@ TARGET_ABI_DIR="
  
  case "$target_arch2" in
    i386)
 -    target_phys_bits=64
    ;;
    x86_64)
      TARGET_BASE_ARCH=i386
      target_long_alignment=8
    ;;
    alpha)
 -    target_phys_bits=64
      target_long_alignment=8
      target_nptl="yes"
    ;;
      bflt="yes"
      target_nptl="yes"
      gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
 -    target_phys_bits=64
      target_llong_alignment=4
      target_libs_softmmu="$fdt_libs"
    ;;
    cris)
      target_nptl="yes"
 -    target_phys_bits=32
    ;;
    lm32)
 -    target_phys_bits=32
      target_libs_softmmu="$opengl_libs"
    ;;
    m68k)
      bflt="yes"
      gdb_xml_files="cf-core.xml cf-fp.xml"
 -    target_phys_bits=32
      target_int_alignment=2
      target_long_alignment=2
      target_llong_alignment=2
      TARGET_ARCH=microblaze
      bflt="yes"
      target_nptl="yes"
 -    target_phys_bits=32
      target_libs_softmmu="$fdt_libs"
    ;;
    mips|mipsel)
      TARGET_ARCH=mips
      echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
      target_nptl="yes"
 -    target_phys_bits=64
    ;;
    mipsn32|mipsn32el)
      TARGET_ARCH=mipsn32
      TARGET_BASE_ARCH=mips
      echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak
 -    target_phys_bits=64
    ;;
    mips64|mips64el)
      TARGET_ARCH=mips64
      TARGET_BASE_ARCH=mips
      echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
 -    target_phys_bits=64
      target_long_alignment=8
    ;;
    or32)
      TARGET_ARCH=openrisc
      TARGET_BASE_ARCH=openrisc
 -    target_phys_bits=32
    ;;
    ppc)
      gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
 -    target_phys_bits=64
      target_nptl="yes"
      target_libs_softmmu="$fdt_libs"
    ;;
      TARGET_BASE_ARCH=ppc
      TARGET_ABI_DIR=ppc
      gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
 -    target_phys_bits=64
      target_nptl="yes"
      target_libs_softmmu="$fdt_libs"
    ;;
      TARGET_BASE_ARCH=ppc
      TARGET_ABI_DIR=ppc
      gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
 -    target_phys_bits=64
      target_long_alignment=8
      target_libs_softmmu="$fdt_libs"
    ;;
      TARGET_ABI_DIR=ppc
      echo "TARGET_ABI32=y" >> $config_target_mak
      gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
 -    target_phys_bits=64
      target_libs_softmmu="$fdt_libs"
    ;;
    sh4|sh4eb)
      TARGET_ARCH=sh4
      bflt="yes"
      target_nptl="yes"
 -    target_phys_bits=32
    ;;
    sparc)
 -    target_phys_bits=64
    ;;
    sparc64)
      TARGET_BASE_ARCH=sparc
 -    target_phys_bits=64
      target_long_alignment=8
    ;;
    sparc32plus)
      TARGET_BASE_ARCH=sparc
      TARGET_ABI_DIR=sparc
      echo "TARGET_ABI32=y" >> $config_target_mak
 -    target_phys_bits=64
    ;;
    s390x)
      target_nptl="yes"
 -    target_phys_bits=64
      target_long_alignment=8
    ;;
    unicore32)
    ;;
    xtensa|xtensaeb)
      TARGET_ARCH=xtensa
 -    target_phys_bits=32
    ;;
    *)
      echo "Unsupported target CPU"
@@@ -3838,6 -3894,7 +3873,6 @@@ echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >
  case "$target_arch2" in
    i386|x86_64)
      if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
 -      target_phys_bits=64
        echo "CONFIG_XEN=y" >> $config_target_mak
        if test "$xen_pci_passthrough" = yes; then
          echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak"
@@@ -3877,10 -3934,11 +3912,10 @@@ if test "$target_bigendian" = "yes" ; t
    echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
  fi
  if test "$target_softmmu" = "yes" ; then
 -  echo "TARGET_PHYS_ADDR_BITS=$target_phys_bits" >> $config_target_mak
    echo "CONFIG_SOFTMMU=y" >> $config_target_mak
    echo "LIBS+=$libs_softmmu $target_libs_softmmu" >> $config_target_mak
 -  echo "HWDIR=../libhw$target_phys_bits" >> $config_target_mak
 -  echo "subdir-$target: subdir-libhw$target_phys_bits" >> $config_host_mak
 +  echo "HWDIR=../libhw" >> $config_target_mak
 +  echo "subdir-$target: subdir-libhw" >> $config_host_mak
    if test "$smartcard_nss" = "yes" ; then
      echo "subdir-$target: subdir-libcacard" >> $config_host_mak
    fi
@@@ -4122,8 -4180,11 +4157,8 @@@ for rom in seabios vgabios ; d
      echo "LD=$ld" >> $config_mak
  done
  
 -for hwlib in 32 64; do
 -  d=libhw$hwlib
 -  symlink "$source_path/Makefile.hw" "$d/Makefile"
 -  echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
 -done
 +d=libhw
 +symlink "$source_path/Makefile.hw" "$d/Makefile"
  
  d=libuser
  symlink "$source_path/Makefile.user" "$d/Makefile"
diff --combined hmp-commands.hx
index 0302458df22083b3612bff1485746bdd19b621e8,27d90a24af7a49c3189508f9c64987d946b9c486..e0b537d0cc5dba778465ad12f67a24c3398acf79
@@@ -99,9 -99,10 +99,10 @@@ ETEX
  
      {
          .name       = "block_job_cancel",
-         .args_type  = "device:B",
-         .params     = "device",
-         .help       = "stop an active background block operation",
+         .args_type  = "force:-f,device:B",
+         .params     = "[-f] device",
+         .help       = "stop an active background block operation (use -f"
+                       "\n\t\t\t if the operation is currently paused)",
          .mhandler.cmd = hmp_block_job_cancel,
      },
  
@@@ -109,6 -110,34 +110,34 @@@ STEX
  @item block_job_cancel
  @findex block_job_cancel
  Stop an active block streaming operation.
+ ETEXI
+     {
+         .name       = "block_job_pause",
+         .args_type  = "device:B",
+         .params     = "device",
+         .help       = "pause an active background block operation",
+         .mhandler.cmd = hmp_block_job_pause,
+     },
+ STEXI
+ @item block_job_pause
+ @findex block_job_pause
+ Pause an active block streaming operation.
+ ETEXI
+     {
+         .name       = "block_job_resume",
+         .args_type  = "device:B",
+         .params     = "device",
+         .help       = "resume a paused background block operation",
+         .mhandler.cmd = hmp_block_job_resume,
+     },
+ STEXI
+ @item block_job_resume
+ @findex block_job_resume
+ Resume a paused block streaming operation.
  ETEXI
  
      {
@@@ -914,11 -943,12 +943,11 @@@ ETEX
  #if defined(CONFIG_HAVE_CORE_DUMP)
      {
          .name       = "dump-guest-memory",
 -        .args_type  = "paging:-p,protocol:s,begin:i?,length:i?",
 -        .params     = "[-p] protocol [begin] [length]",
 +        .args_type  = "paging:-p,filename:F,begin:i?,length:i?",
 +        .params     = "[-p] filename [begin] [length]",
          .help       = "dump guest memory to file"
                        "\n\t\t\t begin(optional): the starting physical address"
                        "\n\t\t\t length(optional): the memory size, in bytes",
 -        .user_print = monitor_user_noop,
          .mhandler.cmd = hmp_dump_guest_memory,
      },
  
@@@ -928,7 -958,8 +957,7 @@@ STEX
  @findex dump-guest-memory
  Dump guest memory to @var{protocol}. The file can be processed with crash or
  gdb.
 -  protocol: destination file(started with "file:") or destination file
 -            descriptor (started with "fd:")
 +  filename: dump file name
      paging: do paging to get guest's memory mapping
       begin: the starting physical address. It's optional, and should be
              specified with length together.
diff --combined hmp.c
index 3306bcdbb446fad76299beee8a8165a342d711fe,df789b2351304003c34601698565c3c8b4a5aafd..70bdec24330e310e6984a3a72b75fbe0c523846e
--- 1/hmp.c
--- 2/hmp.c
+++ b/hmp.c
@@@ -930,7 -930,8 +930,8 @@@ void hmp_block_stream(Monitor *mon, con
      int64_t speed = qdict_get_try_int(qdict, "speed", 0);
  
      qmp_block_stream(device, base != NULL, base,
-                      qdict_haskey(qdict, "speed"), speed, &error);
+                      qdict_haskey(qdict, "speed"), speed,
+                      BLOCKDEV_ON_ERROR_REPORT, true, &error);
  
      hmp_handle_error(mon, &error);
  }
@@@ -950,8 -951,29 +951,29 @@@ void hmp_block_job_cancel(Monitor *mon
  {
      Error *error = NULL;
      const char *device = qdict_get_str(qdict, "device");
+     bool force = qdict_get_try_bool(qdict, "force", 0);
  
-     qmp_block_job_cancel(device, &error);
+     qmp_block_job_cancel(device, true, force, &error);
+     hmp_handle_error(mon, &error);
+ }
+ void hmp_block_job_pause(Monitor *mon, const QDict *qdict)
+ {
+     Error *error = NULL;
+     const char *device = qdict_get_str(qdict, "device");
+     qmp_block_job_pause(device, &error);
+     hmp_handle_error(mon, &error);
+ }
+ void hmp_block_job_resume(Monitor *mon, const QDict *qdict)
+ {
+     Error *error = NULL;
+     const char *device = qdict_get_str(qdict, "device");
+     qmp_block_job_resume(device, &error);
  
      hmp_handle_error(mon, &error);
  }
@@@ -1042,12 -1064,11 +1064,12 @@@ void hmp_dump_guest_memory(Monitor *mon
  {
      Error *errp = NULL;
      int paging = qdict_get_try_bool(qdict, "paging", 0);
 -    const char *file = qdict_get_str(qdict, "protocol");
 +    const char *file = qdict_get_str(qdict, "filename");
      bool has_begin = qdict_haskey(qdict, "begin");
      bool has_length = qdict_haskey(qdict, "length");
      int64_t begin = 0;
      int64_t length = 0;
 +    char *prot;
  
      if (has_begin) {
          begin = qdict_get_int(qdict, "begin");
          length = qdict_get_int(qdict, "length");
      }
  
 -    qmp_dump_guest_memory(paging, file, has_begin, begin, has_length, length,
 +    prot = g_strconcat("file:", file, NULL);
 +
 +    qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
                            &errp);
      hmp_handle_error(mon, &errp);
 +    g_free(prot);
  }
  
  void hmp_netdev_add(Monitor *mon, const QDict *qdict)
@@@ -1113,13 -1131,13 +1135,13 @@@ void hmp_closefd(Monitor *mon, const QD
  void hmp_send_key(Monitor *mon, const QDict *qdict)
  {
      const char *keys = qdict_get_str(qdict, "keys");
 -    QKeyCodeList *keylist, *head = NULL, *tmp = NULL;
 +    KeyValueList *keylist, *head = NULL, *tmp = NULL;
      int has_hold_time = qdict_haskey(qdict, "hold-time");
      int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
      Error *err = NULL;
      char keyname_buf[16];
      char *separator;
 -    int keyname_len, idx;
 +    int keyname_len;
  
      while (1) {
          separator = strchr(keys, '-');
          }
          keyname_buf[keyname_len] = 0;
  
 -        idx = index_from_key(keyname_buf);
 -        if (idx == Q_KEY_CODE_MAX) {
 -            monitor_printf(mon, "invalid parameter: %s\n", keyname_buf);
 -            break;
 -        }
 -
          keylist = g_malloc0(sizeof(*keylist));
 -        keylist->value = idx;
 -        keylist->next = NULL;
 +        keylist->value = g_malloc0(sizeof(*keylist->value));
  
          if (!head) {
              head = keylist;
          }
          tmp = keylist;
  
 +        if (strstart(keyname_buf, "0x", NULL)) {
 +            char *endp;
 +            int value = strtoul(keyname_buf, &endp, 0);
 +            if (*endp != '\0') {
 +                goto err_out;
 +            }
 +            keylist->value->kind = KEY_VALUE_KIND_NUMBER;
 +            keylist->value->number = value;
 +        } else {
 +            int idx = index_from_key(keyname_buf);
 +            if (idx == Q_KEY_CODE_MAX) {
 +                goto err_out;
 +            }
 +            keylist->value->kind = KEY_VALUE_KIND_QCODE;
 +            keylist->value->qcode = idx;
 +        }
 +
          if (!separator) {
              break;
          }
          keys = separator + 1;
      }
  
 -    if (idx != Q_KEY_CODE_MAX) {
 -        qmp_send_key(head, has_hold_time, hold_time, &err);
 -    }
 +    qmp_send_key(head, has_hold_time, hold_time, &err);
      hmp_handle_error(mon, &err);
 -    qapi_free_QKeyCodeList(head);
 +
 +out:
 +    qapi_free_KeyValueList(head);
 +    return;
 +
 +err_out:
 +    monitor_printf(mon, "invalid parameter: %s\n", keyname_buf);
 +    goto out;
  }
  
  void hmp_screen_dump(Monitor *mon, const QDict *qdict)
diff --combined monitor.c
index cd735bbbebb3816454e063e35eb13c08916a9b6b,d4bd5feb60e7fe5314d26f2833592e82a596973f..a0e3ffb92467534c4e9287c665175fbc814f42c9
+++ b/monitor.c
@@@ -450,6 -450,7 +450,7 @@@ static const char *monitor_event_names[
      [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED",
      [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
      [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
+     [QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR",
      [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
      [QEVENT_SUSPEND] = "SUSPEND",
      [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
@@@ -944,6 -945,45 +945,6 @@@ static void do_trace_print_events(Monit
      trace_print_events((FILE *)mon, &monitor_fprintf);
  }
  
 -static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_data)
 -{
 -    const char *protocol  = qdict_get_str(qdict, "protocol");
 -    const char *fdname = qdict_get_str(qdict, "fdname");
 -    CharDriverState *s;
 -
 -    if (strcmp(protocol, "spice") == 0) {
 -        int fd = monitor_get_fd(mon, fdname);
 -        int skipauth = qdict_get_try_bool(qdict, "skipauth", 0);
 -        int tls = qdict_get_try_bool(qdict, "tls", 0);
 -        if (!using_spice) {
 -            /* correct one? spice isn't a device ,,, */
 -            qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
 -            return -1;
 -        }
 -        if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
 -            close(fd);
 -        }
 -        return 0;
 -#ifdef CONFIG_VNC
 -    } else if (strcmp(protocol, "vnc") == 0) {
 -      int fd = monitor_get_fd(mon, fdname);
 -        int skipauth = qdict_get_try_bool(qdict, "skipauth", 0);
 -      vnc_display_add_client(NULL, fd, skipauth);
 -      return 0;
 -#endif
 -    } else if ((s = qemu_chr_find(protocol)) != NULL) {
 -      int fd = monitor_get_fd(mon, fdname);
 -      if (qemu_chr_add_client(s, fd) < 0) {
 -          qerror_report(QERR_ADD_CLIENT_FAILED);
 -          return -1;
 -      }
 -      return 0;
 -    }
 -
 -    qerror_report(QERR_INVALID_PARAMETER, "protocol");
 -    return -1;
 -}
 -
  static int client_migrate_info(Monitor *mon, const QDict *qdict,
                                 MonitorCompletion cb, void *opaque)
  {
@@@ -2079,7 -2119,7 +2080,7 @@@ static void do_loadvm(Monitor *mon, con
      }
  }
  
 -int monitor_get_fd(Monitor *mon, const char *fdname)
 +int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp)
  {
      mon_fd_t *monfd;
  
          return fd;
      }
  
 +    error_setg(errp, "File descriptor named '%s' has not been found", fdname);
      return -1;
  }
  
@@@ -2372,14 -2411,12 +2373,14 @@@ int monitor_fdset_dup_fd_remove(int dup
  int monitor_handle_fd_param(Monitor *mon, const char *fdname)
  {
      int fd;
 +    Error *local_err = NULL;
  
      if (!qemu_isdigit(fdname[0]) && mon) {
  
 -        fd = monitor_get_fd(mon, fdname);
 +        fd = monitor_get_fd(mon, fdname, &local_err);
          if (fd == -1) {
 -            error_report("No file descriptor named %s found", fdname);
 +            qerror_report_err(local_err);
 +            error_free(local_err);
              return -1;
          }
      } else {
@@@ -3223,7 -3260,11 +3224,7 @@@ static int64_t expr_unary(Monitor *mon
          break;
      default:
          errno = 0;
 -#if TARGET_PHYS_ADDR_BITS > 32
          n = strtoull(pch, &p, 0);
 -#else
 -        n = strtoul(pch, &p, 0);
 -#endif
          if (errno == ERANGE) {
              expr_error(mon, "number too large");
          }
diff --combined monitor.h
index e240c3f42d5f3fa2fc529410af55e386913d09f3,43040af1c2199b5bc167a502d9ce093fc2c6aa20..b6e7d95a307e4ff9fa88e0540f09fddd8478d54f
+++ b/monitor.h
@@@ -38,6 -38,7 +38,7 @@@ typedef enum MonitorEvent 
      QEVENT_SPICE_DISCONNECTED,
      QEVENT_BLOCK_JOB_COMPLETED,
      QEVENT_BLOCK_JOB_CANCELLED,
+     QEVENT_BLOCK_JOB_ERROR,
      QEVENT_DEVICE_TRAY_MOVED,
      QEVENT_SUSPEND,
      QEVENT_SUSPEND_DISK,
@@@ -66,7 -67,7 +67,7 @@@ int monitor_read_block_device_key(Monit
                                    BlockDriverCompletionFunc *completion_cb,
                                    void *opaque);
  
 -int monitor_get_fd(Monitor *mon, const char *fdname);
 +int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp);
  int monitor_handle_fd_param(Monitor *mon, const char *fdname);
  
  void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
diff --combined qapi-schema.json
index f4c21855cfabe783ce383e5ea39c2238a8fcf5d9,768b4c785ac0bd460ce72d619484de24e93dea0c..23abb94a1abc67e7f7e1608e2ea945efdb56afbc
              'DeviceNotActive', 'DeviceNotFound', 'KVMMissingCap',
              'MigrationExpected' ] }
  
 +##
 +# @add_client
 +#
 +# Allow client connections for VNC, Spice and socket based
 +# character devices to be passed in to QEMU via SCM_RIGHTS.
 +#
 +# @protocol: protocol name. Valid names are "vnc", "spice" or the
 +#            name of a character device (eg. from -chardev id=XXXX)
 +#
 +# @fdname: file descriptor name previously passed via 'getfd' command
 +#
 +# @skipauth: #optional whether to skip authentication. Only applies
 +#            to "vnc" and "spice" protocols
 +#
 +# @tls: #optional whether to perform TLS. Only applies to the "spice"
 +#       protocol
 +#
 +# Returns: nothing on success.
 +#
 +# Since: 0.14.0
 +##
 +{ 'command': 'add_client',
 +  'data': { 'protocol': 'str', 'fdname': 'str', '*skipauth': 'bool',
 +            '*tls': 'bool' } }
 +
  ##
  # @NameInfo:
  #
  ##
  { 'command': 'query-pci', 'returns': ['PciInfo'] }
  
+ ##
+ # @BlockdevOnError:
+ #
+ # An enumeration of possible behaviors for errors on I/O operations.
+ # The exact meaning depends on whether the I/O was initiated by a guest
+ # or by a block job
+ #
+ # @report: for guest operations, report the error to the guest;
+ #          for jobs, cancel the job
+ #
+ # @ignore: ignore the error, only report a QMP event (BLOCK_IO_ERROR
+ #          or BLOCK_JOB_ERROR)
+ #
+ # @enospc: same as @stop on ENOSPC, same as @report otherwise.
+ #
+ # @stop: for guest operations, stop the virtual machine;
+ #        for jobs, pause the job
+ #
+ # Since: 1.3
+ ##
+ { 'enum': 'BlockdevOnError',
+   'data': ['report', 'ignore', 'enospc', 'stop'] }
  ##
  # @BlockJobInfo:
  #
  #
  # @len: the maximum progress value
  #
+ # @busy: false if the job is known to be in a quiescent state, with
+ #        no pending I/O.  Since 1.3.
+ #
+ # @paused: whether the job is paused or, if @busy is true, will
+ #          pause itself as soon as possible.  Since 1.3.
+ #
  # @offset: the current progress value
  #
  # @speed: the rate limit, bytes per second
  #
+ # @io-status: the status of the job (since 1.3)
+ #
  # Since: 1.1
  ##
  { 'type': 'BlockJobInfo',
    'data': {'type': 'str', 'device': 'str', 'len': 'int',
-            'offset': 'int', 'speed': 'int'} }
+            'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int',
+            'io-status': 'BlockDeviceIoStatus'} }
  
  ##
  # @query-block-jobs:
  # @format: #optional the format of the snapshot image, default is 'qcow2'.
  #
  # @mode: #optional whether and how QEMU should create a new image, default is
 -# 'absolute-paths'.
 +#        'absolute-paths'.
  ##
  { 'type': 'BlockdevSnapshot',
    'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str',
  # @format: #optional the format of the snapshot image, default is 'qcow2'.
  #
  # @mode: #optional whether and how QEMU should create a new image, default is
 -# 'absolute-paths'.
 +#        'absolute-paths'.
  #
  # Returns: nothing on success
  #          If @device is not a valid block device, DeviceNotFound
    'returns': 'str' }
  
  ##
+ # @block-commit
+ #
+ # Live commit of data from overlay image nodes into backing nodes - i.e.,
+ # writes data between 'top' and 'base' into 'base'.
+ #
+ # @device:  the name of the device
+ #
+ # @base:   #optional The file name of the backing image to write data into.
+ #                    If not specified, this is the deepest backing image
+ #
+ # @top:              The file name of the backing image within the image chain,
+ #                    which contains the topmost data to be committed down.
+ #                    Note, the active layer as 'top' is currently unsupported.
+ #
+ #                    If top == base, that is an error.
+ #
+ #
+ # @speed:  #optional the maximum speed, in bytes per second
+ #
+ # Returns: Nothing on success
+ #          If commit or stream is already active on this device, DeviceInUse
+ #          If @device does not exist, DeviceNotFound
+ #          If image commit is not supported by this device, NotSupported
+ #          If @base or @top is invalid, a generic error is returned
+ #          If @top is the active layer, or omitted, a generic error is returned
+ #          If @speed is invalid, InvalidParameter
+ #
+ # Since: 1.3
+ #
+ ##
+ { 'command': 'block-commit',
+   'data': { 'device': 'str', '*base': 'str', 'top': 'str',
+             '*speed': 'int' } }
  # @migrate_cancel
  #
  # Cancel the current executing migration process.
  #
  # @speed:  #optional the maximum speed, in bytes per second
  #
+ # @on-error: #optional the action to take on an error (default report).
+ #            'stop' and 'enospc' can only be used if the block device
+ #            supports io-status (see BlockInfo).  Since 1.3.
+ #
  # Returns: Nothing on success
  #          If @device does not exist, DeviceNotFound
  #
  # Since: 1.1
  ##
- { 'command': 'block-stream', 'data': { 'device': 'str', '*base': 'str',
-                                        '*speed': 'int' } }
+ { 'command': 'block-stream',
+   'data': { 'device': 'str', '*base': 'str', '*speed': 'int',
+             '*on-error': 'BlockdevOnError' } }
  
  ##
  # @block-job-set-speed:
  #
  # @device: the device name
  #
+ # @force: #optional whether to allow cancellation of a paused job (default
+ #         false).  Since 1.3.
+ #
  # Returns: Nothing on success
  #          If no background operation is active on this device, DeviceNotActive
  #
  # Since: 1.1
  ##
- { 'command': 'block-job-cancel', 'data': { 'device': 'str' } }
+ { 'command': 'block-job-cancel', 'data': { 'device': 'str', '*force': 'bool' } }
+ ##
+ # @block-job-pause:
+ #
+ # Pause an active background block operation.
+ #
+ # This command returns immediately after marking the active background block
+ # operation for pausing.  It is an error to call this command if no
+ # operation is in progress.  Pausing an already paused job has no cumulative
+ # effect; a single block-job-resume command will resume the job.
+ #
+ # The operation will pause as soon as possible.  No event is emitted when
+ # the operation is actually paused.  Cancelling a paused job automatically
+ # resumes it.
+ #
+ # @device: the device name
+ #
+ # Returns: Nothing on success
+ #          If no background operation is active on this device, DeviceNotActive
+ #
+ # Since: 1.3
+ ##
+ { 'command': 'block-job-pause', 'data': { 'device': 'str' } }
+ ##
+ # @block-job-resume:
+ #
+ # Resume an active background block operation.
+ #
+ # This command returns immediately after resuming a paused background block
+ # operation.  It is an error to call this command if no operation is in
+ # progress.  Resuming an already running job is not an error.
+ #
+ # This command also clears the error status of the job.
+ #
+ # @device: the device name
+ #
+ # Returns: Nothing on success
+ #          If no background operation is active on this device, DeviceNotActive
+ #
+ # Since: 1.3
+ ##
+ { 'command': 'block-job-resume', 'data': { 'device': 'str' } }
  
  ##
  # @ObjectTypeInfo:
  # supported on i386 and x86_64.
  #
  # @paging: if true, do paging to get guest's memory mapping. This allows
 -# using gdb to process the core file. However, setting @paging to false
 -# may be desirable because of two reasons:
 +#          using gdb to process the core file.
  #
 -#   1. The guest may be in a catastrophic state or can have corrupted
 -#      memory, which cannot be trusted
 -#   2. The guest can be in real-mode even if paging is enabled. For example,
 -#      the guest uses ACPI to sleep, and ACPI sleep state goes in real-mode
 +#          IMPORTANT: this option can make QEMU allocate several gigabytes
 +#                     of RAM. This can happen for a large guest, or a
 +#                     malicious guest pretending to be large.
 +#
 +#          Also, paging=true has the following limitations:
 +#
 +#             1. The guest may be in a catastrophic state or can have corrupted
 +#                memory, which cannot be trusted
 +#             2. The guest can be in real-mode even if paging is enabled. For
 +#                example, the guest uses ACPI to sleep, and ACPI sleep state
 +#                goes in real-mode
  #
  # @protocol: the filename or file descriptor of the vmcore. The supported
 -# protocols are:
 +#            protocols are:
  #
 -#   1. file: the protocol starts with "file:", and the following string is
 -#      the file's path.
 -#   2. fd: the protocol starts with "fd:", and the following string is the
 -#      fd's name.
 +#            1. file: the protocol starts with "file:", and the following
 +#               string is the file's path.
 +#            2. fd: the protocol starts with "fd:", and the following string
 +#               is the fd's name.
  #
  # @begin: #optional if specified, the starting physical address.
  #
  # @length: #optional if specified, the memory size, in bytes. If you don't
 -# want to dump all guest's memory, please specify the start @begin and @length
 +#          want to dump all guest's memory, please specify the start @begin
 +#          and @length
  #
  # Returns: nothing on success
  #
  { 'command': 'dump-guest-memory',
    'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
              '*length': 'int' } }
 +
  ##
  # @netdev_add:
  #
              'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
               'lf', 'help', 'meta_l', 'meta_r', 'compose' ] }
  
 +##
 +# @KeyValue
 +#
 +# Represents a keyboard key.
 +#
 +# Since: 1.3.0
 +##
 +{ 'union': 'KeyValue',
 +  'data': {
 +    'number': 'int',
 +    'qcode': 'QKeyCode' } }
 +
  ##
  # @send-key:
  #
  # Send keys to guest.
  #
 -# @keys: key sequence. 'keys' is the name of the key. Use a JSON array to
 -#        press several keys simultaneously.
 +# @keys: An array of @KeyValue elements. All @KeyValues in this array are
 +#        simultaneously sent to the guest. A @KeyValue.number value is sent
 +#        directly to the guest, while @KeyValue.qcode must be a valid
 +#        @QKeyCode value
  #
  # @hold-time: #optional time to delay key up events, milliseconds. Defaults
  #             to 100
  #
  ##
  { 'command': 'send-key',
 -  'data': { 'keys': ['QKeyCode'], '*hold-time': 'int' } }
 +  'data': { 'keys': ['KeyValue'], '*hold-time': 'int' } }
  
  ##
  # @screendump:
diff --combined qmp-commands.hx
index 36e08d9ffcbf748e14fe978008db872a2dfb72eb,ea93b1d4a92076ce52686d3fc76be245ce11a701..1aef27ca148e5cf7405fd06529e6a387d5e4ce93
@@@ -787,10 -787,16 +787,16 @@@ EQM
  
      {
          .name       = "block-stream",
-         .args_type  = "device:B,base:s?,speed:o?",
+         .args_type  = "device:B,base:s?,speed:o?,on-error:s?",
          .mhandler.cmd_new = qmp_marshal_input_block_stream,
      },
  
+     {
+         .name       = "block-commit",
+         .args_type  = "device:B,base:s?,top:s,speed:o?",
+         .mhandler.cmd_new = qmp_marshal_input_block_commit,
+     },
      {
          .name       = "block-job-set-speed",
          .args_type  = "device:B,speed:o",
  
      {
          .name       = "block-job-cancel",
-         .args_type  = "device:B",
+         .args_type  = "device:B,force:b?",
          .mhandler.cmd_new = qmp_marshal_input_block_job_cancel,
      },
+     {
+         .name       = "block-job-pause",
+         .args_type  = "device:B",
+         .mhandler.cmd_new = qmp_marshal_input_block_job_pause,
+     },
+     {
+         .name       = "block-job-resume",
+         .args_type  = "device:B",
+         .mhandler.cmd_new = qmp_marshal_input_block_job_resume,
+     },
      {
          .name       = "transaction",
          .args_type  = "actions:q",
@@@ -1231,7 -1247,10 +1247,7 @@@ EQM
      {
          .name       = "add_client",
          .args_type  = "protocol:s,fdname:s,skipauth:b?,tls:b?",
 -        .params     = "protocol fdname skipauth tls",
 -        .help       = "add a graphics client",
 -        .user_print = monitor_user_noop,
 -        .mhandler.cmd_new = add_graphics_client,
 +        .mhandler.cmd_new = qmp_marshal_input_add_client,
      },
  
  SQMP