[Spice-commits] 52 commits - VERSION block.c block/commit.c block/cow.c block/qed.c block/raw-posix.c block/stream.c block/vdi.c block/vmdk.c block/vpc.c blockdev.c configure docs/qmp exec.c hmp.c hw/block hw/core hw/input hw/s390x hw/timer hw/usb hw/virtio include/block include/exec include/hw include/qom memory.c net/Makefile.objs net/net.c qapi/block-core.json qapi/event.json qemu-doc.texi qemu-img.texi qmp-commands.hx qom/object.c tests/fdc-test.c tests/libqtest.c tests/qemu-iotests tests/qemu-iotests-quick.sh tests/qom-test.c tests/tmp105-test.c trace-events ui/vnc.c ui/vnc.h vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Wed Jul 2 01:06:32 PDT 2014


 VERSION                          |    2 
 block.c                          |   64 ++++------
 block/commit.c                   |    9 +
 block/cow.c                      |    7 -
 block/qed.c                      |    6 -
 block/raw-posix.c                |   25 ++++
 block/stream.c                   |   11 -
 block/vdi.c                      |   29 ++++
 block/vmdk.c                     |    6 -
 block/vpc.c                      |   29 ++++
 blockdev.c                       |  126 ++++++++++++++++++++-
 configure                        |   16 ++
 docs/qmp/qmp-events.txt          |   26 ++--
 exec.c                           |   12 +-
 hmp.c                            |    2 
 hw/block/dataplane/virtio-blk.c  |   12 +-
 hw/block/virtio-blk.c            |   28 +++-
 hw/core/qdev-properties-system.c |   50 --------
 hw/core/qdev.c                   |   26 ++++
 hw/input/hid.c                   |    4 
 hw/s390x/s390-virtio-bus.c       |   12 --
 hw/s390x/s390-virtio-bus.h       |    1 
 hw/s390x/virtio-ccw.c            |    9 -
 hw/s390x/virtio-ccw.h            |    1 
 hw/timer/mc146818rtc.c           |    9 +
 hw/usb/ccid-card-emulated.c      |   29 +---
 hw/usb/dev-bluetooth.c           |   24 ++--
 hw/usb/host-libusb.c             |    4 
 hw/virtio/virtio-pci.c           |    9 -
 hw/virtio/virtio-pci.h           |    1 
 include/block/block.h            |    4 
 include/block/block_int.h        |    4 
 include/exec/memory.h            |    9 +
 include/hw/qdev-core.h           |    1 
 include/hw/qdev-properties.h     |    5 
 include/hw/virtio/virtio-blk.h   |   19 ---
 include/qom/object.h             |   54 ++++++++-
 memory.c                         |  231 ++++++++++++++++++++++++++++++++++-----
 net/Makefile.objs                |    2 
 net/net.c                        |    4 
 qapi/block-core.json             |   72 ++++++++++--
 qapi/event.json                  |    8 -
 qemu-doc.texi                    |   16 ++
 qemu-img.texi                    |   16 ++
 qmp-commands.hx                  |   63 ++++++++++
 qom/object.c                     |  147 +++++++++++++++++++-----
 tests/fdc-test.c                 |    2 
 tests/libqtest.c                 |   47 ++++++-
 tests/qemu-iotests-quick.sh      |   12 --
 tests/qemu-iotests/040           |   28 +++-
 tests/qemu-iotests/082.out       |   24 ++++
 tests/qemu-iotests/group         |   56 ++++-----
 tests/qom-test.c                 |    6 -
 tests/tmp105-test.c              |    4 
 trace-events                     |    2 
 ui/vnc.c                         |  162 +++++++++++++--------------
 ui/vnc.h                         |   14 +-
 vl.c                             |    5 
 58 files changed, 1151 insertions(+), 455 deletions(-)

New commits:
commit 92259b7f434b382fc865d1f65f7d5adeed295749
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jul 1 18:48:01 2014 +0100

    Update version for v2.1.0-rc0 release
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/VERSION b/VERSION
index 52be4db..36831c3 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.50
+2.0.90
commit 015a33bd05b7fd69f400d4e0e4a9925af9292548
Author: Gonglei <arei.gonglei at huawei.com>
Date:   Tue Jul 1 20:58:08 2014 +0800

    net: add mmsghdr struct check for L2TPV3
    
    The mmsghdr struct is only introduced in Linux 2.6.32; add a
    configure check for it and disable L2TPV3 on hosts which are
    too old to provide it, rather than simply failing to compile.
    
    Reported-by: chenliang <chenliang88 at huawei.com>
    Signed-off-by: Gonglei <arei.gonglei at huawei.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Message-id: 1404219488-11196-1-git-send-email-arei.gonglei at huawei.com
    [PMM: cleaned up commit message and corrected kernel version number]
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/configure b/configure
index ed41eda..7dd43fd 100755
--- a/configure
+++ b/configure
@@ -1712,6 +1712,19 @@ else
 fi
 
 ##########################################
+# L2TPV3 probe
+
+cat > $TMPC <<EOF
+#include <sys/socket.h>
+int main(void) { return sizeof(struct mmsghdr); }
+EOF
+if compile_prog "" "" ; then
+  l2tpv3=yes
+else
+  l2tpv3=no
+fi
+
+##########################################
 # pkg-config probe
 
 if ! has "$pkg_config_exe"; then
@@ -4343,6 +4356,9 @@ fi
 if test "$netmap" = "yes" ; then
   echo "CONFIG_NETMAP=y" >> $config_host_mak
 fi
+if test "$l2tpv3" = "yes" ; then
+  echo "CONFIG_L2TPV3=y" >> $config_host_mak
+fi
 if test "$cap_ng" = "yes" ; then
   echo "CONFIG_LIBCAP=y" >> $config_host_mak
 fi
diff --git a/net/Makefile.objs b/net/Makefile.objs
index a06ba59..ec19cb3 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -2,7 +2,7 @@ common-obj-y = net.o queue.o checksum.o util.o hub.o
 common-obj-y += socket.o
 common-obj-y += dump.o
 common-obj-y += eth.o
-common-obj-$(CONFIG_LINUX) += l2tpv3.o
+common-obj-$(CONFIG_L2TPV3) += l2tpv3.o
 common-obj-$(CONFIG_POSIX) += tap.o vhost-user.o
 common-obj-$(CONFIG_LINUX) += tap-linux.o
 common-obj-$(CONFIG_WIN32) += tap-win32.o
diff --git a/net/net.c b/net/net.c
index 0869c60..6d930ea 100644
--- a/net/net.c
+++ b/net/net.c
@@ -806,7 +806,7 @@ static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
 #ifdef CONFIG_VHOST_NET_USED
         [NET_CLIENT_OPTIONS_KIND_VHOST_USER] = net_init_vhost_user,
 #endif
-#ifdef CONFIG_LINUX
+#ifdef CONFIG_L2TPV3
         [NET_CLIENT_OPTIONS_KIND_L2TPV3]    = net_init_l2tpv3,
 #endif
 };
@@ -845,7 +845,7 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
 #ifdef CONFIG_VHOST_NET_USED
         case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
 #endif
-#ifdef CONFIG_LINUX
+#ifdef CONFIG_L2TPV3
         case NET_CLIENT_OPTIONS_KIND_L2TPV3:
 #endif
             break;
commit 596742db3341390dfd386ec434165e0118cfc0f8
Merge: f9119a2 c1129f6
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jul 1 16:16:19 2014 +0100

    Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20140701-1' into staging
    
    usb bugfixes.
    
    # gpg: Signature made Tue 01 Jul 2014 14:51:19 BST using RSA key ID D3E87138
    # gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
    # gpg:                 aka "Gerd Hoffmann <gerd at kraxel.org>"
    # gpg:                 aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
    
    * remotes/kraxel/tags/pull-usb-20140701-1:
      ccid-card-emulated: use EventNotifier
      usb: initialize libusb_device to avoid crash
      usb: Fix usb-bt-dongle initialization.
      input: fix jumpy mouse cursor with USB mouse emulation
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit f9119a25729644300046efda3dd9f50d68fe2106
Merge: 1aa85f4 bea60dd
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jul 1 15:12:05 2014 +0100

    Merge remote-tracking branch 'remotes/kraxel/tags/pull-vnc-20140701-1' into staging
    
    vnc: two bugfixes (by Peter Lieven).
    
    # gpg: Signature made Tue 01 Jul 2014 12:32:19 BST using RSA key ID D3E87138
    # gpg: Good signature from "Gerd Hoffmann (work) <kraxel at redhat.com>"
    # gpg:                 aka "Gerd Hoffmann <gerd at kraxel.org>"
    # gpg:                 aka "Gerd Hoffmann (private) <kraxel at gmail.com>"
    
    * remotes/kraxel/tags/pull-vnc-20140701-1:
      ui/vnc: fix potential memory corruption issues
      ui/vnc: limit client_cut_text msg payload size
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit c1129f6bffb6fc756f53c06bc554a7997b1f4be4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Mon Jun 23 12:30:36 2014 +0200

    ccid-card-emulated: use EventNotifier
    
    Shut up Coverity's complaint about unchecked fcntl return values,
    and especially make the code simpler and more efficient.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index 7213c89..aa1c37a 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -126,7 +126,7 @@ struct EmulatedState {
     QemuMutex vreader_mutex; /* and guest_apdu_list mutex */
     QemuMutex handle_apdu_mutex;
     QemuCond handle_apdu_cond;
-    int      pipe[2];
+    EventNotifier notifier;
     int      quit_apdu_thread;
     QemuThread apdu_thread_id;
 };
@@ -162,9 +162,7 @@ static void emulated_push_event(EmulatedState *card, EmulEvent *event)
     qemu_mutex_lock(&card->event_list_mutex);
     QSIMPLEQ_INSERT_TAIL(&(card->event_list), event, entry);
     qemu_mutex_unlock(&card->event_list_mutex);
-    if (write(card->pipe[1], card, 1) != 1) {
-        DPRINTF(card, 1, "write to pipe failed\n");
-    }
+    event_notifier_set(&card->notifier);
 }
 
 static void emulated_push_type(EmulatedState *card, uint32_t type)
@@ -358,16 +356,12 @@ static void *event_thread(void *arg)
     return NULL;
 }
 
-static void pipe_read(void *opaque)
+static void card_event_handler(EventNotifier *notifier)
 {
-    EmulatedState *card = opaque;
+    EmulatedState *card = container_of(notifier, EmulatedState, notifier);
     EmulEvent *event, *next;
-    char dummy;
-    int len;
 
-    do {
-        len = read(card->pipe[0], &dummy, sizeof(dummy));
-    } while (len == sizeof(dummy));
+    event_notifier_test_and_clear(&card->notifier);
     qemu_mutex_lock(&card->event_list_mutex);
     QSIMPLEQ_FOREACH_SAFE(event, &card->event_list, entry, next) {
         DPRINTF(card, 2, "event %s\n", emul_event_to_string(event->p.gen.type));
@@ -404,16 +398,13 @@ static void pipe_read(void *opaque)
     qemu_mutex_unlock(&card->event_list_mutex);
 }
 
-static int init_pipe_signaling(EmulatedState *card)
+static int init_event_notifier(EmulatedState *card)
 {
-    if (pipe(card->pipe) < 0) {
-        DPRINTF(card, 2, "pipe creation failed\n");
+    if (event_notifier_init(&card->notifier, false) < 0) {
+        DPRINTF(card, 2, "event notifier creation failed\n");
         return -1;
     }
-    fcntl(card->pipe[0], F_SETFL, O_NONBLOCK);
-    fcntl(card->pipe[1], F_SETFL, O_NONBLOCK);
-    fcntl(card->pipe[0], F_SETOWN, getpid());
-    qemu_set_fd_handler(card->pipe[0], pipe_read, NULL, card);
+    event_notifier_set_handler(&card->notifier, card_event_handler);
     return 0;
 }
 
@@ -500,7 +491,7 @@ static int emulated_initfn(CCIDCardState *base)
     qemu_cond_init(&card->handle_apdu_cond);
     card->reader = NULL;
     card->quit_apdu_thread = 0;
-    if (init_pipe_signaling(card) < 0) {
+    if (init_event_notifier(card) < 0) {
         return -1;
     }
 
commit 1aa85f46b336b6b07d3a03e9807578b0bc081b7b
Merge: 8593efa bc78cff
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jul 1 14:21:50 2014 +0100

    Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
    
    Tracing pull request
    
    # gpg: Signature made Tue 01 Jul 2014 09:56:27 BST using RSA key ID 81AB73C8
    # gpg: Good signature from "Stefan Hajnoczi <stefanha at redhat.com>"
    # gpg:                 aka "Stefan Hajnoczi <stefanha at gmail.com>"
    
    * remotes/stefanha/tags/tracing-pull-request:
      trace: add qemu_system_powerdown_request and qemu_system_shutdown_request trace events
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit 8593efa4fb33b8c1f3e3af04f771d8376ae61092
Merge: c26f3a0 13d8cc5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jul 1 13:13:04 2014 +0100

    Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
    
    Block pull request
    
    # gpg: Signature made Tue 01 Jul 2014 09:47:15 BST using RSA key ID 81AB73C8
    # gpg: Good signature from "Stefan Hajnoczi <stefanha at redhat.com>"
    # gpg:                 aka "Stefan Hajnoczi <stefanha at gmail.com>"
    
    * remotes/stefanha/tags/block-pull-request: (23 commits)
      block: add backing-file option to block-stream
      block: extend block-commit to accept a string for the backing file
      block: add helper function to determine if a BDS is in a chain
      block: add QAPI command to allow live backing file change
      qapi: Change back sector-count to sectors-count in quorum QAPI events.
      block/cow: Avoid use of uninitialized cow_bs in error path
      block: simplify bdrv_find_base() and bdrv_find_overlay()
      block: make 'top' argument to block-commit optional
      iotests: Add more tests to quick group
      iotests: Add qemu tests to quick group
      iotests: Simplify qemu-iotests-quick.sh
      qemu-img create: add 'nocow' option
      virtio-blk: remove need for explicit x-data-plane=on option
      qdev: drop iothread property type
      virtio-blk: replace x-iothread with iothread link property
      virtio-blk: move qdev properties into virtio-blk.c
      virtio: fix virtio-blk child refcount in transports
      virtio-blk: drop virtio_blk_set_conf()
      virtio-blk: use aliases instead of duplicate qdev properties
      qdev: add qdev_alias_all_properties()
      ...
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit bea60dd7679364493a0d7f5b54316c767cf894ef
Author: Peter Lieven <pl at kamp.de>
Date:   Mon Jun 30 10:57:51 2014 +0200

    ui/vnc: fix potential memory corruption issues
    
    this patch makes the VNC server work correctly if the
    server surface and the guest surface have different sizes.
    
    Basically the server surface is adjusted to not exceed VNC_MAX_WIDTH
    x VNC_MAX_HEIGHT and additionally the width is rounded up to multiple of
    VNC_DIRTY_PIXELS_PER_BIT.
    
    If we have a resolution whose width is not dividable by VNC_DIRTY_PIXELS_PER_BIT
    we now get a small black bar on the right of the screen.
    
    If the surface is too big to fit the limits only the upper left area is shown.
    
    On top of that this fixes 2 memory corruption issues:
    
    The first was actually discovered during playing
    around with a Windows 7 vServer. During resolution
    change in Windows 7 it happens sometimes that Windows
    changes to an intermediate resolution where
    server_stride % cmp_bytes != 0 (in vnc_refresh_server_surface).
    This happens only if width % VNC_DIRTY_PIXELS_PER_BIT != 0.
    
    The second is a theoretical issue, but is maybe exploitable
    by the guest. If for some reason the guest surface size is bigger
    than VNC_MAX_WIDTH x VNC_MAX_HEIGHT we end up in severe corruption since
    this limit is nowhere enforced.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 19ce988..548588a 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -432,14 +432,10 @@ static void framebuffer_update_request(VncState *vs, int incremental,
 static void vnc_refresh(DisplayChangeListener *dcl);
 static int vnc_refresh_server_surface(VncDisplay *vd);
 
-static void vnc_dpy_update(DisplayChangeListener *dcl,
-                           int x, int y, int w, int h)
-{
-    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
-    struct VncSurface *s = &vd->guest;
-    int width = surface_width(vd->ds);
-    int height = surface_height(vd->ds);
-
+static void vnc_set_area_dirty(DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT],
+                               VNC_MAX_WIDTH / VNC_DIRTY_PIXELS_PER_BIT),
+                               int width, int height,
+                               int x, int y, int w, int h) {
     /* this is needed this to ensure we updated all affected
      * blocks if x % VNC_DIRTY_PIXELS_PER_BIT != 0 */
     w += (x % VNC_DIRTY_PIXELS_PER_BIT);
@@ -451,11 +447,22 @@ static void vnc_dpy_update(DisplayChangeListener *dcl,
     h = MIN(y + h, height);
 
     for (; y < h; y++) {
-        bitmap_set(s->dirty[y], x / VNC_DIRTY_PIXELS_PER_BIT,
+        bitmap_set(dirty[y], x / VNC_DIRTY_PIXELS_PER_BIT,
                    DIV_ROUND_UP(w, VNC_DIRTY_PIXELS_PER_BIT));
     }
 }
 
+static void vnc_dpy_update(DisplayChangeListener *dcl,
+                           int x, int y, int w, int h)
+{
+    VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
+    struct VncSurface *s = &vd->guest;
+    int width = pixman_image_get_width(vd->server);
+    int height = pixman_image_get_height(vd->server);
+
+    vnc_set_area_dirty(s->dirty, width, height, x, y, w, h);
+}
+
 void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
                             int32_t encoding)
 {
@@ -517,17 +524,15 @@ void buffer_advance(Buffer *buf, size_t len)
 
 static void vnc_desktop_resize(VncState *vs)
 {
-    DisplaySurface *ds = vs->vd->ds;
-
     if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
         return;
     }
-    if (vs->client_width == surface_width(ds) &&
-        vs->client_height == surface_height(ds)) {
+    if (vs->client_width == pixman_image_get_width(vs->vd->server) &&
+        vs->client_height == pixman_image_get_height(vs->vd->server)) {
         return;
     }
-    vs->client_width = surface_width(ds);
-    vs->client_height = surface_height(ds);
+    vs->client_width = pixman_image_get_width(vs->vd->server);
+    vs->client_height = pixman_image_get_height(vs->vd->server);
     vnc_lock_output(vs);
     vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
     vnc_write_u8(vs, 0);
@@ -571,31 +576,24 @@ void *vnc_server_fb_ptr(VncDisplay *vd, int x, int y)
     ptr += x * VNC_SERVER_FB_BYTES;
     return ptr;
 }
-/* this sets only the visible pixels of a dirty bitmap */
-#define VNC_SET_VISIBLE_PIXELS_DIRTY(bitmap, w, h) {\
-        int y;\
-        memset(bitmap, 0x00, sizeof(bitmap));\
-        for (y = 0; y < h; y++) {\
-            bitmap_set(bitmap[y], 0,\
-                       DIV_ROUND_UP(w, VNC_DIRTY_PIXELS_PER_BIT));\
-        } \
-    }
 
 static void vnc_dpy_switch(DisplayChangeListener *dcl,
                            DisplaySurface *surface)
 {
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     VncState *vs;
+    int width, height;
 
     vnc_abort_display_jobs(vd);
 
     /* server surface */
     qemu_pixman_image_unref(vd->server);
     vd->ds = surface;
+    width = MIN(VNC_MAX_WIDTH, ROUND_UP(surface_width(vd->ds),
+                                        VNC_DIRTY_PIXELS_PER_BIT));
+    height = MIN(VNC_MAX_HEIGHT, surface_height(vd->ds));
     vd->server = pixman_image_create_bits(VNC_SERVER_FB_FORMAT,
-                                          surface_width(vd->ds),
-                                          surface_height(vd->ds),
-                                          NULL, 0);
+                                          width, height, NULL, 0);
 
     /* guest surface */
 #if 0 /* FIXME */
@@ -605,9 +603,9 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
     qemu_pixman_image_unref(vd->guest.fb);
     vd->guest.fb = pixman_image_ref(surface->image);
     vd->guest.format = surface->format;
-    VNC_SET_VISIBLE_PIXELS_DIRTY(vd->guest.dirty,
-                                 surface_width(vd->ds),
-                                 surface_height(vd->ds));
+    memset(vd->guest.dirty, 0x00, sizeof(vd->guest.dirty));
+    vnc_set_area_dirty(vd->guest.dirty, width, height, 0, 0,
+                       width, height);
 
     QTAILQ_FOREACH(vs, &vd->clients, next) {
         vnc_colordepth(vs);
@@ -615,9 +613,9 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
         if (vs->vd->cursor) {
             vnc_cursor_define(vs);
         }
-        VNC_SET_VISIBLE_PIXELS_DIRTY(vs->dirty,
-                                     surface_width(vd->ds),
-                                     surface_height(vd->ds));
+        memset(vs->dirty, 0x00, sizeof(vs->dirty));
+        vnc_set_area_dirty(vs->dirty, width, height, 0, 0,
+                           width, height);
     }
 }
 
@@ -911,8 +909,8 @@ static int vnc_update_client(VncState *vs, int has_dirty, bool sync)
          */
         job = vnc_job_new(vs);
 
-        height = MIN(pixman_image_get_height(vd->server), vs->client_height);
-        width = MIN(pixman_image_get_width(vd->server), vs->client_width);
+        height = pixman_image_get_height(vd->server);
+        width = pixman_image_get_width(vd->server);
 
         y = 0;
         for (;;) {
@@ -1501,8 +1499,8 @@ static void check_pointer_type_change(Notifier *notifier, void *data)
         vnc_write_u8(vs, 0);
         vnc_write_u16(vs, 1);
         vnc_framebuffer_update(vs, absolute, 0,
-                               surface_width(vs->vd->ds),
-                               surface_height(vs->vd->ds),
+                               pixman_image_get_width(vs->vd->server),
+                               pixman_image_get_height(vs->vd->server),
                                VNC_ENCODING_POINTER_TYPE_CHANGE);
         vnc_unlock_output(vs);
         vnc_flush(vs);
@@ -1520,8 +1518,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
         [INPUT_BUTTON_WHEEL_DOWN] = 0x10,
     };
     QemuConsole *con = vs->vd->dcl.con;
-    int width = surface_width(vs->vd->ds);
-    int height = surface_height(vs->vd->ds);
+    int width = pixman_image_get_width(vs->vd->server);
+    int height = pixman_image_get_height(vs->vd->server);
 
     if (vs->last_bmask != button_mask) {
         qemu_input_update_buttons(con, bmap, vs->last_bmask, button_mask);
@@ -1869,29 +1867,18 @@ static void ext_key_event(VncState *vs, int down,
 }
 
 static void framebuffer_update_request(VncState *vs, int incremental,
-                                       int x_position, int y_position,
-                                       int w, int h)
+                                       int x, int y, int w, int h)
 {
-    int i;
-    const size_t width = surface_width(vs->vd->ds) / VNC_DIRTY_PIXELS_PER_BIT;
-    const size_t height = surface_height(vs->vd->ds);
-
-    if (y_position > height) {
-        y_position = height;
-    }
-    if (y_position + h >= height) {
-        h = height - y_position;
-    }
+    int width = pixman_image_get_width(vs->vd->server);
+    int height = pixman_image_get_height(vs->vd->server);
 
     vs->need_update = 1;
-    if (!incremental) {
-        vs->force_update = 1;
-        for (i = 0; i < h; i++) {
-            bitmap_set(vs->dirty[y_position + i], 0, width);
-            bitmap_clear(vs->dirty[y_position + i], width,
-                         VNC_DIRTY_BITS - width);
-        }
+
+    if (incremental) {
+        return;
     }
+
+    vnc_set_area_dirty(vs->dirty, width, height, x, y, w, h);
 }
 
 static void send_ext_key_event_ack(VncState *vs)
@@ -1901,8 +1888,8 @@ static void send_ext_key_event_ack(VncState *vs)
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1);
     vnc_framebuffer_update(vs, 0, 0,
-                           surface_width(vs->vd->ds),
-                           surface_height(vs->vd->ds),
+                           pixman_image_get_width(vs->vd->server),
+                           pixman_image_get_height(vs->vd->server),
                            VNC_ENCODING_EXT_KEY_EVENT);
     vnc_unlock_output(vs);
     vnc_flush(vs);
@@ -1915,8 +1902,8 @@ static void send_ext_audio_ack(VncState *vs)
     vnc_write_u8(vs, 0);
     vnc_write_u16(vs, 1);
     vnc_framebuffer_update(vs, 0, 0,
-                           surface_width(vs->vd->ds),
-                           surface_height(vs->vd->ds),
+                           pixman_image_get_width(vs->vd->server),
+                           pixman_image_get_height(vs->vd->server),
                            VNC_ENCODING_AUDIO);
     vnc_unlock_output(vs);
     vnc_flush(vs);
@@ -2094,8 +2081,8 @@ static void vnc_colordepth(VncState *vs)
         vnc_write_u8(vs, 0);
         vnc_write_u16(vs, 1); /* number of rects */
         vnc_framebuffer_update(vs, 0, 0,
-                               surface_width(vs->vd->ds),
-                               surface_height(vs->vd->ds),
+                               pixman_image_get_width(vs->vd->server),
+                               pixman_image_get_height(vs->vd->server),
                                VNC_ENCODING_WMVi);
         pixel_format_message(vs);
         vnc_unlock_output(vs);
@@ -2317,8 +2304,8 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
     }
     vnc_set_share_mode(vs, mode);
 
-    vs->client_width = surface_width(vs->vd->ds);
-    vs->client_height = surface_height(vs->vd->ds);
+    vs->client_width = pixman_image_get_width(vs->vd->server);
+    vs->client_height = pixman_image_get_height(vs->vd->server);
     vnc_write_u16(vs, vs->client_width);
     vnc_write_u16(vs, vs->client_height);
 
@@ -2685,12 +2672,12 @@ static void vnc_rect_updated(VncDisplay *vd, int x, int y, struct timeval * tv)
 
 static int vnc_refresh_server_surface(VncDisplay *vd)
 {
-    int width = pixman_image_get_width(vd->guest.fb);
-    int height = pixman_image_get_height(vd->guest.fb);
-    int y;
+    int width = MIN(pixman_image_get_width(vd->guest.fb),
+                    pixman_image_get_width(vd->server));
+    int height = MIN(pixman_image_get_height(vd->guest.fb),
+                     pixman_image_get_height(vd->server));
+    int cmp_bytes, server_stride, min_stride, guest_stride, y = 0;
     uint8_t *guest_row0 = NULL, *server_row0;
-    int guest_stride = 0, server_stride;
-    int cmp_bytes;
     VncState *vs;
     int has_dirty = 0;
     pixman_image_t *tmpbuf = NULL;
@@ -2707,10 +2694,10 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
      * Check and copy modified bits from guest to server surface.
      * Update server dirty map.
      */
-    cmp_bytes = VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES;
-    if (cmp_bytes > vnc_server_fb_stride(vd)) {
-        cmp_bytes = vnc_server_fb_stride(vd);
-    }
+    server_row0 = (uint8_t *)pixman_image_get_data(vd->server);
+    server_stride = guest_stride = pixman_image_get_stride(vd->server);
+    cmp_bytes = MIN(VNC_DIRTY_PIXELS_PER_BIT * VNC_SERVER_FB_BYTES,
+                    server_stride);
     if (vd->guest.format != VNC_SERVER_FB_FORMAT) {
         int width = pixman_image_get_width(vd->server);
         tmpbuf = qemu_pixman_linebuf_create(VNC_SERVER_FB_FORMAT, width);
@@ -2718,10 +2705,8 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
         guest_row0 = (uint8_t *)pixman_image_get_data(vd->guest.fb);
         guest_stride = pixman_image_get_stride(vd->guest.fb);
     }
-    server_row0 = (uint8_t *)pixman_image_get_data(vd->server);
-    server_stride = pixman_image_get_stride(vd->server);
+    min_stride = MIN(server_stride, guest_stride);
 
-    y = 0;
     for (;;) {
         int x;
         uint8_t *guest_ptr, *server_ptr;
@@ -2747,13 +2732,17 @@ static int vnc_refresh_server_surface(VncDisplay *vd)
 
         for (; x < DIV_ROUND_UP(width, VNC_DIRTY_PIXELS_PER_BIT);
              x++, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
+            int _cmp_bytes = cmp_bytes;
             if (!test_and_clear_bit(x, vd->guest.dirty[y])) {
                 continue;
             }
-            if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0) {
+            if ((x + 1) * cmp_bytes > min_stride) {
+                _cmp_bytes = min_stride - x * cmp_bytes;
+            }
+            if (memcmp(server_ptr, guest_ptr, _cmp_bytes) == 0) {
                 continue;
             }
-            memcpy(server_ptr, guest_ptr, cmp_bytes);
+            memcpy(server_ptr, guest_ptr, _cmp_bytes);
             if (!vd->non_adaptive) {
                 vnc_rect_updated(vd, x * VNC_DIRTY_PIXELS_PER_BIT,
                                  y, &tv);
diff --git a/ui/vnc.h b/ui/vnc.h
index 07af9f7..8f582fd 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -77,14 +77,15 @@ typedef void VncSendHextileTile(VncState *vs,
                                 void *last_fg,
                                 int *has_bg, int *has_fg);
 
-/* VNC_MAX_WIDTH must be a multiple of 16. */
-#define VNC_MAX_WIDTH 2560
-#define VNC_MAX_HEIGHT 2048
-
 /* VNC_DIRTY_PIXELS_PER_BIT is the number of dirty pixels represented
- * by one bit in the dirty bitmap */
+ * by one bit in the dirty bitmap, should be a power of 2 */
 #define VNC_DIRTY_PIXELS_PER_BIT 16
 
+/* VNC_MAX_WIDTH must be a multiple of VNC_DIRTY_PIXELS_PER_BIT. */
+
+#define VNC_MAX_WIDTH ROUND_UP(2560, VNC_DIRTY_PIXELS_PER_BIT)
+#define VNC_MAX_HEIGHT 2048
+
 /* VNC_DIRTY_BITS is the number of bits in the dirty bitmap. */
 #define VNC_DIRTY_BITS (VNC_MAX_WIDTH / VNC_DIRTY_PIXELS_PER_BIT)
 
@@ -126,7 +127,8 @@ typedef struct VncRectStat VncRectStat;
 struct VncSurface
 {
     struct timeval last_freq_check;
-    DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16);
+    DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT],
+                   VNC_MAX_WIDTH / VNC_DIRTY_PIXELS_PER_BIT);
     VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
     pixman_image_t *fb;
     pixman_format_code_t format;
commit f9a70e79391f6d7c2a912d785239ee8effc1922d
Author: Peter Lieven <pl at kamp.de>
Date:   Mon Jun 30 10:07:54 2014 +0200

    ui/vnc: limit client_cut_text msg payload size
    
    currently a malicious client could define a payload
    size of 2^32 - 1 bytes and send up to that size of
    data to the vnc server. The server would allocated
    that amount of memory which could easily create an
    out of memory condition.
    
    This patch limits the payload size to 1MB max.
    
    Please note that client_cut_text messages are currently
    silently ignored.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 14a86c3..19ce988 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2165,13 +2165,20 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
         pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
         break;
     case VNC_MSG_CLIENT_CUT_TEXT:
-        if (len == 1)
+        if (len == 1) {
             return 8;
-
+        }
         if (len == 8) {
             uint32_t dlen = read_u32(data, 4);
-            if (dlen > 0)
+            if (dlen > (1 << 20)) {
+                error_report("vnc: client_cut_text msg payload has %u bytes"
+                             " which exceeds our limit of 1MB.", dlen);
+                vnc_client_error(vs);
+                break;
+            }
+            if (dlen > 0) {
                 return 8 + dlen;
+            }
         }
 
         client_cut_text(vs, read_u32(data, 4), data + 8);
commit 3ce21445387c64032a21ae73c995195307a28a36
Author: Jincheng Miao <jmiao at redhat.com>
Date:   Fri Jun 20 14:12:52 2014 +0800

    usb: initialize libusb_device to avoid crash
    
    If libusb_get_device_list() fails, the uninitialized local variable
    libusb_device would be passed to libusb_free_device_list(), that
    will cause a crash, like:
    (gdb) bt
     #0  0x00007fbbb4bafc10 in pthread_mutex_lock () from /lib64/libpthread.so.0
     #1  0x00007fbbb233e653 in libusb_unref_device (dev=0x6275682d627375)
         at core.c:902
     #2  0x00007fbbb233e739 in libusb_free_device_list (list=0x7fbbb6e8436e,
         unref_devices=<optimized out>) at core.c:653
     #3  0x00007fbbb6cd80a4 in usb_host_auto_check (unused=unused at entry=0x0)
         at hw/usb/host-libusb.c:1446
     #4  0x00007fbbb6cd8525 in usb_host_initfn (udev=0x7fbbbd3c5670)
         at hw/usb/host-libusb.c:912
     #5  0x00007fbbb6cc123b in usb_device_init (dev=0x7fbbbd3c5670)
         at hw/usb/bus.c:106
     ...
    
    So initialize libusb_device at the begin time.
    
    Signed-off-by: Jincheng Miao <jmiao at redhat.com>
    Reviewed-by: Gonglei <arei.gonglei at huawei.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 33b5b9f..c189147 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -1522,7 +1522,7 @@ static void usb_host_auto_check(void *unused)
 {
     struct USBHostDevice *s;
     struct USBAutoFilter *f;
-    libusb_device **devs;
+    libusb_device **devs = NULL;
     struct libusb_device_descriptor ddesc;
     int unconnected = 0;
     int i, n;
@@ -1623,7 +1623,7 @@ static void usb_host_auto_check(void *unused)
 
 void usb_host_info(Monitor *mon, const QDict *qdict)
 {
-    libusb_device **devs;
+    libusb_device **devs = NULL;
     struct libusb_device_descriptor ddesc;
     char port[16];
     int i, n;
commit c340a284f382a5f40774521f41b4bade76ddfa58
Author: Hani Benhabiles <kroosec at gmail.com>
Date:   Wed Jun 18 00:23:34 2014 +0100

    usb: Fix usb-bt-dongle initialization.
    
    Due to an incomplete initialization, adding a usb-bt-dongle device through HMP
    or QMP will cause a segmentation fault.
    
    Signed-off-by: Hani Benhabiles <hani at linux.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index a9661d2..a76e581 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -19,6 +19,7 @@
  */
 
 #include "qemu-common.h"
+#include "qemu/error-report.h"
 #include "hw/usb.h"
 #include "hw/usb/desc.h"
 #include "sysemu/bt.h"
@@ -506,6 +507,14 @@ static int usb_bt_initfn(USBDevice *dev)
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
+    s->dev.opaque = s;
+    if (!s->hci) {
+        s->hci = bt_new_hci(qemu_find_bt_vlan(0));
+    }
+    s->hci->opaque = s;
+    s->hci->evt_recv = usb_bt_out_hci_packet_event;
+    s->hci->acl_recv = usb_bt_out_hci_packet_acl;
+    usb_bt_handle_reset(&s->dev);
     s->intr = usb_ep_get(dev, USB_TOKEN_IN, USB_EVT_EP);
 
     return 0;
@@ -516,6 +525,7 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
     USBDevice *dev;
     struct USBBtState *s;
     HCIInfo *hci;
+    const char *name = "usb-bt-dongle";
 
     if (*cmdline) {
         hci = hci_init(cmdline);
@@ -525,19 +535,17 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline)
 
     if (!hci)
         return NULL;
-    dev = usb_create_simple(bus, "usb-bt-dongle");
+    dev = usb_create(bus, name);
     if (!dev) {
+        error_report("Failed to create USB device '%s'", name);
         return NULL;
     }
     s = DO_UPCAST(struct USBBtState, dev, dev);
-    s->dev.opaque = s;
-
     s->hci = hci;
-    s->hci->opaque = s;
-    s->hci->evt_recv = usb_bt_out_hci_packet_event;
-    s->hci->acl_recv = usb_bt_out_hci_packet_acl;
-
-    usb_bt_handle_reset(&s->dev);
+    if (qdev_init(&dev->qdev) < 0) {
+        error_report("Failed to initialize USB device '%s'", name);
+        return NULL;
+    }
 
     return dev;
 }
commit 35e83d10f230616888cc4258ceddf06a612dde8a
Author: Christian Burger <christian at krikkel.de>
Date:   Sat Jun 14 20:19:41 2014 +0100

    input: fix jumpy mouse cursor with USB mouse emulation
    
    Guest mouse pointer was jumpy, when moving host mouse in the vertical direction (see bug #1327800).
    
    Signed-off-by: Christian Burger <christian at krikkel.de>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/input/hid.c b/hw/input/hid.c
index 9656e90..148c003 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -124,7 +124,7 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
         if (evt->rel->axis == INPUT_AXIS_X) {
             e->xdx += evt->rel->value;
         } else if (evt->rel->axis == INPUT_AXIS_Y) {
-            e->ydy -= evt->rel->value;
+            e->ydy += evt->rel->value;
         }
         break;
 
@@ -191,7 +191,7 @@ static void hid_pointer_sync(DeviceState *dev)
         if (hs->kind == HID_MOUSE) {
             prev->xdx += curr->xdx;
             curr->xdx = 0;
-            prev->ydy -= curr->ydy;
+            prev->ydy += curr->ydy;
             curr->ydy = 0;
         } else {
             prev->xdx = curr->xdx;
commit c26f3a0a6dfe5ef2973ddfab03b1ceff641a7ebe
Merge: b3959ef 352e8da
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Jul 1 11:55:48 2014 +0100

    Merge remote-tracking branch 'remotes/bonzini/memory' into staging
    
    * remotes/bonzini/memory:
      qdev: correctly send DEVICE_DELETED for recursively-deleted devices
      memory: do not give a name to the internal exec.c regions
      memory: MemoryRegion: Add size property
      memory: MemoryRegion: Add may-overlap and priority props
      memory: MemoryRegion: Add container and addr props
      memory: MemoryRegion: replace owner field with QOM parent
      memory: MemoryRegion: QOMify
      memory: MemoryRegion: use /machine as default owner
      libqtest: escape strings in QMP commands, fix leak
      qom: object: Ignore refs/unrefs of NULL
      qom: object: remove parent pointer when unparenting
      mc146818rtc: add "rtc-time" link to "/machine/rtc"
      qom: allow creating an alias of a child<> property
      qom: add a generic mechanism to resolve paths
      qom: add object_property_add_alias()
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

commit bc78cff9757782501db15d39828e6af4186fe331
Author: Yang Zhiyong <yangzy.fnst at cn.fujitsu.com>
Date:   Sun Jun 22 02:43:03 2014 +0800

    trace: add qemu_system_powerdown_request and qemu_system_shutdown_request trace events
    
    We have the experience that the guest doesn't stop successfully
    though it was instructed to shut down.
    
    The root cause may be not in QEMU mostly.  However, QEMU is often
    suspected at the beginning just because the issue occurred in
    virtualization environment.
    
    Therefore, we need to affirm that QEMU received the shutdown
    request and raised ACPI irq from "virsh shutdown" command,
    virt-manger or stopping QEMU process to the VM .
    So that we can affirm the problems was belonged to the Guset OS
    rather than the QEMU itself.
    
    When we stop guests by "virsh shutdown" command or virt-manger,
    or stopping QEMU process, qemu_system_powerdown_request() or
    qemu_system_shutdown_request() is called. Then the below functions
    in main_loop_should_exit() of Vl.c are called roughly in the
    following order.
    
    	if (qemu_powerdown_requested())
    		qemu_system_powerdown()
    			monitor_protocol_event(QEVENT_POWERDOWN, NULL)
    
    	OR
    
    	if(qemu_shutdown_requested()}
    		monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
    
    The tracepoint of monitor_protocol_event() already exists, but no
    tracepoints are defined for qemu_system_powerdown_request() and
    qemu_system_shutdown_request(). So this patch adds two tracepoints for
    the two functions. We believe that it will become much easier to
    isolate the problem mentioned above by these tracepoints.
    
    Signed-off-by: Yang Zhiyong <yangzy.fnst at cn.fujitsu.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace-events b/trace-events
index d071b97..11a17a8 100644
--- a/trace-events
+++ b/trace-events
@@ -511,6 +511,8 @@ g_malloc(size_t size, void *ptr) "size %zu ptr %p"
 g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p"
 g_free(void *ptr) "ptr %p"
 system_wakeup_request(int reason) "reason=%d"
+qemu_system_shutdown_request(void) ""
+qemu_system_powerdown_request(void) ""
 
 # block/qcow2.c
 qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d"
diff --git a/vl.c b/vl.c
index 41ddcd2..34f8726 100644
--- a/vl.c
+++ b/vl.c
@@ -1921,6 +1921,7 @@ void qemu_system_killed(int signal, pid_t pid)
 
 void qemu_system_shutdown_request(void)
 {
+    trace_qemu_system_shutdown_request();
     shutdown_requested = 1;
     qemu_notify_event();
 }
@@ -1933,6 +1934,7 @@ static void qemu_system_powerdown(void)
 
 void qemu_system_powerdown_request(void)
 {
+    trace_qemu_system_powerdown_request();
     powerdown_requested = 1;
     qemu_notify_event();
 }
commit 13d8cc515dfcf5574077f964332d34890c0101d0
Author: Jeff Cody <jcody at redhat.com>
Date:   Wed Jun 25 15:40:11 2014 -0400

    block: add backing-file option to block-stream
    
    On some image chains, QEMU may not always be able to resolve the
    filenames properly, when updating the backing file of an image
    after a block job.
    
    For instance, certain relative pathnames may fail, or drives may
    have been specified originally by file descriptor (e.g. /dev/fd/???),
    or a relative protocol pathname may have been used.
    
    In these instances, QEMU may lack the information to be able to make
    the correct choice, but the user or management layer most likely does
    have that knowledge.
    
    With this extension to the block-stream api, the user is able to change
    the backing file of the active layer as part of the block-stream
    operation.
    
    This allows the change to be 'safe', in the sense that if the attempt
    to write the active image metadata fails, then the block-stream
    operation returns failure, without disrupting the guest.
    
    If a backing file string is not specified in the command, the backing
    file string to use is determined in the same manner as it was
    previously.
    
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/stream.c b/block/stream.c
index 0433409..34de8ba 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -32,7 +32,7 @@ typedef struct StreamBlockJob {
     RateLimit limit;
     BlockDriverState *base;
     BlockdevOnError on_error;
-    char backing_file_id[1024];
+    char *backing_file_str;
 } StreamBlockJob;
 
 static int coroutine_fn stream_populate(BlockDriverState *bs,
@@ -186,7 +186,7 @@ wait:
     if (!block_job_is_cancelled(&s->common) && sector_num == end && ret == 0) {
         const char *base_id = NULL, *base_fmt = NULL;
         if (base) {
-            base_id = s->backing_file_id;
+            base_id = s->backing_file_str;
             if (base->drv) {
                 base_fmt = base->drv->format_name;
             }
@@ -196,6 +196,7 @@ wait:
     }
 
     qemu_vfree(buf);
+    g_free(s->backing_file_str);
     block_job_completed(&s->common, ret);
 }
 
@@ -217,7 +218,7 @@ static const BlockJobDriver stream_job_driver = {
 };
 
 void stream_start(BlockDriverState *bs, BlockDriverState *base,
-                  const char *base_id, int64_t speed,
+                  const char *backing_file_str, int64_t speed,
                   BlockdevOnError on_error,
                   BlockDriverCompletionFunc *cb,
                   void *opaque, Error **errp)
@@ -237,9 +238,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
     }
 
     s->base = base;
-    if (base_id) {
-        pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id);
-    }
+    s->backing_file_str = g_strdup(backing_file_str);
 
     s->on_error = on_error;
     s->common.co = qemu_coroutine_create(stream_run);
diff --git a/blockdev.c b/blockdev.c
index 48315e8..48bd9a3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1871,14 +1871,17 @@ static void block_job_cb(void *opaque, int ret)
     bdrv_put_ref_bh_schedule(bs);
 }
 
-void qmp_block_stream(const char *device, bool has_base,
-                      const char *base, bool has_speed, int64_t speed,
+void qmp_block_stream(const char *device,
+                      bool has_base, const char *base,
+                      bool has_backing_file, const char *backing_file,
+                      bool has_speed, int64_t speed,
                       bool has_on_error, BlockdevOnError on_error,
                       Error **errp)
 {
     BlockDriverState *bs;
     BlockDriverState *base_bs = NULL;
     Error *local_err = NULL;
+    const char *base_name = NULL;
 
     if (!has_on_error) {
         on_error = BLOCKDEV_ON_ERROR_REPORT;
@@ -1894,15 +1897,27 @@ void qmp_block_stream(const char *device, bool has_base,
         return;
     }
 
-    if (base) {
+    if (has_base) {
         base_bs = bdrv_find_backing_image(bs, base);
         if (base_bs == NULL) {
             error_set(errp, QERR_BASE_NOT_FOUND, base);
             return;
         }
+        base_name = base;
     }
 
-    stream_start(bs, base_bs, base, has_speed ? speed : 0,
+    /* if we are streaming the entire chain, the result will have no backing
+     * file, and specifying one is therefore an error */
+    if (base_bs == NULL && has_backing_file) {
+        error_setg(errp, "backing file specified, but streaming the "
+                         "entire chain");
+        return;
+    }
+
+    /* backing_file string overrides base bs filename */
+    base_name = has_backing_file ? backing_file : base_name;
+
+    stream_start(bs, base_bs, base_name, has_speed ? speed : 0,
                  on_error, block_job_cb, bs, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
diff --git a/hmp.c b/hmp.c
index 6429e6b..4d1838e 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1176,7 +1176,7 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
     const char *base = qdict_get_try_str(qdict, "base");
     int64_t speed = qdict_get_try_int(qdict, "speed", 0);
 
-    qmp_block_stream(device, base != NULL, base,
+    qmp_block_stream(device, base != NULL, base, false, NULL,
                      qdict_haskey(qdict, "speed"), speed,
                      true, BLOCKDEV_ON_ERROR_REPORT, &error);
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 5b4d75f..e378653 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -922,6 +922,21 @@
 #
 # @base:   #optional the common backing file name
 #
+# @backing-file: #optional The backing file string to write into the active
+#                          layer. This filename is not validated.
+#
+#                          If a pathname string is such that it cannot be
+#                          resolved by QEMU, that means that subsequent QMP or
+#                          HMP commands must use node-names for the image in
+#                          question, as filename lookup methods will fail.
+#
+#                          If not specified, QEMU will automatically determine
+#                          the backing file string to use, or error out if there
+#                          is no obvious choice.  Care should be taken when
+#                          specifying the string, to specify a valid filename or
+#                          protocol.
+#                          (Since 2.1)
+#
 # @speed:  #optional the maximum speed, in bytes per second
 #
 # @on-error: #optional the action to take on an error (default report).
@@ -934,8 +949,8 @@
 # Since: 1.1
 ##
 { 'command': 'block-stream',
-  'data': { 'device': 'str', '*base': 'str', '*speed': 'int',
-            '*on-error': 'BlockdevOnError' } }
+  'data': { 'device': 'str', '*base': 'str', '*backing-file': 'str',
+            '*speed': 'int', '*on-error': 'BlockdevOnError' } }
 
 ##
 # @block-job-set-speed:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index a3f932c..4be4765 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -979,7 +979,7 @@ EQMP
 
     {
         .name       = "block-stream",
-        .args_type  = "device:B,base:s?,speed:o?,on-error:s?",
+        .args_type  = "device:B,base:s?,speed:o?,backing-file:s?,on-error:s?",
         .mhandler.cmd_new = qmp_marshal_input_block_stream,
     },
 
commit 54e269009099cdc9483be115f1e12d56ad459c5e
Author: Jeff Cody <jcody at redhat.com>
Date:   Wed Jun 25 15:40:10 2014 -0400

    block: extend block-commit to accept a string for the backing file
    
    On some image chains, QEMU may not always be able to resolve the
    filenames properly, when updating the backing file of an image
    after a block commit.
    
    For instance, certain relative pathnames may fail, or drives may
    have been specified originally by file descriptor (e.g. /dev/fd/???),
    or a relative protocol pathname may have been used.
    
    In these instances, QEMU may lack the information to be able to make
    the correct choice, but the user or management layer most likely does
    have that knowledge.
    
    With this extension to the block-commit api, the user is able to change
    the backing file of the overlay image as part of the block-commit
    operation.
    
    This allows the change to be 'safe', in the sense that if the attempt
    to write the overlay image metadata fails, then the block-commit
    operation returns failure, without disrupting the guest.
    
    If the commit top is the active layer, then specifying the backing
    file string will be treated as an error (there is no overlay image
    to modify in that case).
    
    If a backing file string is not specified in the command, the backing
    file string to use is determined in the same manner as it was
    previously.
    
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index f45e63c..f80e2b2 100644
--- a/block.c
+++ b/block.c
@@ -2555,12 +2555,15 @@ typedef struct BlkIntermediateStates {
  *
  * base <- active
  *
+ * If backing_file_str is non-NULL, it will be used when modifying top's
+ * overlay image metadata.
+ *
  * Error conditions:
  *  if active == top, that is considered an error
  *
  */
 int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
-                           BlockDriverState *base)
+                           BlockDriverState *base, const char *backing_file_str)
 {
     BlockDriverState *intermediate;
     BlockDriverState *base_bs = NULL;
@@ -2612,7 +2615,8 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
     }
 
     /* success - we can delete the intermediate states, and link top->base */
-    ret = bdrv_change_backing_file(new_top_bs, base_bs->filename,
+    backing_file_str = backing_file_str ? backing_file_str : base_bs->filename;
+    ret = bdrv_change_backing_file(new_top_bs, backing_file_str,
                                    base_bs->drv ? base_bs->drv->format_name : "");
     if (ret) {
         goto exit;
diff --git a/block/commit.c b/block/commit.c
index 5c09f44..91517d3 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -37,6 +37,7 @@ typedef struct CommitBlockJob {
     BlockdevOnError on_error;
     int base_flags;
     int orig_overlay_flags;
+    char *backing_file_str;
 } CommitBlockJob;
 
 static int coroutine_fn commit_populate(BlockDriverState *bs,
@@ -141,7 +142,7 @@ wait:
 
     if (!block_job_is_cancelled(&s->common) && sector_num == end) {
         /* success */
-        ret = bdrv_drop_intermediate(active, top, base);
+        ret = bdrv_drop_intermediate(active, top, base, s->backing_file_str);
     }
 
 exit_free_buf:
@@ -158,7 +159,7 @@ exit_restore_reopen:
     if (overlay_bs && s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) {
         bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL);
     }
-
+    g_free(s->backing_file_str);
     block_job_completed(&s->common, ret);
 }
 
@@ -182,7 +183,7 @@ static const BlockJobDriver commit_job_driver = {
 void commit_start(BlockDriverState *bs, BlockDriverState *base,
                   BlockDriverState *top, int64_t speed,
                   BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
-                  void *opaque, Error **errp)
+                  void *opaque, const char *backing_file_str, Error **errp)
 {
     CommitBlockJob *s;
     BlockReopenQueue *reopen_queue = NULL;
@@ -244,6 +245,8 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
     s->base_flags          = orig_base_flags;
     s->orig_overlay_flags  = orig_overlay_flags;
 
+    s->backing_file_str = g_strdup(backing_file_str);
+
     s->on_error = on_error;
     s->common.co = qemu_coroutine_create(commit_run);
 
diff --git a/blockdev.c b/blockdev.c
index 57373d3..48315e8 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1915,6 +1915,7 @@ void qmp_block_stream(const char *device, bool has_base,
 void qmp_block_commit(const char *device,
                       bool has_base, const char *base,
                       bool has_top, const char *top,
+                      bool has_backing_file, const char *backing_file,
                       bool has_speed, int64_t speed,
                       Error **errp)
 {
@@ -1980,11 +1981,16 @@ void qmp_block_commit(const char *device,
     }
 
     if (top_bs == bs) {
+        if (has_backing_file) {
+            error_setg(errp, "'backing-file' specified,"
+                             " but 'top' is the active layer");
+            return;
+        }
         commit_active_start(bs, base_bs, speed, on_error, block_job_cb,
                             bs, &local_err);
     } else {
         commit_start(bs, base_bs, top_bs, speed, on_error, block_job_cb, bs,
-                    &local_err);
+                     has_backing_file ? backing_file : NULL, &local_err);
     }
     if (local_err != NULL) {
         error_propagate(errp, local_err);
diff --git a/include/block/block.h b/include/block/block.h
index 29c9e50..baecc26 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -285,7 +285,8 @@ int bdrv_change_backing_file(BlockDriverState *bs,
     const char *backing_file, const char *backing_fmt);
 void bdrv_register(BlockDriver *bdrv);
 int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top,
-                           BlockDriverState *base);
+                           BlockDriverState *base,
+                           const char *backing_file_str);
 BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
                                     BlockDriverState *bs);
 BlockDriverState *bdrv_find_base(BlockDriverState *bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index eaf6e31..8f8e65e 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -463,13 +463,14 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
  * @on_error: The action to take upon error.
  * @cb: Completion function for the job.
  * @opaque: Opaque pointer value passed to @cb.
+ * @backing_file_str: String to use as the backing file in @top's overlay
  * @errp: Error object.
  *
  */
 void commit_start(BlockDriverState *bs, BlockDriverState *base,
                  BlockDriverState *top, int64_t speed,
                  BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
-                 void *opaque, Error **errp);
+                 void *opaque, const char *backing_file_str, Error **errp);
 /**
  * commit_active_start:
  * @bs: Active block device to be committed.
diff --git a/qapi/block-core.json b/qapi/block-core.json
index aa12527..5b4d75f 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -720,6 +720,23 @@
 #                    which contains the topmost data to be committed down. If
 #                    not specified, this is the active layer.
 #
+# @backing-file:  #optional The backing file string to write into the overlay
+#                           image of 'top'.  If 'top' is the active layer,
+#                           specifying a backing file string is an error. This
+#                           filename is not validated.
+#
+#                           If a pathname string is such that it cannot be
+#                           resolved by QEMU, that means that subsequent QMP or
+#                           HMP commands must use node-names for the image in
+#                           question, as filename lookup methods will fail.
+#
+#                           If not specified, QEMU will automatically determine
+#                           the backing file string to use, or error out if
+#                           there is no obvious choice. Care should be taken
+#                           when specifying the string, to specify a valid
+#                           filename or protocol.
+#                           (Since 2.1)
+#
 #                    If top == base, that is an error.
 #                    If top == active, the job will not be completed by itself,
 #                    user needs to complete the job with the block-job-complete
@@ -732,7 +749,6 @@
 #                    size of the smaller top, you can safely truncate it
 #                    yourself once the commit operation successfully completes.
 #
-#
 # @speed:  #optional the maximum speed, in bytes per second
 #
 # Returns: Nothing on success
@@ -747,7 +763,7 @@
 ##
 { 'command': 'block-commit',
   'data': { 'device': 'str', '*base': 'str', '*top': 'str',
-            '*speed': 'int' } }
+            '*backing-file': 'str', '*speed': 'int' } }
 
 ##
 # @drive-backup
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 8534948..a3f932c 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -985,7 +985,7 @@ EQMP
 
     {
         .name       = "block-commit",
-        .args_type  = "device:B,base:s?,top:s?,speed:o?",
+        .args_type  = "device:B,base:s?,top:s?,backing-file:s?,speed:o?",
         .mhandler.cmd_new = qmp_marshal_input_block_commit,
     },
 
@@ -1006,6 +1006,23 @@ Arguments:
           which contains the topmost data to be committed down. If
           not specified, this is the active layer. (json-string, optional)
 
+- backing-file:     The backing file string to write into the overlay
+                    image of 'top'.  If 'top' is the active layer,
+                    specifying a backing file string is an error. This
+                    filename is not validated.
+
+                    If a pathname string is such that it cannot be
+                    resolved by QEMU, that means that subsequent QMP or
+                    HMP commands must use node-names for the image in
+                    question, as filename lookup methods will fail.
+
+                    If not specified, QEMU will automatically determine
+                    the backing file string to use, or error out if
+                    there is no obvious choice. Care should be taken
+                    when specifying the string, to specify a valid
+                    filename or protocol.
+                    (json-string, optional) (Since 2.1)
+
           If top == base, that is an error.
           If top == active, the job will not be completed by itself,
           user needs to complete the job with the block-job-complete
commit 5a6684d2b957f9ec75d7ed7b14332293abec1d6c
Author: Jeff Cody <jcody at redhat.com>
Date:   Wed Jun 25 15:40:09 2014 -0400

    block: add helper function to determine if a BDS is in a chain
    
    This is a small helper function, to determine if 'base' is in the
    chain of BlockDriverState 'top'.  It returns true if it is in the chain,
    and false otherwise.
    
    If either argument is NULL, it will also return false.
    
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index c111c29..f45e63c 100644
--- a/block.c
+++ b/block.c
@@ -3774,6 +3774,17 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
     return NULL;
 }
 
+/* If 'base' is in the same chain as 'top', return true. Otherwise,
+ * return false.  If either argument is NULL, return false. */
+bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base)
+{
+    while (top && top != base) {
+        top = top->backing_hd;
+    }
+
+    return top != NULL;
+}
+
 BlockDriverState *bdrv_next(BlockDriverState *bs)
 {
     if (!bs) {
diff --git a/include/block/block.h b/include/block/block.h
index 7e92f54..29c9e50 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -403,6 +403,7 @@ BlockDeviceInfoList *bdrv_named_nodes_list(void);
 BlockDriverState *bdrv_lookup_bs(const char *device,
                                  const char *node_name,
                                  Error **errp);
+bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base);
 BlockDriverState *bdrv_next(BlockDriverState *bs);
 void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
                   void *opaque);
commit fa40e65622352012dccd435147f28161375a6815
Author: Jeff Cody <jcody at redhat.com>
Date:   Tue Jul 1 09:52:16 2014 +0200

    block: add QAPI command to allow live backing file change
    
    This allows a user to make a live change to the backing file recorded in
    an open image.
    
    The image file to modify can be specified 2 ways:
    
    1) image filename
    2) image node-name
    
    Note: this does not cause the backing file itself to be reopened; it
    merely changes the backing filename in the image file structure, and
    in internal BDS structures.
    
    It is the responsibility of the user to pass a filename string that
    can be resolved when the image chain is reopened, and the filename
    string is not validated.
    
    A good analogy for this command is that it is a live version of
    'qemu-img rebase -u', with respect to changing the backing file string.
    
    [Jeff is offline so I respun this patch in his absence.  Dropped image
    filename since using node-name is preferred and this is a new command.
    No need to introduce the limitations of finding images by filename.
    --Stefan]
    
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 79ce52b..57373d3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2367,6 +2367,85 @@ void qmp_block_job_complete(const char *device, Error **errp)
     block_job_complete(job, errp);
 }
 
+void qmp_change_backing_file(const char *device,
+                             const char *image_node_name,
+                             const char *backing_file,
+                             Error **errp)
+{
+    BlockDriverState *bs = NULL;
+    BlockDriverState *image_bs = NULL;
+    Error *local_err = NULL;
+    bool ro;
+    int open_flags;
+    int ret;
+
+    /* find the top layer BDS of the chain */
+    bs = bdrv_find(device);
+    if (!bs) {
+        error_set(errp, QERR_DEVICE_NOT_FOUND, device);
+        return;
+    }
+
+    image_bs = bdrv_lookup_bs(NULL, image_node_name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (!image_bs) {
+        error_setg(errp, "image file not found");
+        return;
+    }
+
+    if (bdrv_find_base(image_bs) == image_bs) {
+        error_setg(errp, "not allowing backing file change on an image "
+                         "without a backing file");
+        return;
+    }
+
+    /* even though we are not necessarily operating on bs, we need it to
+     * determine if block ops are currently prohibited on the chain */
+    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_CHANGE, errp)) {
+        return;
+    }
+
+    /* final sanity check */
+    if (!bdrv_chain_contains(bs, image_bs)) {
+        error_setg(errp, "'%s' and image file are not in the same chain",
+                   device);
+        return;
+    }
+
+    /* if not r/w, reopen to make r/w */
+    open_flags = image_bs->open_flags;
+    ro = bdrv_is_read_only(image_bs);
+
+    if (ro) {
+        bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+
+    ret = bdrv_change_backing_file(image_bs, backing_file,
+                               image_bs->drv ? image_bs->drv->format_name : "");
+
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "Could not change backing file to '%s'",
+                         backing_file);
+        /* don't exit here, so we can try to restore open flags if
+         * appropriate */
+    }
+
+    if (ro) {
+        bdrv_reopen(image_bs, open_flags, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err); /* will preserve prior errp */
+        }
+    }
+}
+
 void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 {
     QmpOutputVisitor *ov = qmp_output_visitor_new();
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 6a697f1..aa12527 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -680,6 +680,32 @@
   'data': 'BlockdevSnapshot' }
 
 ##
+# @change-backing-file
+#
+# Change the backing file in the image file metadata.  This does not
+# cause QEMU to reopen the image file to reparse the backing filename
+# (it may, however, perform a reopen to change permissions from
+# r/o -> r/w -> r/o, if needed). The new backing file string is written
+# into the image file metadata, and the QEMU internal strings are
+# updated.
+#
+# @image-node-name: The name of the block driver state node of the
+#                   image to modify.
+#
+# @device:          The name of the device that owns image-node-name.
+#
+# @backing-file:    The string to write as the backing file.  This
+#                   string is not validated, so care should be taken
+#                   when specifying the string or the image chain may
+#                   not be able to be reopened again.
+#
+# Since: 2.1
+##
+{ 'command': 'change-backing-file',
+  'data': { 'device': 'str', 'image-node-name': 'str',
+            'backing-file': 'str' } }
+
+##
 # @block-commit
 #
 # Live commit of data from overlay image nodes into backing nodes - i.e.,
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 8c5fdb5..8534948 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1353,6 +1353,45 @@ Example:
 EQMP
 
     {
+        .name       = "change-backing-file",
+        .args_type  = "device:s,image-node-name:s,backing-file:s",
+        .mhandler.cmd_new = qmp_marshal_input_change_backing_file,
+    },
+
+SQMP
+change-backing-file
+-------------------
+Since: 2.1
+
+Change the backing file in the image file metadata.  This does not cause
+QEMU to reopen the image file to reparse the backing filename (it may,
+however, perform a reopen to change permissions from r/o -> r/w -> r/o,
+if needed). The new backing file string is written into the image file
+metadata, and the QEMU internal strings are updated.
+
+Arguments:
+
+- "image-node-name":    The name of the block driver state node of the
+                        image to modify.  The "device" is argument is used to
+                        verify "image-node-name" is in the chain described by
+                        "device".
+                        (json-string, optional)
+
+- "device":             The name of the device.
+                        (json-string)
+
+- "backing-file":       The string to write as the backing file.  This string is
+                        not validated, so care should be taken when specifying
+                        the string or the image chain may not be able to be
+                        reopened again.
+                        (json-string)
+
+Returns: Nothing on success
+         If "device" does not exist or cannot be determined, DeviceNotFound
+
+EQMP
+
+    {
         .name       = "balloon",
         .args_type  = "value:M",
         .mhandler.cmd_new = qmp_marshal_input_balloon,
commit 352e8da743f26948cb12d0ee53c455f328f59bbe
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 26 15:10:03 2014 +0200

    qdev: correctly send DEVICE_DELETED for recursively-deleted devices
    
    When a device is unparented (i.e. made completely hidden from management)
    we want to send a DEVICE_DELETED event only if the device actually was
    realized.  This avoids raising DEVICE_DELETED events when device_add
    fails.
    
    However, this does not work right for recursively-deleted
    devices: the whole tree is _first_ unrealized, _then_ unparented.
    Then device_unparent sees realized==false and fails to trigger
    the event.  The solution is simply to move have_realized into
    the DeviceState struct.  If device_add fails, we never set the
    new field to true and DEVICE_DELETED is not sent.
    
    Fixes qemu-iotests testcase 067 (broken by commit 5942a19, though that
    commit in turn fixed a possible segfault in the same test).
    
    Reported-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index d1eba3c..c520415 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -848,6 +848,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
         if (dev->hotplugged && local_err == NULL) {
             device_reset(dev);
         }
+        dev->pending_deleted_event = false;
     } else if (!value && dev->realized) {
         QLIST_FOREACH(bus, &dev->child_bus, sibling) {
             object_property_set_bool(OBJECT(bus), false, "realized",
@@ -862,6 +863,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
         if (dc->unrealize && local_err == NULL) {
             dc->unrealize(dev, &local_err);
         }
+        dev->pending_deleted_event = true;
     }
 
     if (local_err != NULL) {
@@ -972,7 +974,6 @@ static void device_unparent(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
     BusState *bus;
-    bool have_realized = dev->realized;
 
     if (dev->realized) {
         object_property_set_bool(obj, false, "realized", NULL);
@@ -988,7 +989,7 @@ static void device_unparent(Object *obj)
     }
 
     /* Only send event if the device had been completely realized */
-    if (have_realized) {
+    if (dev->pending_deleted_event) {
         gchar *path = object_get_canonical_path(OBJECT(dev));
 
         qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort);
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 9221cfc..0799ff2 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -156,6 +156,7 @@ struct DeviceState {
 
     const char *id;
     bool realized;
+    bool pending_deleted_event;
     QemuOpts *opts;
     int hotplugged;
     BusState *parent_bus;
commit 1f6245e5aba94ff7acd34f8514da7dfb9712935d
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Jun 13 10:48:06 2014 +0200

    memory: do not give a name to the internal exec.c regions
    
    There is no need to have them visible under /machine.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/exec.c b/exec.c
index df4a080..5a2a25e 100644
--- a/exec.c
+++ b/exec.c
@@ -1801,13 +1801,13 @@ MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index)
 
 static void io_mem_init(void)
 {
-    memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, "rom", UINT64_MAX);
+    memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, NULL, UINT64_MAX);
     memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL,
-                          "unassigned", UINT64_MAX);
+                          NULL, UINT64_MAX);
     memory_region_init_io(&io_mem_notdirty, NULL, &notdirty_mem_ops, NULL,
-                          "notdirty", UINT64_MAX);
+                          NULL, UINT64_MAX);
     memory_region_init_io(&io_mem_watch, NULL, &watch_mem_ops, NULL,
-                          "watch", UINT64_MAX);
+                          NULL, UINT64_MAX);
 }
 
 static void mem_begin(MemoryListener *listener)
commit 52aef7bba74a65d0c9fbec7a6559cc8385ab0e17
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Jun 5 23:17:35 2014 -0700

    memory: MemoryRegion: Add size property
    
    To allow devices to dynamically resize the device. The motivation is
    to allow devices with variable size to init their memory_region
    without size early and then correctly populate size at realize() time.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index 834959b..64d7176 100644
--- a/memory.c
+++ b/memory.c
@@ -971,6 +971,15 @@ static bool memory_region_get_may_overlap(Object *obj, Error **errp)
     return mr->may_overlap;
 }
 
+static void memory_region_get_size(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+    uint64_t value = memory_region_size(mr);
+
+    visit_type_uint64(v, &value, name, errp);
+}
+
 static void memory_region_initfn(Object *obj)
 {
     MemoryRegion *mr = MEMORY_REGION(obj);
@@ -1002,6 +1011,10 @@ static void memory_region_initfn(Object *obj)
                              memory_region_get_may_overlap,
                              NULL, /* memory_region_set_may_overlap */
                              &error_abort);
+    object_property_add(OBJECT(mr), "size", "uint64",
+                        memory_region_get_size,
+                        NULL, /* memory_region_set_size, */
+                        NULL, NULL, &error_abort);
 }
 
 static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
commit d33382da9abe21cb42f26b55945845b56ce9324a
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Jun 5 23:17:01 2014 -0700

    memory: MemoryRegion: Add may-overlap and priority props
    
    QOM propertyify the .may-overlap and .priority fields. The setters
    will re-add the memory as a subregion if needed (i.e. the values change
    when the memory region is already contained).
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    [Remove setters. - Paolo]
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 0c7e825..e2c8e3e 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -157,7 +157,7 @@ struct MemoryRegion {
     bool flush_coalesced_mmio;
     MemoryRegion *alias;
     hwaddr alias_offset;
-    int priority;
+    int32_t priority;
     bool may_overlap;
     QTAILQ_HEAD(subregions, MemoryRegion) subregions;
     QTAILQ_ENTRY(MemoryRegion) subregions_link;
diff --git a/memory.c b/memory.c
index 04dc933..834959b 100644
--- a/memory.c
+++ b/memory.c
@@ -955,6 +955,22 @@ static Object *memory_region_resolve_container(Object *obj, void *opaque,
     return OBJECT(mr->container);
 }
 
+static void memory_region_get_priority(Object *obj, Visitor *v, void *opaque,
+                                       const char *name, Error **errp)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+    int32_t value = mr->priority;
+
+    visit_type_int32(v, &value, name, errp);
+}
+
+static bool memory_region_get_may_overlap(Object *obj, Error **errp)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+
+    return mr->may_overlap;
+}
+
 static void memory_region_initfn(Object *obj)
 {
     MemoryRegion *mr = MEMORY_REGION(obj);
@@ -978,6 +994,14 @@ static void memory_region_initfn(Object *obj)
                         memory_region_get_addr,
                         NULL, /* memory_region_set_addr */
                         NULL, NULL, &error_abort);
+    object_property_add(OBJECT(mr), "priority", "uint32",
+                        memory_region_get_priority,
+                        NULL, /* memory_region_set_priority */
+                        NULL, NULL, &error_abort);
+    object_property_add_bool(OBJECT(mr), "may-overlap",
+                             memory_region_get_may_overlap,
+                             NULL, /* memory_region_set_may_overlap */
+                             &error_abort);
 }
 
 static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
commit 409ddd0139c101f813d16e8ebaa7c7d4b4afb96e
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Jun 5 23:16:27 2014 -0700

    memory: MemoryRegion: Add container and addr props
    
    Expose the already existing .parent and .addr fields as QOM properties.
    .parent (i.e. the field describing the memory region that contains this
    one in Memory hierachy) is renamed "container". This is to avoid
    confusion with the QOM parent.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    [Remove setters.  Do not unref parent on releasing the property. Clean
     up error propagation. - Paolo]
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index 8970081..04dc933 100644
--- a/memory.c
+++ b/memory.c
@@ -16,6 +16,7 @@
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
 #include "exec/ioport.h"
+#include "qapi/visitor.h"
 #include "qemu/bitops.h"
 #include "qom/object.h"
 #include "trace.h"
@@ -922,9 +923,42 @@ void memory_region_init(MemoryRegion *mr,
     }
 }
 
+static void memory_region_get_addr(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+    uint64_t value = mr->addr;
+
+    visit_type_uint64(v, &value, name, errp);
+}
+
+static void memory_region_get_container(Object *obj, Visitor *v, void *opaque,
+                                        const char *name, Error **errp)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+    gchar *path = (gchar *)"";
+
+    if (mr->container) {
+        path = object_get_canonical_path(OBJECT(mr->container));
+    }
+    visit_type_str(v, &path, name, errp);
+    if (mr->container) {
+        g_free(path);
+    }
+}
+
+static Object *memory_region_resolve_container(Object *obj, void *opaque,
+                                               const char *part)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+
+    return OBJECT(mr->container);
+}
+
 static void memory_region_initfn(Object *obj)
 {
     MemoryRegion *mr = MEMORY_REGION(obj);
+    ObjectProperty *op;
 
     mr->ops = &unassigned_mem_ops;
     mr->enabled = true;
@@ -932,6 +966,18 @@ static void memory_region_initfn(Object *obj)
     mr->destructor = memory_region_destructor_none;
     QTAILQ_INIT(&mr->subregions);
     QTAILQ_INIT(&mr->coalesced);
+
+    op = object_property_add(OBJECT(mr), "container",
+                             "link<" TYPE_MEMORY_REGION ">",
+                             memory_region_get_container,
+                             NULL, /* memory_region_set_container */
+                             NULL, NULL, &error_abort);
+    op->resolve = memory_region_resolve_container;
+
+    object_property_add(OBJECT(mr), "addr", "uint64",
+                        memory_region_get_addr,
+                        NULL, /* memory_region_set_addr */
+                        NULL, NULL, &error_abort);
 }
 
 static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
commit 22a893e4f55344f96e1aafc66f5fedc491a5ca97
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Jun 11 10:58:06 2014 +0200

    memory: MemoryRegion: replace owner field with QOM parent
    
    The two are now the same.
    
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/exec/memory.h b/include/exec/memory.h
index 85b56e2..0c7e825 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -141,7 +141,6 @@ struct MemoryRegion {
     const MemoryRegionOps *ops;
     const MemoryRegionIOMMUOps *iommu_ops;
     void *opaque;
-    struct Object *owner;
     MemoryRegion *container;
     Int128 size;
     hwaddr addr;
diff --git a/memory.c b/memory.c
index 9397fec..8970081 100644
--- a/memory.c
+++ b/memory.c
@@ -905,9 +905,11 @@ void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
 {
-    object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
+    if (!owner) {
+        owner = qdev_get_machine();
+    }
 
-    mr->owner = owner ? owner : qdev_get_machine();
+    object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
     mr->size = int128_make64(size);
     if (size == UINT64_MAX) {
         mr->size = int128_2_64();
@@ -915,7 +917,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->name = g_strdup(name);
 
     if (name) {
-        object_property_add_child_array(mr->owner, name, OBJECT(mr));
+        object_property_add_child_array(owner, name, OBJECT(mr));
         object_unref(OBJECT(mr));
     }
 }
@@ -1187,24 +1189,37 @@ void memory_region_destroy(MemoryRegion *mr)
 
 Object *memory_region_owner(MemoryRegion *mr)
 {
-    return mr->owner;
+    Object *obj = OBJECT(mr);
+    return obj->parent;
 }
 
 void memory_region_ref(MemoryRegion *mr)
 {
-    if (mr && mr->owner) {
-        object_ref(mr->owner);
+    /* MMIO callbacks most likely will access data that belongs
+     * to the owner, hence the need to ref/unref the owner whenever
+     * the memory region is in use.
+     *
+     * The memory region is a child of its owner.  As long as the
+     * owner doesn't call unparent itself on the memory region,
+     * ref-ing the owner will also keep the memory region alive.
+     * Memory regions without an owner are supposed to never go away,
+     * but we still ref/unref them for debugging purposes.
+     */
+    Object *obj = OBJECT(mr);
+    if (obj && obj->parent) {
+        object_ref(obj->parent);
     } else {
-        object_ref(OBJECT(mr));
+        object_ref(obj);
     }
 }
 
 void memory_region_unref(MemoryRegion *mr)
 {
-    if (mr && mr->owner) {
-        object_unref(mr->owner);
+    Object *obj = OBJECT(mr);
+    if (obj && obj->parent) {
+        object_unref(obj->parent);
     } else {
-        object_unref(OBJECT(mr));
+        object_unref(obj);
     }
 }
 
commit b4fefef9d52003b6d09866501275a9a57995c6b0
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Jun 5 23:15:52 2014 -0700

    memory: MemoryRegion: QOMify
    
    QOMify memory regions as an Object. The former init() and destroy()
    routines become instance_init() and instance_finalize() resp.
    
    memory_region_init() is re-implemented to be:
    object_initialize() + set fields
    
    memory_region_destroy() is re-implemented to call unparent().
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    [Add newly-created MR as child, unparent on destruction. - Paolo]
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/exec.c b/exec.c
index 18d6c35..df4a080 100644
--- a/exec.c
+++ b/exec.c
@@ -883,7 +883,7 @@ static void phys_section_destroy(MemoryRegion *mr)
 
     if (mr->subpage) {
         subpage_t *subpage = container_of(mr, subpage_t, iomem);
-        memory_region_destroy(&subpage->iomem);
+        object_unref(OBJECT(&subpage->iomem));
         g_free(subpage);
     }
 }
@@ -1768,7 +1768,7 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base)
     mmio->as = as;
     mmio->base = base;
     memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio,
-                          "subpage", TARGET_PAGE_SIZE);
+                          NULL, TARGET_PAGE_SIZE);
     mmio->iomem.subpage = true;
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 3d778d7..85b56e2 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -32,10 +32,15 @@
 #include "qemu/int128.h"
 #include "qemu/notify.h"
 #include "qapi/error.h"
+#include "qom/object.h"
 
 #define MAX_PHYS_ADDR_SPACE_BITS 62
 #define MAX_PHYS_ADDR            (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
 
+#define TYPE_MEMORY_REGION "qemu:memory-region"
+#define MEMORY_REGION(obj) \
+        OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
+
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegionMmio MemoryRegionMmio;
 
@@ -131,6 +136,7 @@ typedef struct CoalescedMemoryRange CoalescedMemoryRange;
 typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
 struct MemoryRegion {
+    Object parent_obj;
     /* All fields are private - violators will be prosecuted */
     const MemoryRegionOps *ops;
     const MemoryRegionIOMMUOps *iommu_ops;
diff --git a/memory.c b/memory.c
index 7eaa1e9..9397fec 100644
--- a/memory.c
+++ b/memory.c
@@ -842,40 +842,94 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr)
     qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
 }
 
+static bool memory_region_need_escape(char c)
+{
+    return c == '/' || c == '[' || c == '\\' || c == ']';
+}
+
+static char *memory_region_escape_name(const char *name)
+{
+    const char *p;
+    char *escaped, *q;
+    uint8_t c;
+    size_t bytes = 0;
+
+    for (p = name; *p; p++) {
+        bytes += memory_region_need_escape(*p) ? 4 : 1;
+    }
+    if (bytes == p - name) {
+       return g_memdup(name, bytes + 1);
+    }
+
+    escaped = g_malloc(bytes + 1);
+    for (p = name, q = escaped; *p; p++) {
+        c = *p;
+        if (unlikely(memory_region_need_escape(c))) {
+            *q++ = '\\';
+            *q++ = 'x';
+            *q++ = "0123456789abcdef"[c >> 4];
+            c = "0123456789abcdef"[c & 15];
+        }
+        *q++ = c;
+    }
+    *q = 0;
+    return escaped;
+}
+
+static void object_property_add_child_array(Object *owner,
+                                            const char *name,
+                                            Object *child)
+{
+    int i;
+    char *base_name = memory_region_escape_name(name);
+
+    for (i = 0; ; i++) {
+        char *full_name = g_strdup_printf("%s[%d]", base_name, i);
+        Error *local_err = NULL;
+
+        object_property_add_child(owner, full_name, child, &local_err);
+        g_free(full_name);
+        if (!local_err) {
+            break;
+        }
+
+        error_free(local_err);
+    }
+
+    g_free(base_name);
+}
+        
+
 void memory_region_init(MemoryRegion *mr,
                         Object *owner,
                         const char *name,
                         uint64_t size)
 {
-    mr->ops = &unassigned_mem_ops;
-    mr->opaque = NULL;
+    object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
+
     mr->owner = owner ? owner : qdev_get_machine();
-    mr->iommu_ops = NULL;
-    mr->container = NULL;
     mr->size = int128_make64(size);
     if (size == UINT64_MAX) {
         mr->size = int128_2_64();
     }
-    mr->addr = 0;
-    mr->subpage = false;
+    mr->name = g_strdup(name);
+
+    if (name) {
+        object_property_add_child_array(mr->owner, name, OBJECT(mr));
+        object_unref(OBJECT(mr));
+    }
+}
+
+static void memory_region_initfn(Object *obj)
+{
+    MemoryRegion *mr = MEMORY_REGION(obj);
+
+    mr->ops = &unassigned_mem_ops;
     mr->enabled = true;
-    mr->terminates = false;
-    mr->ram = false;
     mr->romd_mode = true;
-    mr->readonly = false;
-    mr->rom_device = false;
     mr->destructor = memory_region_destructor_none;
-    mr->priority = 0;
-    mr->may_overlap = false;
-    mr->alias = NULL;
     QTAILQ_INIT(&mr->subregions);
-    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
     QTAILQ_INIT(&mr->coalesced);
-    mr->name = g_strdup(name);
-    mr->dirty_log_mask = 0;
-    mr->ioeventfd_nb = 0;
-    mr->ioeventfds = NULL;
-    mr->flush_coalesced_mmio = false;
 }
 
 static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
@@ -1113,8 +1167,10 @@ void memory_region_init_reservation(MemoryRegion *mr,
     memory_region_init_io(mr, owner, &unassigned_mem_ops, mr, name, size);
 }
 
-void memory_region_destroy(MemoryRegion *mr)
+static void memory_region_finalize(Object *obj)
 {
+    MemoryRegion *mr = MEMORY_REGION(obj);
+
     assert(QTAILQ_EMPTY(&mr->subregions));
     assert(memory_region_transaction_depth == 0);
     mr->destructor(mr);
@@ -1123,6 +1179,12 @@ void memory_region_destroy(MemoryRegion *mr)
     g_free(mr->ioeventfds);
 }
 
+void memory_region_destroy(MemoryRegion *mr)
+{
+    object_unparent(OBJECT(mr));
+}
+
+
 Object *memory_region_owner(MemoryRegion *mr)
 {
     return mr->owner;
@@ -1132,6 +1194,8 @@ void memory_region_ref(MemoryRegion *mr)
 {
     if (mr && mr->owner) {
         object_ref(mr->owner);
+    } else {
+        object_ref(OBJECT(mr));
     }
 }
 
@@ -1139,6 +1203,8 @@ void memory_region_unref(MemoryRegion *mr)
 {
     if (mr && mr->owner) {
         object_unref(mr->owner);
+    } else {
+        object_unref(OBJECT(mr));
     }
 }
 
@@ -1946,3 +2012,18 @@ void mtree_info(fprintf_function mon_printf, void *f)
         g_free(ml);
     }
 }
+
+static const TypeInfo memory_region_info = {
+    .parent             = TYPE_OBJECT,
+    .name               = TYPE_MEMORY_REGION,
+    .instance_size      = sizeof(MemoryRegion),
+    .instance_init      = memory_region_initfn,
+    .instance_finalize  = memory_region_finalize,
+};
+
+static void memory_register_types(void)
+{
+    type_register_static(&memory_region_info);
+}
+
+type_init(memory_register_types)
commit b5c2c3d0c81ea97ac8443113b9a7a0c0ce25368e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Jun 11 10:52:32 2014 +0200

    memory: MemoryRegion: use /machine as default owner
    
    This will be added (after QOMification) as the QOM parent.
    
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/memory.c b/memory.c
index b91a60a..7eaa1e9 100644
--- a/memory.c
+++ b/memory.c
@@ -849,7 +849,7 @@ void memory_region_init(MemoryRegion *mr,
 {
     mr->ops = &unassigned_mem_ops;
     mr->opaque = NULL;
-    mr->owner = owner;
+    mr->owner = owner ? owner : qdev_get_machine();
     mr->iommu_ops = NULL;
     mr->container = NULL;
     mr->size = int128_make64(size);
diff --git a/vl.c b/vl.c
index 41ddcd2..88feeab 100644
--- a/vl.c
+++ b/vl.c
@@ -3986,12 +3986,11 @@ int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    cpu_exec_init_all();
-
     current_machine = MACHINE(object_new(object_class_get_name(
                           OBJECT_CLASS(machine_class))));
     object_property_add_child(object_get_root(), "machine",
                               OBJECT(current_machine), &error_abort);
+    cpu_exec_init_all();
 
     if (machine_class->hw_version) {
         qemu_set_version(machine_class->hw_version);
commit 563890c7c7e977842e2a35afe7a24d06d2103242
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Jun 13 09:35:18 2014 +0200

    libqtest: escape strings in QMP commands, fix leak
    
    libqtest is using g_strdup_printf to format QMP commands, but
    this does not work if the argument strings need to be escaped.
    Instead, use the fancy %-formatting functionality of QObject.
    The only change required in tests is that strings have to be
    formatted as %s, not '%s' or \"%s\".  Luckily this usage of
    parameterized QMP commands is not that frequent.
    
    The leak is in socket_sendf.  Since we are extracting the send
    loop to a new function, fix it now.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 37096dc..c8e1e7b 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -291,7 +291,7 @@ static void test_media_insert(void)
     /* Insert media in drive. DSKCHK should not be reset until a step pulse
      * is sent. */
     qmp_discard_response("{'execute':'change', 'arguments':{"
-                         " 'device':'floppy0', 'target': '%s' }}",
+                         " 'device':'floppy0', 'target': %s }}",
                          test_image);
     qmp_discard_response(""); /* ignore event
                                  (FIXME open -> open transition?!) */
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 71468ac..98e8f4b 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -30,8 +30,9 @@
 
 #include "qemu/compiler.h"
 #include "qemu/osdep.h"
-#include "qapi/qmp/json-streamer.h"
 #include "qapi/qmp/json-parser.h"
+#include "qapi/qmp/json-streamer.h"
+#include "qapi/qmp/qjson.h"
 
 #define MAX_IRQ 256
 #define SOCKET_TIMEOUT 5
@@ -220,19 +221,15 @@ void qtest_quit(QTestState *s)
     g_free(s);
 }
 
-static void socket_sendf(int fd, const char *fmt, va_list ap)
+static void socket_send(int fd, const char *buf, size_t size)
 {
-    gchar *str;
-    size_t size, offset;
-
-    str = g_strdup_vprintf(fmt, ap);
-    size = strlen(str);
+    size_t offset;
 
     offset = 0;
     while (offset < size) {
         ssize_t len;
 
-        len = write(fd, str + offset, size - offset);
+        len = write(fd, buf + offset, size - offset);
         if (len == -1 && errno == EINTR) {
             continue;
         }
@@ -244,6 +241,15 @@ static void socket_sendf(int fd, const char *fmt, va_list ap)
     }
 }
 
+static void socket_sendf(int fd, const char *fmt, va_list ap)
+{
+    gchar *str = g_strdup_vprintf(fmt, ap);
+    size_t size = strlen(str);
+
+    socket_send(fd, str, size);
+    g_free(str);
+}
+
 static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
 {
     va_list ap;
@@ -378,8 +384,29 @@ QDict *qtest_qmp_receive(QTestState *s)
 
 QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
 {
-    /* Send QMP request */
-    socket_sendf(s->qmp_fd, fmt, ap);
+    va_list ap_copy;
+    QObject *qobj;
+
+    /* Going through qobject ensures we escape strings properly.
+     * This seemingly unnecessary copy is required in case va_list
+     * is an array type.
+     */
+    va_copy(ap_copy, ap);
+    qobj = qobject_from_jsonv(fmt, &ap_copy);
+    va_end(ap_copy);
+
+    /* No need to send anything for an empty QObject.  */
+    if (qobj) {
+        QString *qstr = qobject_to_json(qobj);
+        const char *str = qstring_get_str(qstr);
+        size_t size = qstring_get_length(qstr);
+
+        /* Send QMP request */
+        socket_send(s->qmp_fd, str, size);
+
+        QDECREF(qstr);
+        qobject_decref(qobj);
+    }
 
     /* Receive reply */
     return qtest_qmp_receive(s);
diff --git a/tests/qom-test.c b/tests/qom-test.c
index d8d1d8d..4246382 100644
--- a/tests/qom-test.c
+++ b/tests/qom-test.c
@@ -53,7 +53,7 @@ static void test_properties(const char *path, bool recurse)
 
     g_test_message("Obtaining properties of %s", path);
     response = qmp("{ 'execute': 'qom-list',"
-                   "  'arguments': { 'path': '%s' } }", path);
+                   "  'arguments': { 'path': %s } }", path);
     g_assert(response);
 
     if (!recurse) {
@@ -76,8 +76,8 @@ static void test_properties(const char *path, bool recurse)
             const char *prop = qdict_get_str(tuple, "name");
             g_test_message("Testing property %s.%s", path, prop);
             response = qmp("{ 'execute': 'qom-get',"
-                           "  'arguments': { 'path': '%s',"
-                           "                 'property': '%s' } }",
+                           "  'arguments': { 'path': %s,"
+                           "                 'property': %s } }",
                            path, prop);
             /* qom-get may fail but should not, e.g., segfault. */
             g_assert(response);
diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index 15ddaf3..99db538 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -69,7 +69,7 @@ static int qmp_tmp105_get_temperature(const char *id)
     QDict *response;
     int ret;
 
-    response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': '%s', "
+    response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, "
                    "'property': 'temperature' } }", id);
     g_assert(qdict_haskey(response, "return"));
     ret = qdict_get_int(response, "return");
@@ -81,7 +81,7 @@ static void qmp_tmp105_set_temperature(const char *id, int value)
 {
     QDict *response;
 
-    response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': '%s', "
+    response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, "
                    "'property': 'temperature', 'value': %d } }", id, value);
     g_assert(qdict_haskey(response, "return"));
     QDECREF(response);
commit 8ffad850ef5ae14287d0e185d478c9a35820482c
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Jun 5 23:13:36 2014 -0700

    qom: object: Ignore refs/unrefs of NULL
    
    Just do nothing if passed NULL for a ref or unref. This avoids
    call sites that manage a combination of NULL or non-NULL pointers
    having to add iffery around every ref and unref.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qom/object.c b/qom/object.c
index d5de8f6..0e8267b 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -711,11 +711,17 @@ GSList *object_class_get_list(const char *implements_type,
 
 void object_ref(Object *obj)
 {
+    if (!obj) {
+        return;
+    }
      atomic_inc(&obj->ref);
 }
 
 void object_unref(Object *obj)
 {
+    if (!obj) {
+        return;
+    }
     g_assert(obj->ref > 0);
 
     /* parent always holds a reference to its children */
@@ -1160,13 +1166,9 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
         return;
     }
 
-    if (new_target) {
-        object_ref(new_target);
-    }
+    object_ref(new_target);
     *child = new_target;
-    if (old_target != NULL) {
-        object_unref(old_target);
-    }
+    object_unref(old_target);
 }
 
 static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
commit c28322d10cd5f0529605b48684d2b82c9eb9c020
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Mon May 26 17:39:51 2014 -0700

    qom: object: remove parent pointer when unparenting
    
    Certain parts of the QOM framework test this pointer to determine if
    an object is parented. Nuke it when the object is unparented to allow
    for reuse of an object after unparenting.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qom/object.c b/qom/object.c
index f49335f..d5de8f6 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -397,6 +397,7 @@ void object_unparent(Object *obj)
     }
     if (obj->parent) {
         object_property_del_child(obj->parent, obj, NULL);
+        obj->parent = NULL;
     }
     object_unref(obj);
 }
commit 654a36d857ff949e0d1989904b76f53fded9dc83
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Jun 4 14:52:03 2014 -0300

    mc146818rtc: add "rtc-time" link to "/machine/rtc"
    
    Add a link to rtc under /machine providing a stable
    location for management apps to query the value of the
    time.  The link should be added by any object that sends
    RTC_TIME_CHANGE events.
    
    {"execute":"qom-get","arguments":{"path":"/machine","property":"rtc-time"} }
    
    Suggested by Paolo Bonzini and Andreas Faerber.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 307732c..9d817ca 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -909,6 +909,9 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
 
     object_property_add(OBJECT(s), "date", "struct tm",
                         rtc_get_date, NULL, NULL, s, NULL);
+
+    object_property_add_alias(qdev_get_machine(), "rtc-time",
+                              OBJECT(s), "date", NULL);
 }
 
 ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
@@ -950,11 +953,17 @@ static void rtc_class_initfn(ObjectClass *klass, void *data)
     dc->cannot_instantiate_with_device_add_yet = true;
 }
 
+static void rtc_finalize(Object *obj)
+{
+    object_property_del(qdev_get_machine(), "rtc", NULL);
+}
+
 static const TypeInfo mc146818rtc_info = {
     .name          = TYPE_MC146818_RTC,
     .parent        = TYPE_ISA_DEVICE,
     .instance_size = sizeof(RTCState),
     .class_init    = rtc_class_initfn,
+    .instance_finalize = rtc_finalize,
 };
 
 static void mc146818rtc_register_types(void)
commit d190698e6f806198da42c05c35b623760b6e1f00
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Jun 10 11:17:35 2014 +0200

    qom: allow creating an alias of a child<> property
    
    Child properties must be unique.  Fix this problem by
    turning their aliases into links.
    
    The resolve function that forwards to the target property
    does not have any knowledge of the target property's type,
    so it works fine.
    
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/qom/object.c b/qom/object.c
index 7a892ef..f49335f 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1607,22 +1607,32 @@ void object_property_add_alias(Object *obj, const char *name,
     AliasProperty *prop;
     ObjectProperty *op;
     ObjectProperty *target_prop;
+    gchar *prop_type;
 
     target_prop = object_property_find(target_obj, target_name, errp);
     if (!target_prop) {
         return;
     }
 
+    if (object_property_is_child(target_prop)) {
+        prop_type = g_strdup_printf("link%s",
+                                    target_prop->type + strlen("child"));
+    } else {
+        prop_type = g_strdup(target_prop->type);
+    }
+
     prop = g_malloc(sizeof(*prop));
     prop->target_obj = target_obj;
     prop->target_name = target_name;
 
-    op = object_property_add(obj, name, target_prop->type,
+    op = object_property_add(obj, name, prop_type,
                              property_get_alias,
                              property_set_alias,
                              property_release_alias,
                              prop, errp);
     op->resolve = property_resolve_alias;
+
+    g_free(prop_type);
 }
 
 static void object_instance_init(Object *obj)
commit 64607d088132abdb25bf30d93e97d0c8df7b364c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Jun 5 13:11:51 2014 +0200

    qom: add a generic mechanism to resolve paths
    
    It may be desirable to have custom link<> properties that do more
    than just store an object.  Even the addition of a "check"
    function is not enough if setting the link has side effects
    or if a non-standard reference counting is preferrable.
    
    Avoid the assumption that the opaque field of a link<> is a
    LinkProperty struct, by adding a generic "resolve" callback
    to ObjectProperty.  This fixes aliases of link properties.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/qom/object.h b/include/qom/object.h
index 44c513f..8a05a81 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -304,6 +304,25 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
                                       Error **errp);
 
 /**
+ * ObjectPropertyResolve:
+ * @obj: the object that owns the property
+ * @opaque: the opaque registered with the property
+ * @part: the name of the property
+ *
+ * Resolves the #Object corresponding to property @part.
+ *
+ * The returned object can also be used as a starting point
+ * to resolve a relative path starting with "@part".
+ *
+ * Returns: If @path is the path that led to @obj, the function
+ * returns the #Object corresponding to "@path/@part".
+ * If "@path/@part" is not a valid object path, it returns #NULL.
+ */
+typedef Object *(ObjectPropertyResolve)(Object *obj,
+                                        void *opaque,
+                                        const char *part);
+
+/**
  * ObjectPropertyRelease:
  * @obj: the object that owns the property
  * @name: the name of the property
@@ -321,6 +340,7 @@ typedef struct ObjectProperty
     gchar *type;
     ObjectPropertyAccessor *get;
     ObjectPropertyAccessor *set;
+    ObjectPropertyResolve *resolve;
     ObjectPropertyRelease *release;
     void *opaque;
 
@@ -787,12 +807,16 @@ void object_unref(Object *obj);
  *   destruction.  This may be NULL.
  * @opaque: an opaque pointer to pass to the callbacks for the property
  * @errp: returns an error if this function fails
+ *
+ * Returns: The #ObjectProperty; this can be used to set the @resolve
+ * callback for child and link properties.
  */
-void object_property_add(Object *obj, const char *name, const char *type,
-                         ObjectPropertyAccessor *get,
-                         ObjectPropertyAccessor *set,
-                         ObjectPropertyRelease *release,
-                         void *opaque, Error **errp);
+ObjectProperty *object_property_add(Object *obj, const char *name,
+                                    const char *type,
+                                    ObjectPropertyAccessor *get,
+                                    ObjectPropertyAccessor *set,
+                                    ObjectPropertyRelease *release,
+                                    void *opaque, Error **errp);
 
 void object_property_del(Object *obj, const char *name, Error **errp);
 
diff --git a/qom/object.c b/qom/object.c
index a760514..7a892ef 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -356,11 +356,6 @@ static inline bool object_property_is_child(ObjectProperty *prop)
     return strstart(prop->type, "child<", NULL);
 }
 
-static inline bool object_property_is_link(ObjectProperty *prop)
-{
-    return strstart(prop->type, "link<", NULL);
-}
-
 static void object_property_del_all(Object *obj)
 {
     while (!QTAILQ_EMPTY(&obj->properties)) {
@@ -728,11 +723,12 @@ void object_unref(Object *obj)
     }
 }
 
-void object_property_add(Object *obj, const char *name, const char *type,
-                         ObjectPropertyAccessor *get,
-                         ObjectPropertyAccessor *set,
-                         ObjectPropertyRelease *release,
-                         void *opaque, Error **errp)
+ObjectProperty *
+object_property_add(Object *obj, const char *name, const char *type,
+                    ObjectPropertyAccessor *get,
+                    ObjectPropertyAccessor *set,
+                    ObjectPropertyRelease *release,
+                    void *opaque, Error **errp)
 {
     ObjectProperty *prop;
 
@@ -741,7 +737,7 @@ void object_property_add(Object *obj, const char *name, const char *type,
             error_setg(errp, "attempt to add duplicate property '%s'"
                        " to object (type '%s')", name,
                        object_get_typename(obj));
-            return;
+            return NULL;
         }
     }
 
@@ -756,6 +752,7 @@ void object_property_add(Object *obj, const char *name, const char *type,
     prop->opaque = opaque;
 
     QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
+    return prop;
 }
 
 ObjectProperty *object_property_find(Object *obj, const char *name,
@@ -1028,6 +1025,11 @@ static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
     g_free(path);
 }
 
+static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
+{
+    return opaque;
+}
+
 static void object_finalize_child_property(Object *obj, const char *name,
                                            void *opaque)
 {
@@ -1041,15 +1043,18 @@ void object_property_add_child(Object *obj, const char *name,
 {
     Error *local_err = NULL;
     gchar *type;
+    ObjectProperty *op;
 
     type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
 
-    object_property_add(obj, name, type, object_get_child_property, NULL,
-                        object_finalize_child_property, child, &local_err);
+    op = object_property_add(obj, name, type, object_get_child_property, NULL,
+                             object_finalize_child_property, child, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         goto out;
     }
+
+    op->resolve = object_resolve_child_property;
     object_ref(child);
     g_assert(child->parent == NULL);
     child->parent = obj;
@@ -1163,6 +1168,13 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
     }
 }
 
+static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
+{
+    LinkProperty *lprop = opaque;
+
+    return *lprop->child;
+}
+
 static void object_release_link_property(Object *obj, const char *name,
                                          void *opaque)
 {
@@ -1184,6 +1196,7 @@ void object_property_add_link(Object *obj, const char *name,
     Error *local_err = NULL;
     LinkProperty *prop = g_malloc(sizeof(*prop));
     gchar *full_type;
+    ObjectProperty *op;
 
     prop->child = child;
     prop->check = check;
@@ -1191,17 +1204,21 @@ void object_property_add_link(Object *obj, const char *name,
 
     full_type = g_strdup_printf("link<%s>", type);
 
-    object_property_add(obj, name, full_type,
-                        object_get_link_property,
-                        check ? object_set_link_property : NULL,
-                        object_release_link_property,
-                        prop,
-                        &local_err);
+    op = object_property_add(obj, name, full_type,
+                             object_get_link_property,
+                             check ? object_set_link_property : NULL,
+                             object_release_link_property,
+                             prop,
+                             &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         g_free(prop);
+        goto out;
     }
 
+    op->resolve = object_resolve_link_property;
+
+out:
     g_free(full_type);
 }
 
@@ -1260,11 +1277,8 @@ Object *object_resolve_path_component(Object *parent, const gchar *part)
         return NULL;
     }
 
-    if (object_property_is_link(prop)) {
-        LinkProperty *lprop = prop->opaque;
-        return *lprop->child;
-    } else if (object_property_is_child(prop)) {
-        return prop->opaque;
+    if (prop->resolve) {
+        return prop->resolve(parent, prop->opaque, part);
     } else {
         return NULL;
     }
@@ -1571,6 +1585,14 @@ static void property_set_alias(Object *obj, struct Visitor *v, void *opaque,
     object_property_set(prop->target_obj, v, prop->target_name, errp);
 }
 
+static Object *property_resolve_alias(Object *obj, void *opaque,
+                                      const gchar *part)
+{
+    AliasProperty *prop = opaque;
+
+    return object_resolve_path_component(prop->target_obj, prop->target_name);
+}
+
 static void property_release_alias(Object *obj, const char *name, void *opaque)
 {
     AliasProperty *prop = opaque;
@@ -1583,6 +1605,7 @@ void object_property_add_alias(Object *obj, const char *name,
                                Error **errp)
 {
     AliasProperty *prop;
+    ObjectProperty *op;
     ObjectProperty *target_prop;
 
     target_prop = object_property_find(target_obj, target_name, errp);
@@ -1594,11 +1617,12 @@ void object_property_add_alias(Object *obj, const char *name,
     prop->target_obj = target_obj;
     prop->target_name = target_name;
 
-    object_property_add(obj, name, target_prop->type,
-                        property_get_alias,
-                        property_set_alias,
-                        property_release_alias,
-                        prop, errp);
+    op = object_property_add(obj, name, target_prop->type,
+                             property_get_alias,
+                             property_set_alias,
+                             property_release_alias,
+                             prop, errp);
+    op->resolve = property_resolve_alias;
 }
 
 static void object_instance_init(Object *obj)
commit 4e855baabfb548067b618808c32dc413d40e0bc7
Author: Benoît Canet <benoit.canet at irqsave.net>
Date:   Mon Jun 30 17:05:41 2014 +0200

    qapi: Change back sector-count to sectors-count in quorum QAPI events.
    
    fe069d9d had aligned code and documentation while dropping the s from the
    actual JSON output. Fix that.
    
    This also fix test/qemu-iotest/081 since the missing s was causing a permutation.
    
    Signed-off-by: Benoit Canet <benoit at irqsave.net>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt
index 44be891..4a6c2a2 100644
--- a/docs/qmp/qmp-events.txt
+++ b/docs/qmp/qmp-events.txt
@@ -250,14 +250,14 @@ Emitted by the Quorum block driver if it fails to establish a quorum.
 
 Data:
 
-- "reference":    device name if defined else node name.
-- "sector-num":   Number of the first sector of the failed read operation.
-- "sector-count": Failed read operation sector count.
+- "reference":     device name if defined else node name.
+- "sector-num":    Number of the first sector of the failed read operation.
+- "sectors-count": Failed read operation sector count.
 
 Example:
 
 { "event": "QUORUM_FAILURE",
-     "data": { "reference": "usr1", "sector-num": 345435, "sector-count": 5 },
+     "data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
      "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
 
 QUORUM_REPORT_BAD
@@ -267,19 +267,19 @@ Emitted to report a corruption of a Quorum file.
 
 Data:
 
-- "error":        Error message (json-string, optional)
-                  Only present on failure.  This field contains a human-readable
-                  error message.  There are no semantics other than that the
-                  block layer reported an error and clients should not try to
-                  interpret the error string.
-- "node-name":    The graph node name of the block driver state.
-- "sector-num":   Number of the first sector of the failed read operation.
-- "sector-count": Failed read operation sector count.
+- "error":         Error message (json-string, optional)
+                   Only present on failure.  This field contains a human-readable
+                   error message.  There are no semantics other than that the
+                   block layer reported an error and clients should not try to
+                   interpret the error string.
+- "node-name":     The graph node name of the block driver state.
+- "sector-num":    Number of the first sector of the failed read operation.
+- "sectors-count": Failed read operation sector count.
 
 Example:
 
 { "event": "QUORUM_REPORT_BAD",
-     "data": { "node-name": "1.raw", "sector-num": 345435, "sector-count": 5 },
+     "data": { "node-name": "1.raw", "sector-num": 345435, "sectors-count": 5 },
      "timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
 
 RESET
diff --git a/qapi/event.json b/qapi/event.json
index ff97aeb..c51dc49 100644
--- a/qapi/event.json
+++ b/qapi/event.json
@@ -288,12 +288,12 @@
 #
 # @sector-num: number of the first sector of the failed read operation
 #
-# @sector-count: failed read operation sector count
+# @sectors-count: failed read operation sector count
 #
 # Since: 2.0
 ##
 { 'event': 'QUORUM_FAILURE',
-  'data': { 'reference': 'str', 'sector-num': 'int', 'sector-count': 'int' } }
+  'data': { 'reference': 'str', 'sector-num': 'int', 'sectors-count': 'int' } }
 
 ##
 # @QUORUM_REPORT_BAD
@@ -309,13 +309,13 @@
 #
 # @sector-num: number of the first sector of the failed read operation
 #
-# @sector-count: failed read operation sector count
+# @sectors-count: failed read operation sector count
 #
 # Since: 2.0
 ##
 { 'event': 'QUORUM_REPORT_BAD',
   'data': { '*error': 'str', 'node-name': 'str',
-            'sector-num': 'int', 'sector-count': 'int' } }
+            'sector-num': 'int', 'sectors-count': 'int' } }
 
 ##
 # @VSERPORT_CHANGE
commit 6764579f894950afe87d8ec3b323adde8925d4fd
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jun 30 19:03:37 2014 +0100

    block/cow: Avoid use of uninitialized cow_bs in error path
    
    Commit 25814e8987 introduced an error-exit code path which does
    a "goto exit" before the cow_bs variable is initialized, meaning
    we would call bdrv_unref() on an uninitialized variable and
    likely segfault. Fix this by moving the NULL-initialization
    to the top of the function and making the exit code path handle
    the case where it is NULL.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/cow.c b/block/cow.c
index 8f81ee6..6ee4833 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -332,7 +332,7 @@ static int cow_create(const char *filename, QemuOpts *opts, Error **errp)
     char *image_filename = NULL;
     Error *local_err = NULL;
     int ret;
-    BlockDriverState *cow_bs;
+    BlockDriverState *cow_bs = NULL;
 
     /* Read out options */
     image_sectors = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / 512;
@@ -344,7 +344,6 @@ static int cow_create(const char *filename, QemuOpts *opts, Error **errp)
         goto exit;
     }
 
-    cow_bs = NULL;
     ret = bdrv_open(&cow_bs, filename, NULL, NULL,
                     BDRV_O_RDWR | BDRV_O_PROTOCOL, NULL, &local_err);
     if (ret < 0) {
@@ -383,7 +382,9 @@ static int cow_create(const char *filename, QemuOpts *opts, Error **errp)
 
 exit:
     g_free(image_filename);
-    bdrv_unref(cow_bs);
+    if (cow_bs) {
+        bdrv_unref(cow_bs);
+    }
     return ret;
 }
 
commit 4caf0fcd45db46920a6264b1621ae6adc772ef19
Author: Jeff Cody <jcody at redhat.com>
Date:   Wed Jun 25 15:35:26 2014 -0400

    block: simplify bdrv_find_base() and bdrv_find_overlay()
    
    This simplifies the function bdrv_find_overlay().  With this change,
    bdrv_find_base() is just a subset of usage of bdrv_find_overlay(),
    so this also takes advantage of that.
    
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 6856c18..c111c29 100644
--- a/block.c
+++ b/block.c
@@ -2508,32 +2508,23 @@ int bdrv_change_backing_file(BlockDriverState *bs,
  *
  * Returns NULL if bs is not found in active's image chain,
  * or if active == bs.
+ *
+ * Returns the bottommost base image if bs == NULL.
  */
 BlockDriverState *bdrv_find_overlay(BlockDriverState *active,
                                     BlockDriverState *bs)
 {
-    BlockDriverState *overlay = NULL;
-    BlockDriverState *intermediate;
-
-    assert(active != NULL);
-    assert(bs != NULL);
-
-    /* if bs is the same as active, then by definition it has no overlay
-     */
-    if (active == bs) {
-        return NULL;
+    while (active && bs != active->backing_hd) {
+        active = active->backing_hd;
     }
 
-    intermediate = active;
-    while (intermediate->backing_hd) {
-        if (intermediate->backing_hd == bs) {
-            overlay = intermediate;
-            break;
-        }
-        intermediate = intermediate->backing_hd;
-    }
+    return active;
+}
 
-    return overlay;
+/* Given a BDS, searches for the base layer. */
+BlockDriverState *bdrv_find_base(BlockDriverState *bs)
+{
+    return bdrv_find_overlay(bs, NULL);
 }
 
 typedef struct BlkIntermediateStates {
@@ -4326,22 +4317,6 @@ int bdrv_get_backing_file_depth(BlockDriverState *bs)
     return 1 + bdrv_get_backing_file_depth(bs->backing_hd);
 }
 
-BlockDriverState *bdrv_find_base(BlockDriverState *bs)
-{
-    BlockDriverState *curr_bs = NULL;
-
-    if (!bs) {
-        return NULL;
-    }
-
-    curr_bs = bs;
-
-    while (curr_bs->backing_hd) {
-        curr_bs = curr_bs->backing_hd;
-    }
-    return curr_bs;
-}
-
 /**************************************************************/
 /* async I/Os */
 
commit 7676e2c597000eff3a7233b40cca768b358f9bc9
Author: Jeff Cody <jcody at redhat.com>
Date:   Mon Jun 30 15:14:15 2014 +0200

    block: make 'top' argument to block-commit optional
    
    Now that active layer block-commit is supported, the 'top' argument
    no longer needs to be mandatory.
    
    Change it to optional, with the default being the active layer in the
    device chain.
    
    [kwolf: Rebased and resolved conflict in tests/qemu-iotests/040]
    
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Jeff Cody <jcody at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 69b7c2a..79ce52b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1913,7 +1913,8 @@ void qmp_block_stream(const char *device, bool has_base,
 }
 
 void qmp_block_commit(const char *device,
-                      bool has_base, const char *base, const char *top,
+                      bool has_base, const char *base,
+                      bool has_top, const char *top,
                       bool has_speed, int64_t speed,
                       Error **errp)
 {
@@ -1932,6 +1933,11 @@ void qmp_block_commit(const char *device,
     /* drain all i/o before commits */
     bdrv_drain_all();
 
+    /* Important Note:
+     *  libvirt relies on the DeviceNotFound error class in order to probe for
+     *  live commit feature versions; for this to work, we must make sure to
+     *  perform the device lookup before any generic errors that may occur in a
+     *  scenario in which all optional arguments are omitted. */
     bs = bdrv_find(device);
     if (!bs) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
@@ -1945,7 +1951,7 @@ void qmp_block_commit(const char *device,
     /* default top_bs is the active layer */
     top_bs = bs;
 
-    if (top) {
+    if (has_top && top) {
         if (strcmp(bs->filename, top) != 0) {
             top_bs = bdrv_find_backing_image(bs, top);
         }
@@ -1967,6 +1973,12 @@ void qmp_block_commit(const char *device,
         return;
     }
 
+    /* Do not allow attempts to commit an image into itself */
+    if (top_bs == base_bs) {
+        error_setg(errp, "cannot commit an image into itself");
+        return;
+    }
+
     if (top_bs == bs) {
         commit_active_start(bs, base_bs, speed, on_error, block_job_cb,
                             bs, &local_err);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index faf394c..6a697f1 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -690,8 +690,9 @@
 # @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.
+# @top:    #optional The file name of the backing image within the image chain,
+#                    which contains the topmost data to be committed down. If
+#                    not specified, this is the active layer.
 #
 #                    If top == base, that is an error.
 #                    If top == active, the job will not be completed by itself,
@@ -719,7 +720,7 @@
 #
 ##
 { 'command': 'block-commit',
-  'data': { 'device': 'str', '*base': 'str', 'top': 'str',
+  'data': { 'device': 'str', '*base': 'str', '*top': 'str',
             '*speed': 'int' } }
 
 ##
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 1ea18b2..8c5fdb5 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -985,7 +985,7 @@ EQMP
 
     {
         .name       = "block-commit",
-        .args_type  = "device:B,base:s?,top:s,speed:o?",
+        .args_type  = "device:B,base:s?,top:s?,speed:o?",
         .mhandler.cmd_new = qmp_marshal_input_block_commit,
     },
 
@@ -1003,7 +1003,8 @@ Arguments:
           If not specified, this is the deepest backing image
           (json-string, optional)
 - "top":  The file name of the backing image within the image chain,
-          which contains the topmost data to be committed down.
+          which contains the topmost data to be committed down. If
+          not specified, this is the active layer. (json-string, optional)
 
           If top == base, that is an error.
           If top == active, the job will not be completed by itself,
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index d166810..f1e16c1 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -35,11 +35,7 @@ test_img = os.path.join(iotests.test_dir, 'test.img')
 class ImageCommitTestCase(iotests.QMPTestCase):
     '''Abstract base class for image commit test cases'''
 
-    def run_commit_test(self, top, base, need_ready=False):
-        self.assert_no_active_block_jobs()
-        result = self.vm.qmp('block-commit', device='drive0', top=top, base=base)
-        self.assert_qmp(result, 'return', {})
-
+    def wait_for_complete(self, need_ready=False):
         completed = False
         ready = False
         while not completed:
@@ -62,6 +58,18 @@ class ImageCommitTestCase(iotests.QMPTestCase):
         self.assert_no_active_block_jobs()
         self.vm.shutdown()
 
+    def run_commit_test(self, top, base, need_ready=False):
+        self.assert_no_active_block_jobs()
+        result = self.vm.qmp('block-commit', device='drive0', top=top, base=base)
+        self.assert_qmp(result, 'return', {})
+        self.wait_for_complete(need_ready)
+
+    def run_default_commit_test(self):
+        self.assert_no_active_block_jobs()
+        result = self.vm.qmp('block-commit', device='drive0')
+        self.assert_qmp(result, 'return', {})
+        self.wait_for_complete()
+
 class TestSingleDrive(ImageCommitTestCase):
     image_len = 1 * 1024 * 1024
     test_len = 1 * 1024 * 256
@@ -113,17 +121,17 @@ class TestSingleDrive(ImageCommitTestCase):
         self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
         self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
 
+    def test_top_is_default_active(self):
+        self.run_default_commit_test()
+        self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
+        self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
+
     def test_top_and_base_reversed(self):
         self.assert_no_active_block_jobs()
         result = self.vm.qmp('block-commit', device='drive0', top='%s' % backing_img, base='%s' % mid_img)
         self.assert_qmp(result, 'error/class', 'GenericError')
         self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % mid_img)
 
-    def test_top_omitted(self):
-        self.assert_no_active_block_jobs()
-        result = self.vm.qmp('block-commit', device='drive0')
-        self.assert_qmp(result, 'error/class', 'GenericError')
-        self.assert_qmp(result, 'error/desc', "Parameter 'top' is missing")
 
 class TestRelativePaths(ImageCommitTestCase):
     image_len = 1 * 1024 * 1024
commit c891e3bbc5bc3d74ad0ba896852a9796ceb147c2
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Jun 27 22:47:48 2014 +0200

    iotests: Add more tests to quick group
    
    While at it, add some more tests to the quick group (those that run with
    -nocache in under three seconds on my HDD).
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 7a2bfca..6e67f61 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -7,16 +7,16 @@
 #
 # test-group association ... one line per test
 #
-001 rw auto
+001 rw auto quick
 002 rw auto quick
 003 rw auto
 004 rw auto quick
-005 img auto
+005 img auto quick
 006 img auto
 007 snapshot auto
-008 rw auto
-009 rw auto
-010 rw auto
+008 rw auto quick
+009 rw auto quick
+010 rw auto quick
 011 rw auto quick
 012 auto quick
 013 rw auto
@@ -24,36 +24,36 @@
 015 rw snapshot auto
 016 rw auto quick
 017 rw backing auto quick
-018 rw backing auto
+018 rw backing auto quick
 019 rw backing auto quick
 020 rw backing auto quick
-021 io auto
+021 io auto quick
 022 rw snapshot auto
 023 rw auto
 024 rw backing auto quick
 025 rw auto quick
 026 rw blkdbg auto
 027 rw auto quick
-028 rw backing auto
+028 rw backing auto quick
 029 rw auto quick
 030 rw auto backing
 031 rw auto quick
-032 rw auto
+032 rw auto quick
 033 rw auto quick
-034 rw auto backing
+034 rw auto backing quick
 035 rw auto quick
 036 rw auto quick
-037 rw auto backing
-038 rw auto backing
-039 rw auto
+037 rw auto backing quick
+038 rw auto backing quick
+039 rw auto quick
 040 rw auto
 041 rw auto backing
 042 rw auto quick
 043 rw auto backing
 044 rw auto
 045 rw auto quick
-046 rw auto aio
-047 rw auto
+046 rw auto aio quick
+047 rw auto quick
 048 img auto quick
 049 rw auto
 050 rw auto backing quick
@@ -81,20 +81,20 @@
 072 rw auto quick
 073 rw auto quick
 074 rw auto quick
-075 rw auto
+075 rw auto quick
 076 auto
 077 rw auto quick
-078 rw auto
+078 rw auto quick
 079 rw auto
 080 rw auto
 081 rw auto quick
 082 rw auto quick
 083 rw auto
-084 img auto
+084 img auto quick
 085 rw auto
 086 rw auto quick
 087 rw auto quick
-088 rw auto
+088 rw auto quick
 089 rw auto quick
 090 rw auto quick
 091 rw auto quick
commit ee9dd1fc901f7098a1c2af5a2202bd7f41124dbc
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Jun 27 22:47:47 2014 +0200

    iotests: Add qemu tests to quick group
    
    Now that qemu-iotests-quick.sh supports tests using the qemu binary, we
    are free to add such tests to the quick group.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index e3dc4e8..7a2bfca 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -51,7 +51,7 @@
 042 rw auto quick
 043 rw auto backing
 044 rw auto
-045 rw auto
+045 rw auto quick
 046 rw auto aio
 047 rw auto
 048 img auto quick
@@ -71,13 +71,13 @@
 062 rw auto quick
 063 rw auto quick
 064 rw auto quick
-065 rw auto
+065 rw auto quick
 066 rw auto quick
-067 rw auto
-068 rw auto
+067 rw auto quick
+068 rw auto quick
 069 rw auto quick
 070 rw auto quick
-071 rw auto
+071 rw auto quick
 072 rw auto quick
 073 rw auto quick
 074 rw auto quick
@@ -87,16 +87,16 @@
 078 rw auto
 079 rw auto
 080 rw auto
-081 rw auto
+081 rw auto quick
 082 rw auto quick
 083 rw auto
 084 img auto
 085 rw auto
 086 rw auto quick
-087 rw auto
+087 rw auto quick
 088 rw auto
 089 rw auto quick
 090 rw auto quick
-091 rw auto
+091 rw auto quick
 092 rw auto quick
-095 rw auto
+095 rw auto quick
commit 214a081a0dd44e69f7db4a741880a8ae9d174fa2
Author: Max Reitz <mreitz at redhat.com>
Date:   Fri Jun 27 22:47:46 2014 +0200

    iotests: Simplify qemu-iotests-quick.sh
    
    As of the "iotests: Allow out-of-tree run" series, the qemu-iotests may
    (and should) be run directly in the build tree and will then guess the
    binary paths themselves. Therefore, qemu-iotests-quick.sh does not need
    to (and should not) enter the source path anymore; also, it does not
    need to specify the binaries because "check" will guess them
    automatically.
    
    As a side-effect, tests using qemu may now be added to the quick group.
    
    Signed-off-by: Max Reitz <mreitz at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests-quick.sh b/tests/qemu-iotests-quick.sh
index c449e8a..8a9a4c6 100755
--- a/tests/qemu-iotests-quick.sh
+++ b/tests/qemu-iotests-quick.sh
@@ -1,16 +1,6 @@
 #!/bin/sh
 
-# We don't know which of the system emulator binaries there is (or if there is
-# any at all), so the 'quick' group doesn't contain any tests that require
-# running qemu proper. Assign a fake binary name so that qemu-iotests doesn't
-# complain about the missing binary.
-export QEMU_PROG="this_should_be_unused"
-
-export QEMU_IMG_PROG="$(pwd)/qemu-img"
-export QEMU_IO_PROG="$(pwd)/qemu-io"
-export QEMU_NBD_PROG="$(pwd)/qemu-nbd"
-
-cd $SRC_PATH/tests/qemu-iotests
+cd tests/qemu-iotests
 
 ret=0
 ./check -T -nocache -qcow2 -g quick || ret=1
commit 4ab1559085d688dddf4de77f1ead3102e243e668
Author: Chunyan Liu <cyliu at suse.com>
Date:   Mon Jun 30 14:29:58 2014 +0800

    qemu-img create: add 'nocow' option
    
    Add 'nocow' option so that users could have a chance to set NOCOW flag to
    newly created files. It's useful on btrfs file system to enhance performance.
    
    Btrfs has low performance when hosting VM images, even more when the guest
    in those VM are also using btrfs as file system. One way to mitigate this bad
    performance is to turn off COW attributes on VM files. Generally, there are
    two ways to turn off NOCOW on btrfs: a) by mounting fs with nodatacow, then
    all newly created files will be NOCOW. b) per file. Add the NOCOW file
    attribute. It could only be done to empty or new files.
    
    This patch tries the second way, according to the option, it could add NOCOW
    per file.
    
    For most block drivers, since the create file step is in raw-posix.c, so we
    can do setting NOCOW flag ioctl in raw-posix.c only.
    
    But there are some exceptions, like block/vpc.c and block/vdi.c, they are
    creating file by calling qemu_open directly. For them, do the same setting
    NOCOW flag ioctl work in them separately.
    
    [Fixed up 082.out due to the new 'nocow' creation option
    --Stefan]
    
    Signed-off-by: Chunyan Liu <cyliu at suse.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qed.c b/block/qed.c
index eddae92..b69374b 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -567,7 +567,7 @@ static void bdrv_qed_close(BlockDriverState *bs)
 static int qed_create(const char *filename, uint32_t cluster_size,
                       uint64_t image_size, uint32_t table_size,
                       const char *backing_file, const char *backing_fmt,
-                      Error **errp)
+                      QemuOpts *opts, Error **errp)
 {
     QEDHeader header = {
         .magic = QED_MAGIC,
@@ -586,7 +586,7 @@ static int qed_create(const char *filename, uint32_t cluster_size,
     int ret = 0;
     BlockDriverState *bs;
 
-    ret = bdrv_create_file(filename, NULL, &local_err);
+    ret = bdrv_create_file(filename, opts, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         return ret;
@@ -682,7 +682,7 @@ static int bdrv_qed_create(const char *filename, QemuOpts *opts, Error **errp)
     }
 
     ret = qed_create(filename, cluster_size, image_size, table_size,
-                     backing_file, backing_fmt, errp);
+                     backing_file, backing_fmt, opts, errp);
 
 finish:
     g_free(backing_file);
diff --git a/block/raw-posix.c b/block/raw-posix.c
index dacf4fb..825a0c8 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -55,6 +55,9 @@
 #include <linux/cdrom.h>
 #include <linux/fd.h>
 #include <linux/fs.h>
+#ifndef FS_NOCOW_FL
+#define FS_NOCOW_FL                     0x00800000 /* Do not cow file */
+#endif
 #endif
 #ifdef CONFIG_FIEMAP
 #include <linux/fiemap.h>
@@ -1278,12 +1281,14 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
     int fd;
     int result = 0;
     int64_t total_size = 0;
+    bool nocow = false;
 
     strstart(filename, "file:", &filename);
 
     /* Read out options */
     total_size =
         qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0) / BDRV_SECTOR_SIZE;
+    nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false);
 
     fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                    0644);
@@ -1291,6 +1296,21 @@ static int raw_create(const char *filename, QemuOpts *opts, Error **errp)
         result = -errno;
         error_setg_errno(errp, -result, "Could not create file");
     } else {
+        if (nocow) {
+#ifdef __linux__
+            /* Set NOCOW flag to solve performance issue on fs like btrfs.
+             * This is an optimisation. The FS_IOC_SETFLAGS ioctl return value
+             * will be ignored since any failure of this operation should not
+             * block the left work.
+             */
+            int attr;
+            if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0) {
+                attr |= FS_NOCOW_FL;
+                ioctl(fd, FS_IOC_SETFLAGS, &attr);
+            }
+#endif
+        }
+
         if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
             result = -errno;
             error_setg_errno(errp, -result, "Could not resize file");
@@ -1477,6 +1497,11 @@ static QemuOptsList raw_create_opts = {
             .type = QEMU_OPT_SIZE,
             .help = "Virtual disk size"
         },
+        {
+            .name = BLOCK_OPT_NOCOW,
+            .type = QEMU_OPT_BOOL,
+            .help = "Turn off copy-on-write (valid only on btrfs)"
+        },
         { /* end of list */ }
     }
 };
diff --git a/block/vdi.c b/block/vdi.c
index 01fe22e..197bd77 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -53,6 +53,13 @@
 #include "block/block_int.h"
 #include "qemu/module.h"
 #include "migration/migration.h"
+#ifdef __linux__
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#ifndef FS_NOCOW_FL
+#define FS_NOCOW_FL                     0x00800000 /* Do not cow file */
+#endif
+#endif
 
 #if defined(CONFIG_UUID)
 #include <uuid/uuid.h>
@@ -683,6 +690,7 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
     VdiHeader header;
     size_t i;
     size_t bmap_size;
+    bool nocow = false;
 
     logout("\n");
 
@@ -699,6 +707,7 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
         image_type = VDI_TYPE_STATIC;
     }
 #endif
+    nocow = qemu_opt_get_bool_del(opts, BLOCK_OPT_NOCOW, false);
 
     if (bytes > VDI_DISK_SIZE_MAX) {
         result = -ENOTSUP;
@@ -716,6 +725,21 @@ static int vdi_create(const char *filename, QemuOpts *opts, Error **errp)
         goto exit;
     }
 
+    if (nocow) {
+#ifdef __linux__
+        /* Set NOCOW flag to solve performance issue on fs like btrfs.
+         * This is an optimisation. The FS_IOC_SETFLAGS ioctl return value will
+         * be ignored since any failure of this operation should not block the
+         * left work.
+         */
+        int attr;
+        if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0) {
+            attr |= FS_NOCOW_FL;
+            ioctl(fd, FS_IOC_SETFLAGS, &attr);
+        }
+#endif
+    }
+
     /* We need enough blocks to store the given disk size,
        so always round up. */
     blocks = (bytes + block_size - 1) / block_size;
@@ -818,6 +842,11 @@ static QemuOptsList vdi_create_opts = {
             .def_value_str = "off"
         },
 #endif
+        {
+            .name = BLOCK_OPT_NOCOW,
+            .type = QEMU_OPT_BOOL,
+            .help = "Turn off copy-on-write (valid only on btrfs)"
+        },
         /* TODO: An additional option to set UUID values might be useful. */
         { /* end of list */ }
     }
diff --git a/block/vmdk.c b/block/vmdk.c
index d0de019..27a78da 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1529,7 +1529,7 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
 
 static int vmdk_create_extent(const char *filename, int64_t filesize,
                               bool flat, bool compress, bool zeroed_grain,
-                              Error **errp)
+                              QemuOpts *opts, Error **errp)
 {
     int ret, i;
     BlockDriverState *bs = NULL;
@@ -1539,7 +1539,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
     uint32_t *gd_buf = NULL;
     int gd_buf_size;
 
-    ret = bdrv_create_file(filename, NULL, &local_err);
+    ret = bdrv_create_file(filename, opts, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto exit;
@@ -1845,7 +1845,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)
                 path, desc_filename);
 
         if (vmdk_create_extent(ext_filename, size,
-                               flat, compress, zeroed_grain, errp)) {
+                               flat, compress, zeroed_grain, opts, errp)) {
             ret = -EINVAL;
             goto exit;
         }
diff --git a/block/vpc.c b/block/vpc.c
index 798d854..8b376a4 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -29,6 +29,13 @@
 #if defined(CONFIG_UUID)
 #include <uuid/uuid.h>
 #endif
+#ifdef __linux__
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#ifndef FS_NOCOW_FL
+#define FS_NOCOW_FL                     0x00800000 /* Do not cow file */
+#endif
+#endif
 
 /**************************************************************/
 
@@ -751,6 +758,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
     int64_t total_size;
     int disk_type;
     int ret = -EIO;
+    bool nocow = false;
 
     /* Read out options */
     total_size = qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0);
@@ -767,6 +775,7 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
     } else {
         disk_type = VHD_DYNAMIC;
     }
+    nocow = qemu_opt_get_bool_del(opts, BLOCK_OPT_NOCOW, false);
 
     /* Create the file */
     fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
@@ -775,6 +784,21 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
         goto out;
     }
 
+    if (nocow) {
+#ifdef __linux__
+        /* Set NOCOW flag to solve performance issue on fs like btrfs.
+         * This is an optimisation. The FS_IOC_SETFLAGS ioctl return value will
+         * be ignored since any failure of this operation should not block the
+         * left work.
+         */
+        int attr;
+        if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0) {
+            attr |= FS_NOCOW_FL;
+            ioctl(fd, FS_IOC_SETFLAGS, &attr);
+        }
+#endif
+    }
+
     /*
      * Calculate matching total_size and geometry. Increase the number of
      * sectors requested until we get enough (or fail). This ensures that
@@ -884,6 +908,11 @@ static QemuOptsList vpc_create_opts = {
                 "Type of virtual hard disk format. Supported formats are "
                 "{dynamic (default) | fixed} "
         },
+        {
+            .name = BLOCK_OPT_NOCOW,
+            .type = QEMU_OPT_BOOL,
+            .help = "Turn off copy-on-write (valid only on btrfs)"
+        },
         { /* end of list */ }
     }
 };
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 53e77cf..eaf6e31 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -54,6 +54,7 @@
 #define BLOCK_OPT_LAZY_REFCOUNTS    "lazy_refcounts"
 #define BLOCK_OPT_ADAPTER_TYPE      "adapter_type"
 #define BLOCK_OPT_REDUNDANCY        "redundancy"
+#define BLOCK_OPT_NOCOW             "nocow"
 
 typedef struct BdrvTrackedRequest {
     BlockDriverState *bs;
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 88ec9bb..ad92c85 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -589,6 +589,22 @@ check -r all} is required, which may take some time.
 
 This option can only be enabled if @code{compat=1.1} is specified.
 
+ at item nocow
+If this option is set to @code{on}, it will trun off COW of the file. It's only
+valid on btrfs, no effect on other file systems.
+
+Btrfs has low performance when hosting a VM image file, even more when the guest
+on the VM also using btrfs as file system. Turning off COW is a way to mitigate
+this bad performance. Generally there are two ways to turn off COW on btrfs:
+a) Disable it by mounting with nodatacow, then all newly created files will be
+NOCOW. b) For an empty file, add the NOCOW file attribute. That's what this option
+does.
+
+Note: this option is only valid to new or empty files. If there is an existing
+file which is COW and has data blocks already, it couldn't be changed to NOCOW
+by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if
+the NOCOW flag is set or not (Capitabl 'C' is NOCOW flag).
+
 @end table
 
 @item qed
diff --git a/qemu-img.texi b/qemu-img.texi
index c68b541..8496f3b 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -474,6 +474,22 @@ check -r all} is required, which may take some time.
 
 This option can only be enabled if @code{compat=1.1} is specified.
 
+ at item nocow
+If this option is set to @code{on}, it will trun off COW of the file. It's only
+valid on btrfs, no effect on other file systems.
+
+Btrfs has low performance when hosting a VM image file, even more when the guest
+on the VM also using btrfs as file system. Turning off COW is a way to mitigate
+this bad performance. Generally there are two ways to turn off COW on btrfs:
+a) Disable it by mounting with nodatacow, then all newly created files will be
+NOCOW. b) For an empty file, add the NOCOW file attribute. That's what this option
+does.
+
+Note: this option is only valid to new or empty files. If there is an existing
+file which is COW and has data blocks already, it couldn't be changed to NOCOW
+by setting @code{nocow=on}. One can issue @code{lsattr filename} to check if
+the NOCOW flag is set or not (Capitabl 'C' is NOCOW flag).
+
 @end table
 
 @item Other
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
index 28309a0..413e7ef 100644
--- a/tests/qemu-iotests/082.out
+++ b/tests/qemu-iotests/082.out
@@ -66,6 +66,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o ? TEST_DIR/t.qcow2 128M
 Supported options:
@@ -77,6 +78,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 128M
 Supported options:
@@ -88,6 +90,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 128M
 Supported options:
@@ -99,6 +102,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 128M
 Supported options:
@@ -110,6 +114,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 128M
 Supported options:
@@ -121,6 +126,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 128M
 Supported options:
@@ -132,6 +138,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 128M
 Supported options:
@@ -143,6 +150,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
 Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,help' encryption=off cluster_size=65536 lazy_refcounts=off 
@@ -247,6 +255,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 Supported options:
@@ -258,6 +267,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 Supported options:
@@ -269,6 +279,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 Supported options:
@@ -280,6 +291,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 Supported options:
@@ -291,6 +303,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 Supported options:
@@ -302,6 +315,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 Supported options:
@@ -313,6 +327,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 Supported options:
@@ -324,6 +339,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
 qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,help': No such file or directory
@@ -417,6 +433,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
 Supported options:
@@ -428,6 +445,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
 Supported options:
@@ -439,6 +457,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
 Supported options:
@@ -450,6 +469,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
 Supported options:
@@ -461,6 +481,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
 Supported options:
@@ -472,6 +493,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
 Supported options:
@@ -483,6 +505,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
 Supported options:
@@ -494,6 +517,7 @@ encryption       Encrypt the image
 cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata)
 lazy_refcounts   Postpone refcount updates
+nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2
 
commit ef7c7ff6d4ca1955278af1bc5025f47044183250
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:28 2014 +0800

    qom: add object_property_add_alias()
    
    Sometimes an object needs to present a property which is actually on
    another object, or it needs to provide an alias name for an existing
    property.
    
    Examples:
      a.foo -> b.foo
      a.old_name -> a.new_name
    
    The new object_property_add_alias() API allows objects to alias a
    property on the same object or another object.  The source and target
    names can be different.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/include/qom/object.h b/include/qom/object.h
index b882ccc..44c513f 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1231,6 +1231,26 @@ void object_property_add_uint64_ptr(Object *obj, const char *name,
                                     const uint64_t *v, Error **Errp);
 
 /**
+ * object_property_add_alias:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @target_obj: the object to forward property access to
+ * @target_name: the name of the property on the forwarded object
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add an alias for a property on an object.  This function will add a property
+ * of the same type as the forwarded property.
+ *
+ * The caller must ensure that <code>@target_obj</code> stays alive as long as
+ * this property exists.  In the case of a child object or an alias on the same
+ * object this will be the case.  For aliases to other objects the caller is
+ * responsible for taking a reference.
+ */
+void object_property_add_alias(Object *obj, const char *name,
+                               Object *target_obj, const char *target_name,
+                               Error **errp);
+
+/**
  * object_child_foreach:
  * @obj: the object whose children will be navigated
  * @fn: the iterator function to be called
diff --git a/qom/object.c b/qom/object.c
index 3876618..a760514 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1550,6 +1550,57 @@ void object_property_add_uint64_ptr(Object *obj, const char *name,
                         NULL, NULL, (void *)v, errp);
 }
 
+typedef struct {
+    Object *target_obj;
+    const char *target_name;
+} AliasProperty;
+
+static void property_get_alias(Object *obj, struct Visitor *v, void *opaque,
+                               const char *name, Error **errp)
+{
+    AliasProperty *prop = opaque;
+
+    object_property_get(prop->target_obj, v, prop->target_name, errp);
+}
+
+static void property_set_alias(Object *obj, struct Visitor *v, void *opaque,
+                               const char *name, Error **errp)
+{
+    AliasProperty *prop = opaque;
+
+    object_property_set(prop->target_obj, v, prop->target_name, errp);
+}
+
+static void property_release_alias(Object *obj, const char *name, void *opaque)
+{
+    AliasProperty *prop = opaque;
+
+    g_free(prop);
+}
+
+void object_property_add_alias(Object *obj, const char *name,
+                               Object *target_obj, const char *target_name,
+                               Error **errp)
+{
+    AliasProperty *prop;
+    ObjectProperty *target_prop;
+
+    target_prop = object_property_find(target_obj, target_name, errp);
+    if (!target_prop) {
+        return;
+    }
+
+    prop = g_malloc(sizeof(*prop));
+    prop->target_obj = target_obj;
+    prop->target_name = target_name;
+
+    object_property_add(obj, name, target_prop->type,
+                        property_get_alias,
+                        property_set_alias,
+                        property_release_alias,
+                        prop, errp);
+}
+
 static void object_instance_init(Object *obj)
 {
     object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
commit 8698e110f8aa1cdf8ba1afdda8f2658333a4ab01
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Tue Jun 10 09:03:22 2014 +0200

    virtio-blk: remove need for explicit x-data-plane=on option
    
    The x-data-plane=on|off option is no longer useful because the
    iothread=<iothread> option conveys the same information plus which
    IOThread to use.
    
    Do not delete x-data-plane=on|off yet as a convenience to people using
    this legacy experimental option.  We will drop it in QEMU 2.2.
    
    Instead, turn on data-plane when either x-data-plane=on or
    iothread=<iothread> are used.  The following command-line uses
    data-plane:
    
      qemu -device virtio-blk-pci,iothread=foo,drive=drive0
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index f6e1a5d..4c5ba18 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -132,7 +132,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
 
     *dataplane = NULL;
 
-    if (!blk->data_plane) {
+    if (!blk->data_plane && !blk->iothread) {
         return;
     }
 
commit 1351d1ec89eabebc9fdff20451a62c413d7accc1
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Tue Jun 10 09:03:21 2014 +0200

    qdev: drop iothread property type
    
    The iothread property type is no longer used and can be removed.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index 52c2f8a..8e140af 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -385,56 +385,6 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
     nd->instantiated = 1;
 }
 
-/* --- iothread --- */
-
-static char *print_iothread(void *ptr)
-{
-    return iothread_get_id(ptr);
-}
-
-static int parse_iothread(DeviceState *dev, const char *str, void **ptr)
-{
-    IOThread *iothread;
-
-    iothread = iothread_find(str);
-    if (!iothread) {
-        return -ENOENT;
-    }
-    object_ref(OBJECT(iothread));
-    *ptr = iothread;
-    return 0;
-}
-
-static void get_iothread(Object *obj, struct Visitor *v, void *opaque,
-                         const char *name, Error **errp)
-{
-    get_pointer(obj, v, opaque, print_iothread, name, errp);
-}
-
-static void set_iothread(Object *obj, struct Visitor *v, void *opaque,
-                         const char *name, Error **errp)
-{
-    set_pointer(obj, v, opaque, parse_iothread, name, errp);
-}
-
-static void release_iothread(Object *obj, const char *name, void *opaque)
-{
-    DeviceState *dev = DEVICE(obj);
-    Property *prop = opaque;
-    IOThread **ptr = qdev_get_prop_ptr(dev, prop);
-
-    if (*ptr) {
-        object_unref(OBJECT(*ptr));
-    }
-}
-
-PropertyInfo qdev_prop_iothread = {
-    .name = "iothread",
-    .get = get_iothread,
-    .set = set_iothread,
-    .release = release_iothread,
-};
-
 static int qdev_add_one_global(QemuOpts *opts, void *opaque)
 {
     GlobalProperty *g;
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 3726bf3..77fe3a1 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -22,7 +22,6 @@ extern PropertyInfo qdev_prop_bios_chs_trans;
 extern PropertyInfo qdev_prop_drive;
 extern PropertyInfo qdev_prop_netdev;
 extern PropertyInfo qdev_prop_vlan;
-extern PropertyInfo qdev_prop_iothread;
 extern PropertyInfo qdev_prop_pci_devfn;
 extern PropertyInfo qdev_prop_blocksize;
 extern PropertyInfo qdev_prop_pci_host_devaddr;
@@ -143,8 +142,6 @@ extern PropertyInfo qdev_prop_arraylen;
     DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers)
 #define DEFINE_PROP_DRIVE(_n, _s, _f) \
     DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
-#define DEFINE_PROP_IOTHREAD(_n, _s, _f)             \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_iothread, IOThread *)
 #define DEFINE_PROP_MACADDR(_n, _s, _f)         \
     DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
 #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
commit 467b3f33e9b094bf6db5a4d6e6905f077edca0fb
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Tue Jun 10 09:03:20 2014 +0200

    virtio-blk: replace x-iothread with iothread link property
    
    Up until now -device virtio-blk-pci,x-iothread=<id> was used to assign
    an IOThread.  This was a temporary solution while we cleaned up QOM link
    properties.
    
    This patch switches over to a QOM link property since it is now possible
    to restrict the setter to unrealized instances and automatically unref
    the IOThread when the virtio-blk-pci device is freed.
    
    Since the "iothread" property is a QOM property and not a qdev property,
    we must alias it explicitly for virtio-blk-pci, as well as CCW and
    s390-virtio.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index b8d51bb..aec3146 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -784,12 +784,21 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
     virtio_cleanup(vdev);
 }
 
+static void virtio_blk_instance_init(Object *obj)
+{
+    VirtIOBlock *s = VIRTIO_BLK(obj);
+
+    object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
+                             (Object **)&s->blk.iothread,
+                             qdev_prop_allow_set_link_before_realize,
+                             OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
+}
+
 static Property virtio_blk_properties[] = {
     DEFINE_BLOCK_PROPERTIES(VirtIOBlock, blk.conf),
     DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, blk.conf),
     DEFINE_PROP_STRING("serial", VirtIOBlock, blk.serial),
     DEFINE_PROP_BIT("config-wce", VirtIOBlock, blk.config_wce, 0, true),
-    DEFINE_PROP_IOTHREAD("x-iothread", VirtIOBlock, blk.iothread),
 #ifdef __linux__
     DEFINE_PROP_BIT("scsi", VirtIOBlock, blk.scsi, 0, true),
 #endif
@@ -821,6 +830,7 @@ static const TypeInfo virtio_device_info = {
     .name = TYPE_VIRTIO_BLK,
     .parent = TYPE_VIRTIO_DEVICE,
     .instance_size = sizeof(VirtIOBlock),
+    .instance_init = virtio_blk_instance_init,
     .class_init = virtio_blk_class_init,
 };
 
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 3438a88..c0dc365 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -181,6 +181,8 @@ static void s390_virtio_blk_instance_init(Object *obj)
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
     object_unref(OBJECT(&dev->vdev));
     qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+    object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
+                              &error_abort);
 }
 
 static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 0553fea..c279968 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -815,6 +815,8 @@ static void virtio_ccw_blk_instance_init(Object *obj)
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
     object_unref(OBJECT(&dev->vdev));
     qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+    object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
+                              &error_abort);
 }
 
 static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index d41b864..3c42cda 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1103,6 +1103,8 @@ static void virtio_blk_pci_instance_init(Object *obj)
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
     object_unref(OBJECT(&dev->vdev));
     qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
+    object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
+                              &error_abort);
 }
 
 static const TypeInfo virtio_blk_pci_info = {
commit 32a877e4059ad7fd428bdd31d3e954fed72fa21b
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:36 2014 +0800

    virtio-blk: move qdev properties into virtio-blk.c
    
    There is no need to make DEFINE_VIRTIO_BLK_PROPERTIES() public.  Inline
    it into virtio-blk.c so it cannot be used by mistake from other source
    files.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index f1a667c..b8d51bb 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -785,7 +785,17 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
 }
 
 static Property virtio_blk_properties[] = {
-    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlock, blk),
+    DEFINE_BLOCK_PROPERTIES(VirtIOBlock, blk.conf),
+    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, blk.conf),
+    DEFINE_PROP_STRING("serial", VirtIOBlock, blk.serial),
+    DEFINE_PROP_BIT("config-wce", VirtIOBlock, blk.config_wce, 0, true),
+    DEFINE_PROP_IOTHREAD("x-iothread", VirtIOBlock, blk.iothread),
+#ifdef __linux__
+    DEFINE_PROP_BIT("scsi", VirtIOBlock, blk.scsi, 0, true),
+#endif
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+    DEFINE_PROP_BIT("x-data-plane", VirtIOBlock, blk.data_plane, 0, false),
+#endif
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 52e5add..223530e 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -155,29 +155,6 @@ typedef struct VirtIOBlockReq {
 #define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
 
-#ifdef __linux__
-#define DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field) \
-        DEFINE_PROP_BIT("scsi", _state, _field.scsi, 0, true),
-#else
-#define DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field)
-#endif
-
-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-#define DEFINE_VIRTIO_BLK_PROPERTIES_DATA_PLANE(_state, _field) \
-    DEFINE_PROP_BIT("x-data-plane", _state, _field.data_plane, 0, false),
-#else
-#define DEFINE_VIRTIO_BLK_PROPERTIES_DATA_PLANE(_state, _field)
-#endif
-
-#define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \
-        DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field)                    \
-        DEFINE_VIRTIO_BLK_PROPERTIES_DATA_PLANE(_state, _field)               \
-        DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \
-        DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \
-        DEFINE_PROP_STRING("serial", _state, _field.serial),                  \
-        DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \
-        DEFINE_PROP_IOTHREAD("x-iothread", _state, _field.iothread)
-
 int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
                                VirtQueueElement *elem);
 
commit c5d49db4469dfc0cc7f4c01dfb4ed4e8b96bdbcd
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:35 2014 +0800

    virtio: fix virtio-blk child refcount in transports
    
    object_initialize() leaves the object with a refcount of 1.
    object_property_add_child() adds its own reference which is dropped
    again when the property is deleted.
    
    The upshot of this is that we always have a refcount >= 1.  Upon hot
    unplug the virtio-blk child is not finalized!
    
    Drop our reference after the child property has been added to the
    parent.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 38984ab..3438a88 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -179,6 +179,7 @@ static void s390_virtio_blk_instance_init(Object *obj)
     VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj);
     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    object_unref(OBJECT(&dev->vdev));
     qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
 }
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 9fa6f32..0553fea 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -813,6 +813,7 @@ static void virtio_ccw_blk_instance_init(Object *obj)
     VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(obj);
     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    object_unref(OBJECT(&dev->vdev));
     qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
 }
 
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 7359d8d..d41b864 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1101,6 +1101,7 @@ static void virtio_blk_pci_instance_init(Object *obj)
     VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj);
     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    object_unref(OBJECT(&dev->vdev));
     qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
 }
 
commit f7fedda84a8eb316c99a9de647c4844b862a7b38
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:34 2014 +0800

    virtio-blk: drop virtio_blk_set_conf()
    
    This function is no longer used since parent objects now use child
    aliases to set the VirtIOBlkConf directly.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index e59ebc9..f1a667c 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -677,12 +677,6 @@ static const BlockDevOps virtio_block_ops = {
     .resize_cb = virtio_blk_resize,
 };
 
-void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk)
-{
-    VirtIOBlock *s = VIRTIO_BLK(dev);
-    memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf));
-}
-
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
 /* Disable dataplane thread during live migration since it does not
  * update the dirty memory bitmap yet.
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 1d80bcc..52e5add 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -178,8 +178,6 @@ typedef struct VirtIOBlockReq {
         DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \
         DEFINE_PROP_IOTHREAD("x-iothread", _state, _field.iothread)
 
-void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk);
-
 int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
                                VirtQueueElement *elem);
 
commit caffdac363801cd2cf2bf01ad013a8c1e1e43800
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:33 2014 +0800

    virtio-blk: use aliases instead of duplicate qdev properties
    
    virtio-blk-pci, virtio-blk-s390, and virtio-blk-ccw all duplicate the
    qdev properties of their VirtIOBlock child.  This approach does not work
    well with string or pointer properties since we must be careful about
    leaking or double-freeing them.
    
    Use the QOM alias property to forward property accesses to the
    VirtIOBlock child.  This way no duplication is necessary.
    
    Remember to stop calling virtio_blk_set_conf() so that we don't clobber
    the values already set on the VirtIOBlock instance.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 7c8c81b..38984ab 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -167,7 +167,6 @@ static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
 {
     VirtIOBlkS390 *dev = VIRTIO_BLK_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
-    virtio_blk_set_conf(vdev, &(dev->blk));
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
     if (qdev_init(vdev) < 0) {
         return -1;
@@ -180,6 +179,7 @@ static void s390_virtio_blk_instance_init(Object *obj)
     VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj);
     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
 }
 
 static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
@@ -513,18 +513,11 @@ static const TypeInfo s390_virtio_net = {
     .class_init    = s390_virtio_net_class_init,
 };
 
-static Property s390_virtio_blk_properties[] = {
-    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkS390, blk),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
 static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
 {
-    DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
     k->init = s390_virtio_blk_init;
-    dc->props = s390_virtio_blk_properties;
 }
 
 static const TypeInfo s390_virtio_blk = {
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index ac81bd8..ffd0df7 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -124,7 +124,6 @@ void s390_virtio_reset_idx(VirtIOS390Device *dev);
 typedef struct VirtIOBlkS390 {
     VirtIOS390Device parent_obj;
     VirtIOBlock vdev;
-    VirtIOBlkConf blk;
 } VirtIOBlkS390;
 
 /* virtio-scsi-s390 */
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index d7ff0a0..9fa6f32 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -800,7 +800,6 @@ static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
 {
     VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
-    virtio_blk_set_conf(vdev, &(dev->blk));
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
     if (qdev_init(vdev) < 0) {
         return -1;
@@ -814,6 +813,7 @@ static void virtio_ccw_blk_instance_init(Object *obj)
     VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(obj);
     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
 }
 
 static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
@@ -1400,7 +1400,6 @@ static const TypeInfo virtio_ccw_net = {
 static Property virtio_ccw_blk_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
     DEFINE_VIRTIO_BLK_FEATURES(VirtioCcwDevice, host_features[0]),
-    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkCcw, blk),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index b8b8a8a..5a1f16e 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -144,7 +144,6 @@ typedef struct VHostSCSICcw {
 typedef struct VirtIOBlkCcw {
     VirtioCcwDevice parent_obj;
     VirtIOBlock vdev;
-    VirtIOBlkConf blk;
 } VirtIOBlkCcw;
 
 /* virtio-balloon-ccw */
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 653d74e..7359d8d 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1067,7 +1067,6 @@ static Property virtio_blk_pci_properties[] = {
                     VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
     DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkPCI, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -1075,7 +1074,6 @@ static int virtio_blk_pci_init(VirtIOPCIProxy *vpci_dev)
 {
     VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
-    virtio_blk_set_conf(vdev, &(dev->blk));
     qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
     if (qdev_init(vdev) < 0) {
         return -1;
@@ -1103,6 +1101,7 @@ static void virtio_blk_pci_instance_init(Object *obj)
     VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj);
     object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK);
     object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+    qdev_alias_all_properties(DEVICE(&dev->vdev), obj);
 }
 
 static const TypeInfo virtio_blk_pci_info = {
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index dc332ae..1cea157 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -131,7 +131,6 @@ struct VHostSCSIPCI {
 struct VirtIOBlkPCI {
     VirtIOPCIProxy parent_obj;
     VirtIOBlock vdev;
-    VirtIOBlkConf blk;
 };
 
 /*
commit 67cc7e0aaca835ed68cf3bd34f4d51a21232792f
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:32 2014 +0800

    qdev: add qdev_alias_all_properties()
    
    The qdev_alias_all_properties() function creates QOM alias properties
    for each qdev property on a DeviceState.  This is useful for parent
    objects that wish to forward property accesses to their children.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index d1eba3c..732e729 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -780,6 +780,27 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
     }
 }
 
+/* @qdev_alias_all_properties - Add alias properties to the source object for
+ * all qdev properties on the target DeviceState.
+ */
+void qdev_alias_all_properties(DeviceState *target, Object *source)
+{
+    ObjectClass *class;
+    Property *prop;
+
+    class = object_get_class(OBJECT(target));
+    do {
+        DeviceClass *dc = DEVICE_CLASS(class);
+
+        for (prop = dc->props; prop && prop->name; prop++) {
+            object_property_add_alias(source, prop->name,
+                                      OBJECT(target), prop->name,
+                                      &error_abort);
+        }
+        class = object_class_get_parent(class);
+    } while (class != object_class_by_name(TYPE_DEVICE));
+}
+
 static bool device_get_realized(Object *obj, Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index c962b6b..3726bf3 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -193,6 +193,8 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
  */
 void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
 
+void qdev_alias_all_properties(DeviceState *target, Object *source);
+
 /**
  * @qdev_prop_set_after_realize:
  * @dev: device
commit ee512c6f21b2f76ae923e3a4cabbd58899ff7ae1
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:31 2014 +0800

    virtio-blk: move x-data-plane qdev property to virtio-blk.h
    
    Move the x-data-plane property.  Originally it was outside since not
    every transport may wish to support dataplane.  But that makes little
    sense when we have a dedicated CONFIG_VIRTIO_BLK_DATA_PLANE ifdef
    already.
    
    This move makes it easier to switch to property aliases in the next
    patch.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 05656a2..d7ff0a0 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1403,9 +1403,6 @@ static Property virtio_ccw_blk_properties[] = {
     DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkCcw, blk),
     DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
                     VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    DEFINE_PROP_BIT("x-data-plane", VirtIOBlkCcw, blk.data_plane, 0, false),
-#endif
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 317324f..653d74e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1066,9 +1066,6 @@ static Property virtio_blk_pci_properties[] = {
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
                     VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    DEFINE_PROP_BIT("x-data-plane", VirtIOBlkPCI, blk.data_plane, 0, false),
-#endif
     DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
     DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkPCI, blk),
     DEFINE_PROP_END_OF_LIST(),
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index ee43f7a..1d80bcc 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -162,8 +162,16 @@ typedef struct VirtIOBlockReq {
 #define DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field)
 #endif
 
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+#define DEFINE_VIRTIO_BLK_PROPERTIES_DATA_PLANE(_state, _field) \
+    DEFINE_PROP_BIT("x-data-plane", _state, _field.data_plane, 0, false),
+#else
+#define DEFINE_VIRTIO_BLK_PROPERTIES_DATA_PLANE(_state, _field)
+#endif
+
 #define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \
         DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field)                    \
+        DEFINE_VIRTIO_BLK_PROPERTIES_DATA_PLANE(_state, _field)               \
         DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \
         DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \
         DEFINE_PROP_STRING("serial", _state, _field.serial),                  \
commit a9968c77d5a56211ae22be2e6a1dcb07f2016010
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Wed Jun 18 17:58:30 2014 +0800

    dataplane: bail out on unsupported transport
    
    If the virtio transport does not support notifiers (like s390-virtio),
    we can't use dataplane. Bail out early and let the user know what is
    wrong.
    
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 09bd2c7..f6e1a5d 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -127,6 +127,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
     VirtIOBlockDataPlane *s;
     VirtIOBlock *vblk = VIRTIO_BLK(vdev);
     Error *local_err = NULL;
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
 
     *dataplane = NULL;
 
@@ -134,6 +136,14 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
         return;
     }
 
+    /* Don't try if transport does not support notifiers. */
+    if (!k->set_guest_notifiers || !k->set_host_notifier) {
+        error_setg(errp,
+                   "device is incompatible with x-data-plane "
+                   "(transport does not support notifiers)");
+        return;
+    }
+
     /* If dataplane is (re-)enabled while the guest is running there could be
      * block jobs that can conflict.
      */
commit dc80ca6cd6cafdee174af3c883d85e19b7fd70a5
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Jun 18 17:58:29 2014 +0800

    virtio-blk: avoid qdev property definition duplication
    
    It becomes unwiedly to duplicate all virtio-blk qdev property
    definitions due to an #ifdef.  The C preprocessor syntax makes it a
    little hard to resolve this cleanly but we can extract the #ifdef and
    call a macro it defines later.
    
    Avoiding duplication is important since it will only get worse when we
    move the x-data-plane qdev property here too.  We'd have a combinatorial
    explosion since x-data-plane has its own #ifdef.
    
    Suggested-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>

diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index d0fb26f..ee43f7a 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -156,21 +156,19 @@ typedef struct VirtIOBlockReq {
         DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
 
 #ifdef __linux__
-#define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \
-        DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \
-        DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \
-        DEFINE_PROP_STRING("serial", _state, _field.serial),                  \
-        DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \
-        DEFINE_PROP_BIT("scsi", _state, _field.scsi, 0, true),                \
-        DEFINE_PROP_IOTHREAD("x-iothread", _state, _field.iothread)
+#define DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field) \
+        DEFINE_PROP_BIT("scsi", _state, _field.scsi, 0, true),
 #else
+#define DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field)
+#endif
+
 #define DEFINE_VIRTIO_BLK_PROPERTIES(_state, _field)                          \
+        DEFINE_VIRTIO_BLK_PROPERTIES_LINUX(_state, _field)                    \
         DEFINE_BLOCK_PROPERTIES(_state, _field.conf),                         \
         DEFINE_BLOCK_CHS_PROPERTIES(_state, _field.conf),                     \
         DEFINE_PROP_STRING("serial", _state, _field.serial),                  \
         DEFINE_PROP_BIT("config-wce", _state, _field.config_wce, 0, true),    \
         DEFINE_PROP_IOTHREAD("x-iothread", _state, _field.iothread)
-#endif /* __linux__ */
 
 void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk);
 


More information about the Spice-commits mailing list