qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/25] Block layer core and image format patches
@ 2015-06-12 16:23 Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 01/25] iotests: remove assertIsNotNone call Kevin Wolf
                   ` (25 more replies)
  0 siblings, 26 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

The following changes since commit 4cb618abc1818586c08011ff0a84a015787b1672:

  Merge remote-tracking branch 'remotes/lalrae/tags/mips-20150612' into staging (2015-06-12 12:49:40 +0100)

are available in the git repository at:


  git://repo.or.cz/qemu/kevin.git tags/for-upstream

for you to fetch changes up to 67251a311371c4d22e803f151f47fe817175b6c3:

  block: Fix reopen flag inheritance (2015-06-12 17:04:59 +0200)

----------------------------------------------------------------
Block layer core and image format patches

----------------------------------------------------------------
Fam Zheng (3):
      qemu-iotests: Fix 128 if sudo required
      vmdk: Fix index_in_cluster calculation in vmdk_co_get_block_status
      vmdk: Use vmdk_find_index_in_cluster everywhere

John Snow (3):
      iotests: remove assertIsNotNone call
      block: record new size in bdrv_dirty_bitmap_truncate
      block: Change bitmap truncate conditional to assertion

Kevin Wolf (14):
      raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size
      qdict: Add qdict_array_entries()
      qdict: Add qdict_{set,copy}_default()
      check-qdict: Test cases for new functions
      quorum: Use bdrv_open_image()
      vmdk: Use bdrv_open_image()
      block: Use macro for cache option names
      block: Use QemuOpts in bdrv_open_common()
      block: Move flag inheritance to bdrv_open_inherit()
      block: Drain requests before swapping nodes in bdrv_swap()
      queue.h: Add QLIST_FIX_HEAD_PTR()
      block: Add list of children to BlockDriverState
      block: Add BlockDriverState.inherits_from
      block: Fix reopen flag inheritance

Max Reitz (5):
      qcow2: Set MIN_L2_CACHE_SIZE to 2
      iotests: qcow2 COW with minimal L2 cache size
      qcow2: Add DEFAULT_L2_CACHE_CLUSTERS
      block: driver should override flags in bdrv_open()
      iotests: Add tests for overriding BDRV_O_PROTOCOL

 block.c                    | 237 +++++++++++++++++++++++++++++++++++++--------
 block/blkdebug.c           |   2 +-
 block/blkverify.c          |   4 +-
 block/qcow2.c              |  11 ++-
 block/qcow2.h              |   5 +-
 block/quorum.c             |  51 +++-------
 block/raw-posix.c          |   5 +-
 block/vmdk.c               |  84 +++++++---------
 blockdev.c                 |  24 ++---
 include/block/block.h      |  12 ++-
 include/block/block_int.h  |  19 ++++
 include/qapi/qmp/qdict.h   |   4 +
 include/qemu/queue.h       |   6 ++
 qobject/qdict.c            | 111 ++++++++++++++++++++-
 tests/check-qdict.c        |  67 +++++++++++++
 tests/qemu-iotests/051     |   1 -
 tests/qemu-iotests/051.out |   3 -
 tests/qemu-iotests/103     |  10 ++
 tests/qemu-iotests/103.out |   5 +
 tests/qemu-iotests/119     |  60 ++++++++++++
 tests/qemu-iotests/119.out |  11 +++
 tests/qemu-iotests/120     |  65 +++++++++++++
 tests/qemu-iotests/120.out |  15 +++
 tests/qemu-iotests/124     |   2 +-
 tests/qemu-iotests/128     |   4 +-
 tests/qemu-iotests/group   |   2 +
 26 files changed, 660 insertions(+), 160 deletions(-)
 create mode 100755 tests/qemu-iotests/119
 create mode 100644 tests/qemu-iotests/119.out
 create mode 100755 tests/qemu-iotests/120
 create mode 100644 tests/qemu-iotests/120.out

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 01/25] iotests: remove assertIsNotNone call
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 02/25] qemu-iotests: Fix 128 if sudo required Kevin Wolf
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: John Snow <jsnow@redhat.com>

RHEL6 doesn't have Python 2.7, so replace this call with
assertNotEqual(x, None) which will work just as well.

Reported-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/124 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124
index 3ee78cd..8abce2f 100644
--- a/tests/qemu-iotests/124
+++ b/tests/qemu-iotests/124
@@ -125,7 +125,7 @@ class TestIncrementalBackup(iotests.QMPTestCase):
 
         event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED",
                                    match={'data': {'device': kwargs['device']}})
-        self.assertIsNotNone(event)
+        self.assertNotEqual(event, None)
 
         try:
             failure = self.dictpath(event, 'data/error')
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 02/25] qemu-iotests: Fix 128 if sudo required
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 01/25] iotests: remove assertIsNotNone call Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 03/25] qcow2: Set MIN_L2_CACHE_SIZE to 2 Kevin Wolf
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

If passwordless "sudo" works, use it in the qemu-io cmd.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/128 | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/qemu-iotests/128 b/tests/qemu-iotests/128
index 249a865..e2a0f2f 100755
--- a/tests/qemu-iotests/128
+++ b/tests/qemu-iotests/128
@@ -29,6 +29,7 @@ tmp=/tmp/$$
 status=1	# failure is the default!
 
 devname="eiodev$$"
+sudo=""
 
 _setup_eiodev()
 {
@@ -37,6 +38,7 @@ _setup_eiodev()
 		echo "0 $((1024 * 1024 * 1024 / 512)) error" | \
 			$cmd dmsetup create "$devname" 2>/dev/null
 		if [ "$?" -eq 0 ]; then
+			sudo="$cmd"
 			return
 		fi
 	done
@@ -74,7 +76,7 @@ TEST_IMG="/dev/mapper/$devname"
 echo
 echo "== reading from error device =="
 # Opening image should succeed but the read operation should fail
-$QEMU_IO --format "$IMGFMT" --nocache -c "read 0 65536" "$TEST_IMG" | _filter_qemu_io
+$sudo $QEMU_IO --format "$IMGFMT" --nocache -c "read 0 65536" "$TEST_IMG" | _filter_qemu_io
 
 # success, all done
 echo "*** done"
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 03/25] qcow2: Set MIN_L2_CACHE_SIZE to 2
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 01/25] iotests: remove assertIsNotNone call Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 02/25] qemu-iotests: Fix 128 if sudo required Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 04/25] iotests: qcow2 COW with minimal L2 cache size Kevin Wolf
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

The L2 cache must cover at least two L2 tables, because during COW two
L2 tables are accessed simultaneously.

Reported-by: Alexander Graf <agraf@suse.de>
Cc: qemu-stable <qemu-stable@nongnu.org>
Signed-off-by: Max Reitz <mreitz@redhat.com>
Tested-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/block/qcow2.h b/block/qcow2.h
index 0076512..aa20022 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -62,7 +62,8 @@
 #define MIN_CLUSTER_BITS 9
 #define MAX_CLUSTER_BITS 21
 
-#define MIN_L2_CACHE_SIZE 1 /* cluster */
+/* Must be at least 2 to cover COW */
+#define MIN_L2_CACHE_SIZE 2 /* clusters */
 
 /* Must be at least 4 to cover all cases of refcount table growth */
 #define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 04/25] iotests: qcow2 COW with minimal L2 cache size
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (2 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 03/25] qcow2: Set MIN_L2_CACHE_SIZE to 2 Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 05/25] qcow2: Add DEFAULT_L2_CACHE_CLUSTERS Kevin Wolf
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

This adds a test case to test 103 for performing a COW operation in a
qcow2 image using an L2 cache with minimal size (which should be at
least two clusters so the COW can access both source and destination
simultaneously).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/103     | 10 ++++++++++
 tests/qemu-iotests/103.out |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/tests/qemu-iotests/103 b/tests/qemu-iotests/103
index ccab551..fa9a3c1 100755
--- a/tests/qemu-iotests/103
+++ b/tests/qemu-iotests/103
@@ -93,6 +93,16 @@ $QEMU_IO -c "open -o l2-cache-size=1M,refcount-cache-size=0.25M $TEST_IMG" \
          -c 'read -P 42 0 64k' \
     | _filter_qemu_io
 
+echo
+echo '=== Testing minimal L2 cache and COW ==='
+echo
+
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
+# This requires a COW operation, which accesses two L2 tables simultaneously
+# (COW source and destination), so there must be enough space in the cache to
+# place both tables there (and qemu should not crash)
+$QEMU_IO -c "open -o cache-size=0 $TEST_IMG" -c 'write 0 64k' | _filter_qemu_io
+
 # success, all done
 echo '*** done'
 rm -f $seq.full
diff --git a/tests/qemu-iotests/103.out b/tests/qemu-iotests/103.out
index ee705b0..d05f49f 100644
--- a/tests/qemu-iotests/103.out
+++ b/tests/qemu-iotests/103.out
@@ -26,4 +26,9 @@ read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Testing minimal L2 cache and COW ===
+
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 *** done
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 05/25] qcow2: Add DEFAULT_L2_CACHE_CLUSTERS
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (3 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 04/25] iotests: qcow2 COW with minimal L2 cache size Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 06/25] vmdk: Fix index_in_cluster calculation in vmdk_co_get_block_status Kevin Wolf
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

If a relatively large cluster size is chosen, the default of 1 MB L2
cache is not really appropriate. In this case, unless overridden by the
user, the default cache size should not be determined by its size in
bytes but by the number of L2 tables (clusters) it is supposed to
contain.

Note that without this patch, MIN_L2_CACHE_SIZE will effectively take
over the same role. However, providing space for just two L2 tables is
not enough to be the default.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2.c | 11 ++++++++---
 block/qcow2.h |  2 ++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index f7b4cc6..c4f6938 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -483,9 +483,11 @@ static const char *overlap_bool_option_names[QCOW2_OL_MAX_BITNR] = {
     [QCOW2_OL_INACTIVE_L2_BITNR]    = QCOW2_OPT_OVERLAP_INACTIVE_L2,
 };
 
-static void read_cache_sizes(QemuOpts *opts, uint64_t *l2_cache_size,
+static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
+                             uint64_t *l2_cache_size,
                              uint64_t *refcount_cache_size, Error **errp)
 {
+    BDRVQcowState *s = bs->opaque;
     uint64_t combined_cache_size;
     bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
 
@@ -525,7 +527,9 @@ static void read_cache_sizes(QemuOpts *opts, uint64_t *l2_cache_size,
         }
     } else {
         if (!l2_cache_size_set && !refcount_cache_size_set) {
-            *l2_cache_size = DEFAULT_L2_CACHE_BYTE_SIZE;
+            *l2_cache_size = MAX(DEFAULT_L2_CACHE_BYTE_SIZE,
+                                 (uint64_t)DEFAULT_L2_CACHE_CLUSTERS
+                                 * s->cluster_size);
             *refcount_cache_size = *l2_cache_size
                                  / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
         } else if (!l2_cache_size_set) {
@@ -803,7 +807,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    read_cache_sizes(opts, &l2_cache_size, &refcount_cache_size, &local_err);
+    read_cache_sizes(bs, opts, &l2_cache_size, &refcount_cache_size,
+                     &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         ret = -EINVAL;
diff --git a/block/qcow2.h b/block/qcow2.h
index aa20022..5936d29 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -68,6 +68,8 @@
 /* Must be at least 4 to cover all cases of refcount table growth */
 #define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
 
+/* Whichever is more */
+#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
 #define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */
 
 /* The refblock cache needs only a fourth of the L2 cache size to cover as many
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 06/25] vmdk: Fix index_in_cluster calculation in vmdk_co_get_block_status
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (4 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 05/25] qcow2: Add DEFAULT_L2_CACHE_CLUSTERS Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 07/25] vmdk: Use vmdk_find_index_in_cluster everywhere Kevin Wolf
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

It has the similar issue with b1649fae49a8. Since the calculation
is repeated for a few times already, introduce a function so it can be
reused.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vmdk.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index b66745d..3e4d84b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1248,6 +1248,17 @@ static VmdkExtent *find_extent(BDRVVmdkState *s,
     return NULL;
 }
 
+static inline uint64_t vmdk_find_index_in_cluster(VmdkExtent *extent,
+                                                  int64_t sector_num)
+{
+    uint64_t index_in_cluster, extent_begin_sector, extent_relative_sector_num;
+
+    extent_begin_sector = extent->end_sector - extent->sectors;
+    extent_relative_sector_num = sector_num - extent_begin_sector;
+    index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
+    return index_in_cluster;
+}
+
 static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors, int *pnum)
 {
@@ -1285,7 +1296,7 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs,
         break;
     }
 
-    index_in_cluster = sector_num % extent->cluster_sectors;
+    index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
     n = extent->cluster_sectors - index_in_cluster;
     if (n > nb_sectors) {
         n = nb_sectors;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 07/25] vmdk: Use vmdk_find_index_in_cluster everywhere
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (5 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 06/25] vmdk: Fix index_in_cluster calculation in vmdk_co_get_block_status Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 08/25] raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size Kevin Wolf
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vmdk.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index 3e4d84b..56626b0 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1424,7 +1424,6 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
     BDRVVmdkState *s = bs->opaque;
     int ret;
     uint64_t n, index_in_cluster;
-    uint64_t extent_begin_sector, extent_relative_sector_num;
     VmdkExtent *extent = NULL;
     uint64_t cluster_offset;
 
@@ -1436,9 +1435,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
         ret = get_cluster_offset(bs, extent, NULL,
                                  sector_num << 9, false, &cluster_offset,
                                  0, 0);
-        extent_begin_sector = extent->end_sector - extent->sectors;
-        extent_relative_sector_num = sector_num - extent_begin_sector;
-        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
+        index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
         n = extent->cluster_sectors - index_in_cluster;
         if (n > nb_sectors) {
             n = nb_sectors;
@@ -1500,7 +1497,6 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
     VmdkExtent *extent = NULL;
     int ret;
     int64_t index_in_cluster, n;
-    uint64_t extent_begin_sector, extent_relative_sector_num;
     uint64_t cluster_offset;
     VmdkMetaData m_data;
 
@@ -1516,9 +1512,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
         if (!extent) {
             return -EIO;
         }
-        extent_begin_sector = extent->end_sector - extent->sectors;
-        extent_relative_sector_num = sector_num - extent_begin_sector;
-        index_in_cluster = extent_relative_sector_num % extent->cluster_sectors;
+        index_in_cluster = vmdk_find_index_in_cluster(extent, sector_num);
         n = extent->cluster_sectors - index_in_cluster;
         if (n > nb_sectors) {
             n = nb_sectors;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 08/25] raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (6 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 07/25] vmdk: Use vmdk_find_index_in_cluster everywhere Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 09/25] block: record new size in bdrv_dirty_bitmap_truncate Kevin Wolf
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Image files with an unaligned image size have a final hole that starts
at EOF, i.e. in the middle of a sector. Currently, *pnum == 0 is
returned when checking the status of this sector. In qemu-img, this
triggers an assertion failure.

In order to fix this, one type for the sector that contains EOF must be
found. Treating a hole as data is safe, so this patch rounds the
calculated number of data sectors up, so that a partial sector at EOF is
treated as a full data sector.

This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1229394

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Tested-by: Cole Robinson <crobinso@redhat.com>
---
 block/raw-posix.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/block/raw-posix.c b/block/raw-posix.c
index 2990e95..44ade8c 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -1848,8 +1848,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
         *pnum = nb_sectors;
         ret = BDRV_BLOCK_DATA;
     } else if (data == start) {
-        /* On a data extent, compute sectors to the end of the extent.  */
-        *pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE);
+        /* On a data extent, compute sectors to the end of the extent,
+         * possibly including a partial sector at EOF. */
+        *pnum = MIN(nb_sectors, DIV_ROUND_UP(hole - start, BDRV_SECTOR_SIZE));
         ret = BDRV_BLOCK_DATA;
     } else {
         /* On a hole, compute sectors to the beginning of the next extent.  */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 09/25] block: record new size in bdrv_dirty_bitmap_truncate
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (7 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 08/25] raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 10/25] block: Change bitmap truncate conditional to assertion Kevin Wolf
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: John Snow <jsnow@redhat.com>

ce1ffea8 neglected to update the BdrvDirtyBitmap structure
itself for internal consistency. It's currently not an issue,
but for migration and persistence series this will cause headaches.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block.c b/block.c
index 2b9ceae..2786e47 100644
--- a/block.c
+++ b/block.c
@@ -3224,6 +3224,7 @@ static void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
             continue;
         }
         hbitmap_truncate(bitmap->bitmap, size);
+        bitmap->size = size;
     }
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 10/25] block: Change bitmap truncate conditional to assertion
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (8 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 09/25] block: record new size in bdrv_dirty_bitmap_truncate Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 11/25] block: driver should override flags in bdrv_open() Kevin Wolf
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: John Snow <jsnow@redhat.com>

This is an artifact of an older version that had both all-bitmap and
single-bitmap truncate functions, and some info got lost in the shuffle.

Bitmaps can only be frozen during a backup operation, and a backup
operation should prevent a resize operation, so just assert that this
cannot happen.

Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/block.c b/block.c
index 2786e47..4ea2c4f 100644
--- a/block.c
+++ b/block.c
@@ -3220,9 +3220,7 @@ static void bdrv_dirty_bitmap_truncate(BlockDriverState *bs)
     uint64_t size = bdrv_nb_sectors(bs);
 
     QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) {
-        if (bdrv_dirty_bitmap_frozen(bitmap)) {
-            continue;
-        }
+        assert(!bdrv_dirty_bitmap_frozen(bitmap));
         hbitmap_truncate(bitmap->bitmap, size);
         bitmap->size = size;
     }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 11/25] block: driver should override flags in bdrv_open()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (9 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 10/25] block: Change bitmap truncate conditional to assertion Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 12/25] iotests: Add tests for overriding BDRV_O_PROTOCOL Kevin Wolf
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

The BDRV_O_PROTOCOL flag should have an impact only if no driver is
specified explicitly. Therefore, if bdrv_open() is called with an
explicit block driver argument (either through the options QDict or
through the drv parameter) and that block driver is a protocol block
driver, BDRV_O_PROTOCOL should be set; if it is a format block driver,
BDRV_O_PROTOCOL should be unset.

While there was code to unset the flag in case a format block driver
has been selected, it only followed the bdrv_fill_options() function
call whereas the flag in fact needs to be adjusted before it is used
there.

With that change, BDRV_O_PROTOCOL will always be set if the BDS should
be a protocol driver; if the driver has been specified explicitly, the
new code will set it; and bdrv_fill_options() will only "probe" a
protocol driver if BDRV_O_PROTOCOL is set. The probing after
bdrv_fill_options() cannot select a protocol driver.

Thus, bdrv_open_image() to open BDS.file is never called if a protocol
BDS is about to be created. With that change in turn it is impossible to
call bdrv_open_common() with a protocol drv and file != NULL, which
allows us to remove the bdrv_swap() call.

This change breaks a test case in qemu-iotest 051:
"-drive file=t.qcow2,file.driver=qcow2" now works because the explicitly
specified "qcow2" overrides the BDRV_O_PROTOCOL which is automatically
set for the "file" BDS (and the filename is just passed down).
Therefore, this patch removes that test case.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c                    | 49 +++++++++++++++++++++++++++++-----------------
 tests/qemu-iotests/051     |  1 -
 tests/qemu-iotests/051.out |  3 ---
 3 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/block.c b/block.c
index 4ea2c4f..b2e784e 100644
--- a/block.c
+++ b/block.c
@@ -806,14 +806,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     }
     qdict_del(options, "node-name");
 
-    /* bdrv_open() with directly using a protocol as drv. This layer is already
-     * opened, so assign it to bs (while file becomes a closed BlockDriverState)
-     * and return immediately. */
-    if (file != NULL && drv->bdrv_file_open) {
-        bdrv_swap(file, bs);
-        return 0;
-    }
-
     bs->open_flags = flags;
     bs->guest_block_size = 512;
     bs->request_alignment = 512;
@@ -942,14 +934,17 @@ static QDict *parse_json_filename(const char *filename, Error **errp)
 /*
  * Fills in default options for opening images and converts the legacy
  * filename/flags pair to option QDict entries.
+ * The BDRV_O_PROTOCOL flag in *flags will be set or cleared accordingly if a
+ * block driver has been specified explicitly.
  */
-static int bdrv_fill_options(QDict **options, const char **pfilename, int flags,
-                             BlockDriver *drv, Error **errp)
+static int bdrv_fill_options(QDict **options, const char **pfilename,
+                             int *flags, BlockDriver *drv, Error **errp)
 {
     const char *filename = *pfilename;
     const char *drvname;
-    bool protocol = flags & BDRV_O_PROTOCOL;
+    bool protocol = *flags & BDRV_O_PROTOCOL;
     bool parse_filename = false;
+    BlockDriver *tmp_drv;
     Error *local_err = NULL;
 
     /* Parse json: pseudo-protocol */
@@ -967,6 +962,24 @@ static int bdrv_fill_options(QDict **options, const char **pfilename, int flags,
         *pfilename = filename = NULL;
     }
 
+    drvname = qdict_get_try_str(*options, "driver");
+
+    /* If the user has explicitly specified the driver, this choice should
+     * override the BDRV_O_PROTOCOL flag */
+    tmp_drv = drv;
+    if (!tmp_drv && drvname) {
+        tmp_drv = bdrv_find_format(drvname);
+    }
+    if (tmp_drv) {
+        protocol = tmp_drv->bdrv_file_open;
+    }
+
+    if (protocol) {
+        *flags |= BDRV_O_PROTOCOL;
+    } else {
+        *flags &= ~BDRV_O_PROTOCOL;
+    }
+
     /* Fetch the file name from the options QDict if necessary */
     if (protocol && filename) {
         if (!qdict_haskey(*options, "filename")) {
@@ -981,7 +994,6 @@ static int bdrv_fill_options(QDict **options, const char **pfilename, int flags,
 
     /* Find the right block driver */
     filename = qdict_get_try_str(*options, "filename");
-    drvname = qdict_get_try_str(*options, "driver");
 
     if (drv) {
         if (drvname) {
@@ -1317,7 +1329,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
         options = qdict_new();
     }
 
-    ret = bdrv_fill_options(&options, &filename, flags, drv, &local_err);
+    ret = bdrv_fill_options(&options, &filename, &flags, drv, &local_err);
     if (local_err) {
         goto fail;
     }
@@ -1336,11 +1348,6 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
     }
 
     assert(drvname || !(flags & BDRV_O_PROTOCOL));
-    if (drv && !drv->bdrv_file_open) {
-        /* If the user explicitly wants a format driver here, we'll need to add
-         * another layer for the protocol in bs->file */
-        flags &= ~BDRV_O_PROTOCOL;
-    }
 
     bs->options = options;
     options = qdict_clone_shallow(options);
@@ -1377,6 +1384,12 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
         goto fail;
     }
 
+    /* BDRV_O_PROTOCOL must be set iff a protocol BDS is about to be created */
+    assert(!!(flags & BDRV_O_PROTOCOL) == !!drv->bdrv_file_open);
+    /* file must be NULL if a protocol BDS is about to be created
+     * (the inverse results in an error message from bdrv_open_common()) */
+    assert(!(flags & BDRV_O_PROTOCOL) || !file);
+
     /* Open the image */
     ret = bdrv_open_common(bs, file, options, flags, drv, &local_err);
     if (ret < 0) {
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 0360f37..4a8055b 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -194,7 +194,6 @@ echo === Specifying the protocol layer ===
 echo
 
 run_qemu -drive file="$TEST_IMG",file.driver=file
-run_qemu -drive file="$TEST_IMG",file.driver=qcow2
 
 echo
 echo === Leaving out required options ===
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 2890eac..652dd63 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -253,9 +253,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file
 QEMU X.Y.Z monitor - type 'help' for more information
 (qemu) q^[[K^[[Dqu^[[K^[[D^[[Dqui^[[K^[[D^[[D^[[Dquit^[[K
 
-Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Block format 'qcow2' used by device '' doesn't support the option 'filename'
-
 
 === Leaving out required options ===
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 12/25] iotests: Add tests for overriding BDRV_O_PROTOCOL
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (10 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 11/25] block: driver should override flags in bdrv_open() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 13/25] qdict: Add qdict_array_entries() Kevin Wolf
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

This adds tests for overriding the qemu-internal BDRV_O_PROTOCOL flag by
explicitly specifying a block driver. As one test must be run over the
NBD protocol while the other must not, this patch adds two separate
iotests.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/119     | 60 ++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/119.out | 11 ++++++++
 tests/qemu-iotests/120     | 65 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/120.out | 15 +++++++++++
 tests/qemu-iotests/group   |  2 ++
 5 files changed, 153 insertions(+)
 create mode 100755 tests/qemu-iotests/119
 create mode 100644 tests/qemu-iotests/119.out
 create mode 100755 tests/qemu-iotests/120
 create mode 100644 tests/qemu-iotests/120.out

diff --git a/tests/qemu-iotests/119 b/tests/qemu-iotests/119
new file mode 100755
index 0000000..9a11f1b
--- /dev/null
+++ b/tests/qemu-iotests/119
@@ -0,0 +1,60 @@
+#!/bin/bash
+#
+# NBD test case for overriding BDRV_O_PROTOCOL by explicitly specifying
+# a driver
+#
+# Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt raw
+_supported_proto nbd
+_supported_os Linux
+
+_make_test_img 64M
+# This should not crash
+echo "{'execute': 'qmp_capabilities'}
+      {'execute': 'human-monitor-command',
+       'arguments': {'command-line': 'qemu-io drv \"read -P 0 0 64k\"'}}
+      {'execute': 'quit'}" \
+    | $QEMU -drive id=drv,if=none,file="$TEST_IMG",driver=nbd \
+            -qmp stdio -nodefaults \
+    | _filter_qmp | _filter_qemu_io
+
+# success, all done
+echo
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/119.out b/tests/qemu-iotests/119.out
new file mode 100644
index 0000000..58e7114
--- /dev/null
+++ b/tests/qemu-iotests/119.out
@@ -0,0 +1,11 @@
+QA output created by 119
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+QMP_VERSION
+{"return": {}}
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+
+*** done
diff --git a/tests/qemu-iotests/120 b/tests/qemu-iotests/120
new file mode 100755
index 0000000..9f13078
--- /dev/null
+++ b/tests/qemu-iotests/120
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# Non-NBD test cases for overriding BDRV_O_PROTOCOL by explicitly
+# specifying a driver
+#
+# Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+_cleanup()
+{
+	_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt generic
+_supported_proto file
+_supported_os Linux
+
+_make_test_img 64M
+
+echo "{'execute': 'qmp_capabilities'}
+      {'execute': 'human-monitor-command',
+       'arguments': {'command-line': 'qemu-io drv \"write -P 42 0 64k\"'}}
+      {'execute': 'quit'}" \
+    | $QEMU -qmp stdio -nodefaults \
+            -drive id=drv,if=none,file="$TEST_IMG",driver=raw,file.driver=$IMGFMT \
+    | _filter_qmp | _filter_qemu_io
+$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO_PROG -c 'read -P 42 0 64k' \
+    "json:{'driver': 'raw', 'file': {'driver': '$IMGFMT', 'file': {'filename': '$TEST_IMG'}}}" \
+    | _filter_qemu_io
+
+# success, all done
+echo
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out
new file mode 100644
index 0000000..9131b1b
--- /dev/null
+++ b/tests/qemu-iotests/120.out
@@ -0,0 +1,15 @@
+QA output created by 120
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+QMP_VERSION
+{"return": {}}
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 0b817ca..4597fc1 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -121,6 +121,8 @@
 114 rw auto quick
 115 rw auto
 116 rw auto quick
+119 rw auto quick
+120 rw auto quick
 121 rw auto
 122 rw auto
 123 rw auto quick
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 13/25] qdict: Add qdict_array_entries()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (11 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 12/25] iotests: Add tests for overriding BDRV_O_PROTOCOL Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 14/25] qdict: Add qdict_{set,copy}_default() Kevin Wolf
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

This counts the entries in a flattened array in a QDict without
actually splitting the QDict into a QList.

bdrv_open_image() doesn't take a QList, but rather a QDict and a key
prefix string, so this is more convenient for block drivers which have a
dynamically sized list of child nodes (e.g. Quorum) and are to be
converted to using bdrv_open_image() as the standard interface for
opening child nodes.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 include/qapi/qmp/qdict.h |  1 +
 qobject/qdict.c          | 78 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index d68f4eb..d20db94 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -70,6 +70,7 @@ void qdict_flatten(QDict *qdict);
 
 void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
 void qdict_array_split(QDict *src, QList **dst);
+int qdict_array_entries(QDict *src, const char *subqdict);
 
 void qdict_join(QDict *dest, QDict *src, bool overwrite);
 
diff --git a/qobject/qdict.c b/qobject/qdict.c
index ea239f0..50c0ab3 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -597,17 +597,21 @@ void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
     }
 }
 
-static bool qdict_has_prefixed_entries(const QDict *src, const char *start)
+static int qdict_count_prefixed_entries(const QDict *src, const char *start)
 {
     const QDictEntry *entry;
+    int count = 0;
 
     for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
         if (strstart(entry->key, start, NULL)) {
-            return true;
+            if (count == INT_MAX) {
+                return -ERANGE;
+            }
+            count++;
         }
     }
 
-    return false;
+    return count;
 }
 
 /**
@@ -646,7 +650,8 @@ void qdict_array_split(QDict *src, QList **dst)
         snprintf_ret = snprintf(prefix, 32, "%u.", i);
         assert(snprintf_ret < 32);
 
-        is_subqdict = qdict_has_prefixed_entries(src, prefix);
+        /* Overflow is the same as positive non-zero results */
+        is_subqdict = qdict_count_prefixed_entries(src, prefix);
 
         // There may be either a single subordinate object (named "%u") or
         // multiple objects (each with a key prefixed "%u."), but not both.
@@ -667,6 +672,71 @@ void qdict_array_split(QDict *src, QList **dst)
 }
 
 /**
+ * qdict_array_entries(): Returns the number of direct array entries if the
+ * sub-QDict of src specified by the prefix in subqdict (or src itself for
+ * prefix == "") is valid as an array, i.e. the length of the created list if
+ * the sub-QDict would become empty after calling qdict_array_split() on it. If
+ * the array is not valid, -EINVAL is returned.
+ */
+int qdict_array_entries(QDict *src, const char *subqdict)
+{
+    const QDictEntry *entry;
+    unsigned i;
+    unsigned entries = 0;
+    size_t subqdict_len = strlen(subqdict);
+
+    assert(!subqdict_len || subqdict[subqdict_len - 1] == '.');
+
+    /* qdict_array_split() loops until UINT_MAX, but as we want to return
+     * negative errors, we only have a signed return value here. Any additional
+     * entries will lead to -EINVAL. */
+    for (i = 0; i < INT_MAX; i++) {
+        QObject *subqobj;
+        int subqdict_entries;
+        size_t slen = 32 + subqdict_len;
+        char indexstr[slen], prefix[slen];
+        size_t snprintf_ret;
+
+        snprintf_ret = snprintf(indexstr, slen, "%s%u", subqdict, i);
+        assert(snprintf_ret < slen);
+
+        subqobj = qdict_get(src, indexstr);
+
+        snprintf_ret = snprintf(prefix, slen, "%s%u.", subqdict, i);
+        assert(snprintf_ret < slen);
+
+        subqdict_entries = qdict_count_prefixed_entries(src, prefix);
+        if (subqdict_entries < 0) {
+            return subqdict_entries;
+        }
+
+        /* There may be either a single subordinate object (named "%u") or
+         * multiple objects (each with a key prefixed "%u."), but not both. */
+        if (subqobj && subqdict_entries) {
+            return -EINVAL;
+        } else if (!subqobj && !subqdict_entries) {
+            break;
+        }
+
+        entries += subqdict_entries ? subqdict_entries : 1;
+    }
+
+    /* Consider everything handled that isn't part of the given sub-QDict */
+    for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
+        if (!strstart(qdict_entry_key(entry), subqdict, NULL)) {
+            entries++;
+        }
+    }
+
+    /* Anything left in the sub-QDict that wasn't handled? */
+    if (qdict_size(src) != entries) {
+        return -EINVAL;
+    }
+
+    return i;
+}
+
+/**
  * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all
  * elements from src to dest.
  *
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 14/25] qdict: Add qdict_{set,copy}_default()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (12 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 13/25] qdict: Add qdict_array_entries() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 15/25] check-qdict: Test cases for new functions Kevin Wolf
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

In the block layer functions that determine options for a child block
device, it's a common pattern to either copy options from the parent's
options or to set a default string if the option isn't explicitly set
yet for the child. Provide convenience functions so that it becomes a
one-liner for each option.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 include/qapi/qmp/qdict.h |  3 +++
 qobject/qdict.c          | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index d20db94..9fbf68e 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -65,6 +65,9 @@ int64_t qdict_get_try_int(const QDict *qdict, const char *key,
 int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value);
 const char *qdict_get_try_str(const QDict *qdict, const char *key);
 
+void qdict_copy_default(QDict *dst, QDict *src, const char *key);
+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);
 
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 50c0ab3..190791b 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -477,6 +477,39 @@ static void qdict_destroy_obj(QObject *obj)
     g_free(qdict);
 }
 
+/**
+ * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, the
+ * value of 'key' in 'src' is copied there (and the refcount increased
+ * accordingly).
+ */
+void qdict_copy_default(QDict *dst, QDict *src, const char *key)
+{
+    QObject *val;
+
+    if (qdict_haskey(dst, key)) {
+        return;
+    }
+
+    val = qdict_get(src, key);
+    if (val) {
+        qobject_incref(val);
+        qdict_put_obj(dst, key, val);
+    }
+}
+
+/**
+ * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' yet, a
+ * new QString initialised by 'val' is put there.
+ */
+void qdict_set_default_str(QDict *dst, const char *key, const char *val)
+{
+    if (qdict_haskey(dst, key)) {
+        return;
+    }
+
+    qdict_put(dst, key, qstring_from_str(val));
+}
+
 static void qdict_flatten_qdict(QDict *qdict, QDict *target,
                                 const char *prefix);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 15/25] check-qdict: Test cases for new functions
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (13 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 14/25] qdict: Add qdict_{set,copy}_default() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 16/25] quorum: Use bdrv_open_image() Kevin Wolf
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

This adds test cases for the following new QDict functions:

* qdict_array_entries()
* qdict_set_default_str()
* qdict_copy_default()

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 tests/check-qdict.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index a9296f0..a136f2a 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -152,6 +152,28 @@ static void qdict_get_try_str_test(void)
     QDECREF(tests_dict);
 }
 
+static void qdict_defaults_test(void)
+{
+    QDict *dict, *copy;
+
+    dict = qdict_new();
+    copy = qdict_new();
+
+    qdict_set_default_str(dict, "foo", "abc");
+    qdict_set_default_str(dict, "foo", "def");
+    g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "abc");
+    qdict_set_default_str(dict, "bar", "ghi");
+
+    qdict_copy_default(copy, dict, "foo");
+    g_assert_cmpstr(qdict_get_str(copy, "foo"), ==, "abc");
+    qdict_set_default_str(copy, "bar", "xyz");
+    qdict_copy_default(copy, dict, "bar");
+    g_assert_cmpstr(qdict_get_str(copy, "bar"), ==, "xyz");
+
+    QDECREF(copy);
+    QDECREF(dict);
+}
+
 static void qdict_haskey_not_test(void)
 {
     QDict *tests_dict = qdict_new();
@@ -444,6 +466,49 @@ static void qdict_array_split_test(void)
     QDECREF(test_dict);
 }
 
+static void qdict_array_entries_test(void)
+{
+    QDict *dict = qdict_new();
+
+    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
+
+    qdict_put(dict, "bar", qint_from_int(0));
+    qdict_put(dict, "baz.0", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
+
+    qdict_put(dict, "foo.1", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
+    qdict_put(dict, "foo.0", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 2);
+    qdict_put(dict, "foo.bar", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
+    qdict_del(dict, "foo.bar");
+
+    qdict_put(dict, "foo.2.a", qint_from_int(0));
+    qdict_put(dict, "foo.2.b", qint_from_int(0));
+    qdict_put(dict, "foo.2.c", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 3);
+    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
+
+    QDECREF(dict);
+
+    dict = qdict_new();
+    qdict_put(dict, "1", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
+    qdict_put(dict, "0", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, ""), ==, 2);
+    qdict_put(dict, "bar", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
+    qdict_del(dict, "bar");
+
+    qdict_put(dict, "2.a", qint_from_int(0));
+    qdict_put(dict, "2.b", qint_from_int(0));
+    qdict_put(dict, "2.c", qint_from_int(0));
+    g_assert_cmpint(qdict_array_entries(dict, ""), ==, 3);
+
+    QDECREF(dict);
+}
+
 static void qdict_join_test(void)
 {
     QDict *dict1, *dict2;
@@ -663,6 +728,7 @@ int main(int argc, char **argv)
     g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
     g_test_add_func("/public/get_str", qdict_get_str_test);
     g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
+    g_test_add_func("/public/defaults", qdict_defaults_test);
     g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
     g_test_add_func("/public/haskey", qdict_haskey_test);
     g_test_add_func("/public/del", qdict_del_test);
@@ -670,6 +736,7 @@ int main(int argc, char **argv)
     g_test_add_func("/public/iterapi", qdict_iterapi_test);
     g_test_add_func("/public/flatten", qdict_flatten_test);
     g_test_add_func("/public/array_split", qdict_array_split_test);
+    g_test_add_func("/public/array_entries", qdict_array_entries_test);
     g_test_add_func("/public/join", qdict_join_test);
 
     g_test_add_func("/errors/put_exists", qdict_put_exists_test);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 16/25] quorum: Use bdrv_open_image()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (14 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 15/25] check-qdict: Test cases for new functions Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 17/25] vmdk: " Kevin Wolf
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Besides standardising on a single interface for opening child nodes,
this simplifies the .bdrv_open() implementation of the quorum block
driver by using block layer functionality for handling BlockdevRefs.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 block/quorum.c | 51 +++++++++++----------------------------------------
 1 file changed, 11 insertions(+), 40 deletions(-)

diff --git a/block/quorum.c b/block/quorum.c
index f91ef75..a33881a 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -866,25 +866,18 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
     Error *local_err = NULL;
     QemuOpts *opts = NULL;
     bool *opened;
-    QDict *sub = NULL;
-    QList *list = NULL;
-    const QListEntry *lentry;
     int i;
     int ret = 0;
 
     qdict_flatten(options);
-    qdict_extract_subqdict(options, &sub, "children.");
-    qdict_array_split(sub, &list);
 
-    if (qdict_size(sub)) {
-        error_setg(&local_err, "Invalid option children.%s",
-                   qdict_first(sub)->key);
+    /* count how many different children are present */
+    s->num_children = qdict_array_entries(options, "children.");
+    if (s->num_children < 0) {
+        error_setg(&local_err, "Option children is not a valid array");
         ret = -EINVAL;
         goto exit;
     }
-
-    /* count how many different children are present */
-    s->num_children = qlist_size(list);
     if (s->num_children < 2) {
         error_setg(&local_err,
                    "Number of provided children must be greater than 1");
@@ -937,37 +930,17 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
     s->bs = g_new0(BlockDriverState *, s->num_children);
     opened = g_new0(bool, s->num_children);
 
-    for (i = 0, lentry = qlist_first(list); lentry;
-         lentry = qlist_next(lentry), i++) {
-        QDict *d;
-        QString *string;
-
-        switch (qobject_type(lentry->value))
-        {
-            /* List of options */
-            case QTYPE_QDICT:
-                d = qobject_to_qdict(lentry->value);
-                QINCREF(d);
-                ret = bdrv_open(&s->bs[i], NULL, NULL, d, flags, NULL,
-                                &local_err);
-                break;
-
-            /* QMP reference */
-            case QTYPE_QSTRING:
-                string = qobject_to_qstring(lentry->value);
-                ret = bdrv_open(&s->bs[i], NULL, qstring_get_str(string), NULL,
-                                flags, NULL, &local_err);
-                break;
-
-            default:
-                error_setg(&local_err, "Specification of child block device %i "
-                           "is invalid", i);
-                ret = -EINVAL;
-        }
+    for (i = 0; i < s->num_children; i++) {
+        char indexstr[32];
+        ret = snprintf(indexstr, 32, "children.%d", i);
+        assert(ret < 32);
 
+        ret = bdrv_open_image(&s->bs[i], NULL, options, indexstr, flags,
+                              false, &local_err);
         if (ret < 0) {
             goto close_exit;
         }
+
         opened[i] = true;
     }
 
@@ -990,8 +963,6 @@ exit:
     if (local_err) {
         error_propagate(errp, local_err);
     }
-    QDECREF(list);
-    QDECREF(sub);
     return ret;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 17/25] vmdk: Use bdrv_open_image()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (15 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 16/25] quorum: Use bdrv_open_image() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 18/25] block: Use macro for cache option names Kevin Wolf
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Besides standardising on a single interface for opening child nodes,
this patch allows the user to specify options to individual extent
nodes. Overriding file names isn't possible with this yet, so it's of
limited usefulness, but still a step forward.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
---
 block/vmdk.c | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index 56626b0..aad051b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -543,7 +543,7 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
 }
 
 static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
-                               Error **errp);
+                               QDict *options, Error **errp);
 
 static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset,
                             Error **errp)
@@ -582,7 +582,7 @@ static char *vmdk_read_desc(BlockDriverState *file, uint64_t desc_offset,
 
 static int vmdk_open_vmdk4(BlockDriverState *bs,
                            BlockDriverState *file,
-                           int flags, Error **errp)
+                           int flags, QDict *options, Error **errp)
 {
     int ret;
     uint32_t magic;
@@ -606,7 +606,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
             if (!buf) {
                 return -EINVAL;
             }
-            ret = vmdk_open_desc_file(bs, flags, buf, errp);
+            ret = vmdk_open_desc_file(bs, flags, buf, options, errp);
             g_free(buf);
             return ret;
         }
@@ -763,7 +763,7 @@ static int vmdk_parse_description(const char *desc, const char *opt_name,
 /* Open an extent file and append to bs array */
 static int vmdk_open_sparse(BlockDriverState *bs,
                             BlockDriverState *file, int flags,
-                            char *buf, Error **errp)
+                            char *buf, QDict *options, Error **errp)
 {
     uint32_t magic;
 
@@ -773,7 +773,7 @@ static int vmdk_open_sparse(BlockDriverState *bs,
             return vmdk_open_vmfs_sparse(bs, file, flags, errp);
             break;
         case VMDK4_MAGIC:
-            return vmdk_open_vmdk4(bs, file, flags, errp);
+            return vmdk_open_vmdk4(bs, file, flags, options, errp);
             break;
         default:
             error_setg(errp, "Image not in VMDK format");
@@ -783,7 +783,8 @@ static int vmdk_open_sparse(BlockDriverState *bs,
 }
 
 static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
-                              const char *desc_file_path, Error **errp)
+                              const char *desc_file_path, QDict *options,
+                              Error **errp)
 {
     int ret;
     int matches;
@@ -797,6 +798,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
     BlockDriverState *extent_file;
     BDRVVmdkState *s = bs->opaque;
     VmdkExtent *extent;
+    char extent_opt_prefix[32];
 
     while (*p) {
         /* parse extent line in one of below formats:
@@ -846,8 +848,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
         extent_path = g_malloc0(PATH_MAX);
         path_combine(extent_path, PATH_MAX, desc_file_path, fname);
         extent_file = NULL;
-        ret = bdrv_open(&extent_file, extent_path, NULL, NULL,
-                        bs->open_flags | BDRV_O_PROTOCOL, NULL, errp);
+
+        ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
+        assert(ret < 32);
+
+        ret = bdrv_open_image(&extent_file, extent_path,
+                              options, extent_opt_prefix,
+                              bs->open_flags | BDRV_O_PROTOCOL, false, errp);
         g_free(extent_path);
         if (ret) {
             return ret;
@@ -870,7 +877,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
             if (!buf) {
                 ret = -EINVAL;
             } else {
-                ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, buf, errp);
+                ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, buf,
+                                       options, errp);
             }
             g_free(buf);
             if (ret) {
@@ -898,7 +906,7 @@ next_line:
 }
 
 static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
-                               Error **errp)
+                               QDict *options, Error **errp)
 {
     int ret;
     char ct[128];
@@ -920,7 +928,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
     }
     s->create_type = g_strdup(ct);
     s->desc_offset = 0;
-    ret = vmdk_parse_extents(buf, bs, bs->file->exact_filename, errp);
+    ret = vmdk_parse_extents(buf, bs, bs->file->exact_filename, options, errp);
 exit:
     return ret;
 }
@@ -942,11 +950,11 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
     switch (magic) {
         case VMDK3_MAGIC:
         case VMDK4_MAGIC:
-            ret = vmdk_open_sparse(bs, bs->file, flags, buf, errp);
+            ret = vmdk_open_sparse(bs, bs->file, flags, buf, options, errp);
             s->desc_offset = 0x200;
             break;
         default:
-            ret = vmdk_open_desc_file(bs, flags, buf, errp);
+            ret = vmdk_open_desc_file(bs, flags, buf, options, errp);
             break;
     }
     if (ret) {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 18/25] block: Use macro for cache option names
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (16 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 17/25] vmdk: " Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 19/25] block: Use QemuOpts in bdrv_open_common() Kevin Wolf
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
---
 blockdev.c            | 24 ++++++++++++------------
 include/block/block.h |  8 ++++++++
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index de94a8b..fffc9b5 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -391,13 +391,13 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
         }
     }
 
-    if (qemu_opt_get_bool(opts, "cache.writeback", true)) {
+    if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, true)) {
         bdrv_flags |= BDRV_O_CACHE_WB;
     }
-    if (qemu_opt_get_bool(opts, "cache.direct", false)) {
+    if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
         bdrv_flags |= BDRV_O_NOCACHE;
     }
-    if (qemu_opt_get_bool(opts, "cache.no-flush", false)) {
+    if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
         bdrv_flags |= BDRV_O_NO_FLUSH;
     }
 
@@ -733,16 +733,16 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         }
 
         /* Specific options take precedence */
-        if (!qemu_opt_get(all_opts, "cache.writeback")) {
-            qemu_opt_set_bool(all_opts, "cache.writeback",
+        if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_WB)) {
+            qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_WB,
                               !!(flags & BDRV_O_CACHE_WB), &error_abort);
         }
-        if (!qemu_opt_get(all_opts, "cache.direct")) {
-            qemu_opt_set_bool(all_opts, "cache.direct",
+        if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_DIRECT)) {
+            qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_DIRECT,
                               !!(flags & BDRV_O_NOCACHE), &error_abort);
         }
-        if (!qemu_opt_get(all_opts, "cache.no-flush")) {
-            qemu_opt_set_bool(all_opts, "cache.no-flush",
+        if (!qemu_opt_get(all_opts, BDRV_OPT_CACHE_NO_FLUSH)) {
+            qemu_opt_set_bool(all_opts, BDRV_OPT_CACHE_NO_FLUSH,
                               !!(flags & BDRV_O_NO_FLUSH), &error_abort);
         }
         qemu_opt_unset(all_opts, "cache");
@@ -3105,15 +3105,15 @@ QemuOptsList qemu_common_drive_opts = {
             .type = QEMU_OPT_STRING,
             .help = "discard operation (ignore/off, unmap/on)",
         },{
-            .name = "cache.writeback",
+            .name = BDRV_OPT_CACHE_WB,
             .type = QEMU_OPT_BOOL,
             .help = "enables writeback mode for any caches",
         },{
-            .name = "cache.direct",
+            .name = BDRV_OPT_CACHE_DIRECT,
             .type = QEMU_OPT_BOOL,
             .help = "enables use of O_DIRECT (bypass the host page cache)",
         },{
-            .name = "cache.no-flush",
+            .name = BDRV_OPT_CACHE_NO_FLUSH,
             .type = QEMU_OPT_BOOL,
             .help = "ignore any flush requests for the device",
         },{
diff --git a/include/block/block.h b/include/block/block.h
index f7680b6..5f3c2de 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -90,6 +90,14 @@ typedef struct HDGeometry {
 
 #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH)
 
+
+/* Option names of options parsed by the block layer */
+
+#define BDRV_OPT_CACHE_WB       "cache.writeback"
+#define BDRV_OPT_CACHE_DIRECT   "cache.direct"
+#define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
+
+
 #define BDRV_SECTOR_BITS   9
 #define BDRV_SECTOR_SIZE   (1ULL << BDRV_SECTOR_BITS)
 #define BDRV_SECTOR_MASK   ~(BDRV_SECTOR_SIZE - 1)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 19/25] block: Use QemuOpts in bdrv_open_common()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (17 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 18/25] block: Use macro for cache option names Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 20/25] block: Move flag inheritance to bdrv_open_inherit() Kevin Wolf
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Instead of manually parsing options and then deleting them from the
options QDict, just use QemuOpts like most other places that deal with
block device options.

More options will be added there and then QemuOpts is a lot more
manageable than open-coding everything.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 block.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/block.c b/block.c
index b2e784e..ad8b0c7 100644
--- a/block.c
+++ b/block.c
@@ -767,6 +767,19 @@ static void bdrv_assign_node_name(BlockDriverState *bs,
     QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs, node_list);
 }
 
+static QemuOptsList bdrv_runtime_opts = {
+    .name = "bdrv_common",
+    .head = QTAILQ_HEAD_INITIALIZER(bdrv_runtime_opts.head),
+    .desc = {
+        {
+            .name = "node-name",
+            .type = QEMU_OPT_STRING,
+            .help = "Node name of the block device node",
+        },
+        { /* end of list */ }
+    },
+};
+
 /*
  * Common part for opening disk images and files
  *
@@ -778,6 +791,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     int ret, open_flags;
     const char *filename;
     const char *node_name = NULL;
+    QemuOpts *opts;
     Error *local_err = NULL;
 
     assert(drv != NULL);
@@ -798,13 +812,21 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
 
-    node_name = qdict_get_try_str(options, "node-name");
+    opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
+    qemu_opts_absorb_qdict(opts, options, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        ret = -EINVAL;
+        goto fail_opts;
+    }
+
+    node_name = qemu_opt_get(opts, "node-name");
     bdrv_assign_node_name(bs, node_name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
-        return -EINVAL;
+        ret = -EINVAL;
+        goto fail_opts;
     }
-    qdict_del(options, "node-name");
 
     bs->open_flags = flags;
     bs->guest_block_size = 512;
@@ -819,7 +841,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
                         ? "Driver '%s' can only be used for read-only devices"
                         : "Driver '%s' is not whitelisted",
                    drv->format_name);
-        return -ENOTSUP;
+        ret = -ENOTSUP;
+        goto fail_opts;
     }
 
     assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */
@@ -828,7 +851,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
             bdrv_enable_copy_on_read(bs);
         } else {
             error_setg(errp, "Can't use copy-on-read on read-only device");
-            return -EINVAL;
+            ret = -EINVAL;
+            goto fail_opts;
         }
     }
 
@@ -894,6 +918,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
     assert(bdrv_opt_mem_align(bs) != 0);
     assert(bdrv_min_mem_align(bs) != 0);
     assert((bs->request_alignment != 0) || bs->sg);
+
+    qemu_opts_del(opts);
     return 0;
 
 free_and_fail:
@@ -901,6 +927,8 @@ free_and_fail:
     g_free(bs->opaque);
     bs->opaque = NULL;
     bs->drv = NULL;
+fail_opts:
+    qemu_opts_del(opts);
     return ret;
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 20/25] block: Move flag inheritance to bdrv_open_inherit()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (18 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 19/25] block: Use QemuOpts in bdrv_open_common() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 21/25] block: Drain requests before swapping nodes in bdrv_swap() Kevin Wolf
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Instead of letting every caller of bdrv_open() determine the right flags
for its child node manually and pass them to the function, pass the
parent node and the role of the newly opened child (like backing file,
protocol layer, etc.).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 block.c                   | 74 ++++++++++++++++++++++++++++++++++++++---------
 block/blkdebug.c          |  2 +-
 block/blkverify.c         |  4 +--
 block/quorum.c            |  4 +--
 block/vmdk.c              |  5 ++--
 include/block/block.h     |  4 ++-
 include/block/block_int.h |  7 +++++
 7 files changed, 78 insertions(+), 22 deletions(-)

diff --git a/block.c b/block.c
index ad8b0c7..3c04446 100644
--- a/block.c
+++ b/block.c
@@ -79,6 +79,12 @@ static QTAILQ_HEAD(, BlockDriverState) graph_bdrv_states =
 static QLIST_HEAD(, BlockDriver) bdrv_drivers =
     QLIST_HEAD_INITIALIZER(bdrv_drivers);
 
+static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
+                             const char *reference, QDict *options, int flags,
+                             BlockDriverState *parent,
+                             const BdrvChildRole *child_role,
+                             BlockDriver *drv, Error **errp);
+
 static void bdrv_dirty_bitmap_truncate(BlockDriverState *bs);
 /* If non-zero, use only whitelisted block drivers */
 static int use_bdrv_whitelist;
@@ -682,8 +688,8 @@ static int bdrv_temp_snapshot_flags(int flags)
 }
 
 /*
- * Returns the flags that bs->file should get, based on the given flags for
- * the parent BDS
+ * Returns the flags that bs->file should get if a protocol driver is expected,
+ * based on the given flags for the parent BDS
  */
 static int bdrv_inherited_flags(int flags)
 {
@@ -700,6 +706,25 @@ static int bdrv_inherited_flags(int flags)
     return flags;
 }
 
+const BdrvChildRole child_file = {
+    .inherit_flags = bdrv_inherited_flags,
+};
+
+/*
+ * Returns the flags that bs->file should get if the use of formats (and not
+ * only protocols) is permitted for it, based on the given flags for the parent
+ * BDS
+ */
+static int bdrv_inherited_fmt_flags(int parent_flags)
+{
+    int flags = child_file.inherit_flags(parent_flags);
+    return flags & ~BDRV_O_PROTOCOL;
+}
+
+const BdrvChildRole child_format = {
+    .inherit_flags = bdrv_inherited_fmt_flags,
+};
+
 /*
  * Returns the flags that bs->backing_hd should get, based on the given flags
  * for the parent BDS
@@ -715,6 +740,10 @@ static int bdrv_backing_flags(int flags)
     return flags;
 }
 
+static const BdrvChildRole child_backing = {
+    .inherit_flags = bdrv_backing_flags,
+};
+
 static int bdrv_open_flags(BlockDriverState *bs, int flags)
 {
     int open_flags = flags | BDRV_O_CACHE_WB;
@@ -828,7 +857,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
         goto fail_opts;
     }
 
-    bs->open_flags = flags;
     bs->guest_block_size = 512;
     bs->request_alignment = 512;
     bs->zero_beyond_eof = true;
@@ -1158,9 +1186,10 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
     }
 
     assert(bs->backing_hd == NULL);
-    ret = bdrv_open(&backing_hd,
-                    *backing_filename ? backing_filename : NULL, NULL, options,
-                    bdrv_backing_flags(bs->open_flags), NULL, &local_err);
+    ret = bdrv_open_inherit(&backing_hd,
+                            *backing_filename ? backing_filename : NULL,
+                            NULL, options, 0, bs, &child_backing,
+                            NULL, &local_err);
     if (ret < 0) {
         bdrv_unref(backing_hd);
         backing_hd = NULL;
@@ -1194,7 +1223,8 @@ free_exit:
  * To conform with the behavior of bdrv_open(), *pbs has to be NULL.
  */
 int bdrv_open_image(BlockDriverState **pbs, const char *filename,
-                    QDict *options, const char *bdref_key, int flags,
+                    QDict *options, const char *bdref_key,
+                    BlockDriverState* parent, const BdrvChildRole *child_role,
                     bool allow_none, Error **errp)
 {
     QDict *image_options;
@@ -1222,7 +1252,8 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
         goto done;
     }
 
-    ret = bdrv_open(pbs, filename, reference, image_options, flags, NULL, errp);
+    ret = bdrv_open_inherit(pbs, filename, reference, image_options, 0,
+                            parent, child_role, NULL, errp);
 
 done:
     qdict_del(options, bdref_key);
@@ -1309,9 +1340,11 @@ out:
  * should be opened. If specified, neither options nor a filename may be given,
  * nor can an existing BDS be reused (that is, *pbs has to be NULL).
  */
-int bdrv_open(BlockDriverState **pbs, const char *filename,
-              const char *reference, QDict *options, int flags,
-              BlockDriver *drv, Error **errp)
+static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
+                             const char *reference, QDict *options, int flags,
+                             BlockDriverState *parent,
+                             const BdrvChildRole *child_role,
+                             BlockDriver *drv, Error **errp)
 {
     int ret;
     BlockDriverState *file = NULL, *bs;
@@ -1320,6 +1353,8 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
     int snapshot_flags = 0;
 
     assert(pbs);
+    assert(!child_role || !flags);
+    assert(!child_role == !parent);
 
     if (reference) {
         bool options_non_empty = options ? qdict_size(options) : false;
@@ -1357,6 +1392,10 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
         options = qdict_new();
     }
 
+    if (child_role) {
+        flags = child_role->inherit_flags(parent->open_flags);
+    }
+
     ret = bdrv_fill_options(&options, &filename, &flags, drv, &local_err);
     if (local_err) {
         goto fail;
@@ -1377,6 +1416,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
 
     assert(drvname || !(flags & BDRV_O_PROTOCOL));
 
+    bs->open_flags = flags;
     bs->options = options;
     options = qdict_clone_shallow(options);
 
@@ -1391,9 +1431,9 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
         }
 
         assert(file == NULL);
+        bs->open_flags = flags;
         ret = bdrv_open_image(&file, filename, options, "file",
-                              bdrv_inherited_flags(flags),
-                              true, &local_err);
+                              bs, &child_file, true, &local_err);
         if (ret < 0) {
             goto fail;
         }
@@ -1516,6 +1556,14 @@ close_and_fail:
     return ret;
 }
 
+int bdrv_open(BlockDriverState **pbs, const char *filename,
+              const char *reference, QDict *options, int flags,
+              BlockDriver *drv, Error **errp)
+{
+    return bdrv_open_inherit(pbs, filename, reference, options, flags, NULL,
+                             NULL, drv, errp);
+}
+
 typedef struct BlockReopenQueueEntry {
      bool prepared;
      BDRVReopenState state;
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 1e92607..bc247f4 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -429,7 +429,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     /* Open the backing file */
     assert(bs->file == NULL);
     ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-image"), options, "image",
-                          flags | BDRV_O_PROTOCOL, false, &local_err);
+                          bs, &child_file, false, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto out;
diff --git a/block/blkverify.c b/block/blkverify.c
index 438dff8..d277e63 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -125,7 +125,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
     /* Open the raw file */
     assert(bs->file == NULL);
     ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-raw"), options,
-                          "raw", flags | BDRV_O_PROTOCOL, false, &local_err);
+                          "raw", bs, &child_file, false, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto fail;
@@ -134,7 +134,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
     /* Open the test file */
     assert(s->test_file == NULL);
     ret = bdrv_open_image(&s->test_file, qemu_opt_get(opts, "x-image"), options,
-                          "test", flags, false, &local_err);
+                          "test", bs, &child_format, false, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         s->test_file = NULL;
diff --git a/block/quorum.c b/block/quorum.c
index a33881a..77e55b2 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -935,8 +935,8 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
         ret = snprintf(indexstr, 32, "children.%d", i);
         assert(ret < 32);
 
-        ret = bdrv_open_image(&s->bs[i], NULL, options, indexstr, flags,
-                              false, &local_err);
+        ret = bdrv_open_image(&s->bs[i], NULL, options, indexstr, bs,
+                              &child_format, false, &local_err);
         if (ret < 0) {
             goto close_exit;
         }
diff --git a/block/vmdk.c b/block/vmdk.c
index aad051b..3284bec 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -852,9 +852,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
         ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
         assert(ret < 32);
 
-        ret = bdrv_open_image(&extent_file, extent_path,
-                              options, extent_opt_prefix,
-                              bs->open_flags | BDRV_O_PROTOCOL, false, errp);
+        ret = bdrv_open_image(&extent_file, extent_path, options,
+                              extent_opt_prefix, bs, &child_file, false, errp);
         g_free(extent_path);
         if (ret) {
             return ret;
diff --git a/include/block/block.h b/include/block/block.h
index 5f3c2de..45e2340 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -12,6 +12,7 @@
 /* block.c */
 typedef struct BlockDriver BlockDriver;
 typedef struct BlockJob BlockJob;
+typedef struct BdrvChildRole BdrvChildRole;
 
 typedef struct BlockDriverInfo {
     /* in bytes, 0 if irrelevant */
@@ -203,7 +204,8 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
 int bdrv_parse_cache_flags(const char *mode, int *flags);
 int bdrv_parse_discard_flags(const char *mode, int *flags);
 int bdrv_open_image(BlockDriverState **pbs, const char *filename,
-                    QDict *options, const char *bdref_key, int flags,
+                    QDict *options, const char *bdref_key,
+                    BlockDriverState* parent, const BdrvChildRole *child_role,
                     bool allow_none, Error **errp);
 void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd);
 int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index f004378..662dd56 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -330,6 +330,13 @@ typedef struct BdrvAioNotifier {
     QLIST_ENTRY(BdrvAioNotifier) list;
 } BdrvAioNotifier;
 
+struct BdrvChildRole {
+    int (*inherit_flags)(int parent_flags);
+};
+
+extern const BdrvChildRole child_file;
+extern const BdrvChildRole child_format;
+
 /*
  * Note: the function bdrv_append() copies and swaps contents of
  * BlockDriverStates, so if you add new fields to this struct, please
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 21/25] block: Drain requests before swapping nodes in bdrv_swap()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (19 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 20/25] block: Move flag inheritance to bdrv_open_inherit() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 22/25] queue.h: Add QLIST_FIX_HEAD_PTR() Kevin Wolf
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

bdrv_swap() requires that there are no requests in flight on either of
the two devices. The request coroutine would work on the wrong
BlockDriverState object (with bs->opaque even being interpreted as a
different type potentially) and all sorts of bad things would result
from this.

The currently existing callers mostly ensure that there is no I/O
pending on nodes that are swapped. In detail, this is:

1. Live snapshots. This goes through qmp_transaction(), which calls
   bdrv_drain_all() before doing anything. The command is executed
   synchronously, so no new I/O can be issued concurrently.

2. snapshot=on in bdrv_open(). We're in the middle of opening the image
   (both the original image and its temporary overlay), so there can't
   be any I/O in flight yet.

3. Mirroring. bdrv_drain() is already used on the source device so that
   the mirror doesn't miss anything. However, the main loop runs between
   that and the bdrv_swap() (which is actually a bug, being addressed in
   another series), so there is a small window in which new I/O might be
   issued that would be in flight during bdrv_swap().

It is safer to just drain the request queue of both devices in
bdrv_swap() instead of relying on callers to do the right thing.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 block.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/block.c b/block.c
index 3c04446..9a860f1 100644
--- a/block.c
+++ b/block.c
@@ -1959,6 +1959,9 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
 {
     BlockDriverState tmp;
 
+    bdrv_drain(bs_new);
+    bdrv_drain(bs_old);
+
     /* The code needs to swap the node_name but simply swapping node_list won't
      * work so first remove the nodes from the graph list, do the swap then
      * insert them back if needed.
@@ -2002,6 +2005,9 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
         QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_old, node_list);
     }
 
+    assert(QLIST_EMPTY(&bs_old->tracked_requests));
+    assert(QLIST_EMPTY(&bs_new->tracked_requests));
+
     bdrv_rebind(bs_new);
     bdrv_rebind(bs_old);
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 22/25] queue.h: Add QLIST_FIX_HEAD_PTR()
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (20 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 21/25] block: Drain requests before swapping nodes in bdrv_swap() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 23/25] block: Add list of children to BlockDriverState Kevin Wolf
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

If the head of a list has been moved to a different memory location, the
le_prev link in the first list entry has to be fixed up. Provide a macro
that implements this fixup.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 include/qemu/queue.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index f781aa2..a8d3cb8 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -117,6 +117,12 @@ struct {                                                                \
         }                                                               \
 } while (/*CONSTCOND*/0)
 
+#define QLIST_FIX_HEAD_PTR(head, field) do {                            \
+        if ((head)->lh_first != NULL) {                                 \
+            (head)->lh_first->field.le_prev = &(head)->lh_first;        \
+        }                                                               \
+} while (/*CONSTCOND*/0)
+
 #define QLIST_INSERT_AFTER(listelm, elm, field) do {                    \
         if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
                 (listelm)->field.le_next->field.le_prev =               \
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 23/25] block: Add list of children to BlockDriverState
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (21 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 22/25] queue.h: Add QLIST_FIX_HEAD_PTR() Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 24/25] block: Add BlockDriverState.inherits_from Kevin Wolf
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

This allows iterating over all children of a given BDS, not only
including bs->file and bs->backing_hd, but also driver-specific
ones like VMDK extents or Quorum children.

For bdrv_swap(), the list of children of the swapped BDS stays at that
BDS (because that's where the pointers stay as well). The list head
moves and pointers to it must be fixed up therefore.

The list of children in the parent of the swapped BDS is not affected by
the swap. The contents of the BDS objects is swapped, so the existing
pointer in the parent automatically points to the newly swapped in BDS.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 block.c                   | 37 +++++++++++++++++++++++++++++++++++++
 include/block/block_int.h |  8 ++++++++
 2 files changed, 45 insertions(+)

diff --git a/block.c b/block.c
index 9a860f1..209ba39 100644
--- a/block.c
+++ b/block.c
@@ -1325,6 +1325,19 @@ out:
     return ret;
 }
 
+static void bdrv_attach_child(BlockDriverState *parent_bs,
+                              BlockDriverState *child_bs,
+                              const BdrvChildRole *child_role)
+{
+    BdrvChild *child = g_new(BdrvChild, 1);
+    *child = (BdrvChild) {
+        .bs     = child_bs,
+        .role   = child_role,
+    };
+
+    QLIST_INSERT_HEAD(&parent_bs->children, child, next);
+}
+
 /*
  * Opens a disk image (raw, qcow2, vmdk, ...)
  *
@@ -1377,6 +1390,9 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
             return -ENODEV;
         }
         bdrv_ref(bs);
+        if (child_role) {
+            bdrv_attach_child(parent, bs, child_role);
+        }
         *pbs = bs;
         return 0;
     }
@@ -1520,6 +1536,10 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
         goto close_and_fail;
     }
 
+    if (child_role) {
+        bdrv_attach_child(parent, bs, child_role);
+    }
+
     QDECREF(options);
     *pbs = bs;
     return 0;
@@ -1814,6 +1834,13 @@ void bdrv_close(BlockDriverState *bs)
     notifier_list_notify(&bs->close_notifiers, bs);
 
     if (bs->drv) {
+        BdrvChild *child, *next;
+
+        QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
+            QLIST_REMOVE(child, next);
+            g_free(child);
+        }
+
         if (bs->backing_hd) {
             BlockDriverState *backing_hd = bs->backing_hd;
             bdrv_set_backing_hd(bs, NULL);
@@ -2005,9 +2032,18 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
         QTAILQ_INSERT_TAIL(&graph_bdrv_states, bs_old, node_list);
     }
 
+    /*
+     * Update lh_first.le_prev for non-empty lists.
+     *
+     * The head of the op blocker list doesn't change because it is moved back
+     * in bdrv_move_feature_fields().
+     */
     assert(QLIST_EMPTY(&bs_old->tracked_requests));
     assert(QLIST_EMPTY(&bs_new->tracked_requests));
 
+    QLIST_FIX_HEAD_PTR(&bs_new->children, next);
+    QLIST_FIX_HEAD_PTR(&bs_old->children, next);
+
     bdrv_rebind(bs_new);
     bdrv_rebind(bs_old);
 }
@@ -2030,6 +2066,7 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
     /* The contents of 'tmp' will become bs_top, as we are
      * swapping bs_new and bs_top contents. */
     bdrv_set_backing_hd(bs_top, bs_new);
+    bdrv_attach_child(bs_top, bs_new, &child_backing);
 }
 
 static void bdrv_delete(BlockDriverState *bs)
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 662dd56..4ae5860 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -337,6 +337,12 @@ struct BdrvChildRole {
 extern const BdrvChildRole child_file;
 extern const BdrvChildRole child_format;
 
+typedef struct BdrvChild {
+    BlockDriverState *bs;
+    const BdrvChildRole *role;
+    QLIST_ENTRY(BdrvChild) next;
+} BdrvChild;
+
 /*
  * Note: the function bdrv_append() copies and swaps contents of
  * BlockDriverStates, so if you add new fields to this struct, please
@@ -431,6 +437,8 @@ struct BlockDriverState {
     /* long-running background operation */
     BlockJob *job;
 
+    QLIST_HEAD(, BdrvChild) children;
+
     QDict *options;
     BlockdevDetectZeroesOptions detect_zeroes;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 24/25] block: Add BlockDriverState.inherits_from
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (22 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 23/25] block: Add list of children to BlockDriverState Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-12 16:23 ` [Qemu-devel] [PULL 25/25] block: Fix reopen flag inheritance Kevin Wolf
  2015-06-15 12:24 ` [Qemu-devel] [PULL 00/25] Block layer core and image format patches Peter Maydell
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

Currently, the block layer assumes that any block node can have only one
parent, and if it has a parent, that it inherits some options/flags from
this parent.

This is not true any more: With references used in block device
creation, a single node can be used by multiple parents, or it can be
created separately and not inherit flags from any parent.

To handle reopens correctly, a node must know from which parent it
inherited options. This patch adds the information to BlockDriverState.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 block.c                   | 17 +++++++++++++++++
 include/block/block_int.h |  4 ++++
 2 files changed, 21 insertions(+)

diff --git a/block.c b/block.c
index 209ba39..58d12c0 100644
--- a/block.c
+++ b/block.c
@@ -1409,6 +1409,7 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
     }
 
     if (child_role) {
+        bs->inherits_from = parent;
         flags = child_role->inherit_flags(parent->open_flags);
     }
 
@@ -1837,6 +1838,9 @@ void bdrv_close(BlockDriverState *bs)
         BdrvChild *child, *next;
 
         QLIST_FOREACH_SAFE(child, &bs->children, next, next) {
+            if (child->bs->inherits_from == bs) {
+                child->bs->inherits_from = NULL;
+            }
             QLIST_REMOVE(child, next);
             g_free(child);
         }
@@ -1985,6 +1989,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
 void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
 {
     BlockDriverState tmp;
+    BdrvChild *child;
 
     bdrv_drain(bs_new);
     bdrv_drain(bs_old);
@@ -2044,6 +2049,18 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
     QLIST_FIX_HEAD_PTR(&bs_new->children, next);
     QLIST_FIX_HEAD_PTR(&bs_old->children, next);
 
+    /* Update references in bs->opaque and children */
+    QLIST_FOREACH(child, &bs_old->children, next) {
+        if (child->bs->inherits_from == bs_new) {
+            child->bs->inherits_from = bs_old;
+        }
+    }
+    QLIST_FOREACH(child, &bs_new->children, next) {
+        if (child->bs->inherits_from == bs_old) {
+            child->bs->inherits_from = bs_new;
+        }
+    }
+
     bdrv_rebind(bs_new);
     bdrv_rebind(bs_old);
 }
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 4ae5860..2732ccd 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -437,6 +437,10 @@ struct BlockDriverState {
     /* long-running background operation */
     BlockJob *job;
 
+    /* The node that this node inherited default options from (and a reopen on
+     * which can affect this node by changing these defaults). This is always a
+     * parent node of this node. */
+    BlockDriverState *inherits_from;
     QLIST_HEAD(, BdrvChild) children;
 
     QDict *options;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [Qemu-devel] [PULL 25/25] block: Fix reopen flag inheritance
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (23 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 24/25] block: Add BlockDriverState.inherits_from Kevin Wolf
@ 2015-06-12 16:23 ` Kevin Wolf
  2015-06-15 12:24 ` [Qemu-devel] [PULL 00/25] Block layer core and image format patches Peter Maydell
  25 siblings, 0 replies; 27+ messages in thread
From: Kevin Wolf @ 2015-06-12 16:23 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, qemu-devel

When reopening an image, the block layer already takes care to reopen
bs->file as well with recalculated inherited flags. The same must happen
for any other child (most notably missing before this patch: backing
files).

If bs->file (or any other child) didn't originally inherit from bs, e.g.
because it was created separately and then only referenced, it must not
inherit flags on reopen either, so check the inherited_from field before
propagation the reopen down.

VMDK already reopened its extents manually; this code can now be
dropped.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 block.c      | 13 +++++++++++--
 block/vmdk.c | 28 ++--------------------------
 2 files changed, 13 insertions(+), 28 deletions(-)

diff --git a/block.c b/block.c
index 58d12c0..777753c 100644
--- a/block.c
+++ b/block.c
@@ -1615,6 +1615,8 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
     assert(bs != NULL);
 
     BlockReopenQueueEntry *bs_entry;
+    BdrvChild *child;
+
     if (bs_queue == NULL) {
         bs_queue = g_new0(BlockReopenQueue, 1);
         QSIMPLEQ_INIT(bs_queue);
@@ -1623,8 +1625,15 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
     /* bdrv_open() masks this flag out */
     flags &= ~BDRV_O_PROTOCOL;
 
-    if (bs->file) {
-        bdrv_reopen_queue(bs_queue, bs->file, bdrv_inherited_flags(flags));
+    QLIST_FOREACH(child, &bs->children, next) {
+        int child_flags;
+
+        if (child->bs->inherits_from != bs) {
+            continue;
+        }
+
+        child_flags = child->role->inherit_flags(flags);
+        bdrv_reopen_queue(bs_queue, child->bs, child_flags);
     }
 
     bs_entry = g_new0(BlockReopenQueueEntry, 1);
diff --git a/block/vmdk.c b/block/vmdk.c
index 3284bec..be9263a 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -321,37 +321,13 @@ static int vmdk_is_cid_valid(BlockDriverState *bs)
     return 1;
 }
 
-/* Queue extents, if any, for reopen() */
+/* We have nothing to do for VMDK reopen, stubs just return success */
 static int vmdk_reopen_prepare(BDRVReopenState *state,
                                BlockReopenQueue *queue, Error **errp)
 {
-    BDRVVmdkState *s;
-    int ret = -1;
-    int i;
-    VmdkExtent *e;
-
     assert(state != NULL);
     assert(state->bs != NULL);
-
-    if (queue == NULL) {
-        error_setg(errp, "No reopen queue for VMDK extents");
-        goto exit;
-    }
-
-    s = state->bs->opaque;
-
-    assert(s != NULL);
-
-    for (i = 0; i < s->num_extents; i++) {
-        e = &s->extents[i];
-        if (e->file != state->bs->file) {
-            bdrv_reopen_queue(queue, e->file, state->flags);
-        }
-    }
-    ret = 0;
-
-exit:
-    return ret;
+    return 0;
 }
 
 static int vmdk_parent_open(BlockDriverState *bs)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [Qemu-devel] [PULL 00/25] Block layer core and image format patches
  2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
                   ` (24 preceding siblings ...)
  2015-06-12 16:23 ` [Qemu-devel] [PULL 25/25] block: Fix reopen flag inheritance Kevin Wolf
@ 2015-06-15 12:24 ` Peter Maydell
  25 siblings, 0 replies; 27+ messages in thread
From: Peter Maydell @ 2015-06-15 12:24 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: QEMU Developers, qemu-block

On 12 June 2015 at 17:23, Kevin Wolf <kwolf@redhat.com> wrote:
> The following changes since commit 4cb618abc1818586c08011ff0a84a015787b1672:
>
>   Merge remote-tracking branch 'remotes/lalrae/tags/mips-20150612' into staging (2015-06-12 12:49:40 +0100)
>
> are available in the git repository at:
>
>
>   git://repo.or.cz/qemu/kevin.git tags/for-upstream
>
> for you to fetch changes up to 67251a311371c4d22e803f151f47fe817175b6c3:
>
>   block: Fix reopen flag inheritance (2015-06-12 17:04:59 +0200)
>
> ----------------------------------------------------------------
> Block layer core and image format patches

Applied, thanks.

-- PMM

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2015-06-15 12:24 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-12 16:23 [Qemu-devel] [PULL 00/25] Block layer core and image format patches Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 01/25] iotests: remove assertIsNotNone call Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 02/25] qemu-iotests: Fix 128 if sudo required Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 03/25] qcow2: Set MIN_L2_CACHE_SIZE to 2 Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 04/25] iotests: qcow2 COW with minimal L2 cache size Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 05/25] qcow2: Add DEFAULT_L2_CACHE_CLUSTERS Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 06/25] vmdk: Fix index_in_cluster calculation in vmdk_co_get_block_status Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 07/25] vmdk: Use vmdk_find_index_in_cluster everywhere Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 08/25] raw-posix: Fix .bdrv_co_get_block_status() for unaligned image size Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 09/25] block: record new size in bdrv_dirty_bitmap_truncate Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 10/25] block: Change bitmap truncate conditional to assertion Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 11/25] block: driver should override flags in bdrv_open() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 12/25] iotests: Add tests for overriding BDRV_O_PROTOCOL Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 13/25] qdict: Add qdict_array_entries() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 14/25] qdict: Add qdict_{set,copy}_default() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 15/25] check-qdict: Test cases for new functions Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 16/25] quorum: Use bdrv_open_image() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 17/25] vmdk: " Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 18/25] block: Use macro for cache option names Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 19/25] block: Use QemuOpts in bdrv_open_common() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 20/25] block: Move flag inheritance to bdrv_open_inherit() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 21/25] block: Drain requests before swapping nodes in bdrv_swap() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 22/25] queue.h: Add QLIST_FIX_HEAD_PTR() Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 23/25] block: Add list of children to BlockDriverState Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 24/25] block: Add BlockDriverState.inherits_from Kevin Wolf
2015-06-12 16:23 ` [Qemu-devel] [PULL 25/25] block: Fix reopen flag inheritance Kevin Wolf
2015-06-15 12:24 ` [Qemu-devel] [PULL 00/25] Block layer core and image format patches Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).