Re: [Qemu-devel] [PATCH v2 6/7] exec: Factor out section_covers_addr

2016-02-29 Thread Peter Xu
On Tue, Mar 01, 2016 at 02:18:23PM +0800, Fam Zheng wrote:
> This will be shared by the next patch.
> 
> Also add a comment explaining the unobvious condition on "size.hi".
> 
> Signed-off-by: Fam Zheng 

Reviewed-by: Peter Xu 

> ---
>  exec.c | 14 +++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index ad8b826..b4e2eb5 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -307,6 +307,16 @@ static void phys_page_compact_all(AddressSpaceDispatch 
> *d, int nodes_nb)
>  }
>  }
>  
> +static inline bool section_covers_addr(const MemoryRegionSection *section,
> +   hwaddr addr)
> +{
> +/* Memory topology clips a memory region to 2^64, size.hi >= 0 means the
> + * section must cover any addr. */
> +return section->size.hi ||
> +   range_covers_byte(section->offset_within_address_space,
> + section->size.lo, addr);
> +}
> +
>  static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr addr,
> Node *nodes, MemoryRegionSection 
> *sections)
>  {
> @@ -322,9 +332,7 @@ static MemoryRegionSection *phys_page_find(PhysPageEntry 
> lp, hwaddr addr,
>  lp = p[(index >> (i * P_L2_BITS)) & (P_L2_SIZE - 1)];
>  }
>  
> -if (sections[lp.ptr].size.hi ||
> -range_covers_byte(sections[lp.ptr].offset_within_address_space,
> -  sections[lp.ptr].size.lo, addr)) {
> +if (section_covers_addr([lp.ptr], addr)) {
>  return [lp.ptr];
>  } else {
>  return [PHYS_SECTION_UNASSIGNED];
> -- 
> 2.4.3
> 



[Qemu-devel] [PULL 0/2] vga: minor cirrus/qxl bugfixes.

2016-02-29 Thread Gerd Hoffmann
  Hi,

Yet another small bugfix pull request, this time for vga.

please pull,
  Gerd

The following changes since commit 071608b519adf62bc29c914343a21c5407ab1ac9:

  Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-20160229-1' into 
staging (2016-02-29 12:24:26 +)

are available in the git repository at:


  git://git.kraxel.org/qemu tags/pull-vga-20160301-1

for you to fetch changes up to 05fa1c742fd6f66978b989ded0dd981ef11c4a0c:

  qxl: lock current_async update in qxl_soft_reset (2016-03-01 07:51:32 +0100)


vga: minor cirrus/qxl bugfixes.


Gerd Hoffmann (1):
  qxl: lock current_async update in qxl_soft_reset

Paolo Bonzini (1):
  cirrus_vga: fix off-by-one in blit_region_is_unsafe

 hw/display/cirrus_vga.c | 4 ++--
 hw/display/qxl.c| 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)



[Qemu-devel] [PULL 2/2] qxl: lock current_async update in qxl_soft_reset

2016-02-29 Thread Gerd Hoffmann
This should fix a defect report from Coverity.

Signed-off-by: Gerd Hoffmann 
Reviewed-by: Paolo Bonzini 
---
 hw/display/qxl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index a423dee..919dc5c 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1156,7 +1156,9 @@ static void qxl_soft_reset(PCIQXLDevice *d)
 trace_qxl_soft_reset(d->id);
 qxl_check_state(d);
 qxl_clear_guest_bug(d);
+qemu_mutex_lock(>async_lock);
 d->current_async = QXL_UNDEFINED_IO;
+qemu_mutex_unlock(>async_lock);
 
 if (d->id == 0) {
 qxl_enter_vga_mode(d);
-- 
1.8.3.1




[Qemu-devel] [PULL 1/2] cirrus_vga: fix off-by-one in blit_region_is_unsafe

2016-02-29 Thread Gerd Hoffmann
From: Paolo Bonzini 

The "max" value is being compared with >=, but addr + width points to
the first byte that will _not_ be copied.  Laszlo suggested using a
"greater than" comparison, instead of subtracting one like it is
already done above for the height, so that max remains always positive.

The mistake is "safe"---it will reject some blits, but will never cause
out-of-bounds writes.

Cc: Gerd Hoffmann 
Signed-off-by: Paolo Bonzini 
Reviewed-by: Laszlo Ersek 
Message-id: 1455121059-18280-1-git-send-email-pbonz...@redhat.com
Signed-off-by: Gerd Hoffmann 
---
 hw/display/cirrus_vga.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index b6ce1c8..57b91a7 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -276,14 +276,14 @@ static bool blit_region_is_unsafe(struct CirrusVGAState 
*s,
 + ((int64_t)s->cirrus_blt_height-1) * pitch;
 int32_t max = addr
 + s->cirrus_blt_width;
-if (min < 0 || max >= s->vga.vram_size) {
+if (min < 0 || max > s->vga.vram_size) {
 return true;
 }
 } else {
 int64_t max = addr
 + ((int64_t)s->cirrus_blt_height-1) * pitch
 + s->cirrus_blt_width;
-if (max >= s->vga.vram_size) {
+if (max > s->vga.vram_size) {
 return true;
 }
 }
-- 
1.8.3.1




Re: [Qemu-devel] [PATCH v2 3/7] memory: Implement memory_region_get_ram_addr with mr->ram_block

2016-02-29 Thread Gonglei (Arei)
> Subject: [PATCH v2 3/7] memory: Implement memory_region_get_ram_addr
> with mr->ram_block
> 
> Signed-off-by: Fam Zheng 
> ---
>  include/exec/memory.h | 8 +---
>  memory.c  | 5 +
>  2 files changed, 6 insertions(+), 7 deletions(-)
> 

Reviewed-by: Gonglei 


> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index d5284c2..810d2c0 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -978,14 +978,8 @@ void
> memory_region_add_subregion_overlap(MemoryRegion *mr,
>  /**
>   * memory_region_get_ram_addr: Get the ram address associated with a
> memory
>   * region
> - *
> - * DO NOT USE THIS FUNCTION.  This is a temporary workaround while the
> Xen
> - * code is being reworked.
>   */
> -static inline ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
> -{
> -return mr->ram_addr;
> -}
> +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
> 
>  uint64_t memory_region_get_alignment(const MemoryRegion *mr);
>  /**
> diff --git a/memory.c b/memory.c
> index fe70075..b2b2216 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -1596,6 +1596,11 @@ void
> *memory_region_get_ram_ptr(MemoryRegion *mr)
>  return ptr + offset;
>  }
> 
> +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
> +{
> +return mr->ram_block ? mr->ram_block->offset : RAM_ADDR_INVALID;
> +}
> +
>  void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize,
> Error **errp)
>  {
>  assert(mr->ram_addr != RAM_ADDR_INVALID);
> --
> 2.4.3




Re: [Qemu-devel] [PATCH V2 1/3] net/filter-traffic: add filter-traffic.h

2016-02-29 Thread Zhang Chen



On 03/01/2016 11:02 AM, Li Zhijian wrote:



On 02/29/2016 08:23 PM, Zhang Chen wrote:

We can reuse filter-traffic by filter-mirror,
filter-redirector and so on.


Is the main purpose to export filter_traffic_send() ?
IMO, define it as a public API would be better.

Using MirrorState and RedirectorState are clearer rather than 
TrafficState.





OK, I will fix it in next version.


Signed-off-by: Zhang Chen 
Signed-off-by: Wen Congyang 
---
  net/filter-mirror.c  | 70 
+++
  net/filter-traffic.h | 71 


  2 files changed, 80 insertions(+), 61 deletions(-)
  create mode 100644 net/filter-traffic.h

diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index ee13d94..d9698f2 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -9,65 +9,13 @@
   * later.  See the COPYING file in the top-level directory.
   */

-#include "net/filter.h"
-#include "net/net.h"
-#include "qemu-common.h"
-#include "qapi/qmp/qerror.h"
-#include "qapi-visit.h"
-#include "qom/object.h"
-#include "qemu/main-loop.h"
-#include "qemu/error-report.h"
-#include "trace.h"
-#include "sysemu/char.h"
-#include "qemu/iov.h"
-#include "qemu/sockets.h"
+#include "net/filter-traffic.h"

  #define FILTER_MIRROR(obj) \
-OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR)
+OBJECT_CHECK(TrafficState, (obj), TYPE_FILTER_MIRROR)

  #define TYPE_FILTER_MIRROR "filter-mirror"

-typedef struct MirrorState {
-NetFilterState parent_obj;
-char *outdev;
-CharDriverState *chr_out;
-} MirrorState;
-
-static int filter_mirror_send(NetFilterState *nf,
-   const struct iovec *iov,
-   int iovcnt)
-{
-MirrorState *s = FILTER_MIRROR(nf);
-int ret = 0;
-ssize_t size = 0;
-uint32_t len =  0;
-char *buf;
-
-size = iov_size(iov, iovcnt);
-if (!size) {
-return 0;
-}
-
-len = htonl(size);
-ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *), 
sizeof(len));

-if (ret != sizeof(len)) {
-goto err;
-}
-
-buf = g_malloc(size);
-iov_to_buf(iov, iovcnt, 0, buf, size);
-ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)buf, size);
-g_free(buf);
-if (ret != size) {
-goto err;
-}
-
-return 0;
-
-err:
-return ret < 0 ? ret : -EIO;
-}
-
  static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
   NetClientState *sender,
   unsigned flags,
@@ -77,7 +25,7 @@ static ssize_t 
filter_mirror_receive_iov(NetFilterState *nf,

  {
  int ret;

-ret = filter_mirror_send(nf, iov, iovcnt);
+ret = filter_traffic_send(nf, iov, iovcnt);
  if (ret) {
  error_report("filter_mirror_send failed(%s)", strerror(-ret));
  }
@@ -91,7 +39,7 @@ static ssize_t 
filter_mirror_receive_iov(NetFilterState *nf,


  static void filter_mirror_cleanup(NetFilterState *nf)
  {
-MirrorState *s = FILTER_MIRROR(nf);
+TrafficState *s = FILTER_MIRROR(nf);

  if (s->chr_out) {
  qemu_chr_fe_release(s->chr_out);
@@ -100,7 +48,7 @@ static void filter_mirror_cleanup(NetFilterState *nf)

  static void filter_mirror_setup(NetFilterState *nf, Error **errp)
  {
-MirrorState *s = FILTER_MIRROR(nf);
+TrafficState *s = FILTER_MIRROR(nf);

  if (!s->outdev) {
  error_setg(errp, "filter filter mirror needs 'outdev' "
@@ -132,7 +80,7 @@ static void filter_mirror_class_init(ObjectClass 
*oc, void *data)


  static char *filter_mirror_get_outdev(Object *obj, Error **errp)
  {
-MirrorState *s = FILTER_MIRROR(obj);
+TrafficState *s = FILTER_MIRROR(obj);

  return g_strdup(s->outdev);
  }
@@ -140,7 +88,7 @@ static char *filter_mirror_get_outdev(Object *obj, 
Error **errp)

  static void
  filter_mirror_set_outdev(Object *obj, const char *value, Error **errp)
  {
-MirrorState *s = FILTER_MIRROR(obj);
+TrafficState *s = FILTER_MIRROR(obj);

  g_free(s->outdev);
  s->outdev = g_strdup(value);
@@ -159,7 +107,7 @@ static void filter_mirror_init(Object *obj)

  static void filter_mirror_fini(Object *obj)
  {
-MirrorState *s = FILTER_MIRROR(obj);
+TrafficState *s = FILTER_MIRROR(obj);

  g_free(s->outdev);
  }
@@ -170,7 +118,7 @@ static const TypeInfo filter_mirror_info = {
  .class_init = filter_mirror_class_init,
  .instance_init = filter_mirror_init,
  .instance_finalize = filter_mirror_fini,
-.instance_size = sizeof(MirrorState),
+.instance_size = sizeof(TrafficState),
  };

  static void register_types(void)
diff --git a/net/filter-traffic.h b/net/filter-traffic.h
new file mode 100644
index 000..24cb5c3
--- /dev/null
+++ b/net/filter-traffic.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Copyright (c) 2016 Intel 

[Qemu-devel] Postcopy Migration: Recovery from a broken network connection (GSOC 2016)

2016-02-29 Thread Ashijeet Acharya
Hi Dr. David,

Congratulations to Qemu for getting selected as a mentoring organization in
GSOC 2016.

I am keen on working on postcopy migration recovery during a network
failure as my project work for GSOC 2016 . I am aware of your recent work
related to postcopy and have already gone through the links posted on the
ideas page and the source code on github.

I also had some ideas related to it and wanted to discuss those with you.

Please let me know how you are planning to proceed with it and the
technical skills required for the same.

Thanks!

Ashijeet Acharya


Re: [Qemu-devel] [PATCH v2 1/2] net: check packet payload length

2016-02-29 Thread P J P
  Hello Jason,

+-- On Fri, 26 Feb 2016, Jason Wang wrote --+
| Should we count mac header here? Did "plen + hlen >= length" imply "14 +
| hlen + csum_offset + 1" < length?
| 
| Looks not. Consider a TCP packet can report evil plen (e.g 20) but just
| have 10 bytes payload in fact. In this case:
| 
| hlen = 20, plen = 20, csum_offset = 16, length = 44 which can pass all
| the above tests, but 14 + hlen + csum_offset = 50 which is greater than
| length.

  Ummn, not sure. hlen + plen = total length(IP + TCP/UDP), 20+20 != 44. 
'length' is also used to read and allocate requisite buffers in other parts 
from where net_checksum_calculate() is called,

===
   etsec->tx_buffer = g_realloc(etsec->tx_buffer,
 etsec->tx_buffer_len + bd->length);
   ...
   /* Update buffer length */
   etsec->tx_buffer_len += bd->length;

   process_tx_fcb(etsec);
 -> net_checksum_calculate(etsec->tx_buffer + 8,
etsec->tx_buffer_len - 8);

   OR

   memcpy(tmpbuf, page + txreq.offset, txreq.size);
   net_checksum_calculate(tmpbuf, txreq.size);
===

  - With 'length < 14 + 20', we ensure that L2 & L3 headers are complete.
44 - 34 = 10, TCP/UDP header is incomplete.

I think 'plen=20 != 10' hints at an error in other parts of the code? Also if 
data buffer has more space than actual data, OOB access may not occur.

--
Prasad J Pandit / Red Hat Product Security Team
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F



Re: [Qemu-devel] [PATCH] Use special code for sigsetjmp only in cpu-exec.c

2016-02-29 Thread Andrew Baumann
> From: Stefan Weil [mailto:s...@weilnetz.de]
> Sent: Monday, 29 February 2016 9:08 PM
> 
> The rest of the code can use longjmp with stack unwinding.
> 
> Signed-off-by: Stefan Weil 
> ---
> 
> This is a bug fix needed for 64 bit Windows.
> 
> QEMU for Windows currently gets the wrong definition for
> sigsetjmp. It uses stack unwinding for longjmp which results
> in a crash when it is called from generated code.
> 
> Thanks to Andrew Baumann for his reminder that this patch was
> still missing. Andrew, could you please test it with your
> RPi emulation?
> 
> Regards,
> Stefan
> 
>  cpu-exec.c| 9 +
>  include/sysemu/os-win32.h | 8 
>  2 files changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/cpu-exec.c b/cpu-exec.c
> index fd92452..6a725e0 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -33,6 +33,15 @@
>  #endif
>  #include "sysemu/replay.h"
> 
> +#if defined(_WIN64)
> +/* On w64, sigsetjmp is implemented by _setjmp which needs a second
> parameter.
> + * If this parameter is NULL, longjump does no stack unwinding.
> + * That is what we need for QEMU. Passing the value of register rsp
> (default)
> + * lets longjmp try a stack unwinding which will crash with generated code.
> */
> +#undef sigsetjmp
> +#define sigsetjmp(env, savesigs) _setjmp(env, NULL)
> +#endif
> +
>  /* -icount align implementation. */
> 
>  typedef struct SyncClocks {
> diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
> index fbed346..b151e74 100644
> --- a/include/sysemu/os-win32.h
> +++ b/include/sysemu/os-win32.h
> @@ -55,14 +55,6 @@
>  # define EWOULDBLOCK  WSAEWOULDBLOCK
>  #endif
> 
> -#if defined(_WIN64)
> -/* On w64, setjmp is implemented by _setjmp which needs a second
> parameter.
> - * If this parameter is NULL, longjump does no stack unwinding.
> - * That is what we need for QEMU. Passing the value of register rsp (default)
> - * lets longjmp try a stack unwinding which will crash with generated code.
> */
> -# undef setjmp
> -# define setjmp(env) _setjmp(env, NULL)
> -#endif
>  /* QEMU uses sigsetjmp()/siglongjmp() as the portable way to specify
>   * "longjmp and don't touch the signal masks". Since we know that the
>   * savemask parameter will always be zero we can safely define these
> --
> 2.1.4

Thanks Stefan. This works for me with a mingw64 native build.

Tested-by: Andrew Baumann 

Andrew



[Qemu-devel] [PATCH v2 7/7] exec: Introduce AddressSpaceDispatch.mru_section

2016-02-29 Thread Fam Zheng
Under heavy workloads the lookup will likely end up with the same
MemoryRegionSection from last time. Using a pointer to cache the result,
like ram_list.mru_block, significantly reduces cost of
address_space_translate.

During address space topology update, as->dispatch will be reallocated
so the pointer is invalidated automatically.

Perf reports a visible drop on the cpu usage, because phys_page_find is
not called.  Before:

   2.35%  qemu-system-x86_64   [.] phys_page_find
   0.97%  qemu-system-x86_64   [.] address_space_translate_internal
   0.95%  qemu-system-x86_64   [.] address_space_translate
   0.55%  qemu-system-x86_64   [.] address_space_lookup_region

After:

   0.97%  qemu-system-x86_64   [.] address_space_translate_internal
   0.97%  qemu-system-x86_64   [.] address_space_lookup_region
   0.84%  qemu-system-x86_64   [.] address_space_translate

Signed-off-by: Fam Zheng 
---
 exec.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/exec.c b/exec.c
index b4e2eb5..98d7733 100644
--- a/exec.c
+++ b/exec.c
@@ -135,6 +135,7 @@ typedef struct PhysPageMap {
 struct AddressSpaceDispatch {
 struct rcu_head rcu;
 
+MemoryRegionSection *mru_section;
 /* This is a multi-level map on the physical address space.
  * The bottom level has pointers to MemoryRegionSections.
  */
@@ -350,14 +351,25 @@ static MemoryRegionSection 
*address_space_lookup_region(AddressSpaceDispatch *d,
 hwaddr addr,
 bool resolve_subpage)
 {
-MemoryRegionSection *section;
+MemoryRegionSection *section = atomic_read(>mru_section);
 subpage_t *subpage;
+bool update;
 
-section = phys_page_find(d->phys_map, addr, d->map.nodes, d->map.sections);
+if (section && section != >map.sections[PHYS_SECTION_UNASSIGNED] &&
+section_covers_addr(section, addr)) {
+update = false;
+} else {
+section = phys_page_find(d->phys_map, addr, d->map.nodes,
+ d->map.sections);
+update = true;
+}
 if (resolve_subpage && section->mr->subpage) {
 subpage = container_of(section->mr, subpage_t, iomem);
 section = >map.sections[subpage->sub_section[SUBPAGE_IDX(addr)]];
 }
+if (update) {
+atomic_set(>mru_section, section);
+}
 return section;
 }
 
-- 
2.4.3




[Qemu-devel] [PATCH v2 3/7] memory: Implement memory_region_get_ram_addr with mr->ram_block

2016-02-29 Thread Fam Zheng
Signed-off-by: Fam Zheng 
---
 include/exec/memory.h | 8 +---
 memory.c  | 5 +
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/include/exec/memory.h b/include/exec/memory.h
index d5284c2..810d2c0 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -978,14 +978,8 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
 /**
  * memory_region_get_ram_addr: Get the ram address associated with a memory
  * region
- *
- * DO NOT USE THIS FUNCTION.  This is a temporary workaround while the Xen
- * code is being reworked.
  */
-static inline ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
-{
-return mr->ram_addr;
-}
+ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
 
 uint64_t memory_region_get_alignment(const MemoryRegion *mr);
 /**
diff --git a/memory.c b/memory.c
index fe70075..b2b2216 100644
--- a/memory.c
+++ b/memory.c
@@ -1596,6 +1596,11 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
 return ptr + offset;
 }
 
+ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
+{
+return mr->ram_block ? mr->ram_block->offset : RAM_ADDR_INVALID;
+}
+
 void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error 
**errp)
 {
 assert(mr->ram_addr != RAM_ADDR_INVALID);
-- 
2.4.3




[Qemu-devel] [PATCH v2 6/7] exec: Factor out section_covers_addr

2016-02-29 Thread Fam Zheng
This will be shared by the next patch.

Also add a comment explaining the unobvious condition on "size.hi".

Signed-off-by: Fam Zheng 
---
 exec.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/exec.c b/exec.c
index ad8b826..b4e2eb5 100644
--- a/exec.c
+++ b/exec.c
@@ -307,6 +307,16 @@ static void phys_page_compact_all(AddressSpaceDispatch *d, 
int nodes_nb)
 }
 }
 
+static inline bool section_covers_addr(const MemoryRegionSection *section,
+   hwaddr addr)
+{
+/* Memory topology clips a memory region to 2^64, size.hi >= 0 means the
+ * section must cover any addr. */
+return section->size.hi ||
+   range_covers_byte(section->offset_within_address_space,
+ section->size.lo, addr);
+}
+
 static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr addr,
Node *nodes, MemoryRegionSection 
*sections)
 {
@@ -322,9 +332,7 @@ static MemoryRegionSection *phys_page_find(PhysPageEntry 
lp, hwaddr addr,
 lp = p[(index >> (i * P_L2_BITS)) & (P_L2_SIZE - 1)];
 }
 
-if (sections[lp.ptr].size.hi ||
-range_covers_byte(sections[lp.ptr].offset_within_address_space,
-  sections[lp.ptr].size.lo, addr)) {
+if (section_covers_addr([lp.ptr], addr)) {
 return [lp.ptr];
 } else {
 return [PHYS_SECTION_UNASSIGNED];
-- 
2.4.3




[Qemu-devel] [PATCH v2 2/7] memory: Move assignment to ram_block to memory_region_init_*

2016-02-29 Thread Fam Zheng
We don't force "const" qualifiers with pointers in QEMU, but it's still
good to keep a clean function interface. Assigning to mr->ram_block is
in this sense ugly - one initializer mutating its owning object's state.

Move it to memory_region_init_*, where mr->ram_addr is assigned.

Reviewed-by: Gonglei 
Signed-off-by: Fam Zheng 
---
 exec.c   | 1 -
 memory.c | 5 +
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/exec.c b/exec.c
index 2b14b79..83e3f7d 100644
--- a/exec.c
+++ b/exec.c
@@ -1711,7 +1711,6 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, 
ram_addr_t max_size,
 error_propagate(errp, local_err);
 return NULL;
 }
-mr->ram_block = new_block;
 return new_block;
 }
 
diff --git a/memory.c b/memory.c
index ae13ba9..fe70075 100644
--- a/memory.c
+++ b/memory.c
@@ -1233,6 +1233,7 @@ void memory_region_init_ram(MemoryRegion *mr,
 mr->terminates = true;
 mr->destructor = memory_region_destructor_ram;
 ram_block = qemu_ram_alloc(size, mr, errp);
+mr->ram_block = ram_block;
 mr->ram_addr = ram_block->offset;
 mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
 }
@@ -1254,6 +1255,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
 mr->terminates = true;
 mr->destructor = memory_region_destructor_ram;
 ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp);
+mr->ram_block = ram_block;
 mr->ram_addr = ram_block->offset;
 mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
 }
@@ -1274,6 +1276,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
 mr->terminates = true;
 mr->destructor = memory_region_destructor_ram;
 ram_block = qemu_ram_alloc_from_file(size, mr, share, path, errp);
+mr->ram_block = ram_block;
 mr->ram_addr = ram_block->offset;
 mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
 }
@@ -1296,6 +1299,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
 /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL.  */
 assert(ptr != NULL);
 ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, _fatal);
+mr->ram_block = ram_block;
 mr->ram_addr = ram_block->offset;
 }
 
@@ -1333,6 +1337,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
 mr->rom_device = true;
 mr->destructor = memory_region_destructor_rom_device;
 ram_block = qemu_ram_alloc(size, mr, errp);
+mr->ram_block = ram_block;
 mr->ram_addr = ram_block->offset;
 }
 
-- 
2.4.3




[Qemu-devel] [PATCH v2 5/7] exec: Pass RAMBlock pointer to qemu_ram_free

2016-02-29 Thread Fam Zheng
The only caller now knows exactly which RAMBlock to free, so it's not
necessary to do the lookup.

Reviewed-by: Gonglei 
Signed-off-by: Fam Zheng 
---
 exec.c  | 21 +++--
 include/exec/ram_addr.h |  2 +-
 memory.c|  4 ++--
 3 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/exec.c b/exec.c
index 6ed4203..ad8b826 100644
--- a/exec.c
+++ b/exec.c
@@ -1751,22 +1751,15 @@ static void reclaim_ramblock(RAMBlock *block)
 g_free(block);
 }
 
-void qemu_ram_free(ram_addr_t addr)
+void qemu_ram_free(RAMBlock *block)
 {
-RAMBlock *block;
-
 qemu_mutex_lock_ramlist();
-QLIST_FOREACH_RCU(block, _list.blocks, next) {
-if (addr == block->offset) {
-QLIST_REMOVE_RCU(block, next);
-ram_list.mru_block = NULL;
-/* Write list before version */
-smp_wmb();
-ram_list.version++;
-call_rcu(block, reclaim_ramblock, rcu);
-break;
-}
-}
+QLIST_REMOVE_RCU(block, next);
+ram_list.mru_block = NULL;
+/* Write list before version */
+smp_wmb();
+ram_list.version++;
+call_rcu(block, reclaim_ramblock, rcu);
 qemu_mutex_unlock_ramlist();
 }
 
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 865e19b..5adf7a4 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -108,7 +108,7 @@ RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, 
ram_addr_t max_size,
 int qemu_get_ram_fd(ram_addr_t addr);
 void qemu_set_ram_fd(ram_addr_t addr, int fd);
 void *qemu_get_ram_block_host_ptr(ram_addr_t addr);
-void qemu_ram_free(ram_addr_t addr);
+void qemu_ram_free(RAMBlock *block);
 
 int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp);
 
diff --git a/memory.c b/memory.c
index befdf6b..966ff2c 100644
--- a/memory.c
+++ b/memory.c
@@ -858,12 +858,12 @@ static void memory_region_destructor_none(MemoryRegion 
*mr)
 
 static void memory_region_destructor_ram(MemoryRegion *mr)
 {
-qemu_ram_free(memory_region_get_ram_addr(mr));
+qemu_ram_free(mr->ram_block);
 }
 
 static void memory_region_destructor_rom_device(MemoryRegion *mr)
 {
-qemu_ram_free(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK);
+qemu_ram_free(mr->ram_block);
 }
 
 static bool memory_region_need_escape(char c)
-- 
2.4.3




[Qemu-devel] [PATCH v2 4/7] memory: Drop MemoryRegion.ram_addr

2016-02-29 Thread Fam Zheng
All references to mr->ram_addr are replaced by
memory_region_get_ram_addr(mr) (except for a few assertions that are
replaced with mr->ram_block).

Reviewed-by: Gonglei 
Signed-off-by: Fam Zheng 
---
 cputlb.c  |  4 +--
 exec.c|  3 ++-
 hw/misc/ivshmem.c |  9 ---
 include/exec/memory.h |  1 -
 kvm-all.c |  3 ++-
 memory.c  | 71 ---
 6 files changed, 39 insertions(+), 52 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index 3973030..2f7a166 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -416,8 +416,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong 
vaddr,
 /* Write access calls the I/O callback.  */
 te->addr_write = address | TLB_MMIO;
 } else if (memory_region_is_ram(section->mr)
-   && cpu_physical_memory_is_clean(section->mr->ram_addr
-   + xlat)) {
+   && cpu_physical_memory_is_clean(
+memory_region_get_ram_addr(section->mr) + xlat)) {
 te->addr_write = address | TLB_NOTDIRTY;
 } else {
 te->addr_write = address;
diff --git a/exec.c b/exec.c
index 83e3f7d..6ed4203 100644
--- a/exec.c
+++ b/exec.c
@@ -2699,7 +2699,8 @@ MemTxResult address_space_read_continue(AddressSpace *as, 
hwaddr addr,
 }
 } else {
 /* RAM case */
-ptr = qemu_get_ram_ptr(mr->ram_block, mr->ram_addr + addr1);
+ptr = qemu_get_ram_ptr(mr->ram_block,
+   memory_region_get_ram_addr(mr) + addr1);
 memcpy(buf, ptr, l);
 }
 
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 48b7a34..1838bc8 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -400,7 +400,7 @@ static int create_shared_memory_BAR(IVShmemState *s, int 
fd, uint8_t attr,
 
 memory_region_init_ram_ptr(>ivshmem, OBJECT(s), "ivshmem.bar2",
s->ivshmem_size, ptr);
-qemu_set_ram_fd(s->ivshmem.ram_addr, fd);
+qemu_set_ram_fd(memory_region_get_ram_addr(>ivshmem), fd);
 vmstate_register_ram(>ivshmem, DEVICE(s));
 memory_region_add_subregion(>bar, 0, >ivshmem);
 
@@ -661,7 +661,8 @@ static void ivshmem_read(void *opaque, const uint8_t *buf, 
int size)
 }
 memory_region_init_ram_ptr(>ivshmem, OBJECT(s),
"ivshmem.bar2", s->ivshmem_size, map_ptr);
-qemu_set_ram_fd(s->ivshmem.ram_addr, incoming_fd);
+qemu_set_ram_fd(memory_region_get_ram_addr(>ivshmem),
+incoming_fd);
 vmstate_register_ram(>ivshmem, DEVICE(s));
 
 IVSHMEM_DPRINTF("guest h/w addr = %p, size = %" PRIu64 "\n",
@@ -996,8 +997,10 @@ static void pci_ivshmem_exit(PCIDevice *dev)
  strerror(errno));
 }
 
-if ((fd = qemu_get_ram_fd(s->ivshmem.ram_addr)) != -1)
+fd = qemu_get_ram_fd(memory_region_get_ram_addr(>ivshmem));
+if (fd != -1) {
 close(fd);
+}
 }
 
 vmstate_unregister_ram(>ivshmem, DEVICE(dev));
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 810d2c0..2de7898 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -169,7 +169,6 @@ struct MemoryRegion {
 bool flush_coalesced_mmio;
 bool global_locking;
 uint8_t dirty_log_mask;
-ram_addr_t ram_addr;
 RAMBlock *ram_block;
 Object *owner;
 const MemoryRegionIOMMUOps *iommu_ops;
diff --git a/kvm-all.c b/kvm-all.c
index a65e73f..161200e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -366,7 +366,8 @@ static void kvm_log_stop(MemoryListener *listener,
 static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
  unsigned long *bitmap)
 {
-ram_addr_t start = section->offset_within_region + section->mr->ram_addr;
+ram_addr_t start = section->offset_within_region +
+   memory_region_get_ram_addr(section->mr);
 ram_addr_t pages = int128_get64(section->size) / getpagesize();
 
 cpu_physical_memory_set_dirty_lebitmap(bitmap, start, pages);
diff --git a/memory.c b/memory.c
index b2b2216..befdf6b 100644
--- a/memory.c
+++ b/memory.c
@@ -858,12 +858,12 @@ static void memory_region_destructor_none(MemoryRegion 
*mr)
 
 static void memory_region_destructor_ram(MemoryRegion *mr)
 {
-qemu_ram_free(mr->ram_addr);
+qemu_ram_free(memory_region_get_ram_addr(mr));
 }
 
 static void memory_region_destructor_rom_device(MemoryRegion *mr)
 {
-qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
+qemu_ram_free(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK);
 }
 
 static bool memory_region_need_escape(char c)
@@ -994,7 +994,6 @@ static void memory_region_initfn(Object *obj)
 ObjectProperty *op;
 
 mr->ops = _mem_ops;
-mr->ram_addr = 

[Qemu-devel] [PATCH v2 1/7] exec: Return RAMBlock pointer from allocating functions

2016-02-29 Thread Fam Zheng
Previously we return RAMBlock.offset; now return the pointer to the
whole structure.

ram_block_add returns void now, error is completely passed with errp.

Reviewed-by: Gonglei 
Signed-off-by: Fam Zheng 
---
 exec.c  | 51 +
 include/exec/ram_addr.h | 22 ++---
 memory.c| 25 +++-
 3 files changed, 53 insertions(+), 45 deletions(-)

diff --git a/exec.c b/exec.c
index c62c439..2b14b79 100644
--- a/exec.c
+++ b/exec.c
@@ -1554,7 +1554,7 @@ static void dirty_memory_extend(ram_addr_t old_ram_size,
 }
 }
 
-static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
+static void ram_block_add(RAMBlock *new_block, Error **errp)
 {
 RAMBlock *block;
 RAMBlock *last_block = NULL;
@@ -1573,7 +1573,6 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, 
Error **errp)
 if (err) {
 error_propagate(errp, err);
 qemu_mutex_unlock_ramlist();
-return -1;
 }
 } else {
 new_block->host = phys_mem_alloc(new_block->max_length,
@@ -1583,7 +1582,6 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, 
Error **errp)
  "cannot set up guest memory '%s'",
  memory_region_name(new_block->mr));
 qemu_mutex_unlock_ramlist();
-return -1;
 }
 memory_try_enable_merging(new_block->host, new_block->max_length);
 }
@@ -1631,22 +1629,19 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, 
Error **errp)
 kvm_setup_guest_memory(new_block->host, new_block->max_length);
 }
 }
-
-return new_block->offset;
 }
 
 #ifdef __linux__
-ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
-bool share, const char *mem_path,
-Error **errp)
+RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
+   bool share, const char *mem_path,
+   Error **errp)
 {
 RAMBlock *new_block;
-ram_addr_t addr;
 Error *local_err = NULL;
 
 if (xen_enabled()) {
 error_setg(errp, "-mem-path not supported with Xen");
-return -1;
+return NULL;
 }
 
 if (phys_mem_alloc != qemu_anon_ram_alloc) {
@@ -1657,7 +1652,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, 
MemoryRegion *mr,
  */
 error_setg(errp,
"-mem-path not supported with this accelerator");
-return -1;
+return NULL;
 }
 
 size = HOST_PAGE_ALIGN(size);
@@ -1670,29 +1665,28 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, 
MemoryRegion *mr,
  mem_path, errp);
 if (!new_block->host) {
 g_free(new_block);
-return -1;
+return NULL;
 }
 
-addr = ram_block_add(new_block, _err);
+ram_block_add(new_block, _err);
 if (local_err) {
 g_free(new_block);
 error_propagate(errp, local_err);
-return -1;
+return NULL;
 }
-return addr;
+return new_block;
 }
 #endif
 
 static
-ram_addr_t qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
-   void (*resized)(const char*,
-   uint64_t length,
-   void *host),
-   void *host, bool resizeable,
-   MemoryRegion *mr, Error **errp)
+RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
+  void (*resized)(const char*,
+  uint64_t length,
+  void *host),
+  void *host, bool resizeable,
+  MemoryRegion *mr, Error **errp)
 {
 RAMBlock *new_block;
-ram_addr_t addr;
 Error *local_err = NULL;
 
 size = HOST_PAGE_ALIGN(size);
@@ -1711,29 +1705,28 @@ ram_addr_t qemu_ram_alloc_internal(ram_addr_t size, 
ram_addr_t max_size,
 if (resizeable) {
 new_block->flags |= RAM_RESIZEABLE;
 }
-addr = ram_block_add(new_block, _err);
+ram_block_add(new_block, _err);
 if (local_err) {
 g_free(new_block);
 error_propagate(errp, local_err);
-return -1;
+return NULL;
 }
-
 mr->ram_block = new_block;
-return addr;
+return new_block;
 }
 
-ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
+RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
MemoryRegion *mr, Error **errp)
 {
 return qemu_ram_alloc_internal(size, size, NULL, host, 

[Qemu-devel] [PATCH v2 0/7] memory: Clean up MemoryRegion.ram_addr and optimize address_space_translate

2016-02-29 Thread Fam Zheng
v2: In the optimization patch, factor out section_covers_addr() and use it.
[Paolo, Peter]
Check "ram_block == NULL" in patch 3. [Gonglei]
Add Gonglei's rev-by in patches 1, 2, 4 and 5.

The first four patches drop ram_addr from MemoryRegion on top of Gonglei's
optimization.

The next patch simplifies qemu_ram_free a bit by passing the RAMBlock pointer.

The last patch speeds up address_space_translate with a cache pointer inside
the AddressSpaceDispatch.

Fam Zheng (7):
  exec: Return RAMBlock pointer from allocating functions
  memory: Move assignment to ram_block to memory_region_init_*
  memory: Implement memory_region_get_ram_addr with mr->ram_block
  memory: Drop MemoryRegion.ram_addr
  exec: Pass RAMBlock pointer to qemu_ram_free
  exec: Factor out section_covers_addr
  exec: Introduce AddressSpaceDispatch.mru_section

 cputlb.c|   4 +-
 exec.c  | 106 +---
 hw/misc/ivshmem.c   |   9 ++--
 include/exec/memory.h   |   9 +---
 include/exec/ram_addr.h |  24 +--
 kvm-all.c   |   3 +-
 memory.c|  56 ++---
 7 files changed, 111 insertions(+), 100 deletions(-)

-- 
2.4.3




Re: [Qemu-devel] [Qemu-ppc] [PATCH] dbdma: warn when using unassigned channel

2016-02-29 Thread Thomas Huth
On 26.02.2016 06:02, David Gibson wrote:
> On Thu, Feb 25, 2016 at 01:02:11PM +0100, Hervé Poussineau wrote:
>> With this, it's easier to know if a guest uses an invalid and/or 
>> unimplemented
>> DMA channel.
>>
>> Signed-off-by: Hervé Poussineau 
> 
> Merged to ppc-for-2.6, thanks.
> 
> Btw, you're likely to get a prompter response if you CC me directly on
> patches you want merged.  I only sometimes have time to go through the
> qemu-ppc list looking for things.

 David,

I guess the problem is likely that get_maintainers.pl does not list you
for ppc related stuff except the spapr files. How long is Alex still
going to be away? Maybe you should get listed in some more ppc-related
entries as co-maintainer in the MAINTAINERS file, for the time being?

 Thomas




signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v3 2/2] filter-buffer: Add status_changed callback processing

2016-02-29 Thread zhanghailiang
While the status of filter-buffer changing from 'on' to 'off',
it need to release all the buffered packets, and delete the related
timer, while switch from 'off' to 'on', it need to resume the release
packets timer.

Here, we extract the process of setup timer into a new helper,
which will be used in the new status_changed callback.

Signed-off-by: zhanghailiang 
Cc: Jason Wang 
Cc: Yang Hongyang 
---
v3:
- Extract the process of setup timer into a new helper
v2:
- New patch
---
 net/filter-buffer.c | 34 --
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index 12ad2e3..972177b 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -100,6 +100,19 @@ static void filter_buffer_cleanup(NetFilterState *nf)
 }
 }
 
+static void filter_buffer_setup_timer(NetFilterState *nf)
+{
+FilterBufferState *s = FILTER_BUFFER(nf);
+
+if (s->interval) {
+timer_init_us(>release_timer, QEMU_CLOCK_VIRTUAL,
+  filter_buffer_release_timer, nf);
+/* Timer armed to fire in s->interval microseconds. */
+timer_mod(>release_timer,
+  qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
+}
+}
+
 static void filter_buffer_setup(NetFilterState *nf, Error **errp)
 {
 FilterBufferState *s = FILTER_BUFFER(nf);
@@ -115,12 +128,20 @@ static void filter_buffer_setup(NetFilterState *nf, Error 
**errp)
 }
 
 s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
-if (s->interval) {
-timer_init_us(>release_timer, QEMU_CLOCK_VIRTUAL,
-  filter_buffer_release_timer, nf);
-/* Timer armed to fire in s->interval microseconds. */
-timer_mod(>release_timer,
-  qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
+filter_buffer_setup_timer(nf);
+}
+
+static void filter_buffer_status_changed(NetFilterState *nf, Error **errp)
+{
+FilterBufferState *s = FILTER_BUFFER(nf);
+
+if (!nf->on) {
+if (s->interval) {
+timer_del(>release_timer);
+}
+filter_buffer_flush(nf);
+} else {
+filter_buffer_setup_timer(nf);
 }
 }
 
@@ -131,6 +152,7 @@ static void filter_buffer_class_init(ObjectClass *oc, void 
*data)
 nfc->setup = filter_buffer_setup;
 nfc->cleanup = filter_buffer_cleanup;
 nfc->receive_iov = filter_buffer_receive_iov;
+nfc->status_changed = filter_buffer_status_changed;
 }
 
 static void filter_buffer_get_interval(Object *obj, Visitor *v,
-- 
1.8.3.1





[Qemu-devel] [PATCH v3 1/2] filter: Add 'status' property for filter object

2016-02-29 Thread zhanghailiang
With this property, users can control if this filter is 'on'
or 'off'. The default behavior for filter is 'on'.

For some types of filters, they may need to react to status changing,
So here, we introduced status changing callback/notifier for filter class.

We will skip the disabled ('off') filter when delivering packets in net layer.

Signed-off-by: zhanghailiang 
Cc: Jason Wang 
Cc: Yang Hongyang 
---
v3:
- Use 'bool on' instead of member 'char *status' (Jason)
v2:
- Split the processing of buffer-filter into a new patch (Jason)
- Use 'status' instead of 'enabled' to store the filter state (Jason)
- Rename FilterDisable() callback to FilterStatusChanged(Jason)
---
 include/net/filter.h |  4 
 net/filter.c | 41 +
 qemu-options.hx  |  4 +++-
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/include/net/filter.h b/include/net/filter.h
index 5639976..cfb1172 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -36,12 +36,15 @@ typedef ssize_t (FilterReceiveIOV)(NetFilterState *nc,
int iovcnt,
NetPacketSent *sent_cb);
 
+typedef void (FilterStatusChanged) (NetFilterState *nf, Error **errp);
+
 typedef struct NetFilterClass {
 ObjectClass parent_class;
 
 /* optional */
 FilterSetup *setup;
 FilterCleanup *cleanup;
+FilterStatusChanged *status_changed;
 /* mandatory */
 FilterReceiveIOV *receive_iov;
 } NetFilterClass;
@@ -55,6 +58,7 @@ struct NetFilterState {
 char *netdev_id;
 NetClientState *netdev;
 NetFilterDirection direction;
+bool on;
 QTAILQ_ENTRY(NetFilterState) next;
 };
 
diff --git a/net/filter.c b/net/filter.c
index d2a514e..60203a0 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -17,6 +17,11 @@
 #include "qom/object_interfaces.h"
 #include "qemu/iov.h"
 
+static inline bool qemu_can_skip_netfilter(NetFilterState *nf)
+{
+return !nf->on;
+}
+
 ssize_t qemu_netfilter_receive(NetFilterState *nf,
NetFilterDirection direction,
NetClientState *sender,
@@ -25,6 +30,9 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
int iovcnt,
NetPacketSent *sent_cb)
 {
+if (qemu_can_skip_netfilter(nf)) {
+return 0;
+}
 if (nf->direction == direction ||
 nf->direction == NET_FILTER_DIRECTION_ALL) {
 return NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov(
@@ -134,8 +142,38 @@ static void netfilter_set_direction(Object *obj, int 
direction, Error **errp)
 nf->direction = direction;
 }
 
+static char *netfilter_get_status(Object *obj, Error **errp)
+{
+NetFilterState *nf = NETFILTER(obj);
+
+return nf->on ? g_strdup("on") : g_strdup("off");
+}
+
+static void netfilter_set_status(Object *obj, const char *str, Error **errp)
+{
+NetFilterState *nf = NETFILTER(obj);
+NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
+
+if (strcmp(str, "on") && strcmp(str, "off")) {
+error_setg(errp, "Invalid value for netfilter status, "
+ "should be 'on' or 'off'");
+return;
+}
+if (nf->on == !strcmp(str, "on")) {
+return;
+}
+nf->on = !nf->on;
+if (nfc->status_changed) {
+nfc->status_changed(nf, errp);
+}
+}
+
 static void netfilter_init(Object *obj)
 {
+NetFilterState *nf = NETFILTER(obj);
+
+nf->on = true;
+
 object_property_add_str(obj, "netdev",
 netfilter_get_netdev_id, netfilter_set_netdev_id,
 NULL);
@@ -143,6 +181,9 @@ static void netfilter_init(Object *obj)
  NetFilterDirection_lookup,
  netfilter_get_direction, netfilter_set_direction,
  NULL);
+object_property_add_str(obj, "status",
+netfilter_get_status, netfilter_set_status,
+NULL);
 }
 
 static void netfilter_complete(UserCreatable *uc, Error **errp)
diff --git a/qemu-options.hx b/qemu-options.hx
index 144e6a9..10a402b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3788,11 +3788,13 @@ version by providing the @var{passwordid} parameter. 
This provides
 the ID of a previously created @code{secret} object containing the
 password for decryption.
 
-@item -object 
filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}]
+@item -object 
filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}][,status=@var{on|off}]
 
 Interval @var{t} can't be 0, this filter batches the packet delivery: all
 packets arriving in a given interval on netdev @var{netdevid} are delayed
 until the end of the interval. Interval is in microseconds.
+@option{status} is optional that 

[Qemu-devel] [PATCH v3 0/2] Introduce 'status' property for netfilter

2016-02-29 Thread zhanghailiang
This is picked from COLO series, which is to realize the new 'status'
property for filter.

With this property, users can control if the filter is enabled or
disabled.

ChangeLog:
v3:
- Use 'bool on' instead of member 'char *status' (Jason)
- Extract the process of setup timer into a new helper

zhanghailiang (2):
  filter: Add 'status' property for filter object
  filter-buffer: Add status_changed callback processing

 include/net/filter.h |  4 
 net/filter-buffer.c  | 34 --
 net/filter.c | 41 +
 qemu-options.hx  |  4 +++-
 4 files changed, 76 insertions(+), 7 deletions(-)

-- 
1.8.3.1





Re: [Qemu-devel] [PATCH v1 00/17] ARM big-endian and setend support

2016-02-29 Thread Stefan Weil
Am 18.01.2016 um 08:12 schrieb Peter Crosthwaite:
> Hi All,
>
> This patch series adds system-mode big-endian support for ARM. It also
> implements the setend instruction, and loading of BE binaries even in
> LE emulation mode.
>
> Based on Paolo's original work. I have moved all the BE32 related work
> to the back of the series. Multiple parties are interested in the BE8
> work just on its own, so that could potentially be merged w/o BE32.
> PMM requested BE32 be at least thought out architecturally, so this
> series sees BE32 functionality through.
>
> I have tested all of LE. BE8 and BE32 in both linux-user mode (for
> regressions) and system mode (BE8 and BE32 are new here).
> My test application is here, the README gives some example command
> lines you can run:
>
> https://github.com/pcrost/arm-be-test
>
> Regards,
> Peter

It would be nice to get at least the emulation for 'setend' into the
next version, because it is needed for the Raspberry Pi emulation.

Peter C., are you planning a new pull request? Maybe the number
of commits needed can be reduced by adding the already reviewed
ones to QEMU.

Regards,
Stefan




signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v12 17/18] qapi: Simplify semantics of visit_next_list()

2016-02-29 Thread Eric Blake
We have two uses of list visits in the entire code base: one in
spapr_drc (which completely avoids visit_next_list(), feeding in
integers from a different source than uint8List), and one in
qapi-visit.py (that is, all other list visitors are generated
in qapi-visit.c, and share the same paradigm based on a qapi
FooList type).  What's more, the semantics of the list visit are
somewhat baroque, with the following pseudocode when FooList is
used:

start()
for (prev = head; cur = next(prev); prev = ) {
visit(>value)
}

Note that these semantics (advance before visit) requires that
the first call to next() return the list head, while all other
calls return the next element of the list; that is, every visitor
implementation is required to track extra state to decide whether
to return the input as-is, or to advance.  It also requires an
argument of 'GenericList **' to next(), solely because the first
iteration might need to modify the caller's GenericList head, so
that all other calls have to do a layer of dereferencing.

We can greatly simplify things by hoisting the special case
into the start() routine, and flipping the order in the loop
to visit before advance:

start(head)
for (tail = *head; tail; tail = next(tail)) {
visit(>value)
}

With the simpler semantics, visitors have less state to track,
the argument to next() is reduced to 'GenericList *', and it
also becomes obvious whether an input visitor is allocating a
FooList during visit_start_list() (rather than the old way of
not knowing if an allocation happened until the first
visit_next_list()).

The signature of visit_start_list() is chosen to match
visit_start_struct(), with the new parameters after 'name'.

The spapr_drc case is a virtual visit, done by passing NULL for
list, similarly to how NULL is passed to visit_start_struct()
when a qapi type is not used in those visits.  It was easy to
provide these semantics for qmp-output and dealloc visitors,
and a bit harder for qmp-input (several prerequisite patches
refactored things to make this patch straightforward).  But it
turned out that the string and opts visitors munge enough other
state during visit_next_list() to make it easier to just
document and require a GenericList visit for now; an assertion
will remind us to adjust things if we need the semantics in the
future.

Signed-off-by: Eric Blake 

---
v12: rebase to earlier changes, drop R-b, improve documentation,
split out qmp-input cleanups into prereq patches
[no v10, v11]
v9: no change
v8: consistent parameter order, fix qmp_input_get_next_type() to not
skip list entries
v7: new patch
---
 include/qapi/visitor.h   | 46 
 include/qapi/visitor-impl.h  |  7 +++---
 scripts/qapi-visit.py| 18 +++---
 include/qapi/opts-visitor.h  |  2 +-
 include/qapi/string-input-visitor.h  |  3 ++-
 include/qapi/string-output-visitor.h |  3 ++-
 qapi/qapi-visit-core.c   | 12 ++
 hw/ppc/spapr_drc.c   |  2 +-
 qapi/opts-visitor.c  | 33 +++---
 qapi/qapi-dealloc-visitor.c  | 35 ++-
 qapi/qmp-input-visitor.c | 32 -
 qapi/qmp-output-visitor.c| 22 -
 qapi/string-input-visitor.c  | 36 ++--
 qapi/string-output-visitor.c | 41 +++-
 docs/qapi-code-gen.txt   | 17 ++---
 15 files changed, 133 insertions(+), 176 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index fb4582a..a81878d 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -166,7 +166,7 @@
  *  if (err) {
  *  goto outobj;
  *  }
- *  visit_start_list(v, "list", );
+ *  visit_start_list(v, "list", NULL, 0, );
  *  if (err) {
  *  goto outobj;
  *  }
@@ -268,39 +268,43 @@ void visit_end_struct(Visitor *v);
  * @name expresses the relationship of this list to its parent
  * container; see the general description of @name above.
  *
+ * @list must be non-NULL for a real walk, in which case @size
+ * determines how much memory an input visitor will allocate into
+ * *@list (at least sizeof(GenericList)).  Some visitors also allow
+ * @list to be NULL for a virtual walk, in which case @size is
+ * ignored.
+ *
  * @errp must be NULL-initialized, and is set if an error is detected
  * (such as if a member @name is not present, or is present but not a
- * list).
+ * list).  On error, input visitors set *@obj to NULL.
  *
  * After visit_start_list() succeeds, the caller may visit its members
- * one after the other.  A real visit uses visit_next_list() for
- * traversing the linked list, while a virtual visit uses other means.
- * For each list element, call the appropriate visit_type_FOO() with
- * name set to NULL and obj set to the address of the list element.
- * Finally, visit_end_list() needs to be 

[Qemu-devel] [PATCH v12 13/18] qapi: Split visit_end_struct() into pieces

2016-02-29 Thread Eric Blake
As mentioned in previous patches, we want to call visit_end_struct()
functions unconditionally, so that visitors can release resources
tied up since the matching visit_start_struct() without also having
to worry about error priority if more than one error occurs.

Even though error_propagate() can be safely used to ignore a second
error during cleanup caused by a first error, it is simpler if the
cleanup cannot set an error.  So, split out the error checking
portion (basically, input visitors checking for unvisited keys) into
a new function visit_check_struct(), which can be safely skipped if
any earlier errors are encountered, and leave the cleanup portion
(which never fails, but must be called unconditionally if
visit_start_struct() succeeded) in visit_end_struct().

Generated code has diffs resembling:

|@@ -59,10 +59,12 @@ void visit_type_ACPIOSTInfo(Visitor *v,
| goto out_obj;
| }
| visit_type_ACPIOSTInfo_members(v, obj, );
|-error_propagate(errp, err);
|-err = NULL;
|+if (err) {
|+goto out_obj;
|+}
|+visit_check_struct(v, );
| out_obj:
|-visit_end_struct(v, );
|+visit_end_struct(v);
| out:

Signed-off-by: Eric Blake 

---
v12: rebase to earlier changes, fix bug in spapr_drc not calling
visit_end_struct, fold in docs, fix stray DO_UPCAST from sneaking
back in
[no v10, v11]
v9: rebase to earlier changes, drop Marc-Andre's R-b
v8: rebase to 'name' motion
v7: rebase to earlier changes
v6: new patch, revised version of RFC based on discussion of v5 7/46
---
 include/qapi/visitor.h | 13 +++--
 include/qapi/visitor-impl.h|  5 -
 scripts/qapi-event.py  |  3 ++-
 scripts/qapi-visit.py  | 15 +--
 qapi/qapi-visit-core.c | 11 +--
 hw/ppc/spapr_drc.c |  3 ++-
 hw/virtio/virtio-balloon.c | 15 ---
 qapi/opts-visitor.c| 17 +++--
 qapi/qapi-dealloc-visitor.c|  2 +-
 qapi/qmp-input-visitor.c   | 34 +++---
 qapi/qmp-output-visitor.c  |  2 +-
 qom/object.c   |  5 ++---
 qom/object_interfaces.c| 16 +++-
 tests/test-qmp-input-visitor.c |  3 ++-
 docs/qapi-code-gen.txt |  8 +---
 15 files changed, 97 insertions(+), 55 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 2b85c6f..b3ca93c 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -239,17 +239,26 @@ void visit_start_struct(Visitor *v, const char *name, 
void **obj,
 size_t size, Error **errp);

 /*
- * Complete an object visit started earlier.
+ * Prepare for completing an object visit.
  *
  * @errp must be NULL-initialized, and is set if an error is detected
  * (such as unparsed keys remaining in the input stream).
  *
+ * Should be called prior to visit_end_struct() if all other
+ * intermediate visit steps were successful, to allow the visitor one
+ * last chance to report errors.
+ */
+void visit_check_struct(Visitor *v, Error **errp);
+
+/*
+ * Complete an object visit started earlier.
+ *
  * Must be called after any successful use of visit_start_struct(),
  * even if intermediate processing was skipped due to errors, to allow
  * the backend to release any resources.  Destroying the visitor may
  * behave as if this was implicitly called.
  */
-void visit_end_struct(Visitor *v, Error **errp);
+void visit_end_struct(Visitor *v);


 /* === Visiting lists */
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 90bcaec..d44fcd1 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -39,8 +39,11 @@ struct Visitor
 void (*start_struct)(Visitor *v, const char *name, void **obj,
  size_t size, Error **errp);

+/* Optional; intended for input visitors.  */
+void (*check_struct)(Visitor *v, Error **errp);
+
 /* Must be set to visit structs.  */
-void (*end_struct)(Visitor *v, Error **errp);
+void (*end_struct)(Visitor *v);

 /* Must be set.  */
 void (*start_list)(Visitor *v, const char *name, Error **errp);
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 808ed80..2604c3d 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -71,8 +71,9 @@ def gen_event_send(name, arg_type):
 ret += gen_visit_members(arg_type.members, need_cast=True,
  label='out_obj')
 ret += mcgen('''
+visit_check_struct(v, );
 out_obj:
-visit_end_struct(v, err ? NULL : );
+visit_end_struct(v);
 if (err) {
 goto out;
 }
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index aa244cd..db756a0 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -188,9 +188,10 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, 
%(c_name)s **obj, Error
 break;
 }
 visit_type_%(c_type)s_members(v, 

[Qemu-devel] [PATCH v12 16/18] qmp-input: Require struct push to visit members of top dict

2016-02-29 Thread Eric Blake
Don't embed the root of the visit into the stack of current
containers being visited.  That way, we no longer get confused
on whether the first visit of a dictionary is to the dictionary
itself or to one of the members of the dictionary, and we no
longer have to require the root visit to pass name=NULL.

An audit of all qmp_input_visitor_new* call sites shows that
the only places where the visit starts directly on a QDict,
but where the first visit_type_* within the visit had passed
a non-NULL name, were fixed in the previous two places to
properly push into the object with visit_start_struct().

Signed-off-by: Eric Blake 

---
v12: new patch
---
 include/qapi/visitor.h   |  3 +--
 include/qapi/qmp-input-visitor.h |  8 --
 qapi/qmp-input-visitor.c | 54 ++--
 3 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index b3ca93c..fb4582a 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -48,8 +48,7 @@
  *
  * The @name parameter of visit_type_FOO() describes the relation
  * between this QAPI value and its parent container.  When visiting
- * the root of a tree, @name is usually ignored (although some
- * visitors require it to be NULL); when visiting a member of an
+ * the root of a tree, @name is ignored; when visiting a member of an
  * object, @name is the key associated with the value; and when
  * visiting a member of a list, @name is NULL.
  *
diff --git a/include/qapi/qmp-input-visitor.h b/include/qapi/qmp-input-visitor.h
index d75ff98..3ed499c 100644
--- a/include/qapi/qmp-input-visitor.h
+++ b/include/qapi/qmp-input-visitor.h
@@ -19,14 +19,6 @@

 typedef struct QmpInputVisitor QmpInputVisitor;

-/*
- * FIXME: When visiting a QDict, passing a non-NULL @name for the
- * first visit_type_FOO() when the root is a QDict will find that
- * particular key within the QDict.  In the future, the contract may
- * be tightened to require visit_start_struct() with ignored @name as
- * the first visit; in the meantime, the first visit is safest when
- * using NULL for @name.
- */
 QmpInputVisitor *qmp_input_visitor_new(QObject *obj);
 QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj);

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 6b69e9a..2daf83f 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -38,9 +38,11 @@ struct QmpInputVisitor
 {
 Visitor visitor;

-/* Stack of objects being visited.  stack[0] is root of visit,
- * stack[1] and below correspond to visit_start_struct (nested
- * QDict) and visit_start_list (nested QList).  */
+/* Root of visit at visitor creation.  */
+QObject *root;
+
+/* Stack of objects being visited (all entries will be either
+ * QDict or QList).  */
 StackObject stack[QIV_STACK_SIZE];
 int nb_stack;

@@ -57,36 +59,40 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
  const char *name,
  bool consume)
 {
-StackObject *tos = >stack[qiv->nb_stack - 1];
-QObject *qobj = tos->obj;
+StackObject *tos;
+QObject *qobj;

+if (!qiv->nb_stack) {
+/* Starting at root, name is ignored.  */
+return qiv->root;
+}
+
+/* We are in a container; find the next element */
+tos = >stack[qiv->nb_stack - 1];
+qobj = tos->obj;
 assert(qobj);

-/* If we have a name, and we're in a dictionary, then return that
- * value. */
-if (name && qobject_type(qobj) == QTYPE_QDICT) {
+if (qobject_type(qobj) == QTYPE_QDICT) {
+assert(name);
 qobj = qdict_get(qobject_to_qdict(qobj), name);
 if (tos->h && consume && qobj) {
 bool removed = g_hash_table_remove(tos->h, name);
 assert(removed);
 }
-return qobj;
-}
-
-/* If we are in the middle of a list, then return the next element
- * of the list.  */
-if (tos->entry) {
+} else {
 assert(qobject_type(qobj) == QTYPE_QLIST);
-assert(!tos->first);
-qobj = qlist_entry_obj(tos->entry);
-if (consume) {
-tos->entry = qlist_next(tos->entry);
+/* FIXME: assertion needs adjustment if we fix visit-core
+ * to pass "name.0" style name during lists.  */
+assert(!name);
+
+if (tos->entry) {
+assert(!tos->first);
+qobj = qlist_entry_obj(tos->entry);
+if (consume) {
+tos->entry = qlist_next(tos->entry);
+}
 }
-return qobj;
 }
-
-/* Otherwise, we are at the root of the visit or the start of a
- * list, and return the object as-is.  */
 return qobj;
 }

@@ -372,7 +378,7 @@ Visitor *qmp_input_get_visitor(QmpInputVisitor *v)

 void qmp_input_visitor_cleanup(QmpInputVisitor *v)
 {
-qobject_decref(v->stack[0].obj);
+qobject_decref(v->root);

[Qemu-devel] [PATCH v12 15/18] qom: Wrap prop visit in visit_start_struct

2016-02-29 Thread Eric Blake
The qmp-input visitor was playing rather fast and loose: when
visiting a QDict, you could grab members of the root dictionary
without first pushing into the dict.  But we are about to tighten
the input visitor, at which point user_creatable_add_type() MUST
follow the same paradigms as everyone else, of pushing into the
struct before grabbing its keys, because the value of 'name'
should be ignored on the top-level visit.

The change has no impact to the testsuite now, but is required to
avoid a failure in tests/test-netfilter once qmp-input is made
stricter.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 qom/object_interfaces.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index f075b3a..8efb8d1 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -117,12 +117,23 @@ Object *user_creatable_add_type(const char *type, const 
char *id,

 obj = object_new(type);
 if (qdict) {
+visit_start_struct(v, NULL, NULL, 0, _err);
+if (local_err) {
+goto out;
+}
 for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
 object_property_set(obj, v, e->key, _err);
 if (local_err) {
-goto out;
+break;
 }
 }
+if (!local_err) {
+visit_check_struct(v, _err);
+}
+visit_end_struct(v);
+if (local_err) {
+goto out;
+}
 }

 object_property_add_child(object_get_objects_root(),
-- 
2.5.0




[Qemu-devel] [PATCH v12 14/18] qapi-commands: Wrap argument visit in visit_start_struct

2016-02-29 Thread Eric Blake
The qmp-input visitor was playing rather fast and loose: when
visiting a QDict, you could grab members of the root dictionary
without first pushing into the dict.  But we are about to tighten
the input visitor, at which point the generated marshal code
MUST follow the same paradigms as everyone else, of pushing into
the struct before grabbing its keys, because the value of 'name'
should be ignored on the top-level visit.

It will also make things easier to follow when we introduce boxed
command parameters, where we call visit_type_FOO() instead of
individual members of FOO, since visit_type_FOO() also uses a
level of visit_start_struct() for handling the same QDict input.

Generated code grows as follows:

|@@ -63,18 +63,28 @@ void qmp_marshal_add_fd(QDict *args, QOb
| char *opaque = NULL;
|
| v = qmp_input_get_visitor(qiv);
|+visit_start_struct(v, NULL, NULL, 0, );
|+if (err) {
|+goto out;
|+}
| if (visit_optional(v, "fdset-id", _fdset_id)) {
| visit_type_int(v, "fdset-id", _id, );
| if (err) {
|-goto out;
|+goto out_obj;
| }
| }
| if (visit_optional(v, "opaque", _opaque)) {
| visit_type_str(v, "opaque", , );
| if (err) {
|-goto out;
|+goto out_obj;
| }
| }
|+visit_check_struct(v, );
|+out_obj:
|+visit_end_struct(v);
|+if (err) {
|+goto out;
|+}
|
| retval = qmp_add_fd(has_fdset_id, fdset_id, has_opaque, opaque, );

Note that this change could also make it possible for the
marshalling code to automatically detect excess input at the top
level, and not just in nested dictionaries.  However, that checking
is not currently useful (and we rely on the manual checking in
monitor.c:qmp_check_client_args() instead) as long as qmp-commands.hx
uses .args_type, and as long as we have 'name:O' as an arg-type that
explicitly allows unknown top-level keys because we haven't yet
converted 'device_add' and 'netdev_add' to introspectible use of
'any'.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 scripts/qapi-commands.py | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 7c9cfbf..a586676 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -109,14 +109,28 @@ def gen_marshal_input_visit(arg_type, dealloc=False):
 else:
 ret += mcgen('''
 v = qmp_input_get_visitor(qiv);
+visit_start_struct(v, NULL, NULL, 0, );
+if (err) {
+goto out;
+}
 ''')

-ret += gen_visit_members(arg_type.members, skiperr=dealloc)
+ret += gen_visit_members(arg_type.members, skiperr=dealloc,
+ label='out_obj')

 if dealloc:
 ret += mcgen('''
 qapi_dealloc_visitor_cleanup(qdv);
 ''')
+else:
+ret += mcgen('''
+visit_check_struct(v, );
+out_obj:
+visit_end_struct(v);
+if (err) {
+goto out;
+}
+''')
 return ret


-- 
2.5.0




[Qemu-devel] [PATCH v12 12/18] qmp: Tighten output visitor rules

2016-02-29 Thread Eric Blake
Add a new qmp_output_visitor_reset(), which must be called before
reusing an exising QmpOutputVisitor on a new root object.  Tighten
assertions to require that qmp_output_get_qobject() can only be
called after pairing a visit_end_* for every visit_start_* (rather
than allowing it to return a partially built object), and that it
must not be called unless at least one visit_type_* or visit_start/
visit_end pair has occurred since creation/reset (the accidental
return of NULL fixed by commit ab8bf1d7 would have been much
easier to diagnose).

Also, check that we are encountering the expected object or list
type (both during visit_end*, and also by validating whether 'name'
was NULL - although the latter may need to change later if we
improve error messages by always passing in a sensible name).
This provides protection against mismatched push(struct)/pop(list)
or push(list)/pop(struct), similar to the qmp-input protection
added in commit bdd8e6b5.

Signed-off-by: Eric Blake 

---
v12: rebase to latest, move type_null() into earlier patches,
don't change signature of pop, don't auto-reset after a single
get_qobject
[no v10, v11]
v9: rebase to added patch, squash in more sanity checks, drop
Marc-Andre's R-b
v8: rename qmp_output_reset to qmp_output_visitor_reset
v7: new patch, based on discussion about spapr_drc.c
---
 include/qapi/qmp-output-visitor.h |  1 +
 qapi/qmp-output-visitor.c | 39 +++
 tests/test-qmp-output-visitor.c   |  6 ++
 3 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/include/qapi/qmp-output-visitor.h 
b/include/qapi/qmp-output-visitor.h
index 2266770..5093f0d 100644
--- a/include/qapi/qmp-output-visitor.h
+++ b/include/qapi/qmp-output-visitor.h
@@ -21,6 +21,7 @@ typedef struct QmpOutputVisitor QmpOutputVisitor;

 QmpOutputVisitor *qmp_output_visitor_new(void);
 void qmp_output_visitor_cleanup(QmpOutputVisitor *v);
+void qmp_output_visitor_reset(QmpOutputVisitor *v);

 QObject *qmp_output_get_qobject(QmpOutputVisitor *v);
 Visitor *qmp_output_get_visitor(QmpOutputVisitor *v);
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index 5681ad3..7c48dfb 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -82,9 +82,8 @@ static void qmp_output_add_obj(QmpOutputVisitor *qov, const 
char *name,
 QObject *cur = e ? e->value : NULL;

 if (!cur) {
-/* FIXME we should require the user to reset the visitor, rather
- * than throwing away the previous root */
-qobject_decref(qov->root);
+/* Don't allow reuse of visitor on more than one root */
+assert(!qov->root);
 qov->root = value;
 } else {
 switch (qobject_type(cur)) {
@@ -93,6 +92,9 @@ static void qmp_output_add_obj(QmpOutputVisitor *qov, const 
char *name,
 qdict_put_obj(qobject_to_qdict(cur), name, value);
 break;
 case QTYPE_QLIST:
+/* FIXME: assertion needs adjustment if we fix visit-core
+ * to pass "name.0" style name during lists.  */
+assert(!name);
 qlist_append_obj(qobject_to_qlist(cur), value);
 break;
 default:
@@ -114,7 +116,8 @@ static void qmp_output_start_struct(Visitor *v, const char 
*name, void **obj,
 static void qmp_output_end_struct(Visitor *v, Error **errp)
 {
 QmpOutputVisitor *qov = to_qov(v);
-qmp_output_pop(qov);
+QObject *value = qmp_output_pop(qov);
+assert(qobject_type(value) == QTYPE_QDICT);
 }

 static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
@@ -145,7 +148,8 @@ static GenericList *qmp_output_next_list(Visitor *v, 
GenericList **listp,
 static void qmp_output_end_list(Visitor *v)
 {
 QmpOutputVisitor *qov = to_qov(v);
-qmp_output_pop(qov);
+QObject *value = qmp_output_pop(qov);
+assert(qobject_type(value) == QTYPE_QLIST);
 }

 static void qmp_output_type_int64(Visitor *v, const char *name, int64_t *obj,
@@ -202,18 +206,15 @@ static void qmp_output_type_null(Visitor *v, const char 
*name, Error **errp)
 qmp_output_add_obj(qov, name, qnull());
 }

-/* Finish building, and return the root object. Will not be NULL. */
+/* Finish building, and return the root object. Will not be NULL.
+ * Caller must use qobject_decref() on the result.  */
 QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
 {
-/* FIXME: we should require that a visit occurred, and that it is
- * complete (no starts without a matching end) */
-QObject *obj = qov->root;
-if (obj) {
-qobject_incref(obj);
-} else {
-obj = qnull();
-}
-return obj;
+/* A visit must have occurred, with each start paired with end.  */
+assert(qov->root && !QTAILQ_FIRST(>stack));
+
+qobject_incref(qov->root);
+return qov->root;
 }

 Visitor *qmp_output_get_visitor(QmpOutputVisitor *v)
@@ -221,7 +222,7 @@ Visitor *qmp_output_get_visitor(QmpOutputVisitor *v)
 return 

[Qemu-devel] [PATCH v12 06/18] qmp-input: Refactor when list is advanced

2016-02-29 Thread Eric Blake
Refactor the code to advance the QListEntry pointer at the point
where visit_type_FOO() is called, rather than visit_next_list().
This will allow a future patch to move the visit of the list head
into visit_start_list(), and get rid of the 'first' flag.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 qapi/qmp-input-visitor.c | 40 +---
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 4bb7b21..ed54d4c 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -26,9 +26,10 @@ typedef struct StackObject
 {
 QObject *obj; /* Object being visited */

-/* If obj is list: NULL if list is at head, otherwise tail of list
- * still needing visits */
+/* If obj is list: tail of list still needing visits */
 const QListEntry *entry;
+/* If obj is list: true if head is not visited yet */
+bool first;

 GHashTable *h; /* If obj is dict: remaining keys needing visits */
 } StackObject;
@@ -76,7 +77,12 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
  * of the list.  */
 if (tos->entry) {
 assert(qobject_type(qobj) == QTYPE_QLIST);
-return qlist_entry_obj(tos->entry);
+assert(!tos->first);
+qobj = qlist_entry_obj(tos->entry);
+if (consume) {
+tos->entry = qlist_next(tos->entry);
+}
+return qobj;
 }

 /* Otherwise, we are at the root of the visit or the start of a
@@ -90,7 +96,8 @@ static void qdict_add_key(const char *key, QObject *obj, void 
*opaque)
 g_hash_table_insert(h, (gpointer) key, NULL);
 }

-static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
+static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
+   const QListEntry *entry, Error **errp)
 {
 GHashTable *h;
 StackObject *tos = >stack[qiv->nb_stack];
@@ -102,7 +109,8 @@ static void qmp_input_push(QmpInputVisitor *qiv, QObject 
*obj, Error **errp)
 }

 tos->obj = obj;
-tos->entry = NULL;
+tos->entry = entry;
+tos->first = true;
 tos->h = NULL;

 if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
@@ -152,7 +160,7 @@ static void qmp_input_start_struct(Visitor *v, const char 
*name, void **obj,
 return;
 }

-qmp_input_push(qiv, qobj, );
+qmp_input_push(qiv, qobj, NULL, );
 if (err) {
 error_propagate(errp, err);
 return;
@@ -174,6 +182,7 @@ static void qmp_input_start_list(Visitor *v, const char 
*name, Error **errp)
 {
 QmpInputVisitor *qiv = to_qiv(v);
 QObject *qobj = qmp_input_get_object(qiv, name, true);
+const QListEntry *entry;

 if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -181,7 +190,8 @@ static void qmp_input_start_list(Visitor *v, const char 
*name, Error **errp)
 return;
 }

-qmp_input_push(qiv, qobj, errp);
+entry = qlist_first(qobject_to_qlist(qobj));
+qmp_input_push(qiv, qobj, entry, errp);
 }

 static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
@@ -190,23 +200,15 @@ static GenericList *qmp_input_next_list(Visitor *v, 
GenericList **list,
 QmpInputVisitor *qiv = to_qiv(v);
 GenericList *entry;
 StackObject *so = >stack[qiv->nb_stack - 1];
-bool first;

-if (so->entry == NULL) {
-so->entry = qlist_first(qobject_to_qlist(so->obj));
-first = true;
-} else {
-so->entry = qlist_next(so->entry);
-first = false;
-}
-
-if (so->entry == NULL) {
+if (!so->entry) {
 return NULL;
 }

 entry = g_malloc0(size);
-if (first) {
+if (so->first) {
 *list = entry;
+so->first = false;
 } else {
 (*list)->next = entry;
 }
@@ -381,7 +383,7 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
 v->visitor.type_any = qmp_input_type_any;
 v->visitor.optional = qmp_input_optional;

-qmp_input_push(v, obj, NULL);
+qmp_input_push(v, obj, NULL, NULL);
 qobject_incref(obj);

 return v;
-- 
2.5.0




[Qemu-devel] [PATCH v12 18/18] qapi: Change visit_type_FOO() to no longer return partial objects

2016-02-29 Thread Eric Blake
Returning a partial object on error is an invitation for a careless
caller to leak memory.  As no one outside the testsuite was actually
relying on these semantics, it is cleaner to just document and
guarantee that ALL pointer-based visit_type_FOO() functions always
leave a safe value in *obj during an input visitor (either the new
object on success, or NULL if an error is encountered), so callers
can now unconditionally use qapi_free_FOO() to clean up regardless
of whether an error occurred.

The decision is done by enhancing qapi-visit-core to return true
for input visitors (the callbacks themselves do not need
modification); since we've documented that visit_end_* must be
called after any successful visit_start_*, that is a sufficient
point for knowing that something was allocated during start.

Note that we still leave *obj unchanged after a scalar-based
visit_type_FOO(); I did not feel like auditing all uses of
visit_type_Enum() to see if the callers would tolerate a specific
sentinel value (not to mention having to decide whether it would
be better to use 0 or ENUM__MAX as that sentinel).

Signed-off-by: Eric Blake 

---
v12: rebase to latest, don't modify callback signatures, use newer
approach for detecting input visitors, avoid 'allocated' boolean
[no v10, v11]
v9: fix bug in use of errp
v8: rebase to earlier changes
v7: rebase to earlier changes, enhance commit message, also fix
visit_type_str() and visit_type_any()
v6: rebase on top of earlier doc and formatting improvements, mention
that *obj can be uninitialized on entry to an input visitor, rework
semantics to keep valgrind happy on uninitialized input, break some
long lines
---
 include/qapi/visitor.h | 40 ++--
 include/qapi/visitor-impl.h|  8 +---
 scripts/qapi-visit.py  | 25 +
 qapi/qapi-visit-core.c | 41 ++---
 tests/test-qmp-commands.c  | 13 ++---
 tests/test-qmp-input-strict.c  | 19 ---
 tests/test-qmp-input-visitor.c | 10 ++
 docs/qapi-code-gen.txt | 10 --
 8 files changed, 106 insertions(+), 60 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index a81878d..f676991 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -66,14 +66,16 @@
  * }' if an error is encountered on "value" (or to have the visitor
  * core auto-generate the nicer name).
  *
- * FIXME: At present, input visitors may allocate an incomplete *@obj
- * even when visit_type_FOO() reports an error.  Using an output
- * visitor with an incomplete object has undefined behavior; callers
- * must call qapi_free_FOO() (which uses the dealloc visitor, and
- * safely handles an incomplete object) to avoid a memory leak.
+ * If an error is detected during visit_type_FOO() with an input
+ * visitor, then *@obj will be NULL for pointer types, and left
+ * unchanged for scalar types.  Using an output visitor with an
+ * incomplete object has undefined behavior (other than a special case
+ * for visit_type_str() treating NULL like ""), while the dealloc
+ * visitor safely handles incomplete objects.
  *
- * Likewise, the QAPI object types (structs, unions, and alternates)
- * have a generated function in qapi-visit.h compatible with:
+ * Additionally, the QAPI object types (structs, unions, and
+ * alternates) have a generated function in qapi-visit.h compatible
+ * with:
  *
  * void visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp);
  *
@@ -256,8 +258,14 @@ void visit_check_struct(Visitor *v, Error **errp);
  * even if intermediate processing was skipped due to errors, to allow
  * the backend to release any resources.  Destroying the visitor may
  * behave as if this was implicitly called.
+ *
+ * Returns true if this is an input visitor (that is, an allocation
+ * occurred during visit_start_struct() if obj was non-NULL).  The
+ * caller can use this, along with tracking whether a local error
+ * occurred in the meantime, to decide when to undo allocation before
+ * returning control from a visit_type_FOO() function.
  */
-void visit_end_struct(Visitor *v);
+bool visit_end_struct(Visitor *v);


 /* === Visiting lists */
@@ -313,8 +321,14 @@ GenericList *visit_next_list(Visitor *v, GenericList 
*tail, size_t size);
  * even if intermediate processing was skipped due to errors, to allow
  * the backend to release any resources.  Destroying the visitor may
  * behave as if this was implicitly called.
+ *
+ * Returns true if this is an input visitor (that is, an allocation
+ * occurred during visit_start_list() if list was non-NULL).  The
+ * caller can use this, along with tracking whether a local error
+ * occurred in the meantime, to decide when to undo allocation before
+ * returning control from a visit_type_FOO() function.
  */
-void visit_end_list(Visitor *v);
+bool visit_end_list(Visitor *v);


 /* === Visiting alternates */
@@ 

[Qemu-devel] [PATCH v12 08/18] tests: Add check-qnull

2016-02-29 Thread Eric Blake
Add a new test, for checking reference counting of qnull(). As
part of the new file, move a previous reference counting change
added in commit a861564 into a more logical place.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 tests/check-qnull.c | 60 +
 tests/test-qmp-output-visitor.c |  2 --
 tests/.gitignore|  1 +
 tests/Makefile  |  6 -
 4 files changed, 66 insertions(+), 3 deletions(-)
 create mode 100644 tests/check-qnull.c

diff --git a/tests/check-qnull.c b/tests/check-qnull.c
new file mode 100644
index 000..b0fb1e6
--- /dev/null
+++ b/tests/check-qnull.c
@@ -0,0 +1,60 @@
+/*
+ * QNull unit-tests.
+ *
+ * Copyright (C) 2016 Red Hat Inc.
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include 
+
+#include "qapi/qmp/qobject.h"
+#include "qemu-common.h"
+#include "qapi/qmp-output-visitor.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qnull_ref_test(void)
+{
+QObject *obj;
+
+g_assert(qnull_.refcnt == 1);
+obj = qnull();
+g_assert(obj);
+g_assert(obj == _);
+g_assert(qnull_.refcnt == 2);
+g_assert(qobject_type(obj) == QTYPE_QNULL);
+qobject_decref(obj);
+g_assert(qnull_.refcnt == 1);
+}
+
+static void qnull_visit_test(void)
+{
+QObject *obj;
+QmpOutputVisitor *qov;
+
+g_assert(qnull_.refcnt == 1);
+qov = qmp_output_visitor_new();
+/* FIXME: Empty visits are ugly, we should have a visit_type_null(). */
+obj = qmp_output_get_qobject(qov);
+g_assert(obj == _);
+qobject_decref(obj);
+
+qmp_output_visitor_cleanup(qov);
+g_assert(qnull_.refcnt == 1);
+}
+
+int main(int argc, char **argv)
+{
+g_test_init(, , NULL);
+
+g_test_add_func("/public/qnull_ref", qnull_ref_test);
+g_test_add_func("/public/qnull_visit", qnull_visit_test);
+
+return g_test_run();
+}
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index dc35752..81c90bc 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -483,8 +483,6 @@ static void test_visitor_out_empty(TestOutputVisitorData 
*data,

 arg = qmp_output_get_qobject(data->qov);
 g_assert(qobject_type(arg) == QTYPE_QNULL);
-/* Check that qnull reference counting is sane */
-g_assert(arg->refcnt == 2);
 qobject_decref(arg);
 }

diff --git a/tests/.gitignore b/tests/.gitignore
index 787c95c..615f96d 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -3,6 +3,7 @@ check-qfloat
 check-qint
 check-qjson
 check-qlist
+check-qnull
 check-qstring
 check-qom-interface
 check-qom-proplist
diff --git a/tests/Makefile b/tests/Makefile
index cd4bbd4..b0a4f8e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -16,6 +16,8 @@ check-unit-y += tests/check-qstring$(EXESUF)
 gcov-files-check-qstring-y = qobject/qstring.c
 check-unit-y += tests/check-qlist$(EXESUF)
 gcov-files-check-qlist-y = qobject/qlist.c
+check-unit-y += tests/check-qnull$(EXESUF)
+gcov-files-check-qnull-y = qobject/qnull.c
 check-unit-y += tests/check-qjson$(EXESUF)
 gcov-files-check-qjson-y = qobject/qjson.c
 check-unit-y += tests/test-qmp-output-visitor$(EXESUF)
@@ -371,7 +373,8 @@ GENERATED_HEADERS += tests/test-qapi-types.h 
tests/test-qapi-visit.h \
tests/test-qmp-introspect.h

 test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
-   tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
+   tests/check-qlist.o tests/check-qfloat.o tests/check-qnull.o \
+   tests/check-qjson.o \
tests/test-coroutine.o tests/test-string-output-visitor.o \
tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
@@ -399,6 +402,7 @@ tests/check-qstring$(EXESUF): tests/check-qstring.o 
$(test-util-obj-y)
 tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
 tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
 tests/check-qfloat$(EXESUF): tests/check-qfloat.o $(test-util-obj-y)
+tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
 tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
 tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o 
$(test-qom-obj-y)
 tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
-- 
2.5.0




[Qemu-devel] [PATCH v12 09/18] qapi: Add visit_type_null() visitor

2016-02-29 Thread Eric Blake
Right now, qmp-output-visitor happens to produce a QNull result
if nothing is actually visited between the creation of the visitor
and the request for the resulting QObject.  A stronger protocol
would require that a QMP output visit MUST visit something.  But
to still be able to produce a JSON 'null' output, we need a new
visitor function that states our intentions.  Yes, we could say
that such a visit must go through visit_type_any(), but that
feels clunky.

So this patch introduces the new visit_type_null() interface and
its no-op interface in the dealloc visitor, and the next patch
will then wire it up into the qmp visitors.  For the visitors
that will not implement the callback, document the situation.
The code in qapi-visit-core unconditionally dereferences the
callback pointer, so that a segfault will inform a developer if
they need to implement the callback for their choice of visitor.

If QAPI had a 'null' type, we'd also have to use visit_type_null()
in the generated visitor functions (most likely, we'd use it via
an alternate type that permits 'null' or an object); we'll create
that usage when we need it.

Signed-off-by: Eric Blake 

---
v12: rebase to earlier changes, drop R-b due to better documentation
[no v10, v11]
v9: no change
v8: rebase to 'name' motion
v7: new patch, based on discussion about spapr_drc.c
---
 include/qapi/visitor.h   | 12 
 include/qapi/visitor-impl.h  |  3 +++
 include/qapi/opts-visitor.h  |  2 +-
 include/qapi/string-input-visitor.h  |  2 +-
 include/qapi/string-output-visitor.h |  2 +-
 qapi/qapi-visit-core.c   |  5 +
 qapi/qapi-dealloc-visitor.c  |  5 +
 7 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 33ae28a..2b85c6f 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -507,4 +507,16 @@ void visit_type_number(Visitor *v, const char *name, 
double *obj,
  */
 void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp);

+/*
+ * Visit a JSON null value.
+ *
+ * @name expresses the relationship of the null value to its parent
+ * container; see the general description of @name above.
+ *
+ * Unlike all other visit_type_* functions, no obj parameter is
+ * needed; rather, this is a witness that an explicit null value is
+ * expected rather than any other type.
+ */
+void visit_type_null(Visitor *v, const char *name, Error **errp);
+
 #endif
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index d967b18..90bcaec 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -86,6 +86,9 @@ struct Visitor
 void (*type_any)(Visitor *v, const char *name, QObject **obj,
  Error **errp);

+/* Must be set to visit explicit null values.  */
+void (*type_null)(Visitor *v, const char *name, Error **errp);
+
 /* Must be set for input visitors, optional otherwise.  The core
  * takes care of the return type in the public interface.  */
 void (*optional)(Visitor *v, const char *name, bool *present);
diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h
index 2002e37..3fcd327 100644
--- a/include/qapi/opts-visitor.h
+++ b/include/qapi/opts-visitor.h
@@ -31,7 +31,7 @@ typedef struct OptsVisitor OptsVisitor;
  * - values above INT64_MAX or LLONG_MAX are rejected.
  *
  * The Opts input visitor does not yet implement support for visiting
- * QAPI alternates, numbers (other than integers), or arbitrary
+ * QAPI alternates, numbers (other than integers), null, or arbitrary
  * QTypes.
  */
 OptsVisitor *opts_visitor_new(const QemuOpts *opts);
diff --git a/include/qapi/string-input-visitor.h 
b/include/qapi/string-input-visitor.h
index 4c8d1ea..1a34c52 100644
--- a/include/qapi/string-input-visitor.h
+++ b/include/qapi/string-input-visitor.h
@@ -19,7 +19,7 @@ typedef struct StringInputVisitor StringInputVisitor;

 /*
  * The string input visitor does not yet implement support for
- * visiting QAPI structs, alternates, or arbitrary QTypes.
+ * visiting QAPI structs, alternates, null, or arbitrary QTypes.
  */
 StringInputVisitor *string_input_visitor_new(const char *str);
 void string_input_visitor_cleanup(StringInputVisitor *v);
diff --git a/include/qapi/string-output-visitor.h 
b/include/qapi/string-output-visitor.h
index 094a11e..2564833 100644
--- a/include/qapi/string-output-visitor.h
+++ b/include/qapi/string-output-visitor.h
@@ -19,7 +19,7 @@ typedef struct StringOutputVisitor StringOutputVisitor;

 /*
  * The string output visitor does not yet implement support for
- * visiting QAPI structs, alternates, or arbitrary QTypes.
+ * visiting QAPI structs, alternates, null, or arbitrary QTypes.
  */
 StringOutputVisitor *string_output_visitor_new(bool human);
 void string_output_visitor_cleanup(StringOutputVisitor *v);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 1388462..116c627 

[Qemu-devel] [PATCH v12 02/18] qapi: Guarantee NULL obj on input visitor callback error

2016-02-29 Thread Eric Blake
Our existing input visitors were not very consistent on errors
in a function taking 'TYPE **obj'. While all of them set '*obj'
to allocated storage on success, it was not obvious whether
'*obj' was guaranteed safe on failure, or whether it was left
uninitialized.  But a future patch wants to guarantee that
visit_type_FOO() does not leak a partially-constructed obj back
to the caller; it is easier to implement this if we can reliably
state that '*obj' is assigned on exit, even on failures.

The opts-visitor start_struct() doesn't set an error, but it
also was doing a weird check for 0 size; all callers pass in
non-zero size if obj is non-NULL.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 qapi/opts-visitor.c | 3 ++-
 qapi/qmp-input-visitor.c| 4 
 qapi/string-input-visitor.c | 1 +
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index f9a2346..fd90608 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -132,7 +132,7 @@ opts_start_struct(Visitor *v, const char *name, void **obj,
 const QemuOpt *opt;

 if (obj) {
-*obj = g_malloc0(size > 0 ? size : 1);
+*obj = g_malloc0(size);
 }
 if (ov->depth++ > 0) {
 return;
@@ -313,6 +313,7 @@ opts_type_str(Visitor *v, const char *name, char **obj, 
Error **errp)

 opt = lookup_scalar(ov, name, errp);
 if (!opt) {
+*obj = NULL;
 return;
 }
 *obj = g_strdup(opt->str ? opt->str : "");
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 03dcb65..550aed6 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -119,6 +119,9 @@ static void qmp_input_start_struct(Visitor *v, const char 
*name, void **obj,
 QObject *qobj = qmp_input_get_object(qiv, name, true);
 Error *err = NULL;

+if (obj) {
+*obj = NULL;
+}
 if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"QDict");
@@ -266,6 +269,7 @@ static void qmp_input_type_str(Visitor *v, const char 
*name, char **obj,
 QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true));

 if (!qstr) {
+*obj = NULL;
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"string");
 return;
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index d591e67..4087bf9 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -292,6 +292,7 @@ static void parse_type_str(Visitor *v, const char *name, 
char **obj,
 if (siv->string) {
 *obj = g_strdup(siv->string);
 } else {
+*obj = NULL;
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"string");
 }
-- 
2.5.0




[Qemu-devel] [PATCH v12 11/18] spapr_drc: Expose 'null' in qom-get when there is no fdt

2016-02-29 Thread Eric Blake
Now that the QMP output visitor supports an explicit null
output, we should utilize it to make it easier to diagnose
the difference between a missing fdt ('null') vs. a
present-but-empty one ('{}').

(Note that this reverts the behavior of commit ab8bf1d, taking
us back to the behavior of commit 6c2f9a1 [which in turn
stemmed from a crash fix in 1d10b44]; but that this time,
the change is intentional and not an accidental side-effect.)

Signed-off-by: Eric Blake 
Acked-by: David Gibson 

---
v12: tweak commit message
[no v10, v11]
v9: improved commit message
v8: rebase to 'name' motion
v7: new patch, based on discussion about spapr_drc.c
---
 hw/ppc/spapr_drc.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index ef063c0..b1bf193 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -260,11 +260,7 @@ static void prop_get_fdt(Object *obj, Visitor *v, const 
char *name,
 void *fdt;

 if (!drc->fdt) {
-visit_start_struct(v, name, NULL, 0, );
-if (!err) {
-visit_end_struct(v, );
-}
-error_propagate(errp, err);
+visit_type_null(v, NULL, errp);
 return;
 }

-- 
2.5.0




[Qemu-devel] [PATCH v12 10/18] qmp: Support explicit null during visits

2016-02-29 Thread Eric Blake
Implement the new type_null() callback for the qmp input and
output visitors. While we don't yet have a use for this in QAPI
input (the generator will need some tweaks first), one usage
is already envisioned: when changing blockdev parameters, it
would be nice to have a difference between leaving a tuning
parameter unchanged (omit that parameter from the struct) and
to explicitly reset the parameter to its default without having
to know what the default value is (specify the parameter with
an explicit null value, which will require us to allow a QAPI
alternate that chooses between the normal value and an explicit
null).  Meanwhile, the output visitor could already output
explicit null via type_any, but this gives us finer control.

At any rate, it's easy to test that we can round-trip an explicit
null through manual use of visit_type_null().  Repurpose the
test_visitor_out_empty test, particularly since a future patch
will tighten semantics to forbid immediate use of
qmp_output_get_qobject() without at least one visit_type_*.

Signed-off-by: Eric Blake 

---
v12: retitle and merge in output visitor support, move refcount
tests to separate file
[no v10, v11]
v9: new patch
---
 qapi/qmp-input-visitor.c| 12 
 qapi/qmp-output-visitor.c   |  7 +++
 tests/check-qnull.c | 10 +-
 tests/test-qmp-input-visitor.c  | 16 
 tests/test-qmp-output-visitor.c |  9 +
 5 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index ed54d4c..faa40e7 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -338,6 +338,17 @@ static void qmp_input_type_any(Visitor *v, const char 
*name, QObject **obj,
 *obj = qobj;
 }

+static void qmp_input_type_null(Visitor *v, const char *name, Error **errp)
+{
+QmpInputVisitor *qiv = to_qiv(v);
+QObject *qobj = qmp_input_get_object(qiv, name, true);
+
+if (qobject_type(qobj) != QTYPE_QNULL) {
+error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+   "null");
+}
+}
+
 static void qmp_input_optional(Visitor *v, const char *name, bool *present)
 {
 QmpInputVisitor *qiv = to_qiv(v);
@@ -381,6 +392,7 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
 v->visitor.type_str = qmp_input_type_str;
 v->visitor.type_number = qmp_input_type_number;
 v->visitor.type_any = qmp_input_type_any;
+v->visitor.type_null = qmp_input_type_null;
 v->visitor.optional = qmp_input_optional;

 qmp_input_push(v, obj, NULL, NULL);
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index 1f2a7ba..5681ad3 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -196,6 +196,12 @@ static void qmp_output_type_any(Visitor *v, const char 
*name, QObject **obj,
 qmp_output_add_obj(qov, name, *obj);
 }

+static void qmp_output_type_null(Visitor *v, const char *name, Error **errp)
+{
+QmpOutputVisitor *qov = to_qov(v);
+qmp_output_add_obj(qov, name, qnull());
+}
+
 /* Finish building, and return the root object. Will not be NULL. */
 QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
 {
@@ -246,6 +252,7 @@ QmpOutputVisitor *qmp_output_visitor_new(void)
 v->visitor.type_str = qmp_output_type_str;
 v->visitor.type_number = qmp_output_type_number;
 v->visitor.type_any = qmp_output_type_any;
+v->visitor.type_null = qmp_output_type_null;

 QTAILQ_INIT(>stack);

diff --git a/tests/check-qnull.c b/tests/check-qnull.c
index b0fb1e6..e16c783 100644
--- a/tests/check-qnull.c
+++ b/tests/check-qnull.c
@@ -11,6 +11,7 @@

 #include "qapi/qmp/qobject.h"
 #include "qemu-common.h"
+#include "qapi/qmp-input-visitor.h"
 #include "qapi/qmp-output-visitor.h"

 /*
@@ -37,15 +38,22 @@ static void qnull_visit_test(void)
 {
 QObject *obj;
 QmpOutputVisitor *qov;
+QmpInputVisitor *qiv;

 g_assert(qnull_.refcnt == 1);
+obj = qnull();
+qiv = qmp_input_visitor_new(obj);
+qobject_decref(obj);
+visit_type_null(qmp_input_get_visitor(qiv), NULL, _abort);
+
 qov = qmp_output_visitor_new();
-/* FIXME: Empty visits are ugly, we should have a visit_type_null(). */
+visit_type_null(qmp_output_get_visitor(qov), NULL, _abort);
 obj = qmp_output_get_qobject(qov);
 g_assert(obj == _);
 qobject_decref(obj);

 qmp_output_visitor_cleanup(qov);
+qmp_input_visitor_cleanup(qiv);
 g_assert(qnull_.refcnt == 1);
 }

diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 5941e90..46fa1b9 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -278,6 +278,20 @@ static void test_visitor_in_any(TestInputVisitorData *data,
 qobject_decref(res);
 }

+static void test_visitor_in_null(TestInputVisitorData *data,
+ const void *unused)
+{
+Visitor *v;
+
+v = visitor_input_test_init(data, "null");
+

[Qemu-devel] [PATCH v12 04/18] qmp-input: Clean up stack handling

2016-02-29 Thread Eric Blake
Management of the top of stack was a bit verbose; creating a
temporary variable and adding some comments makes the existing
code more legible before the next few patches improve things.
No semantic changes other than asserting that we are always
visiting a QObject, and not a NULL value.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 qapi/qmp-input-visitor.c | 52 ++--
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 550aed6..7428d15 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -24,16 +24,26 @@

 typedef struct StackObject
 {
-QObject *obj;
+QObject *obj; /* Object being visited */
+
+/* If obj is list: NULL if list is at head, otherwise tail of list
+ * still needing visits */
 const QListEntry *entry;
-GHashTable *h;
+
+GHashTable *h; /* If obj is dict: remaining keys needing visits */
 } StackObject;

 struct QmpInputVisitor
 {
 Visitor visitor;
+
+/* Stack of objects being visited.  stack[0] is root of visit,
+ * stack[1] and below correspond to visit_start_struct (nested
+ * QDict) and visit_start_list (nested QList).  */
 StackObject stack[QIV_STACK_SIZE];
 int nb_stack;
+
+/* True to track whether all keys in QDict have been parsed.  */
 bool strict;
 };

@@ -46,19 +56,29 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
  const char *name,
  bool consume)
 {
-QObject *qobj = qiv->stack[qiv->nb_stack - 1].obj;
+StackObject *tos = >stack[qiv->nb_stack - 1];
+QObject *qobj = tos->obj;

-if (qobj) {
-if (name && qobject_type(qobj) == QTYPE_QDICT) {
-if (qiv->stack[qiv->nb_stack - 1].h && consume) {
-g_hash_table_remove(qiv->stack[qiv->nb_stack - 1].h, name);
-}
-return qdict_get(qobject_to_qdict(qobj), name);
-} else if (qiv->stack[qiv->nb_stack - 1].entry) {
-return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
+assert(qobj);
+
+/* If we have a name, and we're in a dictionary, then return that
+ * value. */
+if (name && qobject_type(qobj) == QTYPE_QDICT) {
+if (tos->h && consume) {
+g_hash_table_remove(tos->h, name);
 }
+return qdict_get(qobject_to_qdict(qobj), name);
 }

+/* If we are in the middle of a list, then return the next element
+ * of the list.  */
+if (tos->entry) {
+assert(qobject_type(qobj) == QTYPE_QLIST);
+return qlist_entry_obj(tos->entry);
+}
+
+/* Otherwise, we are at the root of the visit or the start of a
+ * list, and return the object as-is.  */
 return qobj;
 }

@@ -71,20 +91,22 @@ static void qdict_add_key(const char *key, QObject *obj, 
void *opaque)
 static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
 {
 GHashTable *h;
+StackObject *tos = >stack[qiv->nb_stack];

+assert(obj);
 if (qiv->nb_stack >= QIV_STACK_SIZE) {
 error_setg(errp, "An internal buffer overran");
 return;
 }

-qiv->stack[qiv->nb_stack].obj = obj;
-qiv->stack[qiv->nb_stack].entry = NULL;
-qiv->stack[qiv->nb_stack].h = NULL;
+tos->obj = obj;
+tos->entry = NULL;
+tos->h = NULL;

 if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
 h = g_hash_table_new(g_str_hash, g_str_equal);
 qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
-qiv->stack[qiv->nb_stack].h = h;
+tos->h = h;
 }

 qiv->nb_stack++;
-- 
2.5.0




[Qemu-devel] [PATCH v12 01/18] qapi-visit: Add visitor.type classification

2016-02-29 Thread Eric Blake
We have three classes of QAPI visitors: input, output, and dealloc.
Currently, all implementations of these visitors have one thing in
common based on their visitor type: the implementation used for the
visit_type_enum() callback.  But since we plan to add more such
common behavior, in relation to documenting and further refining
the semantics, it makes more sense to have the visitor
implementations advertise which class they belong to, so the common
qapi-visit-core code can use that information in multiple places.

For this patch, knowing the class of a visitor implementation lets
us make input_type_enum() and output_type_enum() become static
functions, by replacing the callback function Visitor.type_enum()
with the simpler enum field Visitor.type.  Share a common assertion
in qapi-visit-core as part of the refactoring.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 include/qapi/visitor-impl.h  | 21 -
 qapi/qapi-visit-core.c   | 28 +++-
 qapi/opts-visitor.c  | 12 ++--
 qapi/qapi-dealloc-visitor.c  |  7 +--
 qapi/qmp-input-visitor.c |  2 +-
 qapi/qmp-output-visitor.c|  2 +-
 qapi/string-input-visitor.c  |  2 +-
 qapi/string-output-visitor.c |  2 +-
 8 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 2bd8f29..228a2a6 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -14,6 +14,15 @@

 #include "qapi/visitor.h"

+/* There are three classes of visitors; setting the class determines
+ * how QAPI enums are visited, as well as what additional restrictions
+ * can be asserted.  */
+typedef enum VisitorType {
+VISITOR_INPUT,
+VISITOR_OUTPUT,
+VISITOR_DEALLOC,
+} VisitorType;
+
 struct Visitor
 {
 /* Must be set */
@@ -36,10 +45,6 @@ struct Visitor
 void (*end_alternate)(Visitor *v);

 /* Must be set. */
-void (*type_enum)(Visitor *v, const char *name, int *obj,
-  const char *const strings[], Error **errp);
-
-/* Must be set. */
 void (*type_int64)(Visitor *v, const char *name, int64_t *obj,
Error **errp);
 /* Must be set. */
@@ -58,11 +63,9 @@ struct Visitor

 /* May be NULL; most useful for input visitors. */
 void (*optional)(Visitor *v, const char *name, bool *present);
+
+/* Must be set.  */
+VisitorType type;
 };

-void input_type_enum(Visitor *v, const char *name, int *obj,
- const char *const strings[], Error **errp);
-void output_type_enum(Visitor *v, const char *name, int *obj,
-  const char *const strings[], Error **errp);
-
 #endif
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 856606b..a08d073 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -71,12 +71,6 @@ bool visit_optional(Visitor *v, const char *name, bool 
*present)
 return *present;
 }

-void visit_type_enum(Visitor *v, const char *name, int *obj,
- const char *const strings[], Error **errp)
-{
-v->type_enum(v, name, obj, strings, errp);
-}
-
 void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
 {
 v->type_int64(v, name, obj, errp);
@@ -207,14 +201,13 @@ void visit_type_any(Visitor *v, const char *name, QObject 
**obj, Error **errp)
 v->type_any(v, name, obj, errp);
 }

-void output_type_enum(Visitor *v, const char *name, int *obj,
-  const char *const strings[], Error **errp)
+static void output_type_enum(Visitor *v, const char *name, int *obj,
+ const char *const strings[], Error **errp)
 {
 int i = 0;
 int value = *obj;
 char *enum_str;

-assert(strings);
 while (strings[i++] != NULL);
 if (value < 0 || value >= i - 1) {
 error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
@@ -225,15 +218,13 @@ void output_type_enum(Visitor *v, const char *name, int 
*obj,
 visit_type_str(v, name, _str, errp);
 }

-void input_type_enum(Visitor *v, const char *name, int *obj,
- const char *const strings[], Error **errp)
+static void input_type_enum(Visitor *v, const char *name, int *obj,
+const char *const strings[], Error **errp)
 {
 Error *local_err = NULL;
 int64_t value = 0;
 char *enum_str;

-assert(strings);
-
 visit_type_str(v, name, _str, _err);
 if (local_err) {
 error_propagate(errp, local_err);
@@ -256,3 +247,14 @@ void input_type_enum(Visitor *v, const char *name, int 
*obj,
 g_free(enum_str);
 *obj = value;
 }
+
+void visit_type_enum(Visitor *v, const char *name, int *obj,
+ const char *const strings[], Error **errp)
+{
+assert(strings);
+if (v->type == VISITOR_INPUT) {
+input_type_enum(v, name, obj, strings, errp);
+} else if (v->type == VISITOR_OUTPUT) {
+output_type_enum(v, 

[Qemu-devel] [PATCH v12 07/18] qapi: Document visitor interfaces, add assertions

2016-02-29 Thread Eric Blake
The visitor interface for mapping between QObject/QemuOpts/string
and QAPI is scandalously under-documented, making changes to visitor
core, individual visitors, and users of visitors difficult to
coordinate.  Among other questions: when is it safe to pass NULL,
vs. when a string must be provided; which visitors implement which
callbacks; the difference between concrete and virtual visits.

Correct this by retrofitting proper contracts, and document where some
of the interface warts remain (for example, we may want to modify
visit_end_* to require the same 'obj' as the visit_start counterpart,
so the dealloc visitor can be simplified).  Later patches in this
series will tackle some, but not all, of these warts.

Add assertions to (partially) enforce the contract.  Some of these
were only made possible by recent cleanup commits.

Signed-off-by: Eric Blake 

---
v12: major rework based on Markus' comments, drop R-b
[no v10, v11]
v9: no change
v8: rebase to 'name' motion
v7: retitle; more wording changes, add asserts to enforce the
wording, place later in series to rebase on fixes that would
otherwise trip the new assertions
v6: mention that input visitors blindly assign over *obj; wording
improvements
---
 include/qapi/visitor.h   | 428 +--
 include/qapi/visitor-impl.h  |  42 +++-
 include/qapi/dealloc-visitor.h   |   4 +
 include/qapi/opts-visitor.h  |   4 +
 include/qapi/qmp-input-visitor.h |   8 +
 include/qapi/string-input-visitor.h  |   4 +
 include/qapi/string-output-visitor.h |   4 +
 qapi/qapi-visit-core.c   |  19 +-
 8 files changed, 491 insertions(+), 22 deletions(-)

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 1000da2..33ae28a 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -17,8 +17,185 @@
 #include "qemu/typedefs.h"
 #include "qapi/qmp/qobject.h"

+/*
+ * The QAPI schema defines both a set of C data types, and a QMP wire
+ * format.  A QAPI object is formed as a directed acyclic graph of
+ * QAPI values.  QAPI also generates visitor functions to walk these
+ * graphs.  This file represents the interface for doing work at each
+ * point of a QAPI graph; it can also be used for a virtual walk,
+ * where there is no actual QAPI C struct.
+ *
+ * There are three kinds of visitor classes: input visitors parse an
+ * external representation and allocate the corresponding QAPI graph
+ * (QMP, string, and QemuOpts), output visitors take a completed QAPI
+ * graph and generate an external representation (QMP and string), and
+ * the dealloc visitor can take a (partial) QAPI graph and recursively
+ * free its resources.  While the dealloc and QMP input/output
+ * visitors are general, the string and QemuOpts visitors have some
+ * implementation limitations; see the documentation for each visitor
+ * for more details on what it supports.  Also, see visitor-impl.h for
+ * the callback contracts implemented by each visitor, and
+ * docs/qapi-code-gen.txt for more about the QAPI code generator.
+ *
+ * All QAPI types have a corresponding function with a signature
+ * roughly compatible with this:
+ *
+ * void visit_type_FOO(Visitor *v, const char *name, void *obj, Error **errp);
+ *
+ * except that *@obj is typed correctly as a pointer or scalar,
+ * depending on the type of FOO.  The scalar visitors are declared
+ * here; the remaining visitors are generated in qapi-visit.h.
+ *
+ * The @name parameter of visit_type_FOO() describes the relation
+ * between this QAPI value and its parent container.  When visiting
+ * the root of a tree, @name is usually ignored (although some
+ * visitors require it to be NULL); when visiting a member of an
+ * object, @name is the key associated with the value; and when
+ * visiting a member of a list, @name is NULL.
+ *
+ * The visit_type_FOO() functions expect a non-NULL @obj argument;
+ * they allocate *@obj during input visits, leave it unchanged on
+ * output visits, and recursively free any resources during a dealloc
+ * visit.  Each function also has an @errp argument which may be NULL
+ * to ignore errors, or point to a NULL Error object on entry for
+ * reporting any errors (such as if a member @name is not present, or
+ * is present but not the specified type).
+ *
+ * FIXME: Clients must pass NULL for @name when visiting a member of a
+ * list, but this leads to poor error messages; it might be nicer to
+ * require a non-NULL name such as "key.0" for '{ "key": [ "value" ]
+ * }' if an error is encountered on "value" (or to have the visitor
+ * core auto-generate the nicer name).
+ *
+ * FIXME: At present, input visitors may allocate an incomplete *@obj
+ * even when visit_type_FOO() reports an error.  Using an output
+ * visitor with an incomplete object has undefined behavior; callers
+ * must call qapi_free_FOO() (which uses the dealloc visitor, and
+ * safely handles an incomplete object) to avoid a memory leak.
+ *
+ * 

[Qemu-devel] [PATCH v12 03/18] qmp: Drop dead command->type

2016-02-29 Thread Eric Blake
Ever since QMP was first added back in commit 43c20a43, we have
never had any QmpCommandType other than QCT_NORMAL.  It's
pointless to carry around the cruft.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 include/qapi/qmp/dispatch.h |  6 --
 qapi/qmp-dispatch.c | 18 +++---
 qapi/qmp-registry.c |  1 -
 3 files changed, 7 insertions(+), 18 deletions(-)

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 4955209..5609946 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -19,11 +19,6 @@

 typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);

-typedef enum QmpCommandType
-{
-QCT_NORMAL,
-} QmpCommandType;
-
 typedef enum QmpCommandOptions
 {
 QCO_NO_OPTIONS = 0x0,
@@ -33,7 +28,6 @@ typedef enum QmpCommandOptions
 typedef struct QmpCommand
 {
 const char *name;
-QmpCommandType type;
 QmpCommandFunc *fn;
 QmpCommandOptions options;
 QTAILQ_ENTRY(QmpCommand) node;
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 8f27c34..072e092 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -93,17 +93,13 @@ static QObject *do_qmp_dispatch(QObject *request, Error 
**errp)
 QINCREF(args);
 }

-switch (cmd->type) {
-case QCT_NORMAL:
-cmd->fn(args, , _err);
-if (local_err) {
-error_propagate(errp, local_err);
-} else if (cmd->options & QCO_NO_SUCCESS_RESP) {
-g_assert(!ret);
-} else if (!ret) {
-ret = QOBJECT(qdict_new());
-}
-break;
+cmd->fn(args, , _err);
+if (local_err) {
+error_propagate(errp, local_err);
+} else if (cmd->options & QCO_NO_SUCCESS_RESP) {
+g_assert(!ret);
+} else if (!ret) {
+ret = QOBJECT(qdict_new());
 }

 QDECREF(args);
diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c
index 4ebfbcc..4332a68 100644
--- a/qapi/qmp-registry.c
+++ b/qapi/qmp-registry.c
@@ -25,7 +25,6 @@ void qmp_register_command(const char *name, QmpCommandFunc 
*fn,
 QmpCommand *cmd = g_malloc0(sizeof(*cmd));

 cmd->name = name;
-cmd->type = QCT_NORMAL;
 cmd->fn = fn;
 cmd->enabled = true;
 cmd->options = options;
-- 
2.5.0




[Qemu-devel] [PATCH v12 05/18] qmp-input: Don't consume input when checking has_member

2016-02-29 Thread Eric Blake
Commit e8316d7 mistakenly passed consume=true when checking if
an optional member was present, but the mistake was silently
ignored since the code happily let us extract a member more than
once.  Tighten up the input visitor to ensure that a member is
consumed exactly once.  To keep the testsuite happy in the case
of incomplete input, we have to check whether a member exists
in the dictionary before trying to remove it.

Signed-off-by: Eric Blake 

---
v12: new patch
---
 qapi/qmp-input-visitor.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 7428d15..4bb7b21 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -64,10 +64,12 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
 /* If we have a name, and we're in a dictionary, then return that
  * value. */
 if (name && qobject_type(qobj) == QTYPE_QDICT) {
-if (tos->h && consume) {
-g_hash_table_remove(tos->h, name);
+qobj = qdict_get(qobject_to_qdict(qobj), name);
+if (tos->h && consume && qobj) {
+bool removed = g_hash_table_remove(tos->h, name);
+assert(removed);
 }
-return qdict_get(qobject_to_qdict(qobj), name);
+return qobj;
 }

 /* If we are in the middle of a list, then return the next element
@@ -337,7 +339,7 @@ static void qmp_input_type_any(Visitor *v, const char 
*name, QObject **obj,
 static void qmp_input_optional(Visitor *v, const char *name, bool *present)
 {
 QmpInputVisitor *qiv = to_qiv(v);
-QObject *qobj = qmp_input_get_object(qiv, name, true);
+QObject *qobj = qmp_input_get_object(qiv, name, false);

 if (!qobj) {
 *present = false;
-- 
2.5.0




[Qemu-devel] [PATCH v12 00/18] qapi visitor cleanups (post-introspection cleanups subset E)

2016-02-29 Thread Eric Blake
Requires these patches first:
https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg06079.html

v12: This series (finally) finishes the review comments against the
tail end of my v9 subset E series:
https://lists.gnu.org/archive/html/qemu-devel/2016-01/msg03504.html

v10 and v11 of the series dealt with the first half, and are now
mostly applied (or part of the pre-requisite series).

Also available as a tag at this location:
git fetch git://repo.or.cz/qemu/ericb.git qapi-cleanupv12e

and will soon be part of my branch with the rest of the v5 series, at:
http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi

There are a number of new patches listed here, the biggest reason
is splitting several large patches into smaller chunks.

001/18:[down] 'qapi-visit: Add visitor.type classification'
002/18:[down] 'qapi: Guarantee NULL obj on input visitor callback error'
003/18:[down] 'qmp: Drop dead command->type'
004/18:[down] 'qmp-input: Clean up stack handling'
005/18:[down] 'qmp-input: Don't consume input when checking has_member'
006/18:[down] 'qmp-input: Refactor when list is advanced'
007/18:[0655] [FC] 'qapi: Document visitor interfaces, add assertions'
008/18:[down] 'tests: Add check-qnull'
009/18:[0024] [FC] 'qapi: Add visit_type_null() visitor'
010/18:[down] 'qmp: Support explicit null during visits'
011/18:[] [--] 'spapr_drc: Expose 'null' in qom-get when there is no fdt'
012/18:[0047] [FC] 'qmp: Tighten output visitor rules'
013/18:[0088] [FC] 'qapi: Split visit_end_struct() into pieces'
014/18:[down] 'qapi-commands: Wrap argument visit in visit_start_struct'
015/18:[down] 'qom: Wrap prop visit in visit_start_struct'
016/18:[down] 'qmp-input: Require struct push to visit members of top dict'
017/18:[0273] [FC] 'qapi: Simplify semantics of visit_next_list()'
018/18:[0255] [FC] 'qapi: Change visit_type_FOO() to no longer return partial 
objects'

Eric Blake (18):
  qapi-visit: Add visitor.type classification
  qapi: Guarantee NULL obj on input visitor callback error
  qmp: Drop dead command->type
  qmp-input: Clean up stack handling
  qmp-input: Don't consume input when checking has_member
  qmp-input: Refactor when list is advanced
  qapi: Document visitor interfaces, add assertions
  tests: Add check-qnull
  qapi: Add visit_type_null() visitor
  qmp: Support explicit null during visits
  spapr_drc: Expose 'null' in qom-get when there is no fdt
  qmp: Tighten output visitor rules
  qapi: Split visit_end_struct() into pieces
  qapi-commands: Wrap argument visit in visit_start_struct
  qom: Wrap prop visit in visit_start_struct
  qmp-input: Require struct push to visit members of top dict
  qapi: Simplify semantics of visit_next_list()
  qapi: Change visit_type_FOO() to no longer return partial objects

 include/qapi/visitor.h   | 482 +--
 include/qapi/visitor-impl.h  |  80 --
 scripts/qapi-commands.py |  16 +-
 scripts/qapi-event.py|   3 +-
 scripts/qapi-visit.py|  56 ++--
 include/qapi/dealloc-visitor.h   |   4 +
 include/qapi/opts-visitor.h  |   4 +
 include/qapi/qmp-output-visitor.h|   1 +
 include/qapi/qmp/dispatch.h  |   6 -
 include/qapi/string-input-visitor.h  |   5 +
 include/qapi/string-output-visitor.h |   5 +
 qapi/qapi-visit-core.c   | 112 ++--
 hw/ppc/spapr_drc.c   |  11 +-
 hw/virtio/virtio-balloon.c   |  15 +-
 qapi/opts-visitor.c  |  65 ++---
 qapi/qapi-dealloc-visitor.c  |  43 +---
 qapi/qmp-dispatch.c  |  18 +-
 qapi/qmp-input-visitor.c | 168 +++-
 qapi/qmp-output-visitor.c|  72 +++---
 qapi/qmp-registry.c  |   1 -
 qapi/string-input-visitor.c  |  39 +--
 qapi/string-output-visitor.c |  43 ++--
 qom/object.c |   5 +-
 qom/object_interfaces.c  |  29 ++-
 tests/check-qnull.c  |  68 +
 tests/test-qmp-commands.c|  13 +-
 tests/test-qmp-input-strict.c|  19 +-
 tests/test-qmp-input-visitor.c   |  27 +-
 tests/test-qmp-output-visitor.c  |  17 +-
 docs/qapi-code-gen.txt   |  33 ++-
 tests/.gitignore |   1 +
 tests/Makefile   |   6 +-
 32 files changed, 1079 insertions(+), 388 deletions(-)
 create mode 100644 tests/check-qnull.c

-- 
2.5.0




[Qemu-devel] [PATCH] Use special code for sigsetjmp only in cpu-exec.c

2016-02-29 Thread Stefan Weil
The rest of the code can use longjmp with stack unwinding.

Signed-off-by: Stefan Weil 
---

This is a bug fix needed for 64 bit Windows.

QEMU for Windows currently gets the wrong definition for
sigsetjmp. It uses stack unwinding for longjmp which results
in a crash when it is called from generated code.

Thanks to Andrew Baumann for his reminder that this patch was
still missing. Andrew, could you please test it with your
RPi emulation?

Regards,
Stefan

 cpu-exec.c| 9 +
 include/sysemu/os-win32.h | 8 
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index fd92452..6a725e0 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -33,6 +33,15 @@
 #endif
 #include "sysemu/replay.h"
 
+#if defined(_WIN64)
+/* On w64, sigsetjmp is implemented by _setjmp which needs a second parameter.
+ * If this parameter is NULL, longjump does no stack unwinding.
+ * That is what we need for QEMU. Passing the value of register rsp (default)
+ * lets longjmp try a stack unwinding which will crash with generated code. */
+#undef sigsetjmp
+#define sigsetjmp(env, savesigs) _setjmp(env, NULL)
+#endif
+
 /* -icount align implementation. */
 
 typedef struct SyncClocks {
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index fbed346..b151e74 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -55,14 +55,6 @@
 # define EWOULDBLOCK  WSAEWOULDBLOCK
 #endif
 
-#if defined(_WIN64)
-/* On w64, setjmp is implemented by _setjmp which needs a second parameter.
- * If this parameter is NULL, longjump does no stack unwinding.
- * That is what we need for QEMU. Passing the value of register rsp (default)
- * lets longjmp try a stack unwinding which will crash with generated code. */
-# undef setjmp
-# define setjmp(env) _setjmp(env, NULL)
-#endif
 /* QEMU uses sigsetjmp()/siglongjmp() as the portable way to specify
  * "longjmp and don't touch the signal masks". Since we know that the
  * savemask parameter will always be zero we can safely define these
-- 
2.1.4




Re: [Qemu-devel] [WIP:COLO: 1] Flush colo ram in parallel

2016-02-29 Thread Li Zhijian

Great work!!
I like this patch very much.


On 02/29/2016 08:41 PM, Hailiang Zhang wrote:

On 2016/2/29 18:19, Dr. David Alan Gilbert (git) wrote:

From: "Dr. David Alan Gilbert" 

Flush the colo ram cache in parallel; use the same number
of threads as CPU cores.

On a VM with 4 cores, and 4GB RAM, I've seen a reduction from
~20ms to ~16ms using this, which is helpful but not as much
as I hoped;   I guess one problem might be that all the changes
could be concentrated in one area of RAM?  Perhaps another approach


Agreed. The dirty pages happened in continuous address are common in real
usage scene, Here, the idea of dividing ramblock by address, and flushing
them in parallel could be used in colo_init_ram_cache(),
where we need to backup the SVM's RAM into cache.


Agreed,  the backup job is very expensive currently, that is a good 
optimization.

Best regards.
Li Zhijian



would be to have one thread searching the bitmap and other threads
doing the copy with some type of work queueu.



I guess, in most case, the time of finding the dirty bitmap
is much faster than copy one page. So i think this method could be more
effective and more reasonable, but let's realize and test it first ;)

Thanks,
Hailiang


[Note: Not for merging at the moment, just for discussion with the COLO guys]

Signed-off-by: Dr. David Alan Gilbert 
---
  migration/ram.c | 215 +---
  1 file changed, 174 insertions(+), 41 deletions(-)

diff --git a/migration/ram.c b/migration/ram.c
index 188c3a1..6458863 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -42,6 +42,7 @@
  #include "qemu/rcu_queue.h"
  #include "migration/colo.h"
  #include "crypto/hash.h"
+#include "sysemu/sysemu.h"

  #ifdef DEBUG_MIGRATION_RAM
  #define DPRINTF(fmt, ...) \
@@ -616,18 +617,18 @@ static inline bool 
migration_bitmap_clear_dirty(ram_addr_t addr)
  ret = test_and_clear_bit(nr, bitmap);

  if (ret) {
-migration_dirty_pages--;
+atomic_dec(_dirty_pages);
  }
  return ret;
  }

  static inline
  ram_addr_t ramlist_bitmap_find_and_reset_dirty(RAMBlock *rb,
-   ram_addr_t start)
+   ram_addr_t start,
+   uint64_t rb_size)
  {
  unsigned long base = rb->offset >> TARGET_PAGE_BITS;
  unsigned long nr = base + (start >> TARGET_PAGE_BITS);
-uint64_t rb_size = rb->used_length;
  unsigned long size = base + (rb_size >> TARGET_PAGE_BITS);
  unsigned long next;

@@ -2721,6 +2722,141 @@ static int ram_load(QEMUFile *f, void *opaque, int 
version_id)
  return ret;
  }

+/* For parallel flushing of colo ram cache; it has 'n' threads,
+ * trying 'n'==number of cpus, but might be smarter to do something NUMA
+ * Each thread waits for 'triggers' and signals 'completes'.
+ */
+typedef struct ram_cache_threads {
+QemuThread *threads;
+QemuEvent  *triggers;
+QemuEvent  *completes;
+boolquit;
+} ColoRamCacheThreads;
+
+static ColoRamCacheThreads colo_flush_threads;
+
+/*
+ * Helper for colo_flush_thread.
+ * Given the current block and the bounds of ram (in pages)
+ * that we're dealing with, then find our next useable block,
+ * and set offset_out/used_out to the limits we're interested in.
+ * Result is NULL when we run out of blocks.
+ */
+static RAMBlock *flush_find_next_block(RAMBlock *block,
+   ram_addr_t lower_bound,
+   ram_addr_t upper_bound,
+   ram_addr_t *offset_out,
+   ram_addr_t *used_out)
+{
+do {
+if (!block) {
+block = QLIST_FIRST_RCU(_list.blocks);
+} else {
+block = QLIST_NEXT_RCU(block, next);
+}
+if (block &&
+(block->offset + block->used_length) >= lower_bound &&
+(block->offset < upper_bound)) {
+/* OK, good, the block is at least partially within our bounds */
+if (block->offset <= lower_bound) {
+*offset_out = lower_bound - block->offset;
+} else {
+*offset_out = 0;
+}
+if ((block->offset + block->used_length) >= upper_bound) {
+*used_out = upper_bound - block->offset;
+} else {
+*used_out = block->used_length;
+}
+break;
+}
+} while (block);
+
+return block;
+}
+
+/* Flush thread for COLO ram cache, synchronises a proportion of the
+ * ram cache.
+ */
+static void *colo_flush_thread(void *opaque)
+{
+int i = (int)(intptr_t)opaque;
+int64_t ram_cache_pages = last_ram_offset() >> TARGET_PAGE_BITS;
+ram_addr_t lower, upper;
+/* work out our range, lower..upper-1
+ * want to avoid SMP issues on the dirty bitmap, so make sure
+ 

Re: [Qemu-devel] [PATCH V2 2/3] net/filter-redirector:Add filter-redirector

2016-02-29 Thread Li Zhijian



On 02/29/2016 08:23 PM, Zhang Chen wrote:

Filter-redirector is a netfilter plugin.
It gives qemu the ability to redirect net packet.
redirector can redirect filter's net packet to outdev.
and redirect indev's packet to filter.

  filter
+
|
|
   redirector   |
+-+
|   | |
|   | |
|   | |
   indev ++ +>  outdev
| |   |
| |   |
| |   |
+-+
  |
  |
  v
   filter
  |
  |
  v
   filter--> guest

usage:

-netdev tap,id=hn0
-chardev socket,id=s0,host=ip_primary,port=X,server,nowait
-chardev socket,id=s1,host=ip_primary,port=Y,server,nowait
-filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0,outdev=s1

Signed-off-by: Zhang Chen 
Signed-off-by: Wen Congyang 
---
  net/Makefile.objs   |   1 +
  net/filter-redirector.c | 216 
  qemu-options.hx |   8 ++
  vl.c|   3 +-
  4 files changed, 227 insertions(+), 1 deletion(-)
  create mode 100644 net/filter-redirector.c

diff --git a/net/Makefile.objs b/net/Makefile.objs
index b7c22fd..8af9932 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -16,3 +16,4 @@ common-obj-$(CONFIG_NETMAP) += netmap.o
  common-obj-y += filter.o
  common-obj-y += filter-buffer.o
  common-obj-y += filter-mirror.o
+common-obj-y += filter-redirector.o
diff --git a/net/filter-redirector.c b/net/filter-redirector.c
new file mode 100644
index 000..d0eb76d
--- /dev/null
+++ b/net/filter-redirector.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Author: Zhang Chen 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "net/filter-traffic.h"
+
+#define FILTER_REDIRECTOR(obj) \
+OBJECT_CHECK(TrafficState, (obj), TYPE_FILTER_REDIRECTOR)
+
+#define TYPE_FILTER_REDIRECTOR "filter-redirector"
+#define REDIRECT_HEADER_LEN sizeof(uint32_t)
+
+static int filter_redirector_send(NetFilterState *nf,
+   const struct iovec *iov,
+   int iovcnt)
+{
+return filter_traffic_send(nf, iov, iovcnt);
+}
+
+static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb)
+{
+TrafficState *s = FILTER_REDIRECTOR(nf);
+ssize_t ret = 0;
+
+if (s->chr_out) {
+ret = filter_redirector_send(nf, iov, iovcnt);
+if (ret < 0) {
+error_report("filter_redirector_send failed");
+}
+return iov_size(iov, iovcnt);
+} else {
+return 0;
+}
+}
+
+static void filter_redirector_cleanup(NetFilterState *nf)
+{
+TrafficState *s = FILTER_REDIRECTOR(nf);
+
+if (s->chr_in) {
+qemu_chr_fe_release(s->chr_in);
+}
+if (s->chr_out) {
+qemu_chr_fe_release(s->chr_out);
+}
+}
+
+static int redirector_chr_can_read(void *opaque)
+{
+return REDIRECT_HEADER_LEN;
+}
+
+static void redirector_chr_read(void *opaque, const uint8_t *buf, int size)
+{
+NetFilterState *nf = opaque;
+TrafficState *s = FILTER_REDIRECTOR(nf);
+uint32_t len;
+int ret = 0;
+uint8_t *recv_buf;
+int offset = size;
+
+while (offset < REDIRECT_HEADER_LEN) {
+ret = s->chr_in->chr_sync_read(s->chr_in, (uint8_t *)buf + offset,
+REDIRECT_HEADER_LEN - offset);
+if (ret == -1 && errno == EAGAIN) {
+g_usleep(100);
+}
+offset += ret;

if 'ret' is a nagative value, you will cut 'offset'.



+}
+
+memcpy(, buf, sizeof(len));
+len = ntohl(len);
+
+if (len > 0 && len < NET_BUFSIZE) {
+recv_buf = g_malloc(len);
+ret = qemu_chr_fe_read_all(s->chr_in, recv_buf, len);
+if (ret != len) {
+error_report("filter-redirector recv buf failed");
+g_free(recv_buf);
+return;
+}
+
+ret = 

Re: [Qemu-devel] [RFC PATCH v2 1/3] vGPU Core driver

2016-02-29 Thread Jike Song
On 03/01/2016 07:17 AM, Neo Jia wrote:
> On Mon, Feb 29, 2016 at 05:39:02AM +, Tian, Kevin wrote:
>>> From: Kirti Wankhede
>>> Sent: Wednesday, February 24, 2016 12:24 AM
>>>
>>> Signed-off-by: Kirti Wankhede 
>>> Signed-off-by: Neo Jia 
>>
>> Hi, Kirti/Neo,
>>
>> Thanks a lot for you updated version. Having not looked into detail
>> code, first come with some high level comments.
>>
>> First, in a glimpse the majority of the code (possibly >95%) is device
>> agnostic, though we call it vgpu today. Just thinking about the
>> extensibility and usability of this framework, would it be better to 
>> name it in a way that any other type of I/O device can be fit into 
>> this framework? I don't have a good idea of the name now, but 
>> a simple idea is to replace vgpu with vdev (vdev-core, vfio-vdev,
>> vfio-iommu-type1-vdev, etc.), and then underlying GPU drivers are
>> just one category of users of this general vdev framework. In the
>> future it's easily extended to support other I/O virtualization based 
>> on similar vgpu concept;
>>
>> Second, are these 3 patches already working with nvidia device,
>> or are they just conceptual implementation w/o completing actual
>> test yet? We'll start moving our implementation toward this direction
>> too, so would be good to know the current status and how we can
>> further cooperate to move forward. Based on that we can start 
>> giving more comments on next level detail.
>>
> 
> Hi Kevin,
> 
> Yes, we do have an engineering prototype up and running with this set of 
> kernel
> patches we have posted.
> 

Good to know that :)

> Please let us know if you have any questions while integrating your vgpu 
> solution
> within this framework.

Thanks for your work, we are evaluating the integrate of the framework
with our vgpu implementation, will make/propose changes to this.

> 
> Thanks,
> Neo
> 
--
Thanks,
Jike




Re: [Qemu-devel] [PATCH V2 1/3] net/filter-traffic: add filter-traffic.h

2016-02-29 Thread Li Zhijian



On 02/29/2016 08:23 PM, Zhang Chen wrote:

We can reuse filter-traffic by filter-mirror,
filter-redirector and so on.


Is the main purpose to export filter_traffic_send() ?
IMO, define it as a public API would be better.

Using MirrorState and RedirectorState are clearer rather than TrafficState.



Signed-off-by: Zhang Chen 
Signed-off-by: Wen Congyang 
---
  net/filter-mirror.c  | 70 +++
  net/filter-traffic.h | 71 
  2 files changed, 80 insertions(+), 61 deletions(-)
  create mode 100644 net/filter-traffic.h

diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index ee13d94..d9698f2 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -9,65 +9,13 @@
   * later.  See the COPYING file in the top-level directory.
   */

-#include "net/filter.h"
-#include "net/net.h"
-#include "qemu-common.h"
-#include "qapi/qmp/qerror.h"
-#include "qapi-visit.h"
-#include "qom/object.h"
-#include "qemu/main-loop.h"
-#include "qemu/error-report.h"
-#include "trace.h"
-#include "sysemu/char.h"
-#include "qemu/iov.h"
-#include "qemu/sockets.h"
+#include "net/filter-traffic.h"

  #define FILTER_MIRROR(obj) \
-OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR)
+OBJECT_CHECK(TrafficState, (obj), TYPE_FILTER_MIRROR)

  #define TYPE_FILTER_MIRROR "filter-mirror"

-typedef struct MirrorState {
-NetFilterState parent_obj;
-char *outdev;
-CharDriverState *chr_out;
-} MirrorState;
-
-static int filter_mirror_send(NetFilterState *nf,
-   const struct iovec *iov,
-   int iovcnt)
-{
-MirrorState *s = FILTER_MIRROR(nf);
-int ret = 0;
-ssize_t size = 0;
-uint32_t len =  0;
-char *buf;
-
-size = iov_size(iov, iovcnt);
-if (!size) {
-return 0;
-}
-
-len = htonl(size);
-ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *), sizeof(len));
-if (ret != sizeof(len)) {
-goto err;
-}
-
-buf = g_malloc(size);
-iov_to_buf(iov, iovcnt, 0, buf, size);
-ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)buf, size);
-g_free(buf);
-if (ret != size) {
-goto err;
-}
-
-return 0;
-
-err:
-return ret < 0 ? ret : -EIO;
-}
-
  static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
   NetClientState *sender,
   unsigned flags,
@@ -77,7 +25,7 @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
  {
  int ret;

-ret = filter_mirror_send(nf, iov, iovcnt);
+ret = filter_traffic_send(nf, iov, iovcnt);
  if (ret) {
  error_report("filter_mirror_send failed(%s)", strerror(-ret));
  }
@@ -91,7 +39,7 @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,

  static void filter_mirror_cleanup(NetFilterState *nf)
  {
-MirrorState *s = FILTER_MIRROR(nf);
+TrafficState *s = FILTER_MIRROR(nf);

  if (s->chr_out) {
  qemu_chr_fe_release(s->chr_out);
@@ -100,7 +48,7 @@ static void filter_mirror_cleanup(NetFilterState *nf)

  static void filter_mirror_setup(NetFilterState *nf, Error **errp)
  {
-MirrorState *s = FILTER_MIRROR(nf);
+TrafficState *s = FILTER_MIRROR(nf);

  if (!s->outdev) {
  error_setg(errp, "filter filter mirror needs 'outdev' "
@@ -132,7 +80,7 @@ static void filter_mirror_class_init(ObjectClass *oc, void 
*data)

  static char *filter_mirror_get_outdev(Object *obj, Error **errp)
  {
-MirrorState *s = FILTER_MIRROR(obj);
+TrafficState *s = FILTER_MIRROR(obj);

  return g_strdup(s->outdev);
  }
@@ -140,7 +88,7 @@ static char *filter_mirror_get_outdev(Object *obj, Error 
**errp)
  static void
  filter_mirror_set_outdev(Object *obj, const char *value, Error **errp)
  {
-MirrorState *s = FILTER_MIRROR(obj);
+TrafficState *s = FILTER_MIRROR(obj);

  g_free(s->outdev);
  s->outdev = g_strdup(value);
@@ -159,7 +107,7 @@ static void filter_mirror_init(Object *obj)

  static void filter_mirror_fini(Object *obj)
  {
-MirrorState *s = FILTER_MIRROR(obj);
+TrafficState *s = FILTER_MIRROR(obj);

  g_free(s->outdev);
  }
@@ -170,7 +118,7 @@ static const TypeInfo filter_mirror_info = {
  .class_init = filter_mirror_class_init,
  .instance_init = filter_mirror_init,
  .instance_finalize = filter_mirror_fini,
-.instance_size = sizeof(MirrorState),
+.instance_size = sizeof(TrafficState),
  };

  static void register_types(void)
diff --git a/net/filter-traffic.h b/net/filter-traffic.h
new file mode 100644
index 000..24cb5c3
--- /dev/null
+++ b/net/filter-traffic.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Author: Zhang Chen 
+ *
+ * This work is 

Re: [Qemu-devel] How to make changes to qapi-types.h

2016-02-29 Thread Fam Zheng
On Mon, 02/29 21:38, Programmingkid wrote:
> 
> On Feb 29, 2016, at 8:59 PM, Fam Zheng wrote:
> 
> > On Mon, 02/29 20:26, Programmingkid wrote:
> >> I need to add a variable to the QKeyCode enum in the file qapi-types.h. 
> >> This
> >> file is auto-generated so using traditional means to create a patch is not
> >> possible. Would anyone know how I can add to this file?
> > 
> > The file to look at is qapi-schema.json. The generator is also documented in
> > docs/qapi-code-gen.txt.
> 
> Thank you very much for your help, but the information in the files you sent
> did not seem to help. Maybe I should say exactly what I'm trying to do. 
> 
> In the file qapi-types.h, there is an enum called QKeyCode. I want to add
> this to the enum:
> 
>  Q_KEY_CODE_KP_EQUALS = 125,
> 
> Would anyone know how to do this so I can submit this change as a patch?

You missed what I was trying to point out.

diff --git a/qapi-schema.json b/qapi-schema.json
index 7b8f2a1..ad50b06 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3096,7 +3096,7 @@
 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
 'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'ro',
-'kp_comma' ] }
+'kp_comma', 'kp_equals' ] }
 
 ##
 # @KeyValue




Re: [Qemu-devel] [PATCH 3/6] memory: Implement memory_region_get_ram_addr with mr->ram_block

2016-02-29 Thread Fam Zheng
On Tue, 03/01 02:32, Gonglei (Arei) wrote:
> 
> > Subject: [Qemu-devel] [PATCH 3/6] memory: Implement
> > memory_region_get_ram_addr with mr->ram_block
> > 
> > Signed-off-by: Fam Zheng 
> > ---
> >  include/exec/memory.h | 8 +---
> >  memory.c  | 5 +
> >  2 files changed, 6 insertions(+), 7 deletions(-)
> > 
> > diff --git a/include/exec/memory.h b/include/exec/memory.h
> > index d5284c2..810d2c0 100644
> > --- a/include/exec/memory.h
> > +++ b/include/exec/memory.h
> > @@ -978,14 +978,8 @@ void
> > memory_region_add_subregion_overlap(MemoryRegion *mr,
> >  /**
> >   * memory_region_get_ram_addr: Get the ram address associated with a
> > memory
> >   * region
> > - *
> > - * DO NOT USE THIS FUNCTION.  This is a temporary workaround while the
> > Xen
> > - * code is being reworked.
> >   */
> > -static inline ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
> > -{
> > -return mr->ram_addr;
> > -}
> > +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
> > 
> >  uint64_t memory_region_get_alignment(const MemoryRegion *mr);
> >  /**
> > diff --git a/memory.c b/memory.c
> > index fe70075..769825e 100644
> > --- a/memory.c
> > +++ b/memory.c
> > @@ -1596,6 +1596,11 @@ void
> > *memory_region_get_ram_ptr(MemoryRegion *mr)
> >  return ptr + offset;
> >  }
> > 
> > +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
> > +{
> > +return mr->ram_block->offset;
> > +}
> > +
> 
> Do we need add NULL check for mr->ram_block ?

Yes, will add it. Thanks!

Fam



Re: [Qemu-devel] [PATCH 5/6] exec: Pass RAMBlock pointer to qemu_ram_free

2016-02-29 Thread Gonglei (Arei)

> Subject: [Qemu-devel] [PATCH 5/6] exec: Pass RAMBlock pointer to
> qemu_ram_free
> 
> The only caller now knows exactly which RAMBlock to free, so it's not
> necessary to do the lookup.
> 
> Signed-off-by: Fam Zheng 
> ---
>  exec.c  | 21 +++--
>  include/exec/ram_addr.h |  2 +-
>  memory.c|  4 ++--
>  3 files changed, 10 insertions(+), 17 deletions(-)
> 

Nice ;)

Reviewed-by: Gonglei 


> diff --git a/exec.c b/exec.c
> index 6ed4203..ad8b826 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1751,22 +1751,15 @@ static void reclaim_ramblock(RAMBlock *block)
>  g_free(block);
>  }
> 
> -void qemu_ram_free(ram_addr_t addr)
> +void qemu_ram_free(RAMBlock *block)
>  {
> -RAMBlock *block;
> -
>  qemu_mutex_lock_ramlist();
> -QLIST_FOREACH_RCU(block, _list.blocks, next) {
> -if (addr == block->offset) {
> -QLIST_REMOVE_RCU(block, next);
> -ram_list.mru_block = NULL;
> -/* Write list before version */
> -smp_wmb();
> -ram_list.version++;
> -call_rcu(block, reclaim_ramblock, rcu);
> -break;
> -}
> -}
> +QLIST_REMOVE_RCU(block, next);
> +ram_list.mru_block = NULL;
> +/* Write list before version */
> +smp_wmb();
> +ram_list.version++;
> +call_rcu(block, reclaim_ramblock, rcu);
>  qemu_mutex_unlock_ramlist();
>  }
> 
> diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
> index 865e19b..5adf7a4 100644
> --- a/include/exec/ram_addr.h
> +++ b/include/exec/ram_addr.h
> @@ -108,7 +108,7 @@ RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t
> size, ram_addr_t max_size,
>  int qemu_get_ram_fd(ram_addr_t addr);
>  void qemu_set_ram_fd(ram_addr_t addr, int fd);
>  void *qemu_get_ram_block_host_ptr(ram_addr_t addr);
> -void qemu_ram_free(ram_addr_t addr);
> +void qemu_ram_free(RAMBlock *block);
> 
>  int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp);
> 
> diff --git a/memory.c b/memory.c
> index b221f3c..32d2912 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -858,12 +858,12 @@ static void
> memory_region_destructor_none(MemoryRegion *mr)
> 
>  static void memory_region_destructor_ram(MemoryRegion *mr)
>  {
> -qemu_ram_free(memory_region_get_ram_addr(mr));
> +qemu_ram_free(mr->ram_block);
>  }
> 
>  static void memory_region_destructor_rom_device(MemoryRegion *mr)
>  {
> -qemu_ram_free(memory_region_get_ram_addr(mr) &
> TARGET_PAGE_MASK);
> +qemu_ram_free(mr->ram_block);
>  }
> 
>  static bool memory_region_need_escape(char c)
> --
> 2.4.3
> 




Re: [Qemu-devel] [PATCH v2 2/2] filter-buffer: Add status_changed callback processing

2016-02-29 Thread Jason Wang


On 02/29/2016 03:36 PM, Hailiang Zhang wrote:
> On 2016/2/29 15:27, Jason Wang wrote:
>>
>>
>> On 02/29/2016 09:46 AM, zhanghailiang wrote:
>>> While the status of filter-buffer changing from 'on' to 'off',
>>> it need to release all the buffered packets, and delete the related
>>> timer, while switch from 'off' to 'on', it need to resume the release
>>> packets timer.
>>>
>>> Signed-off-by: zhanghailiang 
>>> Cc: Jason Wang 
>>> Cc: Yang Hongyang 
>>> ---
>>> v2:
>>> - New patch
>>> ---
>>>   net/filter-buffer.c | 19 +++
>>>   1 file changed, 19 insertions(+)
>>>
>>> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
>>> index 12ad2e3..ed3f19e 100644
>>> --- a/net/filter-buffer.c
>>> +++ b/net/filter-buffer.c
>>> @@ -124,6 +124,24 @@ static void filter_buffer_setup(NetFilterState
>>> *nf, Error **errp)
>>>   }
>>>   }
>>>
>>> +static void filter_buffer_status_changed(NetFilterState *nf, Error
>>> **errp)
>>> +{
>>> +FilterBufferState *s = FILTER_BUFFER(nf);
>>> +
>>> +if (!strcmp(nf->status, "off")) {
>>> +if (s->interval) {
>>> +timer_del(>release_timer);
>>> +}
>>> +filter_buffer_flush(nf);
>>> +} else {
>>> +if (s->interval) {
>>> +timer_init_us(>release_timer, QEMU_CLOCK_VIRTUAL,
>>> +filter_buffer_release_timer, nf);
>>> +timer_mod(>release_timer,
>>> +qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
>>> +}
>>
>> The code looks duplicated with filter_buffer_setup().
>>
>
> Yea, extract them into a new helper ? filter_buffer_setup_timer() ?

Right.

>
>>> +}
>>> +}
>>>   static void filter_buffer_class_init(ObjectClass *oc, void *data)
>>>   {
>>>   NetFilterClass *nfc = NETFILTER_CLASS(oc);
>>> @@ -131,6 +149,7 @@ static void filter_buffer_class_init(ObjectClass
>>> *oc, void *data)
>>>   nfc->setup = filter_buffer_setup;
>>>   nfc->cleanup = filter_buffer_cleanup;
>>>   nfc->receive_iov = filter_buffer_receive_iov;
>>> +nfc->status_changed = filter_buffer_status_changed;
>>>   }
>>>
>>>   static void filter_buffer_get_interval(Object *obj, Visitor *v,
>>
>>
>> .
>>
>
>




Re: [Qemu-devel] [RFC PATCH v2 00/10] Add colo-proxy based on netfilter

2016-02-29 Thread Li Zhijian



On 03/01/2016 04:04 AM, Dr. David Alan Gilbert wrote:

* Zhang Chen (zhangchen.f...@cn.fujitsu.com) wrote:

From: zhangchen 

Hi,all

This patch add an colo-proxy object, COLO-Proxy is a part of COLO,
based on qemu netfilter and it's a plugin for qemu netfilter. the function
keep Secondary VM connect normal to Primary VM and compare packets
sent by PVM to sent by SVM.if the packet difference,notify COLO do
checkpoint and send all primary packet has queued.


Hi Zhangchen,
   How are you dealing with the IP 'identification' field?
It's a very very random field, and not just the initial value in the connection.
I can't see how the kernel colo-proxy dealt with it either; but I think it's
comparison was after defragementation so probably ignored the identification
field

You are right, most kernel colo-proxy code is working at mangle table (after 
defrag).
and colo proxy only compare the contents of L4(TCP/UDP) excluding IP 
identification.


 - wouldn't that confuse a client at failover?

Err..., instersting question.

for example, a COLO including primay(PVM) adn secondary(SVM)
1. primay is sending a compared P_IP packet(identification=0x12345, split to 
IP_s1, IP_s2..IP_s100) to client
2. client is receiving the ip segment(but IP_s2, IP_s50, IP_s80..IP_s99 are 
missing)
   and primary host is down.
3. secondary VM takeover, and send a S_IP packet(ip contents is always same as 
at PVM)

in step 3,
if the S_IP identification isn't 0x12345, client will drop the ip segment at 
step 2 because of defrag timeout.
if the S_IP identification isn 0x12345, client may mix the segment from PVM or 
SVM(just like segment come
from different router), but that's Okay, because we have ensured the ip 
contents is identical.

so IMO, it will not confuse the client at failover.



Dave


You can also get the series from:

https://github.com/zhangckid/qemu/tree/colo-v2.2-periodic-mode-with-colo-proxyV2

Usage:

primary:
-netdev tap,id=bn0 -device e1000,netdev=bn0
-object colo-proxy,id=f0,netdev=bn0,queue=all,mode=primary,addr=host:port

secondary:
-netdev tap,id=bn0 -device e1000,netdev=bn0
-object colo-proxy,id=f0,netdev=bn0,queue=all,mode=secondary,addr=host:port

NOTE:
queue must set "all". See enum NetFilterDirection for detail.
colo-proxy need queue all packets
colo-proxy V2 just can compare ip packet


## Background

COLO FT/HA (COarse-grain LOck-stepping Virtual Machines for Non-stop Service)
project is a high availability solution. Both Primary VM (PVM) and Secondary VM
(SVM) run in parallel. They receive the same request from client, and generate
responses in parallel too. If the response packets from PVM and SVM are
identical, they are released immediately. Otherwise, a VM checkpoint (on
demand)is conducted.

Paper:
http://www.socc2013.org/home/program/a3-dong.pdf?attredirects=0

COLO on Xen:
http://wiki.xen.org/wiki/COLO_-_Coarse_Grain_Lock_Stepping

COLO on Qemu/KVM:
http://wiki.qemu.org/Features/COLO

By the needs of capturing response packets from PVM and SVM and finding out
whether they are identical, we introduce a new module to qemu networking
called colo-proxy.

V2:
   rebase colo-proxy with qemu-colo-v2.2-periodic-mode
   fix dave's comments
   fix wency's comments
   fix zhanghailiang's comments

v1:
   initial patch.



zhangchen (10):
   Init colo-proxy object based on netfilter
   Jhash: add linux kernel jhashtable in qemu
   Colo-proxy: add colo-proxy framework
   Colo-proxy: add data structure and jhash func
   net/colo-proxy: Add colo interface to use proxy
   net/colo-proxy: add socket used by forward func
   net/colo-proxy: Add packet enqueue & handle func
   net/colo-proxy: Handle packet and connection
   net/colo-proxy: Compare pri pkt to sec pkt
   net/colo-proxy: Colo-proxy do checkpoint and clear

  include/qemu/jhash.h |  61 
  net/Makefile.objs|   1 +
  net/colo-proxy.c | 939 +++
  net/colo-proxy.h |  24 ++
  qemu-options.hx  |   6 +
  trace-events |   8 +
  vl.c |   3 +-
  7 files changed, 1041 insertions(+), 1 deletion(-)
  create mode 100644 include/qemu/jhash.h
  create mode 100644 net/colo-proxy.c
  create mode 100644 net/colo-proxy.h

--
1.9.1




--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK


.



--
Best regards.
Li Zhijian (8555)





Re: [Qemu-devel] [PATCH 4/6] memory: Drop MemoryRegion.ram_addr

2016-02-29 Thread Gonglei (Arei)
> Subject: [Qemu-devel] [PATCH 4/6] memory: Drop MemoryRegion.ram_addr
> 
> All references to mr->ram_addr are replaced by
> memory_region_get_ram_addr(mr) (except for a few assertions that are
> replaced with mr->ram_block).
> 
> Signed-off-by: Fam Zheng 
> ---
>  cputlb.c  |  4 +--
>  exec.c|  3 ++-
>  hw/misc/ivshmem.c |  9 ---
>  include/exec/memory.h |  1 -
>  kvm-all.c |  3 ++-
>  memory.c  | 71
> ---
>  6 files changed, 39 insertions(+), 52 deletions(-)
> 

Reviewed-by: Gonglei 


> diff --git a/cputlb.c b/cputlb.c
> index 3973030..2f7a166 100644
> --- a/cputlb.c
> +++ b/cputlb.c
> @@ -416,8 +416,8 @@ void tlb_set_page_with_attrs(CPUState *cpu,
> target_ulong vaddr,
>  /* Write access calls the I/O callback.  */
>  te->addr_write = address | TLB_MMIO;
>  } else if (memory_region_is_ram(section->mr)
> -   &&
> cpu_physical_memory_is_clean(section->mr->ram_addr
> -   + xlat)) {
> +   && cpu_physical_memory_is_clean(
> +memory_region_get_ram_addr(section->mr) +
> xlat)) {
>  te->addr_write = address | TLB_NOTDIRTY;
>  } else {
>  te->addr_write = address;
> diff --git a/exec.c b/exec.c
> index 83e3f7d..6ed4203 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2699,7 +2699,8 @@ MemTxResult
> address_space_read_continue(AddressSpace *as, hwaddr addr,
>  }
>  } else {
>  /* RAM case */
> -ptr = qemu_get_ram_ptr(mr->ram_block, mr->ram_addr +
> addr1);
> +ptr = qemu_get_ram_ptr(mr->ram_block,
> +
> memory_region_get_ram_addr(mr) + addr1);
>  memcpy(buf, ptr, l);
>  }
> 
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index 48b7a34..1838bc8 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -400,7 +400,7 @@ static int create_shared_memory_BAR(IVShmemState
> *s, int fd, uint8_t attr,
> 
>  memory_region_init_ram_ptr(>ivshmem, OBJECT(s),
> "ivshmem.bar2",
> s->ivshmem_size, ptr);
> -qemu_set_ram_fd(s->ivshmem.ram_addr, fd);
> +qemu_set_ram_fd(memory_region_get_ram_addr(>ivshmem), fd);
>  vmstate_register_ram(>ivshmem, DEVICE(s));
>  memory_region_add_subregion(>bar, 0, >ivshmem);
> 
> @@ -661,7 +661,8 @@ static void ivshmem_read(void *opaque, const uint8_t
> *buf, int size)
>  }
>  memory_region_init_ram_ptr(>ivshmem, OBJECT(s),
> "ivshmem.bar2", s->ivshmem_size,
> map_ptr);
> -qemu_set_ram_fd(s->ivshmem.ram_addr, incoming_fd);
> +qemu_set_ram_fd(memory_region_get_ram_addr(>ivshmem),
> +incoming_fd);
>  vmstate_register_ram(>ivshmem, DEVICE(s));
> 
>  IVSHMEM_DPRINTF("guest h/w addr = %p, size = %" PRIu64 "\n",
> @@ -996,8 +997,10 @@ static void pci_ivshmem_exit(PCIDevice *dev)
>   strerror(errno));
>  }
> 
> -if ((fd = qemu_get_ram_fd(s->ivshmem.ram_addr)) != -1)
> +fd =
> qemu_get_ram_fd(memory_region_get_ram_addr(>ivshmem));
> +if (fd != -1) {
>  close(fd);
> +}
>  }
> 
>  vmstate_unregister_ram(>ivshmem, DEVICE(dev));
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index 810d2c0..2de7898 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -169,7 +169,6 @@ struct MemoryRegion {
>  bool flush_coalesced_mmio;
>  bool global_locking;
>  uint8_t dirty_log_mask;
> -ram_addr_t ram_addr;
>  RAMBlock *ram_block;
>  Object *owner;
>  const MemoryRegionIOMMUOps *iommu_ops;
> diff --git a/kvm-all.c b/kvm-all.c
> index a65e73f..161200e 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -366,7 +366,8 @@ static void kvm_log_stop(MemoryListener *listener,
>  static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
>   unsigned long *bitmap)
>  {
> -ram_addr_t start = section->offset_within_region +
> section->mr->ram_addr;
> +ram_addr_t start = section->offset_within_region +
> +   memory_region_get_ram_addr(section->mr);
>  ram_addr_t pages = int128_get64(section->size) / getpagesize();
> 
>  cpu_physical_memory_set_dirty_lebitmap(bitmap, start, pages);
> diff --git a/memory.c b/memory.c
> index 769825e..b221f3c 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -858,12 +858,12 @@ static void
> memory_region_destructor_none(MemoryRegion *mr)
> 
>  static void memory_region_destructor_ram(MemoryRegion *mr)
>  {
> -qemu_ram_free(mr->ram_addr);
> +qemu_ram_free(memory_region_get_ram_addr(mr));
>  }
> 
>  static void memory_region_destructor_rom_device(MemoryRegion *mr)
>  {
> -

Re: [Qemu-devel] How to make changes to qapi-types.h

2016-02-29 Thread Programmingkid

On Feb 29, 2016, at 8:59 PM, Fam Zheng wrote:

> On Mon, 02/29 20:26, Programmingkid wrote:
>> I need to add a variable to the QKeyCode enum in the file qapi-types.h. This
>> file is auto-generated so using traditional means to create a patch is not
>> possible. Would anyone know how I can add to this file?
> 
> The file to look at is qapi-schema.json. The generator is also documented in
> docs/qapi-code-gen.txt.

Thank you very much for your help, but the information in the files you sent 
did not seem to help. Maybe I should say exactly what I'm trying to do. 

In the file qapi-types.h, there is an enum called QKeyCode. I want to add this 
to the enum:

 Q_KEY_CODE_KP_EQUALS = 125,

Would anyone know how to do this so I can submit this change as a patch?


Re: [Qemu-devel] [PATCH v2 1/2] filter: Add 'status' property for filter object

2016-02-29 Thread Jason Wang


On 02/29/2016 03:34 PM, Hailiang Zhang wrote:
> On 2016/2/29 15:26, Jason Wang wrote:
>>
>>
>> On 02/29/2016 09:46 AM, zhanghailiang wrote:
>>> With this property, users can control if this filter is 'on'
>>> or 'off'. The default behavior for filter is 'on'.
>>>
>>> For some types of filters, they may need to react to status changing,
>>> So here, we introduced status changing callback/notifier for filter
>>> class.
>>>
>>> We will skip the disabled ('off') filter when delivering packets in
>>> net layer.
>>>
>>> Signed-off-by: zhanghailiang 
>>> Cc: Jason Wang 
>>> Cc: Yang Hongyang 
>>> ---
>>> v2:
>>> - Split the processing of buffer-filter into a new patch (Jason)
>>> - Use 'status' instead of 'enabled' to store the filter state (Jason)
>>> - Rename FilterDisable() callback to FilterStatusChanged(Jason)
>>> ---
>>
>> Thanks, looks good, just few nits.
>>
>>>   include/net/filter.h |  4 
>>>   net/filter.c | 42 ++
>>>   qemu-options.hx  |  4 +++-
>>>   3 files changed, 49 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/include/net/filter.h b/include/net/filter.h
>>> index 5639976..ebef0dc 100644
>>> --- a/include/net/filter.h
>>> +++ b/include/net/filter.h
>>> @@ -36,12 +36,15 @@ typedef ssize_t
>>> (FilterReceiveIOV)(NetFilterState *nc,
>>>  int iovcnt,
>>>  NetPacketSent *sent_cb);
>>>
>>> +typedef void (FilterStatusChanged) (NetFilterState *nf, Error **errp);
>>> +
>>>   typedef struct NetFilterClass {
>>>   ObjectClass parent_class;
>>>
>>>   /* optional */
>>>   FilterSetup *setup;
>>>   FilterCleanup *cleanup;
>>> +FilterStatusChanged *status_changed;
>>>   /* mandatory */
>>>   FilterReceiveIOV *receive_iov;
>>>   } NetFilterClass;
>>> @@ -55,6 +58,7 @@ struct NetFilterState {
>>>   char *netdev_id;
>>>   NetClientState *netdev;
>>>   NetFilterDirection direction;
>>> +char *status;
>>
>> Let's use bool instead.
>>
>
> Er, then status=true means 'on' ? false means 'off' ?
> That looks odd.  What about using 'bool status_on' ?

Or just "bool on" :)

>
>>
>> .
>>
>
>




Re: [Qemu-devel] [PATCH 3/6] memory: Implement memory_region_get_ram_addr with mr->ram_block

2016-02-29 Thread Gonglei (Arei)

> Subject: [Qemu-devel] [PATCH 3/6] memory: Implement
> memory_region_get_ram_addr with mr->ram_block
> 
> Signed-off-by: Fam Zheng 
> ---
>  include/exec/memory.h | 8 +---
>  memory.c  | 5 +
>  2 files changed, 6 insertions(+), 7 deletions(-)
> 
> diff --git a/include/exec/memory.h b/include/exec/memory.h
> index d5284c2..810d2c0 100644
> --- a/include/exec/memory.h
> +++ b/include/exec/memory.h
> @@ -978,14 +978,8 @@ void
> memory_region_add_subregion_overlap(MemoryRegion *mr,
>  /**
>   * memory_region_get_ram_addr: Get the ram address associated with a
> memory
>   * region
> - *
> - * DO NOT USE THIS FUNCTION.  This is a temporary workaround while the
> Xen
> - * code is being reworked.
>   */
> -static inline ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
> -{
> -return mr->ram_addr;
> -}
> +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
> 
>  uint64_t memory_region_get_alignment(const MemoryRegion *mr);
>  /**
> diff --git a/memory.c b/memory.c
> index fe70075..769825e 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -1596,6 +1596,11 @@ void
> *memory_region_get_ram_ptr(MemoryRegion *mr)
>  return ptr + offset;
>  }
> 
> +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
> +{
> +return mr->ram_block->offset;
> +}
> +

Do we need add NULL check for mr->ram_block ?


Regards,
-Gonglei

>  void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize,
> Error **errp)
>  {
>  assert(mr->ram_addr != RAM_ADDR_INVALID);
> --
> 2.4.3
> 




Re: [Qemu-devel] [PATCH 2/6] memory: Move assignment to ram_block to memory_region_init_*

2016-02-29 Thread Gonglei (Arei)

> Subject: [Qemu-devel] [PATCH 2/6] memory: Move assignment to ram_block to
> memory_region_init_*
> 
> We don't force "const" qualifiers with pointers in QEMU, but it's still
> good to keep a clean function interface. Assigning to mr->ram_block is
> in this sense ugly - one initializer mutating its owning object's state.
> 
> Move it to memory_region_init_*, where mr->ram_addr is assigned.
> 
> Signed-off-by: Fam Zheng 
> ---
>  exec.c   | 1 -
>  memory.c | 5 +
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 

Reviewed-by: Gonglei 


> diff --git a/exec.c b/exec.c
> index 2b14b79..83e3f7d 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1711,7 +1711,6 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t
> size, ram_addr_t max_size,
>  error_propagate(errp, local_err);
>  return NULL;
>  }
> -mr->ram_block = new_block;
>  return new_block;
>  }
> 
> diff --git a/memory.c b/memory.c
> index ae13ba9..fe70075 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -1233,6 +1233,7 @@ void memory_region_init_ram(MemoryRegion *mr,
>  mr->terminates = true;
>  mr->destructor = memory_region_destructor_ram;
>  ram_block = qemu_ram_alloc(size, mr, errp);
> +mr->ram_block = ram_block;
>  mr->ram_addr = ram_block->offset;
>  mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
>  }
> @@ -1254,6 +1255,7 @@ void
> memory_region_init_resizeable_ram(MemoryRegion *mr,
>  mr->terminates = true;
>  mr->destructor = memory_region_destructor_ram;
>  ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr,
> errp);
> +mr->ram_block = ram_block;
>  mr->ram_addr = ram_block->offset;
>  mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
>  }
> @@ -1274,6 +1276,7 @@ void
> memory_region_init_ram_from_file(MemoryRegion *mr,
>  mr->terminates = true;
>  mr->destructor = memory_region_destructor_ram;
>  ram_block = qemu_ram_alloc_from_file(size, mr, share, path, errp);
> +mr->ram_block = ram_block;
>  mr->ram_addr = ram_block->offset;
>  mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
>  }
> @@ -1296,6 +1299,7 @@ void memory_region_init_ram_ptr(MemoryRegion
> *mr,
>  /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL.  */
>  assert(ptr != NULL);
>  ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, _fatal);
> +mr->ram_block = ram_block;
>  mr->ram_addr = ram_block->offset;
>  }
> 
> @@ -1333,6 +1337,7 @@ void
> memory_region_init_rom_device(MemoryRegion *mr,
>  mr->rom_device = true;
>  mr->destructor = memory_region_destructor_rom_device;
>  ram_block = qemu_ram_alloc(size, mr, errp);
> +mr->ram_block = ram_block;
>  mr->ram_addr = ram_block->offset;
>  }
> 
> --
> 2.4.3
> 




Re: [Qemu-devel] [PATCH 1/6] exec: Return RAMBlock pointer from allocating functions

2016-02-29 Thread Gonglei (Arei)
>
> Subject: [Qemu-devel] [PATCH 1/6] exec: Return RAMBlock pointer from
> allocating functions
> 
> Previously we return RAMBlock.offset; now return the pointer to the
> whole structure.
> 
> ram_block_add returns void now, error is completely passed with errp.
> 
> Signed-off-by: Fam Zheng 
> ---
>  exec.c  | 51
> +
>  include/exec/ram_addr.h | 22 ++---
>  memory.c| 25 +++-
>  3 files changed, 53 insertions(+), 45 deletions(-)
> 

Reviewed-by: Gonglei 


> diff --git a/exec.c b/exec.c
> index c62c439..2b14b79 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1554,7 +1554,7 @@ static void dirty_memory_extend(ram_addr_t
> old_ram_size,
>  }
>  }
> 
> -static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
> +static void ram_block_add(RAMBlock *new_block, Error **errp)
>  {
>  RAMBlock *block;
>  RAMBlock *last_block = NULL;
> @@ -1573,7 +1573,6 @@ static ram_addr_t ram_block_add(RAMBlock
> *new_block, Error **errp)
>  if (err) {
>  error_propagate(errp, err);
>  qemu_mutex_unlock_ramlist();
> -return -1;
>  }
>  } else {
>  new_block->host = phys_mem_alloc(new_block->max_length,
> @@ -1583,7 +1582,6 @@ static ram_addr_t ram_block_add(RAMBlock
> *new_block, Error **errp)
>   "cannot set up guest memory '%s'",
> 
> memory_region_name(new_block->mr));
>  qemu_mutex_unlock_ramlist();
> -return -1;
>  }
>  memory_try_enable_merging(new_block->host,
> new_block->max_length);
>  }
> @@ -1631,22 +1629,19 @@ static ram_addr_t ram_block_add(RAMBlock
> *new_block, Error **errp)
>  kvm_setup_guest_memory(new_block->host,
> new_block->max_length);
>  }
>  }
> -
> -return new_block->offset;
>  }
> 
>  #ifdef __linux__
> -ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
> -bool share, const char
> *mem_path,
> -Error **errp)
> +RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
> +   bool share, const char
> *mem_path,
> +   Error **errp)
>  {
>  RAMBlock *new_block;
> -ram_addr_t addr;
>  Error *local_err = NULL;
> 
>  if (xen_enabled()) {
>  error_setg(errp, "-mem-path not supported with Xen");
> -return -1;
> +return NULL;
>  }
> 
>  if (phys_mem_alloc != qemu_anon_ram_alloc) {
> @@ -1657,7 +1652,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t
> size, MemoryRegion *mr,
>   */
>  error_setg(errp,
> "-mem-path not supported with this accelerator");
> -return -1;
> +return NULL;
>  }
> 
>  size = HOST_PAGE_ALIGN(size);
> @@ -1670,29 +1665,28 @@ ram_addr_t
> qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
>   mem_path, errp);
>  if (!new_block->host) {
>  g_free(new_block);
> -return -1;
> +return NULL;
>  }
> 
> -addr = ram_block_add(new_block, _err);
> +ram_block_add(new_block, _err);
>  if (local_err) {
>  g_free(new_block);
>  error_propagate(errp, local_err);
> -return -1;
> +return NULL;
>  }
> -return addr;
> +return new_block;
>  }
>  #endif
> 
>  static
> -ram_addr_t qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t
> max_size,
> -   void (*resized)(const char*,
> -   uint64_t
> length,
> -   void *host),
> -   void *host, bool resizeable,
> -   MemoryRegion *mr, Error **errp)
> +RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t
> max_size,
> +  void (*resized)(const char*,
> +  uint64_t length,
> +  void *host),
> +  void *host, bool resizeable,
> +  MemoryRegion *mr, Error **errp)
>  {
>  RAMBlock *new_block;
> -ram_addr_t addr;
>  Error *local_err = NULL;
> 
>  size = HOST_PAGE_ALIGN(size);
> @@ -1711,29 +1705,28 @@ ram_addr_t
> qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
>  if (resizeable) {
>  new_block->flags |= RAM_RESIZEABLE;
>  }
> -addr = ram_block_add(new_block, _err);
> +ram_block_add(new_block, _err);
>  if (local_err) {
>  g_free(new_block);
>  error_propagate(errp, local_err);
> -return -1;
> +return NULL;
>  }

Re: [Qemu-devel] [RFC PATCH 0/2] ARM: add QMP command to query GIC version

2016-02-29 Thread Peter Xu
On Mon, Feb 29, 2016 at 05:30:36PM +0100, Andrea Bolognani wrote:
> On Mon, 2016-02-22 at 09:35 +0800, Peter Xu wrote:
> > On Fri, Feb 19, 2016 at 01:33:09PM +0100, Andrea Bolognani wrote:
> > > 
> > > I didn't say it would be hard :)
> > > 
> > > I just said that such compatibility code would have to be kept
> > > around forever. We already support lots and lots of similar cases
> > > in libvirt, the difference being that in this case we would add
> > > support for a new command *knowing in advance* that it will become
> > > obsolete as soon as a proper implementation is available.
> > > 
> > > It might still be the right thing to do! I just want to make sure
> > > everything's been properly considered and discussed beforehand.
> > 
> > I totally agree with you to think more before doing. :)
> 
> So, anyone else willing to give their $0.2 on how to implement
> this The Right Way™?
> 
> I just skimmed the whole thread again and it doesn't look to me
> like any consensus has been reached.

Hi, Andrea,

I have sent another non-rfc patchset about this already:

https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg05270.html

I am not sure whether you have received it or not (you should be in
the CC list :), just pasting it again here. Do you think this would
work for us?

Btw, the thread is receiving none reviews till now. Looking forward
to have any of your further comments!

Thanks!
Peter

> 
> Cheers.
> 
> -- 
> Andrea Bolognani
> Software Engineer - Virtualization Team



Re: [Qemu-devel] How to make changes to qapi-types.h

2016-02-29 Thread Fam Zheng
On Mon, 02/29 20:26, Programmingkid wrote:
> I need to add a variable to the QKeyCode enum in the file qapi-types.h. This
> file is auto-generated so using traditional means to create a patch is not
> possible. Would anyone know how I can add to this file?

The file to look at is qapi-schema.json. The generator is also documented in
docs/qapi-code-gen.txt.

Fam



Re: [Qemu-devel] make distclean can fail do to a configuration check

2016-02-29 Thread Fam Zheng
On Mon, 02/29 11:49, John Snow wrote:
> 
> 
> On 02/14/2016 02:17 AM, Fam Zheng wrote:
> Fam, didn't you have patches to allow e.g. cleans and "make tags" and so
> on without re-incurring a full reconfiguration?

Do you mean this?

fam@fam-t430:~/work/qemu [master]$ git grep UNCHECKED_GOALS
Makefile:UNCHECKED_GOALS := %clean TAGS cscope ctags
Makefile:ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if 
$(MAKECMDGOALS),,fail))
Makefile:ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if 
$(MAKECMDGOALS),,fail))

Fam



Re: [Qemu-devel] [RFC] QMP: add query-hotpluggable-cpus

2016-02-29 Thread David Gibson
On Mon, Feb 29, 2016 at 04:42:58PM +0100, Igor Mammedov wrote:
> On Thu, 25 Feb 2016 14:52:06 -0300
> Eduardo Habkost  wrote:
> 
> > On Wed, Feb 24, 2016 at 03:42:18PM +0100, Igor Mammedov wrote:
> > > On Tue, 23 Feb 2016 18:26:20 -0300
> > > Eduardo Habkost  wrote:
> > >   
> > > > On Tue, Feb 23, 2016 at 10:46:45AM +0100, Igor Mammedov wrote:  
> > > > > On Mon, 22 Feb 2016 13:54:32 +1100
> > > > > David Gibson  wrote:
> > > > [...]  
> > > > > > This is why Eduardo suggested - and I agreed - that it's probably
> > > > > > better to implement the "1st layer" as an internal 
> > > > > > structure/interface
> > > > > > only, and implement the 2nd layer on top of that.  When/if we need 
> > > > > > to
> > > > > > we can revisit a user-accessible interface to the 1st layer.
> > > > > We are going around QOM based CPU introspecting interface for
> > > > > years now and that's exactly what 2nd layer is, just another
> > > > > implementation. I've just lost hope in this approach.
> > > > > 
> > > > > What I'm suggesting in this RFC is to forget controversial
> > > > > QOM approach for now and use -device/device_add + QMP introspection,  
> > > > >   
> > > > 
> > > > You have a point about it looking controversial, but I would like
> > > > to understand why exactly it is controversial. Discussions seem
> > > > to get stuck every single time we try to do something useful with
> > > > the QOM tree, and I don't undertsand why.  
> > > Maybe because we are trying to create a universal solution to fit
> > > ALL platforms? And every time some one posts patches to show
> > > implementation, it would break something in existing machine
> > > or is not complete in terms of how interface would work wrt
> > > mgmt/CLI/migration.  
> > 
> > That's true.
> > 
> > >   
> > > >   
> > > > > i.e. completely split interface from how boards internally implement
> > > > > CPU hotplug.
> > > > 
> > > > A QOM-based interface may still split the interface from how
> > > > boards internally implement CPU hotplug. They don't need to
> > > > affect the device tree of the machine, we just need to create QOM
> > > > objects or links at predictable paths, that implement certain
> > > > interfaces.  
> > > Beside of not being able to reach consensus for a long time,
> > > I'm fine with isolated QOM interface if it allow us to move forward.
> > > However static QMP/QAPI interface seems to be better describing and
> > > has better documentation vs current very flexible poorly self-describing 
> > > QOM.  
> > 
> > You have a good point: QMP is more stable and better documented.
> > QOM is easier for making experiments, and I would really like to
> > see it being used more. But if we still don't understand the
> > requirements enough to design a QMP interface, we won't be able
> > to implement the same functionality using QOM either.
> > 
> > If we figure out the requirements, I believe we should be able to
> > design equivalent QMP and QOM interfaces.
> So not to stall CPU hotplug progress, I'd start with stable QMP query
> interface for general use, leaving experimental QOM interface for later
> as difficult to discover and poorly documented one from mgmt pov,
> meaning mgmt would have to:
>  - instantiate a particular machine type to find if QOM interface is 
> supported,
>i.e. '-machine none' won't work with it as it's board depended VS static 
> compile time qapi-schema in QMP case
>  - execute a bunch of qom-list/qom-read requests over wire to enumerate/query
>objects starting at some fixed entry point (/machine/cpus) VS a single 
> command that does 'atomic' enumeration in QMP case.

That sounds reasonable to me.

However, before even that, I think we need to work out exactly what
device_add of a multi-thread cpu module looks like.  I think that's
less of a solved problem than everyone seems to be assuming.

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [RFC PATCH v0 2/6] spapr: CPU core device

2016-02-29 Thread David Gibson
On Mon, Feb 29, 2016 at 04:15:25PM +0100, Igor Mammedov wrote:
> On Mon, 29 Feb 2016 18:25:25 +0530
> Bharata B Rao  wrote:
> > On Mon, Feb 29, 2016 at 11:03:16AM +0100, Igor Mammedov wrote:
> > > On Mon, 29 Feb 2016 11:20:19 +0530
> > > Bharata B Rao  wrote:
[snip]
> > > > > "slot" seems intended to be a machine-agnostic of mapping device
> > > > > types discovered from qmp_query_cpu_slots() to an appropriate
> > > > > "bus" location, but here's it a field specific to TYPE_SPAPR_CPU_CORE.
> > > > > It seems like maybe TYPE_CPU_CORE is a better place, but then on
> > > > > x86 I suppose it might be TYPE_CPU_SOCKET or something instead...
> > > > 
> > > > Correct.
> > > >   
> > > > > 
> > > > > It almost seems like a TYPE_INTERFACE_SLOTABLE would be the
> > > > > right approach, but I don't know how we could expose that as
> > > > > a property. I guess it's somewhat implied that this "interface"
> > > > > exists if qmp_query_cpu_slots() returns the type, but I wonder
> > > > > if something a bit more formal should be modeled to make the
> > > > > implementation requirements a bit clearer.
> > > > > 
> > > > > Maybe have TYPE_CPU_{CORE,SOCKET} classes have a get_slot/set_slot
> > > > > class method, expose them via "slot" property, then have the
> > > > > defaults generate "not implemented" errors?
> > > > 
> > > > Yes makes sense. In fact David has often times said that generic
> > > > properties/routines should be pushed to base class wherever possible.
> > > > 
> > > > I didn't do that in this first iteration to keep the generic changes
> > > > as minimum as possible, but yes slot should be a property of the
> > > > base class of core or socket.  
> > > Then what will happen to slot if there isn't any core/socket device
> > > to query it, i.e. cpu hasn't been plugged in yet?
> > > To me slot looks like a machine belonged feature.  
> > 
> > Yes slot belongs to the machine and it is represented by a link that
> > is created b/n the machine object and the core object that sits in
> > the slot.
> > 
> > In the context of this thread, slot is actually the slot name that
> > identifies the machine slot which the core occupies or will occupy after
> > hotplug. Thus slot name which is named slot here, it is a property of the
> > core device.
> > 
> > (qemu) device_add spapr-cpu-core,slot=core[2]
> >  ^
> Is 'slot' a term used by SPAPR on real hardware?

So.. PAPR is a para-virtualized interface, so it never appears on real
hardware.

But, no, "slot" is not a term used by PAPR.

> I'd thought that it's 'core', that's why I suggested to use
> 'core' for POWER as that matched real world concept, see
> my other reply in "[RFC PATCH v0 4/6] spapr: CPU hotplug support" thread
> of this series.

I don't think it uses "core" either, I believe it uses just "cpu" but
meaning a multi-thread core, rather than a single logical cpu thread.

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


[Qemu-devel] How to make changes to qapi-types.h

2016-02-29 Thread Programmingkid
I need to add a variable to the QKeyCode enum in the file qapi-types.h. This 
file is auto-generated so using traditional means to create a patch is not 
possible. Would anyone know how I can add to this file?


Re: [Qemu-devel] [PATCH v2 03/15] docker: Add images

2016-02-29 Thread Fam Zheng
On Mon, 02/29 17:18, Alex Bennée wrote:
> 
> Fam Zheng  writes:
> 
> > Signed-off-by: Fam Zheng 
> 
> I think we need to include the dtc libs in here unless we need to ship
> all submodules in the tree as well.

OK, will take a look.

> 
> Is there a way to get a plain install shell? PAUSE=1 on the test shells
> doesn't seem to allow me to install anything.

What is the error when you install things? I think it is an unmodified shell
and "yum" or "apt-get" should just work. It's just that when the container
exits the changes will be discarded.

Fam



Re: [Qemu-devel] [PATCH v2 01/15] tests: Add utilities for docker testing

2016-02-29 Thread Fam Zheng
On Mon, 02/29 16:46, Alex Bennée wrote:
> 
> Fam Zheng  writes:
> 
> > docker_run: A wrapper for "docker run" (or "sudo -n docker run" if
> > necessary), which takes care of killing and removing the running
> > container at SIGINT.
> >
> > docker_clean: A tool to tear down all the containers including inactive
> > ones that are started by docker_run.
> >
> > docker_build: A tool to compare an image from given dockerfile and
> > rebuild it if they're different.
> >
> > Signed-off-by: Fam Zheng 
> > ---
> >  tests/docker/docker.py| 113 
> > ++
> >  tests/docker/docker_build |  42 +
> >  tests/docker/docker_clean |  22 +
> >  tests/docker/docker_run   |  29 
> >  4 files changed, 206 insertions(+)
> >  create mode 100755 tests/docker/docker.py
> >  create mode 100755 tests/docker/docker_build
> >  create mode 100755 tests/docker/docker_clean
> >  create mode 100755 tests/docker/docker_run
> >
> > diff --git a/tests/docker/docker.py b/tests/docker/docker.py
> > new file mode 100755
> > index 000..d175a86
> > --- /dev/null
> > +++ b/tests/docker/docker.py
> > @@ -0,0 +1,113 @@
> > +#!/usr/bin/env python2 -B
> > +#
> > +# Docker controlling module
> > +#
> > +# Copyright (c) 2016 Red Hat Inc.
> > +#
> > +# Authors:
> > +#  Fam Zheng 
> > +#
> > +# This work is licensed under the terms of the GNU GPL, version 2
> > +# or (at your option) any later version. See the COPYING file in
> > +# the top-level directory.
> > +
> > +import os
> > +import subprocess
> > +import json
> > +import hashlib
> > +import atexit
> > +import uuid
> > +
> > +class ContainerTerminated(Exception):
> > +""" Raised if the container has already existed """
> > +pass
> > +
> > +class Docker(object):
> > +""" Running Docker commands """
> > +def __init__(self):
> > +self._command = self._guess_command()
> > +self._instances = []
> > +atexit.register(self._kill_instances)
> > +
> > +def _do(self, cmd, quiet=True, **kwargs):
> > +if quiet:
> > +kwargs["stdout"] = subprocess.PIPE
> > +return subprocess.call(self._command + cmd, **kwargs)
> > +
> > +def _do_kill_instances(self, only_known, only_active=True):
> > +cmd = ["ps", "-q"]
> 
> Hmm ps -q barfs on my command line:
> 
> 16:04 alex@zen/x86_64  [qemu.git/mttcg/multi_tcg_v8_ajb-r2] >ps -q
> error: unsupported SysV option
> 
> Is there not a more portable way of doing this, even if it is a standard
> library?

Down the road this is "sudo docker ps" command. :)

> 
> > +if not only_active:
> > +cmd.append("-a")
> > +for i in self._output(cmd).split():
> > +resp = self._output(["inspect", i])
> > +labels = json.loads(resp)[0]["Config"]["Labels"]
> > +active = json.loads(resp)[0]["State"]["Running"]
> > +if not labels:
> > +continue
> > +instance_uuid = labels.get("com.qemu.instance.uuid", None)
> > +if not instance_uuid:
> > +continue
> > +if only_known and instance_uuid not in self._instances:
> > +continue
> > +print "Terminating", i
> > +if active:
> > +self._do(["kill", i])
> > +self._do(["rm", i])
> > +
> > +def clean(self):
> > +self._do_kill_instances(False, False)
> > +return 0
> > +
> > +def _kill_instances(self):
> > +return self._do_kill_instances(True)
> > +
> > +def _output(self, cmd, **kwargs):
> > +return subprocess.check_output(self._command + cmd,
> > +   stderr=subprocess.STDOUT,
> > +   **kwargs)
> > +
> > +def _guess_command(self):
> > +commands = [["docker"], ["sudo", "-n", "docker"]]
> > +for cmd in commands:
> > +if subprocess.call(cmd + ["images"],
> > +   stdout=subprocess.PIPE,
> > +   stderr=subprocess.PIPE) == 0:
> > +return cmd
> > +commands_txt = "\n".join(["  " + " ".join(x) for x in commands])
> > +raise Exception("Cannot find working docker command. Tried:\n%s" % 
> > commands_txt)
> > +
> > +def get_image_dockerfile_checksum(self, tag):
> > +resp = self._output(["inspect", tag])
> > +labels = json.loads(resp)[0]["Config"].get("Labels", {})
> > +return labels.get("com.qemu.dockerfile-checksum", "")
> > +
> > +def checksum(self, text):
> > +return hashlib.sha1(text).hexdigest()
> > +
> > +def build_image(self, tag, dockerfile, df, quiet=True):
> > +tmp = dockerfile + "\n" + \
> > +  "LABEL com.qemu.dockerfile-checksum=%s" % 
> > self.checksum(dockerfile)
> > +tmp_df = df + ".tmp"
> > +tmp_file = open(tmp_df, "wb")
> > +   

Re: [Qemu-devel] [PATCH v2 02/15] Makefile: Rules for docker testing

2016-02-29 Thread Fam Zheng
On Mon, 02/29 17:08, Alex Bennée wrote:
> 
> Fam Zheng  writes:
> 
> > This adds a group of make targets to run docker tests, all are available
> > in source tree without running ./configure.
> >
> > The usage is shown by "make docker".
> >
> > Besides the fixed ones, dynamic targets for building each image and
> > running each test in each image are generated automatically by make,
> > scanning $(SRC_PATH)/tests/docker/ files with specific patterns.
> >
> > Alternative to manually list particular targets (docker-run-FOO@BAR)
> > set, you can control which tests/images to run by filtering variables,
> > TESTS= and IMAGES=, which are expressed in Makefile pattern syntax,
> > "foo% %bar ...". For example:
> >
> > $ make docker-run IMAGES="ubuntu fedora"
> 
> This doesn't seem to work for me:
> 
> 16:49 alex@zen/x86_64  [qemu.git/review/docker-tests-v2] >make
> docker-run IMAGES="ubuntu" V=1
> /home/alex/lsrc/qemu/qemu.git/rules.mak:178: warning: overriding
> commands for target `clean-timestamp'
> /home/alex/lsrc/qemu/qemu.git/rules.mak:178: warning: ignoring old
> commands for target `clean-timestamp'
> make: *** No rule to make target `docker-run'. Stop.

The commit message is stale, as the help text, the target is now "docker-test"
which is more intuitive.

Fam

> `
> 
> >
> > Unfortunately, it's impossible to propagate "-j $JOBS" into make in
> > containers, however since each combination is made a first class target
> > is the top Makefile, "make -j$N docker-run" still parallels the tests
> > coarsely.
> >
> > Signed-off-by: Fam Zheng 
> > ---
> >  Makefile  |  4 +-
> >  tests/docker/Makefile.include | 93 
> > +++
> >  2 files changed, 96 insertions(+), 1 deletion(-)
> >  create mode 100644 tests/docker/Makefile.include
> >
> > diff --git a/Makefile b/Makefile
> > index f9fae3a..f104a08 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -6,7 +6,7 @@ BUILD_DIR=$(CURDIR)
> >  # Before including a proper config-host.mak, assume we are in the source 
> > tree
> >  SRC_PATH=.
> >
> > -UNCHECKED_GOALS := %clean TAGS cscope ctags
> > +UNCHECKED_GOALS := %clean TAGS cscope ctags docker docker-%
> >
> >  # All following code might depend on configuration variables
> >  ifneq ($(wildcard config-host.mak),)
> > @@ -651,3 +651,5 @@ endif
> >  # Include automatically generated dependency files
> >  # Dependencies in Makefile.objs files come from our recursive subdir rules
> >  -include $(wildcard *.d tests/*.d)
> > +
> > +include $(SRC_PATH)/tests/docker/Makefile.include
> > diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
> > new file mode 100644
> > index 000..d8c55c3
> > --- /dev/null
> > +++ b/tests/docker/Makefile.include
> > @@ -0,0 +1,93 @@
> > +# Makefile for Docker tests
> > +
> > +$(if $(quiet-command),,$(eval include $(SRC_PATH)/rules.mak))
> > +
> > +.PHONY: docker docker-test docker-clean docker-image
> > +
> > +DOCKER_SUFFIX := .docker
> > +
> > +DOCKER_IMAGES := $(notdir $(basename \
> > +   $(wildcard $(SRC_PATH)/tests/docker/dockerfiles/*)))
> > +
> > +DOCKER_TESTS := $(notdir $(shell \
> > +   find $(SRC_PATH)/tests/docker/ -name 'test-*' -type f -executable))
> > +
> > +DOCKER_TOOLS := travis
> > +
> > +TESTS ?= %
> > +IMAGES ?= %
> > +
> > +$(foreach i,$(DOCKER_IMAGES), \
> > +   $(eval docker-image: docker-image-$i) \
> > +   $(eval docker-image-$i: IMAGE = $i) \
> > +   $(eval .PHONY: docker-image-$i docker-@$i) \
> > +   $(foreach t,$(DOCKER_TESTS) $(DOCKER_TOOLS), \
> > +   $(eval .PHONY: docker-$t@$i) \
> > +   $(eval docker-$t@$i: docker-image-$i) \
> > +   $(eval docker-$t@$i: docker-run-$t@$i) \
> > +   $(eval docker-@$i: docker-$t@$i) \
> > +   $(eval docker-test: docker-run-$t@$i) \
> > +   ) \
> > +)
> > +
> > +docker:
> > +   @echo 'Building QEMU and running tests inside Docker containers'
> > +   @echo
> > +   @echo 'Available targets:'
> > +   @echo
> > +   @echo 'docker:  Print this help.'
> > +   @echo 'docker-test: Run all image/test combinations.'
> > +   @echo 'docker-clean:Kill and remove residual docker testing 
> > containers.'
> > +   @echo 'docker-TEST@IMAGE:   Run "TEST" in container "IMAGE".'
> > +   @echo ' Note: "TEST" is one of the listed test 
> > name,'
> > +   @echo ' or a script name under 
> > $$QEMU_SRC/tests/docker/;'
> > +   @echo ' "IMAGE" is one of the listed container 
> > name."'
> > +   @echo 'docker-@IMAGE:   Run all tests in container "IMAGE".'
> > +   @echo 'docker-image:Build all images.'
> > +   @echo 'docker-image-IMAGE:  Build image "IMG".'
> > +   @echo
> > +   @echo 'Available container images:'
> > +   @echo '$(DOCKER_IMAGES)'
> > +   @echo
> > +   @echo 'Available tests:'
> > +   @echo '$(DOCKER_TESTS)'
> > +   @echo
> > +   @echo 

Re: [Qemu-devel] [PATCH v2 00/16] qapi: Allow blockdev-add for NBD

2016-02-29 Thread Max Reitz
On 01.03.2016 00:24, Eric Blake wrote:
> On 02/29/2016 04:19 PM, Max Reitz wrote:
>> Turns out NBD is not so simple to do if you do it right. Anyway, this
>> series adds blockdev-add support for NBD clients.
>>
>> Patches 1 and 2 add one less and one more complicated QDict function,
>> respectively, which I needed in later NBD patches: Patch 1 for handling
>> legacy options (move "host" to "address.data.host" etc.) and patch 2
>> because I'd like to use the input visitor for transforming the NBD
>> options into a SocketAddress. Unfortunately, the block layer uses
>> flattened QDicts everywhere, so we'll have to unflatten (erect?) them
>> before we can use that visitor.
> 
> Dan had a patch proposal that called the operation "crumple"; I need to
> review both proposals and see which one I like.
> https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg04618.html

Well, here I go again, not looking at patches on the list...

Looking at the design, I like his idea of having an escape sequence;
also, his qdict_crumple() can return boths lists and dicts where my
qdict_unflatten() only returns dicts (then again, this is what
qdict_flatten() always works on). And his patch doesn't suffer from as
much indentation as mine does.

What I like more about my patch, however, is that I'm reusing
qdict_array_split() and qdict_array_entries(). That is mostly because my
function modifies the given QDict, where Dan's does not.

>>
>> Patch 3 adds a test for qdict_unflatten().
>>
>> Patches 4, 5, 6, and 7 are minor patches with no functional relation to
>> this series, other than later patches will touch the code they touch,
>> too.
>>
>> Patches 8 and 9 prepare the code for the addition of a new option
>> prefix, which is "address.".
>>
>> Patch 10 makes the NBD client accept a SocketAddress under the "address"
>> option (or rather, a flattened SocketAddress QDict with its keys
>> prefixed by "address."). The old options "host", "port", and "path" are
>> supported as legacy options and translated to the respective
>> SocketAddress representation.
>>
>> Patch 11 drops usage of "host", "port", and "path" outside of
>> nbd_has_filename_options_conflict(),
>> nbd_process_legacy_socket_options(), and nbd_refresh_filename(), making
>> those options nothing but legacy.
>>
>> Patch 12, the goal of this series, is again not very complicated.
>>
>> Patches 13, 14, and 15 are required for the iotest added in patch 16. It
>> will invoke qemu-nbd, so patch 13 is required. Besides qemu-nbd, it will
>> launch an NBD server VM concurrently to the client VM, which is why
>> patch 14 is required. And finally, it will test whether we can add an
>> NBD BDS by passing it a file descriptor, which patch 15 is needed for
>> (so we use the socket_scm_helper to pass sockets to qemu).
>>
>> Patch 16 then adds the iotest for NBD's blockdev-add interface.
>>
>>
>> Note on the relation to v1: As you can see, most of this series is
>> completely new. Patch 5 was patch 1 in v1, and the only thing that has
>> changed is that I removed the full stop at the end of the error message;
>> consequently I kept Eric's R-b.
> 
> Looks like my review queue is getting longer because I (like several
> other people) are trying to post last-minute series before soft freeze.

So is mine. :-)

Yes, during the last week I had to prioritize patches over reviewing.

Max



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v2 10/16] block/nbd: Accept SocketAddress

2016-02-29 Thread Max Reitz
Add a new option "address" to the NBD block driver which accepts a
SocketAddress.

"path", "host" and "port" are still supported as legacy options and are
mapped to their corresponding SocketAddress representation.

Signed-off-by: Max Reitz 
---
 block/nbd.c   | 93 +++
 tests/qemu-iotests/051.out|  4 +-
 tests/qemu-iotests/051.pc.out |  4 +-
 3 files changed, 62 insertions(+), 39 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 86907bc..213ba70 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -31,6 +31,8 @@
 #include "qemu/uri.h"
 #include "block/block_int.h"
 #include "qemu/module.h"
+#include "qapi-visit.h"
+#include "qapi/qmp-input-visitor.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qjson.h"
 #include "qapi/qmp/qint.h"
@@ -127,7 +129,9 @@ static bool nbd_has_filename_options_conflict(QDict 
*options, Error **errp)
 if (!strcmp(e->key, "host")
 || !strcmp(e->key, "port")
 || !strcmp(e->key, "path")
-|| !strcmp(e->key, "export"))
+|| !strcmp(e->key, "export")
+|| !strcmp(e->key, "address")
+|| !strncmp(e->key, "address.", 8))
 {
 error_setg(errp, "Option '%s' cannot be used with a file name",
e->key);
@@ -201,44 +205,64 @@ out:
 g_free(file);
 }
 
+static bool nbd_process_legacy_socket_options(QDict *options, Error **errp)
+{
+if (qdict_haskey(options, "path") && qdict_haskey(options, "host")) {
+error_setg(errp, "path and host may not be used at the same time");
+return false;
+} else if (qdict_haskey(options, "path")) {
+if (qdict_haskey(options, "port")) {
+error_setg(errp, "port may not be used without host");
+return false;
+}
+
+qdict_put(options, "address.type", qstring_from_str("unix"));
+qdict_change_key(options, "path", "address.data.path");
+} else if (qdict_haskey(options, "host")) {
+qdict_put(options, "address.type", qstring_from_str("inet"));
+qdict_change_key(options, "host", "address.data.host");
+if (!qdict_change_key(options, "port", "address.data.port")) {
+qdict_put(options, "address.data.port",
+  qstring_from_str(stringify(NBD_DEFAULT_PORT)));
+}
+}
+
+return true;
+}
+
 static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, char 
**export,
  Error **errp)
 {
-SocketAddress *saddr;
+SocketAddress *saddr = NULL;
+QDict *addr = NULL;
+QmpInputVisitor *iv;
+Error *local_err = NULL;
 
-if (qdict_haskey(options, "path") == qdict_haskey(options, "host")) {
-if (qdict_haskey(options, "path")) {
-error_setg(errp, "path and host may not be used at the same time");
-} else {
-error_setg(errp, "one of path and host must be specified");
-}
-return NULL;
+if (!nbd_process_legacy_socket_options(options, errp)) {
+goto fail;
 }
-if (qdict_haskey(options, "port") && !qdict_haskey(options, "host")) {
-error_setg(errp, "port may not be used without host");
-return NULL;
+
+qdict_extract_subqdict(options, , "address.");
+if (!qdict_unflatten(addr, errp)) {
+goto fail;
 }
 
-saddr = g_new0(SocketAddress, 1);
+if (!qdict_size(addr)) {
+error_setg(errp, "NBD server address missing");
+goto fail;
+}
 
-if (qdict_haskey(options, "path")) {
-saddr->type = SOCKET_ADDRESS_KIND_UNIX;
-saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
-saddr->u.q_unix->path = g_strdup(qdict_get_str(options, "path"));
-qdict_del(options, "path");
-} else {
-saddr->type = SOCKET_ADDRESS_KIND_INET;
-saddr->u.inet = g_new0(InetSocketAddress, 1);
-saddr->u.inet->host = g_strdup(qdict_get_str(options, "host"));
-if (!qdict_get_try_str(options, "port")) {
-saddr->u.inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
-} else {
-saddr->u.inet->port = g_strdup(qdict_get_str(options, "port"));
-}
-qdict_del(options, "host");
-qdict_del(options, "port");
+iv = qmp_input_visitor_new(QOBJECT(addr));
+visit_type_SocketAddress(qmp_input_get_visitor(iv), NULL, ,
+ _err);
+qmp_input_visitor_cleanup(iv);
+if (local_err) {
+error_propagate(errp, local_err);
+goto fail;
 }
 
+/* TODO: Detect superfluous (unused) options under in addr */
+
 s->client.is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
 
 *export = g_strdup(qdict_get_try_str(options, "export"));
@@ -246,7 +270,12 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict 
*options, char **export,
 qdict_del(options, "export");
 }
 
+QDECREF(addr);
 return saddr;
+
+fail:
+QDECREF(addr);

[Qemu-devel] [PATCH v2 11/16] block/nbd: Use SocketAddress options

2016-02-29 Thread Max Reitz
Drop the use of legacy options in favor of the SocketAddress
representation, even for internal use (i.e. for storing the result of
the filename parsing).

Signed-off-by: Max Reitz 
---
 block/nbd.c | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 213ba70..471395a 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -88,9 +88,13 @@ static int nbd_parse_uri(const char *filename, QDict 
*options)
 ret = -EINVAL;
 goto out;
 }
-qdict_put(options, "path", qstring_from_str(qp->p[0].value));
+qdict_put(options, "address.type", qstring_from_str("unix"));
+qdict_put(options, "address.data.path",
+  qstring_from_str(qp->p[0].value));
 } else {
 QString *host;
+char *port_str;
+
 /* nbd[+tcp]://host[:port]/export */
 if (!uri->server) {
 ret = -EINVAL;
@@ -105,12 +109,12 @@ static int nbd_parse_uri(const char *filename, QDict 
*options)
 host = qstring_from_str(uri->server);
 }
 
-qdict_put(options, "host", host);
-if (uri->port) {
-char* port_str = g_strdup_printf("%d", uri->port);
-qdict_put(options, "port", qstring_from_str(port_str));
-g_free(port_str);
-}
+qdict_put(options, "address.type", qstring_from_str("inet"));
+qdict_put(options, "address.data.host", host);
+
+port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT);
+qdict_put(options, "address.data.port", qstring_from_str(port_str));
+g_free(port_str);
 }
 
 out:
@@ -187,7 +191,8 @@ static void nbd_parse_filename(const char *filename, QDict 
*options,
 
 /* are we a UNIX or TCP socket? */
 if (strstart(host_spec, "unix:", )) {
-qdict_put(options, "path", qstring_from_str(unixpath));
+qdict_put(options, "address.type", qstring_from_str("unix"));
+qdict_put(options, "address.data.path", qstring_from_str(unixpath));
 } else {
 InetSocketAddress *addr = NULL;
 
@@ -196,8 +201,9 @@ static void nbd_parse_filename(const char *filename, QDict 
*options,
 goto out;
 }
 
-qdict_put(options, "host", qstring_from_str(addr->host));
-qdict_put(options, "port", qstring_from_str(addr->port));
+qdict_put(options, "address.type", qstring_from_str("inet"));
+qdict_put(options, "address.data.host", qstring_from_str(addr->host));
+qdict_put(options, "address.data.port", qstring_from_str(addr->port));
 qapi_free_InetSocketAddress(addr);
 }
 
@@ -506,10 +512,12 @@ static void nbd_refresh_filename(BlockDriverState *bs, 
QDict *options)
 }
 } else {
 if (path) {
-qdict_put(opts, "path", qstring_from_str(path));
+qdict_put(opts, "address.type", qstring_from_str("unix"));
+qdict_put(opts, "address.data.path", qstring_from_str(path));
 } else {
-qdict_put(opts, "host", qstring_from_str(host));
-qdict_put(opts, "port", qstring_from_str(port));
+qdict_put(opts, "address.type", qstring_from_str("inet"));
+qdict_put(opts, "address.data.host", qstring_from_str(host));
+qdict_put(opts, "address.data.port", qstring_from_str(port));
 }
 }
 if (export) {
-- 
2.7.1




Re: [Qemu-devel] [PATCH v2 00/16] qapi: Allow blockdev-add for NBD

2016-02-29 Thread Eric Blake
On 02/29/2016 04:19 PM, Max Reitz wrote:
> Turns out NBD is not so simple to do if you do it right. Anyway, this
> series adds blockdev-add support for NBD clients.
> 
> Patches 1 and 2 add one less and one more complicated QDict function,
> respectively, which I needed in later NBD patches: Patch 1 for handling
> legacy options (move "host" to "address.data.host" etc.) and patch 2
> because I'd like to use the input visitor for transforming the NBD
> options into a SocketAddress. Unfortunately, the block layer uses
> flattened QDicts everywhere, so we'll have to unflatten (erect?) them
> before we can use that visitor.

Dan had a patch proposal that called the operation "crumple"; I need to
review both proposals and see which one I like.
https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg04618.html

> 
> Patch 3 adds a test for qdict_unflatten().
> 
> Patches 4, 5, 6, and 7 are minor patches with no functional relation to
> this series, other than later patches will touch the code they touch,
> too.
> 
> Patches 8 and 9 prepare the code for the addition of a new option
> prefix, which is "address.".
> 
> Patch 10 makes the NBD client accept a SocketAddress under the "address"
> option (or rather, a flattened SocketAddress QDict with its keys
> prefixed by "address."). The old options "host", "port", and "path" are
> supported as legacy options and translated to the respective
> SocketAddress representation.
> 
> Patch 11 drops usage of "host", "port", and "path" outside of
> nbd_has_filename_options_conflict(),
> nbd_process_legacy_socket_options(), and nbd_refresh_filename(), making
> those options nothing but legacy.
> 
> Patch 12, the goal of this series, is again not very complicated.
> 
> Patches 13, 14, and 15 are required for the iotest added in patch 16. It
> will invoke qemu-nbd, so patch 13 is required. Besides qemu-nbd, it will
> launch an NBD server VM concurrently to the client VM, which is why
> patch 14 is required. And finally, it will test whether we can add an
> NBD BDS by passing it a file descriptor, which patch 15 is needed for
> (so we use the socket_scm_helper to pass sockets to qemu).
> 
> Patch 16 then adds the iotest for NBD's blockdev-add interface.
> 
> 
> Note on the relation to v1: As you can see, most of this series is
> completely new. Patch 5 was patch 1 in v1, and the only thing that has
> changed is that I removed the full stop at the end of the error message;
> consequently I kept Eric's R-b.

Looks like my review queue is getting longer because I (like several
other people) are trying to post last-minute series before soft freeze.

-- 
Eric Blake   eblake redhat com+1-919-301-3266
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [PATCH v2 09/16] block/nbd: "address" in nbd_refresh_filename()

2016-02-29 Thread Max Reitz
As of a future patch, the NBD block driver will accept a SocketAddress
structure for a new "address" option. In order to support this,
nbd_refresh_filename() needs some changes.

The two TODOs introduced by this patch will be removed in the very next
one. They exist to explain that it is currently impossible for
nbd_refresh_filename() to emit an "address.*" option (which the NBD
block driver does not handle yet). The next patch will arm these code
paths, but it will also enable handling of these options.

Signed-off-by: Max Reitz 
---
 block/nbd.c | 80 +
 1 file changed, 59 insertions(+), 21 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 2d96dd1..86907bc 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -419,37 +419,75 @@ static void nbd_attach_aio_context(BlockDriverState *bs,
 static void nbd_refresh_filename(BlockDriverState *bs, QDict *options)
 {
 QDict *opts = qdict_new();
-const char *path   = qdict_get_try_str(options, "path");
-const char *host   = qdict_get_try_str(options, "host");
-const char *port   = qdict_get_try_str(options, "port");
+bool can_generate_filename = true;
+const char *path = NULL, *host = NULL, *port = NULL;
 const char *export = qdict_get_try_str(options, "export");
 const char *tlscreds = qdict_get_try_str(options, "tls-creds");
 
-if (host && !port) {
-port = stringify(NBD_DEFAULT_PORT);
+if (qdict_get_try_str(options, "address.type")) {
+/* This path will only be possible as of a future patch;
+ * TODO: Remove this note once it is */
+
+const char *type = qdict_get_str(options, "address.type");
+
+if (!strcmp(type, "unix")) {
+path = qdict_get_str(options, "address.data.path");
+} else if (!strcmp(type, "inet")) {
+host = qdict_get_str(options, "address.data.host");
+port = qdict_get_str(options, "address.data.port");
+
+can_generate_filename = !qdict_haskey(options, "address.data.to")
+ && !qdict_haskey(options, "address.data.ipv4")
+ && !qdict_haskey(options, 
"address.data.ipv6");
+} else {
+can_generate_filename = false;
+}
+} else {
+path = qdict_get_try_str(options, "path");
+host = qdict_get_try_str(options, "host");
+port = qdict_get_try_str(options, "port");
+
+if (host && !port) {
+port = stringify(NBD_DEFAULT_PORT);
+}
 }
 
 qdict_put(opts, "driver", qstring_from_str("nbd"));
 
-if (path && export) {
-snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "nbd+unix:///%s?socket=%s", export, path);
-} else if (path && !export) {
-snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "nbd+unix://?socket=%s", path);
-} else if (!path && export) {
-snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "nbd://%s:%s/%s", host, port, export);
-} else if (!path && !export) {
-snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "nbd://%s:%s", host, port);
+if (can_generate_filename) {
+if (path && export) {
+snprintf(bs->exact_filename, sizeof(bs->exact_filename),
+ "nbd+unix:///%s?socket=%s", export, path);
+} else if (path && !export) {
+snprintf(bs->exact_filename, sizeof(bs->exact_filename),
+ "nbd+unix://?socket=%s", path);
+} else if (!path && export) {
+snprintf(bs->exact_filename, sizeof(bs->exact_filename),
+ "nbd://%s:%s/%s", host, port, export);
+} else if (!path && !export) {
+snprintf(bs->exact_filename, sizeof(bs->exact_filename),
+ "nbd://%s:%s", host, port);
+}
 }
 
-if (path) {
-qdict_put(opts, "path", qstring_from_str(path));
+if (qdict_get_try_str(options, "address.type")) {
+/* This path will only be possible as of a future patch;
+ * TODO: Remove this note once it is */
+
+const QDictEntry *e;
+for (e = qdict_first(options); e; e = qdict_next(options, e)) {
+if (!strncmp(e->key, "address.", 8)) {
+qobject_incref(e->value);
+qdict_put_obj(opts, e->key, e->value);
+}
+}
 } else {
-qdict_put(opts, "host", qstring_from_str(host));
-qdict_put(opts, "port", qstring_from_str(port));
+if (path) {
+qdict_put(opts, "path", qstring_from_str(path));
+} else {
+qdict_put(opts, "host", qstring_from_str(host));
+qdict_put(opts, "port", qstring_from_str(port));
+}
 }
 if (export) {
 qdict_put(opts, "export", qstring_from_str(export));
-- 
2.7.1




[Qemu-devel] [PATCH v2 15/16] socket_scm_helper: Accept fd directly

2016-02-29 Thread Max Reitz
This gives us more freedom about the fd that is passed to qemu, allowing
us to e.g. pass sockets.

Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/socket_scm_helper.c | 29 ++---
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/tests/qemu-iotests/socket_scm_helper.c 
b/tests/qemu-iotests/socket_scm_helper.c
index 80cadf4..eb76d31 100644
--- a/tests/qemu-iotests/socket_scm_helper.c
+++ b/tests/qemu-iotests/socket_scm_helper.c
@@ -60,7 +60,7 @@ static int send_fd(int fd, int fd_to_send)
 }
 
 /* Convert string to fd number. */
-static int get_fd_num(const char *fd_str)
+static int get_fd_num(const char *fd_str, bool silent)
 {
 int sock;
 char *err;
@@ -68,12 +68,16 @@ static int get_fd_num(const char *fd_str)
 errno = 0;
 sock = strtol(fd_str, , 10);
 if (errno) {
-fprintf(stderr, "Failed in strtol for socket fd, reason: %s\n",
-strerror(errno));
+if (!silent) {
+fprintf(stderr, "Failed in strtol for socket fd, reason: %s\n",
+strerror(errno));
+}
 return -1;
 }
 if (!*fd_str || *err || sock < 0) {
-fprintf(stderr, "bad numerical value for socket fd '%s'\n", fd_str);
+if (!silent) {
+fprintf(stderr, "bad numerical value for socket fd '%s'\n", 
fd_str);
+}
 return -1;
 }
 
@@ -104,18 +108,21 @@ int main(int argc, char **argv, char **envp)
 }
 
 
-sock = get_fd_num(argv[1]);
+sock = get_fd_num(argv[1], false);
 if (sock < 0) {
 return EXIT_FAILURE;
 }
 
-/* Now only open a file in readonly mode for test purpose. If more precise
-   control is needed, use python script in file operation, which is
-   supposed to fork and exec this program. */
-fd = open(argv[2], O_RDONLY);
+fd = get_fd_num(argv[2], true);
 if (fd < 0) {
-fprintf(stderr, "Failed to open file '%s'\n", argv[2]);
-return EXIT_FAILURE;
+/* Now only open a file in readonly mode for test purpose. If more
+   precise control is needed, use python script in file operation, 
which
+   is supposed to fork and exec this program. */
+fd = open(argv[2], O_RDONLY);
+if (fd < 0) {
+fprintf(stderr, "Failed to open file '%s'\n", argv[2]);
+return EXIT_FAILURE;
+}
 }
 
 ret = send_fd(sock, fd);
-- 
2.7.1




[Qemu-devel] [PATCH v2 07/16] block/nbd: Use qdict_put()

2016-02-29 Thread Max Reitz
Instead of inlining this nice macro (i.e. resorting to
qdict_put_obj(..., QOBJECT(...))), use it.

Signed-off-by: Max Reitz 
---
 block/nbd.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 8d9a217..145db39 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -415,7 +415,7 @@ static void nbd_refresh_filename(BlockDriverState *bs, 
QDict *options)
 port = stringify(NBD_DEFAULT_PORT);
 }
 
-qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("nbd")));
+qdict_put(opts, "driver", qstring_from_str("nbd"));
 
 if (path && export) {
 snprintf(bs->exact_filename, sizeof(bs->exact_filename),
@@ -432,16 +432,16 @@ static void nbd_refresh_filename(BlockDriverState *bs, 
QDict *options)
 }
 
 if (path) {
-qdict_put_obj(opts, "path", QOBJECT(qstring_from_str(path)));
+qdict_put(opts, "path", qstring_from_str(path));
 } else {
-qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host)));
-qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port)));
+qdict_put(opts, "host", qstring_from_str(host));
+qdict_put(opts, "port", qstring_from_str(port));
 }
 if (export) {
-qdict_put_obj(opts, "export", QOBJECT(qstring_from_str(export)));
+qdict_put(opts, "export", qstring_from_str(export));
 }
 if (tlscreds) {
-qdict_put_obj(opts, "tls-creds", QOBJECT(qstring_from_str(tlscreds)));
+qdict_put(opts, "tls-creds", qstring_from_str(tlscreds));
 }
 
 bs->full_open_options = opts;
-- 
2.7.1




[Qemu-devel] [PATCH v2 12/16] qapi: Allow blockdev-add for NBD

2016-02-29 Thread Max Reitz
Signed-off-by: Max Reitz 
---
 qapi/block-core.json | 23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 9bf1b22..21760e0 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1633,13 +1633,14 @@
 # Drivers that are supported in block device operations.
 #
 # @host_device, @host_cdrom: Since 2.1
+# @nbd: Since 2.6
 #
 # Since: 2.0
 ##
 { 'enum': 'BlockdevDriver',
   'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
 'dmg', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
-'http', 'https', 'null-aio', 'null-co', 'parallels',
+'http', 'https', 'nbd', 'null-aio', 'null-co', 'parallels',
 'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp', 'vdi', 'vhdx',
 'vmdk', 'vpc', 'vvfat' ] }
 
@@ -2068,6 +2069,24 @@
 '*read-pattern': 'QuorumReadPattern' } }
 
 ##
+# @BlockdevOptionsNbd
+#
+# Driver specific block device options for NBD.
+#
+# @address: NBD server address
+#
+# @export:  #optional export name
+#
+# @tls-creds:   #optional TLS credentials ID
+#
+# Since: 2.6
+##
+{ 'struct': 'BlockdevOptionsNbd',
+  'data': { 'address': 'SocketAddress',
+'*export': 'str',
+'*tls-creds': 'str' } }
+
+##
 # @BlockdevOptions
 #
 # Options for creating a block device.
@@ -2093,7 +2112,7 @@
   'http':   'BlockdevOptionsFile',
   'https':  'BlockdevOptionsFile',
 # TODO iscsi: Wait for structured options
-# TODO nbd: Should take InetSocketAddress for 'host'?
+  'nbd':'BlockdevOptionsNbd',
 # TODO nfs: Wait for structured options
   'null-aio':   'BlockdevOptionsNull',
   'null-co':'BlockdevOptionsNull',
-- 
2.7.1




[Qemu-devel] [PATCH v2 14/16] iotests.py: Allow concurrent qemu instances

2016-02-29 Thread Max Reitz
By adding an optional suffix to the files used for communication with a
VM, we can launch multiple VM instances concurrently.

Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/iotests.py | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index dd8805a..fed5301 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -130,10 +130,13 @@ def event_match(event, match=None):
 class VM(object):
 '''A QEMU VM'''
 
-def __init__(self):
-self._monitor_path = os.path.join(test_dir, 'qemu-mon.%d' % 
os.getpid())
-self._qemu_log_path = os.path.join(test_dir, 'qemu-log.%d' % 
os.getpid())
-self._qtest_path = os.path.join(test_dir, 'qemu-qtest.%d' % 
os.getpid())
+def __init__(self, path_suffix=''):
+self._monitor_path = os.path.join(test_dir, 'qemu-mon%s.%d' %
+(path_suffix, os.getpid()))
+self._qemu_log_path = os.path.join(test_dir, 'qemu-log%s.%d' %
+ (path_suffix, 
os.getpid()))
+self._qtest_path = os.path.join(test_dir, 'qemu-qtest%s.%d' %
+  (path_suffix, os.getpid()))
 self._args = qemu_args + ['-chardev',
  'socket,id=mon,path=' + self._monitor_path,
  '-mon', 'chardev=mon,mode=control',
-- 
2.7.1




[Qemu-devel] [PATCH v2 06/16] block/nbd: Default port in nbd_refresh_filename()

2016-02-29 Thread Max Reitz
Instead of not emitting the port in nbd_refresh_filename(), just set it
to the default if the user did not specify it. This makes the logic a
bit simpler.

Signed-off-by: Max Reitz 
---
 block/nbd.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 6a2fc27..8d9a217 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -411,6 +411,10 @@ static void nbd_refresh_filename(BlockDriverState *bs, 
QDict *options)
 const char *export = qdict_get_try_str(options, "export");
 const char *tlscreds = qdict_get_try_str(options, "tls-creds");
 
+if (host && !port) {
+port = stringify(NBD_DEFAULT_PORT);
+}
+
 qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("nbd")));
 
 if (path && export) {
@@ -419,27 +423,19 @@ static void nbd_refresh_filename(BlockDriverState *bs, 
QDict *options)
 } else if (path && !export) {
 snprintf(bs->exact_filename, sizeof(bs->exact_filename),
  "nbd+unix://?socket=%s", path);
-} else if (!path && export && port) {
+} else if (!path && export) {
 snprintf(bs->exact_filename, sizeof(bs->exact_filename),
  "nbd://%s:%s/%s", host, port, export);
-} else if (!path && export && !port) {
-snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "nbd://%s/%s", host, export);
-} else if (!path && !export && port) {
+} else if (!path && !export) {
 snprintf(bs->exact_filename, sizeof(bs->exact_filename),
  "nbd://%s:%s", host, port);
-} else if (!path && !export && !port) {
-snprintf(bs->exact_filename, sizeof(bs->exact_filename),
- "nbd://%s", host);
 }
 
 if (path) {
 qdict_put_obj(opts, "path", QOBJECT(qstring_from_str(path)));
-} else if (port) {
-qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host)));
-qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port)));
 } else {
 qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host)));
+qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port)));
 }
 if (export) {
 qdict_put_obj(opts, "export", QOBJECT(qstring_from_str(export)));
-- 
2.7.1




[Qemu-devel] [PATCH v2 16/16] iotests: Add test for NBD's blockdev-add interface

2016-02-29 Thread Max Reitz
Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/147 | 194 +
 tests/qemu-iotests/147.out |   5 ++
 tests/qemu-iotests/group   |   1 +
 3 files changed, 200 insertions(+)
 create mode 100755 tests/qemu-iotests/147
 create mode 100644 tests/qemu-iotests/147.out

diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
new file mode 100755
index 000..f31de69
--- /dev/null
+++ b/tests/qemu-iotests/147
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+#
+# Test case for the QMP 'change' command and all other associated
+# commands
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+
+import os
+import socket
+import stat
+import time
+import iotests
+from iotests import cachemode, imgfmt, qemu_img, qemu_nbd
+
+NBD_PORT = 10811
+
+test_img = os.path.join(iotests.test_dir, 'test.img')
+
+class NBDBlockdevAddBase(iotests.QMPTestCase):
+def blockdev_add_options(self, address, export=None):
+options = { 'id': 'drive0',
+'driver': 'raw',
+'file': {
+'driver': 'nbd',
+'address': address
+} }
+if export is not None:
+options['file']['export'] = export
+return options
+
+def client_test(self, filename, address, export=None):
+bao = self.blockdev_add_options(address, export)
+result = self.vm.qmp('blockdev-add', options=bao)
+self.assert_qmp(result, 'return', {})
+
+result = self.vm.qmp('query-block')
+self.assert_qmp(result, 'return[0]/inserted/image/filename', filename)
+
+result = self.vm.qmp('x-blockdev-del', id='drive0')
+self.assert_qmp(result, 'return', {})
+
+
+class QemuNBD(NBDBlockdevAddBase):
+def setUp(self):
+qemu_img('create', '-f', iotests.imgfmt, test_img, '64k')
+self.vm = iotests.VM()
+self.vm.launch()
+self.qemu_nbd = None
+
+def tearDown(self):
+self.vm.shutdown()
+if self.qemu_nbd is not None:
+self.qemu_nbd.wait()
+os.remove(test_img)
+
+def _server_up(self, *args):
+self.qemu_nbd = qemu_nbd('-f', imgfmt, test_img, *args)
+time.sleep(1)
+
+def test_inet(self):
+self._server_up('-p', str(NBD_PORT))
+address = { 'type': 'inet',
+'data': {
+'host': 'localhost',
+'port': str(NBD_PORT)
+} }
+self.client_test('nbd://localhost:%i' % NBD_PORT, address)
+
+def test_unix(self):
+socket = os.path.join(iotests.test_dir, 'qemu-nbd.socket')
+self._server_up('-k', socket)
+address = { 'type': 'unix',
+'data': { 'path': socket } }
+self.client_test('nbd+unix://?socket=' + socket, address)
+os.remove(socket)
+
+
+class BuiltinNBD(NBDBlockdevAddBase):
+def setUp(self):
+qemu_img('create', '-f', iotests.imgfmt, test_img, '64k')
+self.vm = iotests.VM()
+self.vm.launch()
+self.server = iotests.VM('.server')
+self.server.add_drive_raw('if=none,id=nbd-export,' +
+  'file=%s,' % test_img +
+  'format=%s,' % imgfmt +
+  'cache=%s' % cachemode)
+self.server.launch()
+
+def tearDown(self):
+self.vm.shutdown()
+self.server.shutdown()
+os.remove(test_img)
+
+def _server_up(self, address):
+result = self.server.qmp('nbd-server-start', addr=address)
+self.assert_qmp(result, 'return', {})
+
+result = self.server.qmp('nbd-server-add', device='nbd-export')
+self.assert_qmp(result, 'return', {})
+
+def _server_down(self):
+result = self.server.qmp('nbd-server-stop')
+self.assert_qmp(result, 'return', {})
+
+def test_inet(self):
+address = { 'type': 'inet',
+'data': {
+'host': 'localhost',
+'port': str(NBD_PORT)
+} }
+self._server_up(address)
+self.client_test('nbd://localhost:%i/nbd-export' % NBD_PORT,
+ address, 'nbd-export')
+self._server_down()
+
+def test_inet6(self):
+

[Qemu-devel] [PATCH v2 04/16] block/nbd: Drop trailing "." in error messages

2016-02-29 Thread Max Reitz
Signed-off-by: Max Reitz 
---
 block/nbd.c   | 4 ++--
 tests/qemu-iotests/051.out| 4 ++--
 tests/qemu-iotests/051.pc.out | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index db57b49..ce31119 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -194,9 +194,9 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict 
*options, char **export,
 
 if (qdict_haskey(options, "path") == qdict_haskey(options, "host")) {
 if (qdict_haskey(options, "path")) {
-error_setg(errp, "path and host may not be used at the same 
time.");
+error_setg(errp, "path and host may not be used at the same time");
 } else {
-error_setg(errp, "one of path and host must be specified.");
+error_setg(errp, "one of path and host must be specified");
 }
 return NULL;
 }
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 0f8a8d3..5166bea 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -222,7 +222,7 @@ Testing: -drive driver=file
 QEMU_PROG: -drive driver=file: The 'file' block driver requires a file name
 
 Testing: -drive driver=nbd
-QEMU_PROG: -drive driver=nbd: one of path and host must be specified.
+QEMU_PROG: -drive driver=nbd: one of path and host must be specified
 
 Testing: -drive driver=raw
 QEMU_PROG: -drive driver=raw: Can't use 'raw' as a block driver for the 
protocol level
@@ -231,7 +231,7 @@ Testing: -drive file.driver=file
 QEMU_PROG: -drive file.driver=file: The 'file' block driver requires a file 
name
 
 Testing: -drive file.driver=nbd
-QEMU_PROG: -drive file.driver=nbd: one of path and host must be specified.
+QEMU_PROG: -drive file.driver=nbd: one of path and host must be specified
 
 Testing: -drive file.driver=raw
 QEMU_PROG: -drive file.driver=raw: Can't use 'raw' as a block driver for the 
protocol level
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
index 85fc05d..d0bbfcb 100644
--- a/tests/qemu-iotests/051.pc.out
+++ b/tests/qemu-iotests/051.pc.out
@@ -316,7 +316,7 @@ Testing: -drive driver=file
 QEMU_PROG: -drive driver=file: The 'file' block driver requires a file name
 
 Testing: -drive driver=nbd
-QEMU_PROG: -drive driver=nbd: one of path and host must be specified.
+QEMU_PROG: -drive driver=nbd: one of path and host must be specified
 
 Testing: -drive driver=raw
 QEMU_PROG: -drive driver=raw: Can't use 'raw' as a block driver for the 
protocol level
@@ -325,7 +325,7 @@ Testing: -drive file.driver=file
 QEMU_PROG: -drive file.driver=file: The 'file' block driver requires a file 
name
 
 Testing: -drive file.driver=nbd
-QEMU_PROG: -drive file.driver=nbd: one of path and host must be specified.
+QEMU_PROG: -drive file.driver=nbd: one of path and host must be specified
 
 Testing: -drive file.driver=raw
 QEMU_PROG: -drive file.driver=raw: Can't use 'raw' as a block driver for the 
protocol level
-- 
2.7.1




[Qemu-devel] [PATCH v2 03/16] check-qdict: Add a test for qdict_unflatten()

2016-02-29 Thread Max Reitz
Signed-off-by: Max Reitz 
---
 tests/check-qdict.c | 267 
 1 file changed, 267 insertions(+)

diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index a43056c..f6a5cda 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -325,6 +325,272 @@ static void qdict_flatten_test(void)
 QDECREF(dict3);
 }
 
+static void qdict_unflatten_test(void)
+{
+QDict *dict;
+QList *list_a, *list_o;
+QDict *dict_a1, *dict_d, *dict_df, *dict_dh, *dict_i, *dict_l;
+const QListEntry *le;
+
+/*
+ * Test the unflattening of
+ *
+ * {
+ * "a.0": 0,
+ * "a.1.b": 1,
+ * "a.1.c": 2,
+ * "a.2": 3,
+ * "d.e": 4,
+ * "d.f.g": 5,
+ * "d.h.0": 6,
+ * "d.h.2": 7,
+ * "i.0": 8,
+ * "i.j": 9,
+ * "k": 10,
+ * "l": {
+ * "m": 11
+ * },
+ * "l.n": 12,
+ * "o": [],
+ * "o.0": 13
+ * }
+ *
+ * to
+ *
+ * {
+ * "a": [
+ * 0,
+ * {
+ * "b": 1,
+ * "c": 2
+ * },
+ * 3
+ * ],
+ * "d": {
+ * "e": 4,
+ * "f": {
+ * "g": 5
+ * },
+ * "h": {
+ * "0": 6,
+ * "2": 7
+ * },
+ * },
+ * "i": {
+ * "0": 8,
+ * "j": 9
+ * },
+ * "k": 10,
+ * "l": {
+ * "m": 11,
+ * "n": 12
+ * },
+ * "o": [
+ * 13
+ * ]
+ * }
+ *
+ * This tests:
+ * - Unflattening in general
+ * - Conversion of "x.0", "x.2" into a dict instead of a list
+ * - Conversion of "x.0", "x.y" into a dict instead of a list
+ * - Merging of previously existing and new unflattened dicts
+ *   ({ "x": { "y": 0 }, "x.z": 1 } => { "x": { "y": 0, "z": 1 } })
+ * - Merging of previously existing and new unflattened lists; only works
+ *   if the previous list was empty
+ *   ({ "x": [], "x.0": 0 } => { "x": [ 0 ] })
+ */
+
+dict = qdict_new();
+
+qdict_put(dict, "a.0",   qint_from_int( 0));
+qdict_put(dict, "a.1.b", qint_from_int( 1));
+qdict_put(dict, "a.1.c", qint_from_int( 2));
+qdict_put(dict, "a.2",   qint_from_int( 3));
+qdict_put(dict, "d.e",   qint_from_int( 4));
+qdict_put(dict, "d.f.g", qint_from_int( 5));
+qdict_put(dict, "d.h.0", qint_from_int( 6));
+qdict_put(dict, "d.h.2", qint_from_int( 7));
+qdict_put(dict, "i.0",   qint_from_int( 8));
+qdict_put(dict, "i.j",   qint_from_int( 9));
+qdict_put(dict, "k", qint_from_int(10));
+qdict_put(dict, "l", qdict_new());
+qdict_put(qdict_get_qdict(dict, "l"), "m", qint_from_int(11));
+qdict_put(dict, "l.n",   qint_from_int(12));
+qdict_put(dict, "o", qlist_new());
+qdict_put(dict, "o.0",   qint_from_int(13));
+
+qdict_unflatten(dict, _abort);
+
+list_a = qdict_get_qlist(dict, "a");
+g_assert(list_a);
+
+/* a.0 */
+le = qlist_first(list_a);
+g_assert(le);
+g_assert(qint_get_int(qobject_to_qint(le->value)) == 0);
+/* a.1 */
+le = qlist_next(le);
+g_assert(le);
+dict_a1 = qobject_to_qdict(le->value);
+g_assert(dict_a1);
+g_assert(qdict_get_int(dict_a1, "b") == 1);
+g_assert(qdict_get_int(dict_a1, "c") == 2);
+g_assert(qdict_size(dict_a1) == 2);
+/* a.2 */
+le = qlist_next(le);
+g_assert(le);
+g_assert(qint_get_int(qobject_to_qint(le->value)) == 3);
+
+g_assert(!qlist_next(le));
+
+dict_d = qdict_get_qdict(dict, "d");
+g_assert(dict_d);
+g_assert(qdict_get_int(dict_d, "e") == 4);
+
+dict_df = qdict_get_qdict(dict_d, "f");
+g_assert(dict_df);
+g_assert(qdict_get_int(dict_df, "g") == 5);
+g_assert(qdict_size(dict_df) == 1);
+
+dict_dh = qdict_get_qdict(dict_d, "h");
+g_assert(dict_dh);
+g_assert(qdict_get_int(dict_dh, "0") == 6);
+g_assert(qdict_get_int(dict_dh, "2") == 7);
+g_assert(qdict_size(dict_dh) == 2);
+
+g_assert(qdict_size(dict_d) == 3);
+
+dict_i = qdict_get_qdict(dict, "i");
+g_assert(dict_i);
+g_assert(qdict_get_int(dict_i, "0") == 8);
+g_assert(qdict_get_int(dict_i, "j") == 9);
+g_assert(qdict_size(dict_i) == 2);
+
+g_assert(qdict_get_int(dict, "k") == 10);
+
+dict_l = qdict_get_qdict(dict, "l");
+g_assert(dict_l);
+g_assert(qdict_get_int(dict_l, "m") == 11);
+g_assert(qdict_get_int(dict_l, "n") == 12);
+g_assert(qdict_size(dict_l) == 2);
+
+list_o = qdict_get_qlist(dict, "o");
+g_assert(list_o);
+
+/* o.0 */
+le = qlist_first(list_o);
+g_assert(le);
+g_assert(qint_get_int(qobject_to_qint(le->value)) == 13);
+
+g_assert(!qlist_next(le));
+
+g_assert(qdict_size(dict) == 6);
+
+QDECREF(dict);
+
+
+/*
+ * Test that 

[Qemu-devel] [PATCH v2 13/16] iotests.py: Add qemu_nbd function

2016-02-29 Thread Max Reitz
Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/iotests.py | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 0a238ec..dd8805a 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -28,7 +28,7 @@ import qmp
 import qtest
 import struct
 
-__all__ = ['imgfmt', 'imgproto', 'test_dir' 'qemu_img', 'qemu_io',
+__all__ = ['imgfmt', 'imgproto', 'test_dir' 'qemu_img', 'qemu_io', 'qemu_nbd',
'VM', 'QMPTestCase', 'notrun', 'main']
 
 # This will not work if arguments contain spaces but is necessary if we
@@ -41,6 +41,10 @@ qemu_io_args = [os.environ.get('QEMU_IO_PROG', 'qemu-io')]
 if os.environ.get('QEMU_IO_OPTIONS'):
 qemu_io_args += os.environ['QEMU_IO_OPTIONS'].strip().split(' ')
 
+qemu_nbd_args = [os.environ.get('QEMU_NBD_PROG', 'qemu-nbd')]
+if os.environ.get('QEMU_NBD_OPTIONS'):
+qemu_nbd_args += os.environ['QEMU_NBD_OPTIONS'].strip().split(' ')
+
 qemu_args = [os.environ.get('QEMU_PROG', 'qemu')]
 if os.environ.get('QEMU_OPTIONS'):
 qemu_args += os.environ['QEMU_OPTIONS'].strip().split(' ')
@@ -86,6 +90,11 @@ def qemu_io(*args):
 sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' 
'.join(args)))
 return subp.communicate()[0]
 
+def qemu_nbd(*args):
+'''Run qemu-nbd in the background'''
+subp = subprocess.Popen(qemu_nbd_args + list(args))
+return subp
+
 def compare_images(img1, img2):
 '''Return True if two image files are identical'''
 return qemu_img('compare', '-f', imgfmt,
-- 
2.7.1




[Qemu-devel] [PATCH v2 08/16] block/nbd: Add nbd_has_filename_options_conflict()

2016-02-29 Thread Max Reitz
Right now, we have four possible options that conflict with specifying
an NBD filename, and a future patch will add another one ("address").
This future option is a nested QDict that is flattened at this point,
requiring as to test each option whether its key has an "address."
prefix. Therefore, we will then need to iterate through all options.

Adding this iteration logic now will simplify adding the new option
later. A nice side effect is that the user will not receive a long list
of five options which are not supposed to be specified with a filename,
but we can actually print the problematic option.

Signed-off-by: Max Reitz 
---
 block/nbd.c | 26 --
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/block/nbd.c b/block/nbd.c
index 145db39..2d96dd1 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -119,6 +119,25 @@ out:
 return ret;
 }
 
+static bool nbd_has_filename_options_conflict(QDict *options, Error **errp)
+{
+const QDictEntry *e;
+
+for (e = qdict_first(options); e; e = qdict_next(options, e)) {
+if (!strcmp(e->key, "host")
+|| !strcmp(e->key, "port")
+|| !strcmp(e->key, "path")
+|| !strcmp(e->key, "export"))
+{
+error_setg(errp, "Option '%s' cannot be used with a file name",
+   e->key);
+return true;
+}
+}
+
+return false;
+}
+
 static void nbd_parse_filename(const char *filename, QDict *options,
Error **errp)
 {
@@ -127,12 +146,7 @@ static void nbd_parse_filename(const char *filename, QDict 
*options,
 const char *host_spec;
 const char *unixpath;
 
-if (qdict_haskey(options, "host")
-|| qdict_haskey(options, "port")
-|| qdict_haskey(options, "path"))
-{
-error_setg(errp, "host/port/path and a file name may not be specified "
- "at the same time");
+if (nbd_has_filename_options_conflict(options, errp)) {
 return;
 }
 
-- 
2.7.1




[Qemu-devel] [PATCH v2 05/16] block/nbd: Reject port parameter without host

2016-02-29 Thread Max Reitz
This is better than the generic block layer finding out later that the
port parameter has not been used.

Signed-off-by: Max Reitz 
Reviewed-by: Eric Blake 
---
 block/nbd.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/block/nbd.c b/block/nbd.c
index ce31119..6a2fc27 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -200,6 +200,10 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict 
*options, char **export,
 }
 return NULL;
 }
+if (qdict_haskey(options, "port") && !qdict_haskey(options, "host")) {
+error_setg(errp, "port may not be used without host");
+return NULL;
+}
 
 saddr = g_new0(SocketAddress, 1);
 
-- 
2.7.1




[Qemu-devel] [PATCH v2 02/16] qdict: Add qdict_unflatten()

2016-02-29 Thread Max Reitz
The QMP input visitor is rather unhappy with flattened QDicts, which is
how they are generally used in the block layer. This function allows
unflattening a QDict so we can use an input visitor on it.

Signed-off-by: Max Reitz 
---
 include/qapi/qmp/qdict.h |   1 +
 qobject/qdict.c  | 189 +++
 2 files changed, 190 insertions(+)

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 223f746..0ec7477 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -70,6 +70,7 @@ void qdict_set_default_str(QDict *dst, const char *key, const 
char *val);
 
 QDict *qdict_clone_shallow(const QDict *src);
 void qdict_flatten(QDict *qdict);
+bool qdict_unflatten(QDict *qdict, Error **errp);
 
 void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
 void qdict_array_split(QDict *src, QList **dst);
diff --git a/qobject/qdict.c b/qobject/qdict.c
index bbfe39f..800af38 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -771,6 +771,195 @@ int qdict_array_entries(QDict *src, const char *subqdict)
 }
 
 /**
+ * qlist_unflatten(): Recursive helper function for qdict_unflatten(). Invokes
+ * qdict_unflatten() and qlist_unflatten() on all its QDict and QList members,
+ * respectively.
+ */
+static bool qlist_unflatten(QList *qlist, Error **errp)
+{
+const QListEntry *entry;
+
+for (entry = qlist_first(qlist); entry; entry = qlist_next(entry)) {
+switch (qobject_type(entry->value)) {
+case QTYPE_QDICT:
+if (!qdict_unflatten(qobject_to_qdict(entry->value), errp)) {
+return false;
+}
+break;
+
+case QTYPE_QLIST:
+if (!qlist_unflatten(qobject_to_qlist(entry->value), errp)) {
+return false;
+}
+break;
+
+default:
+break;
+}
+}
+
+return true;
+}
+
+/**
+ * qdict_unflatten(): The opposite of qdict_flatten().
+ *
+ * Every entry whose key is of the form "${prefix}.${index}" is moved to index
+ * "${index}" in a QList whose key in @qdict is "${prefix}", if
+ * qdict_array_entries(qdict, "${prefix}.") yields a positive value.
+ *
+ * Every entry whose key is of the form "${prefix}.${index}.${trailing}" is
+ * moved into a QDict at index "${index}" in a QList whose key in @qdict is
+ * "${prefix}". The moved object's key in the nested QDict is "${trailing}".
+ * This is only done if qdict_array_entries(qdict, "${prefix}.") yields a
+ * positive value.
+ *
+ * Every remaining entry whose key is of the form "${prefix}.${trailing}" is
+ * moved into a QDict whose key in @qdict is "${prefix}". The moved object's 
key
+ * in the nested QDict is "${trailing}".
+ *
+ * This algorithm then recurses on all QDict members (including indirect ones
+ * in QLists) of this QDict.
+ *
+ * This function will never overwrite existing members. For instance:
+ *   qdict_unflatten({ "x": 42, "x.y": 23 })
+ * is an error because there already is an "x" element which is not a QDict.
+ * However,
+ *   qdict_unflatten({ "x": { "a": 0 }, "x.y": 23 })
+ *   => { "x": { "a": 0, "y": 23 } }
+ * because the flattened "x.y" can be merged into the existing "x" QDict 
without
+ * overwriting any of its members. In contrast to that,
+ *   qdict_unflatten({ "x": { "y": 0 }, "x.y": 23 })
+ * is an error because "y" nested in "x" would need to be overwritten.
+ *
+ * This function returns true on success and false on error (in which case 
*errp
+ * is set). On error, the contents of @qdict are undefined.
+ */
+bool qdict_unflatten(QDict *qdict, Error **errp)
+{
+const QDictEntry *entry;
+
+/* First pass: Unflatten this level */
+entry = qdict_first(qdict);
+while (entry) {
+const char *prefix_end = strchr(entry->key, '.');
+
+if (prefix_end) {
+size_t prefix_length = prefix_end - entry->key;
+char *prefix, *prefix_dot;
+
+prefix = g_malloc(prefix_length + 1);
+strncpy(prefix, entry->key, prefix_length);
+prefix[prefix_length] = 0;
+
+prefix_dot = g_strdup_printf("%s.", prefix);
+
+if (qdict_array_entries(qdict, prefix_dot) > 0) {
+/* Move all entries with this prefix into a nested QList */
+QDict *array_qdict;
+QList *target_qlist;
+
+/* We cannot merge two non-empty lists without one overwriting
+ * members of the other */
+if (qdict_haskey(qdict, prefix)) {
+if (qobject_type(qdict_get(qdict, prefix)) != QTYPE_QLIST 
||
+!qlist_empty(qdict_get_qlist(qdict, prefix)))
+{
+error_setg(errp, "Cannot unflatten list '%s': Overlaps 
"
+   "with existing member", prefix);
+g_free(prefix);
+g_free(prefix_dot);
+

[Qemu-devel] [PATCH v2 01/16] qdict: Add qdict_change_key()

2016-02-29 Thread Max Reitz
This is a shorthand function for changing a QDict's entry's key.

Signed-off-by: Max Reitz 
---
 include/qapi/qmp/qdict.h |  1 +
 qobject/qdict.c  | 23 +++
 2 files changed, 24 insertions(+)

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 71b8eb0..223f746 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -39,6 +39,7 @@ size_t qdict_size(const QDict *qdict);
 void qdict_put_obj(QDict *qdict, const char *key, QObject *value);
 void qdict_del(QDict *qdict, const char *key);
 int qdict_haskey(const QDict *qdict, const char *key);
+bool qdict_change_key(QDict *qdict, const char *old_key, const char *new_key);
 QObject *qdict_get(const QDict *qdict, const char *key);
 QDict *qobject_to_qdict(const QObject *obj);
 void qdict_iter(const QDict *qdict,
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 9833bd0..bbfe39f 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -168,6 +168,29 @@ int qdict_haskey(const QDict *qdict, const char *key)
 }
 
 /**
+ * qdict_change_key(): Changes an entry's key
+ *
+ * Removes the entry with the key 'old_key' and inserts its associated value as
+ * a new entry with the key 'new_key'.
+ *
+ * Returns false if 'old_key' does not exist, true otherwise.
+ */
+bool qdict_change_key(QDict *qdict, const char *old_key, const char *new_key)
+{
+QObject *value = qdict_get(qdict, old_key);
+
+if (!value) {
+return false;
+}
+
+qobject_incref(value);
+qdict_del(qdict, old_key);
+qdict_put_obj(qdict, new_key, value);
+
+return true;
+}
+
+/**
  * qdict_size(): Return the size of the dictionary
  */
 size_t qdict_size(const QDict *qdict)
-- 
2.7.1




[Qemu-devel] [PATCH v2 00/16] qapi: Allow blockdev-add for NBD

2016-02-29 Thread Max Reitz
Turns out NBD is not so simple to do if you do it right. Anyway, this
series adds blockdev-add support for NBD clients.

Patches 1 and 2 add one less and one more complicated QDict function,
respectively, which I needed in later NBD patches: Patch 1 for handling
legacy options (move "host" to "address.data.host" etc.) and patch 2
because I'd like to use the input visitor for transforming the NBD
options into a SocketAddress. Unfortunately, the block layer uses
flattened QDicts everywhere, so we'll have to unflatten (erect?) them
before we can use that visitor.

Patch 3 adds a test for qdict_unflatten().

Patches 4, 5, 6, and 7 are minor patches with no functional relation to
this series, other than later patches will touch the code they touch,
too.

Patches 8 and 9 prepare the code for the addition of a new option
prefix, which is "address.".

Patch 10 makes the NBD client accept a SocketAddress under the "address"
option (or rather, a flattened SocketAddress QDict with its keys
prefixed by "address."). The old options "host", "port", and "path" are
supported as legacy options and translated to the respective
SocketAddress representation.

Patch 11 drops usage of "host", "port", and "path" outside of
nbd_has_filename_options_conflict(),
nbd_process_legacy_socket_options(), and nbd_refresh_filename(), making
those options nothing but legacy.

Patch 12, the goal of this series, is again not very complicated.

Patches 13, 14, and 15 are required for the iotest added in patch 16. It
will invoke qemu-nbd, so patch 13 is required. Besides qemu-nbd, it will
launch an NBD server VM concurrently to the client VM, which is why
patch 14 is required. And finally, it will test whether we can add an
NBD BDS by passing it a file descriptor, which patch 15 is needed for
(so we use the socket_scm_helper to pass sockets to qemu).

Patch 16 then adds the iotest for NBD's blockdev-add interface.


Note on the relation to v1: As you can see, most of this series is
completely new. Patch 5 was patch 1 in v1, and the only thing that has
changed is that I removed the full stop at the end of the error message;
consequently I kept Eric's R-b.


Max Reitz (16):
  qdict: Add qdict_change_key()
  qdict: Add qdict_unflatten()
  check-qdict: Add a test for qdict_unflatten()
  block/nbd: Drop trailing "." in error messages
  block/nbd: Reject port parameter without host
  block/nbd: Default port in nbd_refresh_filename()
  block/nbd: Use qdict_put()
  block/nbd: Add nbd_has_filename_options_conflict()
  block/nbd: "address" in nbd_refresh_filename()
  block/nbd: Accept SocketAddress
  block/nbd: Use SocketAddress options
  qapi: Allow blockdev-add for NBD
  iotests.py: Add qemu_nbd function
  iotests.py: Allow concurrent qemu instances
  socket_scm_helper: Accept fd directly
  iotests: Add test for NBD's blockdev-add interface

 block/nbd.c| 231 +++-
 include/qapi/qmp/qdict.h   |   2 +
 qapi/block-core.json   |  23 ++-
 qobject/qdict.c| 212 ++
 tests/check-qdict.c| 267 +
 tests/qemu-iotests/051.out |   4 +-
 tests/qemu-iotests/051.pc.out  |   4 +-
 tests/qemu-iotests/147 | 194 
 tests/qemu-iotests/147.out |   5 +
 tests/qemu-iotests/group   |   1 +
 tests/qemu-iotests/iotests.py  |  22 ++-
 tests/qemu-iotests/socket_scm_helper.c |  29 ++--
 12 files changed, 898 insertions(+), 96 deletions(-)
 create mode 100755 tests/qemu-iotests/147
 create mode 100644 tests/qemu-iotests/147.out

-- 
2.7.1




Re: [Qemu-devel] [RFC PATCH v2 1/3] vGPU Core driver

2016-02-29 Thread Neo Jia
On Mon, Feb 29, 2016 at 05:39:02AM +, Tian, Kevin wrote:
> > From: Kirti Wankhede
> > Sent: Wednesday, February 24, 2016 12:24 AM
> > 
> > Signed-off-by: Kirti Wankhede 
> > Signed-off-by: Neo Jia 
> 
> Hi, Kirti/Neo,
> 
> Thanks a lot for you updated version. Having not looked into detail
> code, first come with some high level comments.
> 
> First, in a glimpse the majority of the code (possibly >95%) is device
> agnostic, though we call it vgpu today. Just thinking about the
> extensibility and usability of this framework, would it be better to 
> name it in a way that any other type of I/O device can be fit into 
> this framework? I don't have a good idea of the name now, but 
> a simple idea is to replace vgpu with vdev (vdev-core, vfio-vdev,
> vfio-iommu-type1-vdev, etc.), and then underlying GPU drivers are
> just one category of users of this general vdev framework. In the
> future it's easily extended to support other I/O virtualization based 
> on similar vgpu concept;
> 
> Second, are these 3 patches already working with nvidia device,
> or are they just conceptual implementation w/o completing actual
> test yet? We'll start moving our implementation toward this direction
> too, so would be good to know the current status and how we can
> further cooperate to move forward. Based on that we can start 
> giving more comments on next level detail.
> 

Hi Kevin,

Yes, we do have an engineering prototype up and running with this set of kernel
patches we have posted.

Please let us know if you have any questions while integrating your vgpu 
solution
within this framework.

Thanks,
Neo

> Thanks
> Kevin



[Qemu-devel] [PATCH RFC] bcm2835_dma: add emulation of Raspberry Pi DMA controller

2016-02-29 Thread Andrew Baumann
Signed-off-by: Andrew Baumann 
---
This patch applies on top of the previous series for Windows and
framebuffer support:
  https://lists.gnu.org/archive/html/qemu-devel/2016-02/msg06387.html

After preparing that, I was disappointed to discover that Raspbian
won't boot cleanly without the DMA controller. In the hope of beating
the freeze deadline (it's still February 29 here :-) I'm sending this
for review.

After applying this patch, it is possible to boot Raspbian to the GUI
using a command such as:

  qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd
  2015-09-24-raspbian-jessie.img -append "rw earlyprintk loglevel=8
  console=ttyAMA0 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootwait"
  -dtb raspbian-boot/bcm2709-rpi-2-b.dtb -serial stdio

As before, this derives from the original (out of tree) work of
Gregory Estrade, Stefan Weil and others to support Raspberry Pi
1. This patch in particulary is Gregory's code, which I have cleaned
up for submission.

Thanks,
Andrew

 hw/arm/bcm2835_peripherals.c |  26 +++
 hw/dma/Makefile.objs |   1 +
 hw/dma/bcm2835_dma.c | 397 +++
 include/hw/arm/bcm2835_peripherals.h |   2 +
 include/hw/dma/bcm2835_dma.h |  47 +
 5 files changed, 473 insertions(+)
 create mode 100644 hw/dma/bcm2835_dma.c
 create mode 100644 include/hw/dma/bcm2835_dma.h

diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index c2b812a..fdd346e 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -87,6 +87,14 @@ static void bcm2835_peripherals_init(Object *obj)
 object_initialize(>sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
 object_property_add_child(obj, "sdhci", OBJECT(>sdhci), NULL);
 qdev_set_parent_bus(DEVICE(>sdhci), sysbus_get_default());
+
+/* DMA Channels */
+object_initialize(>dma, sizeof(s->dma), TYPE_BCM2835_DMA);
+object_property_add_child(obj, "dma", OBJECT(>dma), NULL);
+qdev_set_parent_bus(DEVICE(>dma), sysbus_get_default());
+
+object_property_add_const_link(OBJECT(>dma), "dma-mr",
+   OBJECT(>gpu_bus_mr), _abort);
 }
 
 static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
@@ -246,6 +254,24 @@ static void bcm2835_peripherals_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
+/* DMA Channels */
+object_property_set_bool(OBJECT(>dma), true, "realized", );
+if (err) {
+error_propagate(errp, err);
+return;
+}
+
+memory_region_add_subregion(>peri_mr, DMA_OFFSET,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(>dma), 0));
+memory_region_add_subregion(>peri_mr, DMA15_OFFSET,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(>dma), 1));
+
+for (n = 0; n <= 12; n++) {
+sysbus_connect_irq(SYS_BUS_DEVICE(>dma), n,
+   qdev_get_gpio_in_named(DEVICE(>ic),
+  BCM2835_IC_GPU_IRQ,
+  INTERRUPT_DMA0 + n));
+}
 }
 
 static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
index 0e65ed0..a1abbcf 100644
--- a/hw/dma/Makefile.objs
+++ b/hw/dma/Makefile.objs
@@ -11,3 +11,4 @@ common-obj-$(CONFIG_SUN4M) += sun4m_iommu.o
 
 obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
 obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
+obj-$(CONFIG_RASPI) += bcm2835_dma.o
diff --git a/hw/dma/bcm2835_dma.c b/hw/dma/bcm2835_dma.c
new file mode 100644
index 000..1b3cdcf
--- /dev/null
+++ b/hw/dma/bcm2835_dma.c
@@ -0,0 +1,397 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/dma/bcm2835_dma.h"
+
+/* DMA CS Control and Status bits */
+#define BCM2708_DMA_ACTIVE  (1 << 0)
+#define BCM2708_DMA_END (1 << 1) /* GE */
+#define BCM2708_DMA_INT (1 << 2)
+#define BCM2708_DMA_ISPAUSED(1 << 4)  /* Pause requested or not active */
+#define BCM2708_DMA_ISHELD  (1 << 5)  /* Is held by DREQ flow control */
+#define BCM2708_DMA_ERR (1 << 8)
+#define BCM2708_DMA_ABORT   (1 << 30) /* stop current CB, go to next, WO */
+#define BCM2708_DMA_RESET   (1 << 31) /* WO, self clearing */
+
+/* DMA control block "info" field bits */
+#define BCM2708_DMA_INT_EN  (1 << 0)
+#define BCM2708_DMA_TDMODE  (1 << 1)
+#define BCM2708_DMA_WAIT_RESP   (1 << 3)
+#define BCM2708_DMA_D_INC   (1 << 4)
+#define BCM2708_DMA_D_WIDTH (1 << 5)
+#define BCM2708_DMA_D_DREQ  (1 << 6)
+#define BCM2708_DMA_D_IGNORE(1 << 7)
+#define BCM2708_DMA_S_INC   (1 << 8)
+#define BCM2708_DMA_S_WIDTH (1 << 9)
+#define BCM2708_DMA_S_DREQ  (1 << 10)
+#define BCM2708_DMA_S_IGNORE(1 << 11)
+
+/* Register offsets */
+#define BCM2708_DMA_CS  0x00 /* Control and Status */
+#define 

Re: [Qemu-devel] [PATCH v3 2/2] docs: Add a generic loader explanation document

2016-02-29 Thread Alistair Francis
On Fri, Feb 26, 2016 at 7:59 AM, Peter Maydell  wrote:
> On 19 February 2016 at 20:40, Alistair Francis
>  wrote:
>> Signed-off-by: Alistair Francis 
>> ---
>>
>>  docs/generic-loader.txt | 21 +
>>  1 file changed, 21 insertions(+)
>>  create mode 100644 docs/generic-loader.txt
>>
>> diff --git a/docs/generic-loader.txt b/docs/generic-loader.txt
>> new file mode 100644
>> index 000..69e262d
>> --- /dev/null
>> +++ b/docs/generic-loader.txt
>> @@ -0,0 +1,21 @@
>> +Copyright (c) 2016 Xilinx Inc.
>> +
>> +This work is licensed under the terms of the GNU GPL, version 2 or later.  
>> See
>> +the COPYING file in the top-level directory.
>> +
>> +
>> +This loader allows the user to load multiple images or values into QEMU at 
>> startup.
>
> This is a bit confusing, because it's not entirely clear what
> "this" is referring to. Something with a heading and then a
> paragraph starting "The 'loader' device allows ..." might be
> better.
>
>> +
>> +Loading Memory Values
>> +---
>> +Memory values can be loaded like this:
>> +-device loader,addr=0xfd1a0104,data=0x800e,data-len=4
>
> What values are permitted for data-len ? What endianness is
> the data stored as? What address space is the data written to?
> Is 'cpu=N' valid here as it is for the image loader syntax below?
>
>> +
>> +Loading Images
>> +---
>> +Images can be loaded like this:
>> +-device loader,file=./images/boot.elf,cpu=0
>> +
>> +The limiation for arch is based off settting the ELF_ARCH macro.
>
> I don't understand this sentence (also it has two typos in it :-))
>
>
>> +
>> +At the moment only the ARM arhitectures are supported
>
> "architectures". Why is there an architecture limitation? Missing
> full stop.
>
> Straightforward documentation of all possible options, followed
> by examples, is probably a better way to structure this than
> trying to describe it only by example.

Agreed! I am re-writing it, it is now much more comprehensive.

Thanks,

Alistair

>
> thanks
> -- PMM
>



Re: [Qemu-devel] [Qemu-block] [PATCH v3 11/15] block: Assert that bdrv_release_dirty_bitmap succeeded

2016-02-29 Thread John Snow


On 02/27/2016 04:20 AM, Fam Zheng wrote:
> We use a loop over bs->dirty_bitmaps to make sure the caller is
> only releasing a bitmap owned by bs. Let's also assert that in this case
> the caller is releasing a bitmap that does exist.
> 
> Signed-off-by: Fam Zheng 
> ---
>  block/dirty-bitmap.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
> index a0c5acb..27d33e7 100644
> --- a/block/dirty-bitmap.c
> +++ b/block/dirty-bitmap.c
> @@ -304,6 +304,9 @@ static void 
> bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs,
>  }
>  }
>  }
> +if (bitmap) {
> +abort();
> +}
>  }
>  
>  void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
> 

Bad context, but I assume what happens is if we have a bitmap, we have
an early return above, so this should be unreachable.

Reviewed-by: John Snow 



Re: [Qemu-devel] [Qemu-block] [PATCH v3 09/15] block: Support meta dirty bitmap

2016-02-29 Thread John Snow


On 02/27/2016 04:20 AM, Fam Zheng wrote:
> The added group of operations enables tracking of the changed bits in
> the dirty bitmap.
> 
> Signed-off-by: Fam Zheng 
> ---
>  block/dirty-bitmap.c | 51 
> 
>  include/block/dirty-bitmap.h |  9 
>  2 files changed, 60 insertions(+)
> 
> diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
> index 16f73b2..5f19320 100644
> --- a/block/dirty-bitmap.c
> +++ b/block/dirty-bitmap.c
> @@ -38,6 +38,7 @@
>   */
>  struct BdrvDirtyBitmap {
>  HBitmap *bitmap;/* Dirty sector bitmap implementation */
> +HBitmap *meta;  /* Meta dirty bitmap */
>  BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */
>  char *name; /* Optional non-empty unique ID */
>  int64_t size;   /* Size of the bitmap (Number of sectors) */
> @@ -103,6 +104,56 @@ BdrvDirtyBitmap 
> *bdrv_create_dirty_bitmap(BlockDriverState *bs,
>  return bitmap;
>  }
>  
> +/* bdrv_create_meta_dirty_bitmap
> + *
> + * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. 
> I.e.
> + * when a dirty status bit in @bitmap is changed (either from reset to set or
> + * the other way around), its respective meta dirty bitmap bit will be marked
> + * dirty as well.
> + *
> + * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap.
> + * @chunk_size: how many bytes of bitmap data does each bit in the meta 
> bitmap
> + * track.
> + */
> +void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap,
> +   int chunk_size)
> +{
> +assert(!bitmap->meta);
> +bitmap->meta = hbitmap_create_meta(bitmap->bitmap,
> +   chunk_size * BITS_PER_BYTE);
> +}
> +
> +void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap)
> +{
> +assert(bitmap->meta);
> +hbitmap_free_meta(bitmap->bitmap);
> +bitmap->meta = NULL;
> +}
> +
> +int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs,
> +   BdrvDirtyBitmap *bitmap, int64_t sector,
> +   int nb_sectors)
> +{
> +uint64_t i;
> +int gran = bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
> +
> +/* To optimize: we can make hbitmap to internally check the range in a
> + * coarse level, or at least do it word by word. */
> +for (i = sector; i < sector + nb_sectors; i += gran) {
> +if (hbitmap_get(bitmap->meta, i)) {
> +return true;
> +}
> +}
> +return false;
> +}
> +
> +void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs,
> +  BdrvDirtyBitmap *bitmap, int64_t sector,
> +  int nb_sectors)
> +{
> +hbitmap_reset(bitmap->meta, sector, nb_sectors);
> +}
> +
>  bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
>  {
>  return bitmap->successor;
> diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
> index e1dbd8e..3b27742 100644
> --- a/include/block/dirty-bitmap.h
> +++ b/include/block/dirty-bitmap.h
> @@ -9,6 +9,9 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState 
> *bs,
>uint32_t granularity,
>const char *name,
>Error **errp);
> +void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap,
> +   int chunk_size);
> +void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap);
>  int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
> BdrvDirtyBitmap *bitmap,
> Error **errp);
> @@ -37,6 +40,12 @@ void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap,
> int64_t cur_sector, int nr_sectors);
>  void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
>   int64_t cur_sector, int nr_sectors);
> +int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs,
> +   BdrvDirtyBitmap *bitmap, int64_t sector,
> +   int nb_sectors);
> +void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs,
> +  BdrvDirtyBitmap *bitmap, int64_t sector,
> +  int nb_sectors);
>  BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap,
>   uint64_t first_sector);
>  void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter);
> 

Do we need to amend the teardown in bdrv_do_release_matching_dirty_bitmap?



Re: [Qemu-devel] [Qemu-block] [PATCH v3 08/15] tests: Add test code for meta bitmap

2016-02-29 Thread John Snow


On 02/27/2016 04:20 AM, Fam Zheng wrote:
> Signed-off-by: Fam Zheng 
> Reviewed-by: John Snow 
> ---
>  tests/test-hbitmap.c | 116 
> +++
>  1 file changed, 116 insertions(+)
> 
> diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c
> index abe1427..c00c2b5 100644
> --- a/tests/test-hbitmap.c
> +++ b/tests/test-hbitmap.c
> @@ -12,6 +12,7 @@
>  #include "qemu/osdep.h"
>  #include 
>  #include "qemu/hbitmap.h"
> +#include "block/block.h"
>  
>  #define LOG_BITS_PER_LONG  (BITS_PER_LONG == 32 ? 5 : 6)
>  
> @@ -21,6 +22,7 @@
>  
>  typedef struct TestHBitmapData {
>  HBitmap   *hb;
> +HBitmap   *meta;
>  unsigned long *bits;
>  size_t size;
>  size_t old_size;
> @@ -92,6 +94,14 @@ static void hbitmap_test_init(TestHBitmapData *data,
>  }
>  }
>  
> +static void hbitmap_test_init_meta(TestHBitmapData *data,
> +   uint64_t size, int granularity,
> +   int meta_chunk)
> +{
> +hbitmap_test_init(data, size, granularity);
> +data->meta = hbitmap_create_meta(data->hb, meta_chunk);
> +}
> +
>  static inline size_t hbitmap_test_array_size(size_t bits)
>  {
>  size_t n = (bits + BITS_PER_LONG - 1) / BITS_PER_LONG;
> @@ -134,6 +144,9 @@ static void hbitmap_test_teardown(TestHBitmapData *data,
>const void *unused)
>  {
>  if (data->hb) {
> +if (data->meta) {
> +hbitmap_free_meta(data->hb);
> +}
>  hbitmap_free(data->hb);
>  data->hb = NULL;
>  }
> @@ -635,6 +648,103 @@ static void 
> test_hbitmap_truncate_shrink_large(TestHBitmapData *data,
>  hbitmap_test_truncate(data, size, -diff, 0);
>  }
>  
> +static void hbitmap_check_meta(TestHBitmapData *data,
> +   int64_t start, int count)
> +{
> +int64_t i;
> +
> +for (i = 0; i < data->size; i++) {
> +if (i >= start && i < start + count) {
> +g_assert(hbitmap_get(data->meta, i));
> +} else {
> +g_assert(!hbitmap_get(data->meta, i));
> +}
> +}
> +}
> +
> +static void hbitmap_test_meta(TestHBitmapData *data,
> +  int64_t start, int count,
> +  int64_t check_start, int check_count)
> +{
> +hbitmap_reset_all(data->hb);
> +hbitmap_reset_all(data->meta);
> +
> +/* Test "unset" -> "unset" will not update meta. */
> +hbitmap_reset(data->hb, start, count);
> +hbitmap_check_meta(data, 0, 0);
> +
> +/* Test "unset" -> "set" will update meta */
> +hbitmap_set(data->hb, start, count);
> +hbitmap_check_meta(data, check_start, check_count);
> +
> +/* Test "set" -> "set" will not update meta */
> +hbitmap_reset_all(data->meta);
> +hbitmap_set(data->hb, start, count);
> +hbitmap_check_meta(data, 0, 0);
> +
> +/* Test "set" -> "unset" will update meta */
> +hbitmap_reset_all(data->meta);
> +hbitmap_reset(data->hb, start, count);
> +hbitmap_check_meta(data, check_start, check_count);
> +}
> +
> +static void hbitmap_test_meta_do(TestHBitmapData *data, int chunk_size)
> +{
> +uint64_t size = chunk_size * 100;
> +hbitmap_test_init_meta(data, size, 0, chunk_size);
> +
> +hbitmap_test_meta(data, 0, 1, 0, chunk_size);
> +hbitmap_test_meta(data, 0, chunk_size, 0, chunk_size);
> +hbitmap_test_meta(data, chunk_size - 1, 1, 0, chunk_size);
> +hbitmap_test_meta(data, chunk_size - 1, 2, 0, chunk_size * 2);
> +hbitmap_test_meta(data, chunk_size - 1, chunk_size + 1, 0, chunk_size * 
> 2);
> +hbitmap_test_meta(data, chunk_size - 1, chunk_size + 2, 0, chunk_size * 
> 3);
> +hbitmap_test_meta(data, 7 * chunk_size - 1, chunk_size + 2,
> +  6 * chunk_size, chunk_size * 3);
> +hbitmap_test_meta(data, size - 1, 1, size - chunk_size, chunk_size);
> +hbitmap_test_meta(data, 0, size, 0, size);
> +}
> +
> +static void test_hbitmap_meta_byte(TestHBitmapData *data, const void *unused)
> +{
> +hbitmap_test_meta_do(data, BITS_PER_BYTE);
> +}
> +
> +static void test_hbitmap_meta_word(TestHBitmapData *data, const void *unused)
> +{
> +hbitmap_test_meta_do(data, BITS_PER_LONG);
> +}
> +
> +static void test_hbitmap_meta_sector(TestHBitmapData *data, const void 
> *unused)
> +{
> +hbitmap_test_meta_do(data, BDRV_SECTOR_SIZE * BITS_PER_BYTE);
> +}
> +
> +/**
> + * Create an HBitmap and test set/unset.
> + */
> +static void test_hbitmap_meta_one(TestHBitmapData *data, const void *unused)
> +{
> +int i;
> +int64_t offsets[] = {
> +0, 1, L1 - 1, L1, L1 + 1, L2 - 1, L2, L2 + 1, L3 - 1, L3, L3 + 1
> +};
> +
> +hbitmap_test_init_meta(data, L3 * 2, 0, 1);
> +for (i = 0; i < ARRAY_SIZE(offsets); i++) {
> +hbitmap_test_meta(data, offsets[i], 1, offsets[i], 1);
> +hbitmap_test_meta(data, offsets[i], L1, 

Re: [Qemu-devel] [PATCH v2 7/9] i.MX: Add i.MX6 SOC implementation.

2016-02-29 Thread Jean-Christophe DUBOIS

Le 29/02/2016 22:14, Peter Maydell a écrit :

On 29 February 2016 at 20:34, Jean-Christophe DUBOIS
 wrote:

Le 29/02/2016 18:58, Peter Maydell a écrit :

To answer the question of "which of these is the correct thing to do"
we need to look at what the real hardware does when it's running Linux:
does it run Linux in Secure or Nonsecure?


i.MX6 is definitively able to boot in secure/trustzone mode (there are some
demo out there about it) so I guess it might be booting in secure mode.


Mmm. The other question I had about the system reset controller
is whether it's really purely hardware doing the "start secondary CPU",
or is it just a funny way of asking the system firmware to start
things, or is the stuff like the register for startup address
just a place to leave information that the system firmware
on the secondary CPU will read as part of its boot sequence?

Is there a datasheet available for this?


Well the SRC device is described in the i.MX6 reference manual.

http://cache.nxp.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf?fpsp=1_TYPE=Reference%20Manuals_VENDOR=FREESCALE_FILE_FORMAT=pdf_ASSET=Documentation=.pdf

I believe it is hardware based. Now it might involve some of the 
functions of the internal ROM in the process but we cannot change this 
behavior in any way.




thanks
-- PMM






Re: [Qemu-devel] [PATCH] target-arm: Implement MRS (banked) and MSR (banked) instructions

2016-02-29 Thread Edgar E. Iglesias
On Mon, Feb 29, 2016 at 04:18:54PM +, Peter Maydell wrote:
> Starting with the ARMv7 Virtualization Extensions, the A32 and T32
> instruction sets provide instructions "MSR (banked)" and "MRS
> (banked)" which can be used to access registers for a mode other
> than the current one:
>  * R_
>  * ELR_hyp
>  * SPSR_
> 
> Implement the missing instructions.

Wow, these insns were a bit messy to follow... Anyway, AFAIK this looks OK:

Acked-by: Edgar E. Iglesias 


> 
> Signed-off-by: Peter Maydell 
> ---
> We don't support EL2 yet, but you can get at these on a v8 CPU in
> 32-bit EL1 if EL3 is enabled. Obviously there's not going to be much
> 32-bit EL1 code out there that uses the insns though, as it wouldn't
> work on v7 if it did...
> 
>  target-arm/helper.h|   3 +
>  target-arm/op_helper.c | 120 
>  target-arm/translate.c | 246 
> -
>  3 files changed, 366 insertions(+), 3 deletions(-)
> 
> diff --git a/target-arm/helper.h b/target-arm/helper.h
> index ea13202..de3c644 100644
> --- a/target-arm/helper.h
> +++ b/target-arm/helper.h
> @@ -76,6 +76,9 @@ DEF_HELPER_1(exception_return, void, env)
>  DEF_HELPER_2(get_r13_banked, i32, env, i32)
>  DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
>  
> +DEF_HELPER_3(mrs_banked, i32, env, i32, i32)
> +DEF_HELPER_4(msr_banked, void, env, i32, i32, i32)
> +
>  DEF_HELPER_2(get_user_reg, i32, env, i32)
>  DEF_HELPER_3(set_user_reg, void, env, i32, i32)
>  
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index 4881e34..a2afdd8 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -489,6 +489,126 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, 
> uint32_t mode)
>  }
>  }
>  
> +static void msr_mrs_banked_exc_checks(CPUARMState *env, uint32_t tgtmode,
> +  uint32_t regno)
> +{
> +/* Raise an exception if the requested access is one of the UNPREDICTABLE
> + * cases; otherwise return. This broadly corresponds to the pseudocode
> + * BankedRegisterAccessValid() and SPSRAccessValid(),
> + * except that we have already handled some cases at translate time.
> + */
> +int curmode = env->uncached_cpsr & CPSR_M;
> +
> +if (curmode == tgtmode) {
> +goto undef;
> +}
> +
> +if (tgtmode == ARM_CPU_MODE_USR) {
> +switch (regno) {
> +case 8 ... 12:
> +if (curmode != ARM_CPU_MODE_FIQ) {
> +goto undef;
> +}
> +break;
> +case 13:
> +if (curmode == ARM_CPU_MODE_SYS) {
> +goto undef;
> +}
> +break;
> +case 14:
> +if (curmode == ARM_CPU_MODE_HYP || curmode == ARM_CPU_MODE_SYS) {
> +goto undef;
> +}
> +break;
> +default:
> +break;
> +}
> +}
> +
> +if (tgtmode == ARM_CPU_MODE_HYP) {
> +switch (regno) {
> +case 17: /* ELR_Hyp */
> +if (curmode != ARM_CPU_MODE_HYP && curmode != ARM_CPU_MODE_MON) {
> +goto undef;
> +}
> +break;
> +default:
> +if (curmode != ARM_CPU_MODE_MON) {
> +goto undef;
> +}
> +break;
> +}
> +}
> +
> +return;
> +
> +undef:
> +raise_exception(env, EXCP_UDEF, syn_uncategorized(),
> +exception_target_el(env));
> +}
> +
> +void HELPER(msr_banked)(CPUARMState *env, uint32_t value, uint32_t tgtmode,
> +uint32_t regno)
> +{
> +msr_mrs_banked_exc_checks(env, tgtmode, regno);
> +
> +switch (regno) {
> +case 16: /* SPSRs */
> +env->banked_spsr[bank_number(tgtmode)] = value;
> +break;
> +case 17: /* ELR_Hyp */
> +env->elr_el[2] = value;
> +break;
> +case 13:
> +env->banked_r13[bank_number(tgtmode)] = value;
> +break;
> +case 14:
> +env->banked_r14[bank_number(tgtmode)] = value;
> +break;
> +case 8 ... 12:
> +switch (tgtmode) {
> +case ARM_CPU_MODE_USR:
> +env->usr_regs[regno - 8] = value;
> +break;
> +case ARM_CPU_MODE_FIQ:
> +env->fiq_regs[regno - 8] = value;
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +}
> +
> +uint32_t HELPER(mrs_banked)(CPUARMState *env, uint32_t tgtmode, uint32_t 
> regno)
> +{
> +msr_mrs_banked_exc_checks(env, tgtmode, regno);
> +
> +switch (regno) {
> +case 16: /* SPSRs */
> +return env->banked_spsr[bank_number(tgtmode)];
> +case 17: /* ELR_Hyp */
> +return env->elr_el[2];
> +case 13:
> +return env->banked_r13[bank_number(tgtmode)];
> +case 14:
> +return 

Re: [Qemu-devel] [PATCH v2 7/9] i.MX: Add i.MX6 SOC implementation.

2016-02-29 Thread Peter Maydell
On 29 February 2016 at 20:34, Jean-Christophe DUBOIS
 wrote:
> Le 29/02/2016 18:58, Peter Maydell a écrit :
>> To answer the question of "which of these is the correct thing to do"
>> we need to look at what the real hardware does when it's running Linux:
>> does it run Linux in Secure or Nonsecure?
>
>
> i.MX6 is definitively able to boot in secure/trustzone mode (there are some
> demo out there about it) so I guess it might be booting in secure mode.


Mmm. The other question I had about the system reset controller
is whether it's really purely hardware doing the "start secondary CPU",
or is it just a funny way of asking the system firmware to start
things, or is the stuff like the register for startup address
just a place to leave information that the system firmware
on the secondary CPU will read as part of its boot sequence?

Is there a datasheet available for this?

thanks
-- PMM



Re: [Qemu-devel] [PATCH v2 7/9] i.MX: Add i.MX6 SOC implementation.

2016-02-29 Thread Jean-Christophe DUBOIS

Le 29/02/2016 18:58, Peter Maydell a écrit :

On 19 February 2016 at 06:32, Jean-Christophe DUBOIS
 wrote:

If I set has_el3 to false, I can boot the 4 cores without problem. With
has_el3 set to true (default value) I am getting the above behavior (boot OK
in uniprocessor mode, and misbehaving if -smp >= 2).

I worked out why this happens -- it's because the secondary CPUs and
the primary disagree about whether they're booting in Secure mode.
You can either:
(1) have the board code say "boot the primary in Secure mode":
--- a/hw/arm/sabrelite.c
+++ b/hw/arm/sabrelite.c
@@ -85,6 +85,7 @@ static void sabrelite_init(MachineState *machine)
  sabrelite_binfo.kernel_cmdline = machine->kernel_cmdline;
  sabrelite_binfo.initrd_filename = machine->initrd_filename;
  sabrelite_binfo.nb_cpus = smp_cpus;
+sabrelite_binfo.secure_boot = true;
  sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary;
  sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary;

or (2) have the code in imx6_src.c tell the secondaries that
they should start in non-secure mode:

--- a/hw/misc/imx6_src.c
+++ b/hw/misc/imx6_src.c
@@ -144,6 +144,7 @@ static void imx6_src_cpu_on(uint32_t cpuid,
uint32_t entry, uint32_t context_id)

  target_cpu->env.regs[0] = context_id;
  target_cpu->env.thumb = entry & 1;
+target_cpu->env.cp15.scr_el3 |= SCR_NS;

  target_cpu_class->set_pc(target_cpu_state, entry);
  }

If you do either of these then the system will boot the kernel that
you sent the link to.


Thanks Peter, It does work.



To answer the question of "which of these is the correct thing to do"
we need to look at what the real hardware does when it's running Linux:
does it run Linux in Secure or Nonsecure?


i.MX6 is definitively able to boot in secure/trustzone mode (there are 
some demo out there about it) so I guess it might be booting in secure mode.




thanks
-- PMM






Re: [Qemu-devel] [Qemu-ppc] Migrating decrementer

2016-02-29 Thread Mark Cave-Ayland
On 29/02/16 03:57, David Gibson wrote:

> On Fri, Feb 26, 2016 at 12:29:51PM +, Mark Cave-Ayland wrote:
>> On 26/02/16 04:35, David Gibson wrote:
>>
 Sign. And let me try that again, this time after caffeine:

 cpu_start/resume():
 cpu->tb_env->tb_offset =
 muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
  cpu->tb_env->tb_freq, NANOSECONDS_PER_SECOND) +
 cpu->tb_env->tb_offset -
 cpu_get_host_ticks();

 This should translate to: at CPU start, calculate the difference between
 the current guest virtual timebase and the host timebase, storing the
 difference in cpu->tb_env->tb_offset.
>>>
>>> Ummm... I think that's right.  Except that you need to make sure you
>>> calculate the tb_offset just once, and set the same value to all guest
>>> CPUs.  Otherwise the guest TBs may be slightly out of sync with each
>>> other, which is bad (the host should have already ensure that all host
>>> TBs are in sync with each other).
>>
>> Nods. The reason I really like this solution is because it correctly
>> handles both paused/live machines and simplifies the migration logic
>> significantly. In fact, with this solution the only information you
>> would need in vmstate_ppc_timebase for migration would be the current
>> tb_offset so the receiving host can calculate the guest timebase from
>> the virtual clock accordingly.
> 
>>> We really should make helper routines that each Power machine type can
>>> use for this.  Unfortunately we can't put it directly into the common
>>> ppc cpu migration code because of the requirement to keep the TBs
>>> synced across the machine.
>>
>> Effectively I believe there are 2 cases here: TCG and KVM. For TCG all
>> of this is a no-op since tb/decr are already derived from the virtual
>> clock + tb_offset already so that really just leaves KVM.
>>
>> >From what you're saying we would need 2 hooks for KVM here: one on
>> machine start/resume which updates tb_offset for all vCPUs and one for
>> vCPU resume which updates just that one particular vCPU.
>>
>> Just curious as to your comment regarding helper routines for each Power
>> machine type - is there any reason not to enable this globally for all
>> Power machine types? If tb_offset isn't supported by the guest then the
>> problem with not being able to handle a jump in timebase post-migration
>> still remains exactly the same.
> 
> Well, I can't see a place to put it globally.  We can't put it in the
> general vCPU stuff, because that would migrate each CPU's timebase
> independently, but we want to migrate as a system wide operation, to
> ensure the TBs are all synchronized in the destination guest.
> 
> To do the platform wide stuff, it pretty much has to be in the machine
> type.

(goes and looks)

It strikes me that a good solution here would be to introduce a new
PPCMachineClass from which all of the PPC machines could derive instead
of each different machine being a direct subclass of MachineClass (this
is not dissimilar as to the existing PCMachineClass) and move the
timebase and decrementer information into it. With this then all of the
PPC machine types can pick up the changes automatically.

>> The other question of course relates to the reason this thread was
>> started which is will this approach still support migrating the
>> decrementer? My feeling is that this would still work in that we would
>> encode the number of ticks before the decrementer reaches its interrupt
>> value into vmstate_ppc_timebase, whether high or low. For TCG it is easy
>> to ensure that the decrementer will still fire in n ticks time
>> post-migration (which solves my particular use case), but I don't have a
>> feeling as to whether this is possible, or indeed desirable for KVM.
> 
> Yes, for TCG it should be fairly straightforward.  The DECR should be
> calculated from the timebase.  We do need to check it on incoming
> migration though, and check when we need to refire the decrementer
> interrupt.

So just to confirm that while reads from the timebase are not privileged
(and so cannot be intercepted between host and guest), we still have
individual control of the per-guest decrementer interrupts?

> For KVM we'll need to load an appropriate value into the real
> decrementer.  We probably want to migrate a difference between the TB
> and the decrementer.  What could get hairy here is that there are a
> number of different variants between ppc models on how exactly the
> decrementer interrupt triggers: is it edge-triggered on 1->0
> transition, edge-triggered on 0->-1 transition, or level triggered on
> the DECR's sign bit.  

I don't think that is too much of a problem, since for TCG the logic is
already encapsulated in hw/ppc/ppc.c's __cpu_ppc_store_decr(). It should
be possible to move this logic into a shared helper function to keep
everything in one place.

Finally just to re-iterate that while I can write and compile-test a
potential patchset, I 

Re: [Qemu-devel] [PATCH v2 5/9] i.MX: Add i.MX6 CCM and ANALOG device.

2016-02-29 Thread Jean-Christophe DUBOIS

Le 29/02/2016 18:33, Peter Maydell a écrit :

On 8 February 2016 at 22:08, Jean-Christophe Dubois  
wrote:

Signed-off-by: Jean-Christophe Dubois 
---
+static uint64_t imx6_ccm_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint32 value = 0;

This should be 'uint32_t', not 'uint32'.

(You'll find this doesn't compile on current master if you rebase it;
uint32 was a type intended only for use with the softfloat code, and
we've just eliminated it.)

Similar issues in imx6_src_read() and imx_spi_read().

You also need to make sure all your new .c files have #include "qemu/osdep.h"
as the first include they do, or they won't build on current master.


OK, I'll do.



thanks
-- PMM






[Qemu-devel] [PULL 08/12] mirror: Rewrite mirror_iteration

2016-02-29 Thread Jeff Cody
From: Fam Zheng 

The "pnum < nb_sectors" condition in deciding whether to actually copy
data is unnecessarily strict, and the qiov initialization is
unnecessarily for bdrv_aio_write_zeroes and bdrv_aio_discard.

Rewrite mirror_iteration to fix both flaws.

The output of iotests 109 is updated because we now report the offset
and len slightly differently in mirroring progress.

Signed-off-by: Fam Zheng 
Reviewed-by: Max Reitz 
Message-id: 1454637630-10585-2-git-send-email-f...@redhat.com
Signed-off-by: Jeff Cody 
---
 block/mirror.c | 335 +++--
 tests/qemu-iotests/109.out |  80 +--
 trace-events   |   1 -
 3 files changed, 243 insertions(+), 173 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 2c0edfa..48cd0b3 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -47,7 +47,6 @@ typedef struct MirrorBlockJob {
 BlockdevOnError on_source_error, on_target_error;
 bool synced;
 bool should_complete;
-int64_t sector_num;
 int64_t granularity;
 size_t buf_size;
 int64_t bdev_length;
@@ -64,6 +63,8 @@ typedef struct MirrorBlockJob {
 int ret;
 bool unmap;
 bool waiting_for_io;
+int target_cluster_sectors;
+int max_iov;
 } MirrorBlockJob;
 
 typedef struct MirrorOp {
@@ -159,116 +160,79 @@ static void mirror_read_complete(void *opaque, int ret)
 mirror_write_complete, op);
 }
 
-static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
+/* Round sector_num and/or nb_sectors to target cluster if COW is needed, and
+ * return the offset of the adjusted tail sector against original. */
+static int mirror_cow_align(MirrorBlockJob *s,
+int64_t *sector_num,
+int *nb_sectors)
+{
+bool need_cow;
+int ret = 0;
+int chunk_sectors = s->granularity >> BDRV_SECTOR_BITS;
+int64_t align_sector_num = *sector_num;
+int align_nb_sectors = *nb_sectors;
+int max_sectors = chunk_sectors * s->max_iov;
+
+need_cow = !test_bit(*sector_num / chunk_sectors, s->cow_bitmap);
+need_cow |= !test_bit((*sector_num + *nb_sectors - 1) / chunk_sectors,
+  s->cow_bitmap);
+if (need_cow) {
+bdrv_round_to_clusters(s->target, *sector_num, *nb_sectors,
+   _sector_num, _nb_sectors);
+}
+
+if (align_nb_sectors > max_sectors) {
+align_nb_sectors = max_sectors;
+if (need_cow) {
+align_nb_sectors = QEMU_ALIGN_DOWN(align_nb_sectors,
+   s->target_cluster_sectors);
+}
+}
+
+ret = align_sector_num + align_nb_sectors - (*sector_num + *nb_sectors);
+*sector_num = align_sector_num;
+*nb_sectors = align_nb_sectors;
+assert(ret >= 0);
+return ret;
+}
+
+/* Submit async read while handling COW.
+ * Returns: nb_sectors if no alignment is necessary, or
+ *  (new_end - sector_num) if tail is rounded up or down due to
+ *  alignment or buffer limit.
+ */
+static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
+  int nb_sectors)
 {
 BlockDriverState *source = s->common.bs;
-int nb_sectors, sectors_per_chunk, nb_chunks, max_iov;
-int64_t end, sector_num, next_chunk, next_sector, hbitmap_next_sector;
-uint64_t delay_ns = 0;
+int sectors_per_chunk, nb_chunks;
+int ret = nb_sectors;
 MirrorOp *op;
-int pnum;
-int64_t ret;
-BlockDriverState *file;
 
-max_iov = MIN(source->bl.max_iov, s->target->bl.max_iov);
-
-s->sector_num = hbitmap_iter_next(>hbi);
-if (s->sector_num < 0) {
-bdrv_dirty_iter_init(s->dirty_bitmap, >hbi);
-s->sector_num = hbitmap_iter_next(>hbi);
-trace_mirror_restart_iter(s, bdrv_get_dirty_count(s->dirty_bitmap));
-assert(s->sector_num >= 0);
-}
-
-hbitmap_next_sector = s->sector_num;
-sector_num = s->sector_num;
 sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;
-end = s->bdev_length / BDRV_SECTOR_SIZE;
 
-/* Extend the QEMUIOVector to include all adjacent blocks that will
- * be copied in this operation.
- *
- * We have to do this if we have no backing file yet in the destination,
- * and the cluster size is very large.  Then we need to do COW ourselves.
- * The first time a cluster is copied, copy it entirely.  Note that,
- * because both the granularity and the cluster size are powers of two,
- * the number of sectors to copy cannot exceed one cluster.
- *
- * We also want to extend the QEMUIOVector to include more adjacent
- * dirty blocks if possible, to limit the number of I/O operations and
- * run efficiently even with a small granularity.
- */
-nb_chunks = 0;
-nb_sectors = 0;
-next_sector = sector_num;
-next_chunk = sector_num / 

[Qemu-devel] [PULL 07/12] vhdx: Simplify vhdx_set_shift_bits()

2016-02-29 Thread Jeff Cody
From: Max Reitz 

For values which are powers of two (and we do assume all of these to
be), sizeof(x) * 8 - 1 - clz(x) == ctz(x). Therefore, use ctz().

Signed-off-by: Max Reitz 
Message-id: 1450451066-13335-3-git-send-email-mre...@redhat.com
Signed-off-by: Jeff Cody 
---
 block/vhdx.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/block/vhdx.c b/block/vhdx.c
index 1e7e03e..9a51428 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -264,10 +264,10 @@ static void vhdx_region_unregister_all(BDRVVHDXState *s)
 
 static void vhdx_set_shift_bits(BDRVVHDXState *s)
 {
-s->logical_sector_size_bits = 31 - clz32(s->logical_sector_size);
-s->sectors_per_block_bits =   31 - clz32(s->sectors_per_block);
-s->chunk_ratio_bits = 63 - clz64(s->chunk_ratio);
-s->block_size_bits =  31 - clz32(s->block_size);
+s->logical_sector_size_bits = ctz32(s->logical_sector_size);
+s->sectors_per_block_bits =   ctz32(s->sectors_per_block);
+s->chunk_ratio_bits = ctz64(s->chunk_ratio);
+s->block_size_bits =  ctz32(s->block_size);
 }
 
 /*
-- 
1.9.3




[Qemu-devel] [PULL 12/12] iotests/124: Add cluster_size mismatch test

2016-02-29 Thread Jeff Cody
From: John Snow 

If a backing file isn't specified in the target image and the
cluster_size is larger than the bitmap granularity, we run the risk of
creating bitmaps with allocated clusters but empty/no data which will
prevent the proper reading of the backup in the future.

Signed-off-by: John Snow 
Reviewed-by: Fam Zheng 
Message-id: 1456433911-24718-4-git-send-email-js...@redhat.com
Signed-off-by: Jeff Cody 
---
 tests/qemu-iotests/124 | 58 ++
 tests/qemu-iotests/124.out |  4 ++--
 2 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124
index 7d33422..de7cdbe 100644
--- a/tests/qemu-iotests/124
+++ b/tests/qemu-iotests/124
@@ -132,14 +132,16 @@ class TestIncrementalBackupBase(iotests.QMPTestCase):
 
 
 def img_create(self, img, fmt=iotests.imgfmt, size='64M',
-   parent=None, parentFormat=None):
+   parent=None, parentFormat=None, **kwargs):
+optargs = []
+for k,v in kwargs.iteritems():
+optargs = optargs + ['-o', '%s=%s' % (k,v)]
+args = ['create', '-f', fmt] + optargs + [img, size]
 if parent:
 if parentFormat is None:
 parentFormat = fmt
-iotests.qemu_img('create', '-f', fmt, img, size,
- '-b', parent, '-F', parentFormat)
-else:
-iotests.qemu_img('create', '-f', fmt, img, size)
+args = args + ['-b', parent, '-F', parentFormat]
+iotests.qemu_img(*args)
 self.files.append(img)
 
 
@@ -307,6 +309,52 @@ class TestIncrementalBackup(TestIncrementalBackupBase):
 return self.do_incremental_simple(granularity=131072)
 
 
+def test_larger_cluster_target(self):
+'''
+Test: Create and verify backups made to a larger cluster size target.
+
+With a default granularity of 64KiB, verify that backups made to a
+larger cluster size target of 128KiB without a backing file works.
+'''
+drive0 = self.drives[0]
+
+# Create a cluster_size=128k full backup / "anchor" backup
+self.img_create(drive0['backup'], cluster_size='128k')
+self.assertTrue(self.do_qmp_backup(device=drive0['id'], sync='full',
+   format=drive0['fmt'],
+   target=drive0['backup'],
+   mode='existing'))
+
+# Create bitmap and dirty it with some new writes.
+# overwrite [32736, 32799] which will dirty bitmap clusters at
+# 32M-64K and 32M. 32M+64K will be left undirtied.
+bitmap0 = self.add_bitmap('bitmap0', drive0)
+self.hmp_io_writes(drive0['id'],
+   (('0xab', 0, 512),
+('0xfe', '16M', '256k'),
+('0x64', '32736k', '64k')))
+
+
+# Prepare a cluster_size=128k backup target without a backing file.
+(target, _) = bitmap0.new_target()
+self.img_create(target, bitmap0.drive['fmt'], cluster_size='128k')
+
+# Perform Incremental Backup
+self.assertTrue(self.do_qmp_backup(device=bitmap0.drive['id'],
+   sync='incremental',
+   bitmap=bitmap0.name,
+   format=bitmap0.drive['fmt'],
+   target=target,
+   mode='existing'))
+self.make_reference_backup(bitmap0)
+
+# Add the backing file, then compare and exit.
+iotests.qemu_img('rebase', '-f', drive0['fmt'], '-u', '-b',
+ drive0['backup'], '-F', drive0['fmt'], target)
+self.vm.shutdown()
+self.check_backups()
+
+
 def test_incremental_transaction(self):
 '''Test: Verify backups made from transactionally created bitmaps.
 
diff --git a/tests/qemu-iotests/124.out b/tests/qemu-iotests/124.out
index dae404e..36376be 100644
--- a/tests/qemu-iotests/124.out
+++ b/tests/qemu-iotests/124.out
@@ -1,5 +1,5 @@
-.
+..
 --
-Ran 9 tests
+Ran 10 tests
 
 OK
-- 
1.9.3




  1   2   3   >