All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/42] Block patches
@ 2014-01-15 10:22 Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 01/42] rbd: switch from pipe to QEMUBH completion notification Kevin Wolf
                   ` (41 more replies)
  0 siblings, 42 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

The following changes since commit 1cf892ca2689c84960b4ce4d2723b6bee453711c:

  SPARC: Fix LEON3 power down instruction (2014-01-15 15:37:33 +1000)

are available in the git repository at:

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

for you to fetch changes up to 01dfcc17541a97e2662b6ce403ff8b06a8ec4280:

  block: fix backing file segfault (2014-01-15 11:02:51 +0100)

----------------------------------------------------------------
Block patches

----------------------------------------------------------------
Bharata B Rao (3):
      gluster: Convert aio routines into coroutines
      gluster: Implement .bdrv_co_write_zeroes for gluster
      gluster: Add support for creating zero-filled image

Fam Zheng (4):
      qemu-iotests: Introduce _unsupported_imgopts
      qemu-iotests: Add _unsupported_imgopts for vmdk subformats
      qemu-iotests: Clean up all extents for vmdk
      vmdk: Fix big flat extent IO

Kewei Yu (1):
      qtest: Fix the bug about disable vnc causes "make check" fail

Liu Yuan (1):
      sheepdog: fix clone operation by 'qemu-img create -b'

Max Reitz (24):
      blkdebug: Use errp for read_config()
      blkdebug: Don't require sophisticated filename
      qdict: Add qdict_array_split()
      qapi: extend qdict_flatten() for QLists
      qemu-option: Add qemu_config_parse_qdict()
      blkdebug: Always call read_config()
      blkdebug: Use command-line in read_config()
      block: Allow reference for bdrv_file_open()
      block: Pass reference to bdrv_file_open()
      block: Allow block devices without files
      block: Add bdrv_open_image()
      block: Use bdrv_open_image() in bdrv_open()
      block: Allow recursive "file"s
      blockdev: Move "file" to legacy_opts
      blkdebug: Allow command-line file configuration
      blkverify: Allow command-line configuration
      blkverify: Don't require protocol filename
      qapi: Add "errno" to the list of polluted words
      qapi: QMP interface for blkdebug and blkverify
      qemu-io: Make filename optional
      tests: Add test for qdict_array_split()
      tests: Add test for qdict_flatten()
      iotests: Test new blkdebug/blkverify interface
      iotests: Test file format nesting

Peter Feiner (1):
      block: fix backing file segfault

Peter Lieven (1):
      block/iscsi: return -ENOMEM if an async call fails immediately

Stefan Hajnoczi (7):
      rbd: switch from pipe to QEMUBH completion notification
      docs: qcow2 compat=1.1 is now the default
      readline: decouple readline from the monitor
      readline: move readline to a generic location
      osdep: add qemu_set_tty_echo()
      qemu-io: use readline.c
      qemu-io: add command completion

 Makefile.objs                        |   1 -
 block.c                              | 128 ++++++++++++--
 block/blkdebug.c                     |  59 ++++---
 block/blkverify.c                    |  29 +---
 block/cow.c                          |   3 +-
 block/gluster.c                      | 318 ++++++++++++++++++-----------------
 block/iscsi.c                        |  12 +-
 block/qcow.c                         |   3 +-
 block/qcow2.c                        |   2 +-
 block/qed.c                          |   4 +-
 block/rbd.c                          | 130 +++-----------
 block/sheepdog.c                     |  20 +--
 block/vhdx.c                         |   2 +-
 block/vmdk.c                         |  12 +-
 blockdev.c                           |  19 ++-
 configure                            |   8 +
 hmp.c                                |   6 +-
 include/block/block.h                |   6 +-
 include/monitor/monitor.h            |   2 +-
 include/qapi/qmp/qdict.h             |   1 +
 include/qemu-io.h                    |   3 +
 include/qemu/config-file.h           |   6 +
 include/qemu/osdep.h                 |   2 +
 include/{monitor => qemu}/readline.h |  20 ++-
 monitor.c                            |  41 ++++-
 qapi-schema.json                     | 113 ++++++++++++-
 qemu-doc.texi                        |   8 +-
 qemu-img.texi                        |   8 +-
 qemu-io-cmds.c                       |  15 ++
 qemu-io.c                            | 119 +++++++------
 qobject/qdict.c                      |  91 +++++++++-
 scripts/qapi.py                      |   2 +-
 tests/check-qdict.c                  | 156 +++++++++++++++++
 tests/fdc-test.c                     |   5 +-
 tests/ide-test.c                     |   3 -
 tests/qemu-iotests/017               |   1 +
 tests/qemu-iotests/018               |   1 +
 tests/qemu-iotests/019               |   3 +
 tests/qemu-iotests/020               |   3 +
 tests/qemu-iotests/034               |   3 +
 tests/qemu-iotests/037               |   3 +
 tests/qemu-iotests/051.out           |   2 +-
 tests/qemu-iotests/059               |  10 ++
 tests/qemu-iotests/059.out           |  74 ++++++++
 tests/qemu-iotests/063               |   3 +
 tests/qemu-iotests/069               |   1 +
 tests/qemu-iotests/071               | 239 ++++++++++++++++++++++++++
 tests/qemu-iotests/071.out           |  90 ++++++++++
 tests/qemu-iotests/072               |  69 ++++++++
 tests/qemu-iotests/072.out           |  21 +++
 tests/qemu-iotests/common.rc         |  28 ++-
 tests/qemu-iotests/group             |   2 +
 util/Makefile.objs                   |   1 +
 util/oslib-posix.c                   |  18 ++
 util/oslib-win32.c                   |  19 +++
 util/qemu-config.c                   | 100 +++++++++++
 readline.c => util/readline.c        |  46 ++---
 57 files changed, 1617 insertions(+), 477 deletions(-)
 rename include/{monitor => qemu}/readline.h (69%)
 create mode 100755 tests/qemu-iotests/071
 create mode 100644 tests/qemu-iotests/071.out
 create mode 100755 tests/qemu-iotests/072
 create mode 100644 tests/qemu-iotests/072.out
 rename readline.c => util/readline.c (92%)

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

* [Qemu-devel] [PULL 01/42] rbd: switch from pipe to QEMUBH completion notification
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 02/42] qemu-iotests: Introduce _unsupported_imgopts Kevin Wolf
                   ` (40 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

rbd callbacks are called from non-QEMU threads.  Up until now a pipe was
used to signal completion back to the QEMU iothread.

The pipe writer code handles EAGAIN using select(2).  The select(2) API
is not scalable since fd_set size is static.  FD_SET() can write beyond
the end of fd_set if the file descriptor number is too high.  (QEMU's
main loop uses poll(2) to avoid this issue with select(2).)

Since the pipe itself is quite clumsy to use and QEMUBH is now
thread-safe, just schedule a BH from the rbd callback function.  This
way we can simplify I/O completion in addition to eliminating the
potential FD_SET() crash when file descriptor numbers become too high.

Crash scenario: QEMU already has 1024 file descriptors open.  Hotplug an
rbd drive and get the pipe writer to take the select(2) code path.

Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Tested-by: Josh Durgin <josh.durgin@inktank.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/rbd.c | 130 ++++++++++--------------------------------------------------
 1 file changed, 22 insertions(+), 108 deletions(-)

diff --git a/block/rbd.c b/block/rbd.c
index f453f04..121fae2 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -95,18 +95,13 @@ typedef struct RADOSCB {
 #define RBD_FD_WRITE 1
 
 typedef struct BDRVRBDState {
-    int fds[2];
     rados_t cluster;
     rados_ioctx_t io_ctx;
     rbd_image_t image;
     char name[RBD_MAX_IMAGE_NAME_SIZE];
     char *snap;
-    int event_reader_pos;
-    RADOSCB *event_rcb;
 } BDRVRBDState;
 
-static void rbd_aio_bh_cb(void *opaque);
-
 static int qemu_rbd_next_tok(char *dst, int dst_len,
                              char *src, char delim,
                              const char *name,
@@ -369,9 +364,8 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options,
 }
 
 /*
- * This aio completion is being called from qemu_rbd_aio_event_reader()
- * and runs in qemu context. It schedules a bh, but just in case the aio
- * was not cancelled before.
+ * This aio completion is being called from rbd_finish_bh() and runs in qemu
+ * BH context.
  */
 static void qemu_rbd_complete_aio(RADOSCB *rcb)
 {
@@ -401,36 +395,19 @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
             acb->ret = r;
         }
     }
-    /* Note that acb->bh can be NULL in case where the aio was cancelled */
-    acb->bh = qemu_bh_new(rbd_aio_bh_cb, acb);
-    qemu_bh_schedule(acb->bh);
-    g_free(rcb);
-}
 
-/*
- * aio fd read handler. It runs in the qemu context and calls the
- * completion handling of completed rados aio operations.
- */
-static void qemu_rbd_aio_event_reader(void *opaque)
-{
-    BDRVRBDState *s = opaque;
+    g_free(rcb);
 
-    ssize_t ret;
+    if (acb->cmd == RBD_AIO_READ) {
+        qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
+    }
+    qemu_vfree(acb->bounce);
+    acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
+    acb->status = 0;
 
-    do {
-        char *p = (char *)&s->event_rcb;
-
-        /* now read the rcb pointer that was sent from a non qemu thread */
-        ret = read(s->fds[RBD_FD_READ], p + s->event_reader_pos,
-                   sizeof(s->event_rcb) - s->event_reader_pos);
-        if (ret > 0) {
-            s->event_reader_pos += ret;
-            if (s->event_reader_pos == sizeof(s->event_rcb)) {
-                s->event_reader_pos = 0;
-                qemu_rbd_complete_aio(s->event_rcb);
-            }
-        }
-    } while (ret < 0 && errno == EINTR);
+    if (!acb->cancelled) {
+        qemu_aio_release(acb);
+    }
 }
 
 /* TODO Convert to fine grained options */
@@ -538,23 +515,9 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
 
     bs->read_only = (s->snap != NULL);
 
-    s->event_reader_pos = 0;
-    r = qemu_pipe(s->fds);
-    if (r < 0) {
-        error_report("error opening eventfd");
-        goto failed;
-    }
-    fcntl(s->fds[0], F_SETFL, O_NONBLOCK);
-    fcntl(s->fds[1], F_SETFL, O_NONBLOCK);
-    qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader,
-                            NULL, s);
-
-
     qemu_opts_del(opts);
     return 0;
 
-failed:
-    rbd_close(s->image);
 failed_open:
     rados_ioctx_destroy(s->io_ctx);
 failed_shutdown:
@@ -569,10 +532,6 @@ static void qemu_rbd_close(BlockDriverState *bs)
 {
     BDRVRBDState *s = bs->opaque;
 
-    close(s->fds[0]);
-    close(s->fds[1]);
-    qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], NULL, NULL, NULL);
-
     rbd_close(s->image);
     rados_ioctx_destroy(s->io_ctx);
     g_free(s->snap);
@@ -600,34 +559,11 @@ static const AIOCBInfo rbd_aiocb_info = {
     .cancel = qemu_rbd_aio_cancel,
 };
 
-static int qemu_rbd_send_pipe(BDRVRBDState *s, RADOSCB *rcb)
+static void rbd_finish_bh(void *opaque)
 {
-    int ret = 0;
-    while (1) {
-        fd_set wfd;
-        int fd = s->fds[RBD_FD_WRITE];
-
-        /* send the op pointer to the qemu thread that is responsible
-           for the aio/op completion. Must do it in a qemu thread context */
-        ret = write(fd, (void *)&rcb, sizeof(rcb));
-        if (ret >= 0) {
-            break;
-        }
-        if (errno == EINTR) {
-            continue;
-        }
-        if (errno != EAGAIN) {
-            break;
-        }
-
-        FD_ZERO(&wfd);
-        FD_SET(fd, &wfd);
-        do {
-            ret = select(fd + 1, NULL, &wfd, NULL, NULL);
-        } while (ret < 0 && errno == EINTR);
-    }
-
-    return ret;
+    RADOSCB *rcb = opaque;
+    qemu_bh_delete(rcb->acb->bh);
+    qemu_rbd_complete_aio(rcb);
 }
 
 /*
@@ -635,40 +571,18 @@ static int qemu_rbd_send_pipe(BDRVRBDState *s, RADOSCB *rcb)
  *
  * Note: this function is being called from a non qemu thread so
  * we need to be careful about what we do here. Generally we only
- * write to the block notification pipe, and do the rest of the
- * io completion handling from qemu_rbd_aio_event_reader() which
- * runs in a qemu context.
+ * schedule a BH, and do the rest of the io completion handling
+ * from rbd_finish_bh() which runs in a qemu context.
  */
 static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb)
 {
-    int ret;
+    RBDAIOCB *acb = rcb->acb;
+
     rcb->ret = rbd_aio_get_return_value(c);
     rbd_aio_release(c);
-    ret = qemu_rbd_send_pipe(rcb->s, rcb);
-    if (ret < 0) {
-        error_report("failed writing to acb->s->fds");
-        g_free(rcb);
-    }
-}
-
-/* Callback when all queued rbd_aio requests are complete */
 
-static void rbd_aio_bh_cb(void *opaque)
-{
-    RBDAIOCB *acb = opaque;
-
-    if (acb->cmd == RBD_AIO_READ) {
-        qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
-    }
-    qemu_vfree(acb->bounce);
-    acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
-    qemu_bh_delete(acb->bh);
-    acb->bh = NULL;
-    acb->status = 0;
-
-    if (!acb->cancelled) {
-        qemu_aio_release(acb);
-    }
+    acb->bh = qemu_bh_new(rbd_finish_bh, rcb);
+    qemu_bh_schedule(acb->bh);
 }
 
 static int rbd_aio_discard_wrapper(rbd_image_t image,
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 02/42] qemu-iotests: Introduce _unsupported_imgopts
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 01/42] rbd: switch from pipe to QEMUBH completion notification Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 03/42] qemu-iotests: Add _unsupported_imgopts for vmdk subformats Kevin Wolf
                   ` (39 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

Introduce _unsupported_imgopts that causes _notrun for specific image
options.

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

diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 28ba0d9..2489c43 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -406,6 +406,17 @@ _default_cache_mode()
     fi
 }
 
+_unsupported_imgopts()
+{
+    for bad_opt
+    do
+        if echo "$IMGOPTS" | grep -q 2>/dev/null "$bad_opt"
+        then
+            _notrun "not suitable for image option: $bad_opt"
+        fi
+    done
+}
+
 # this test requires that a specified command (executable) exists
 #
 _require_command()
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 03/42] qemu-iotests: Add _unsupported_imgopts for vmdk subformats
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 01/42] rbd: switch from pipe to QEMUBH completion notification Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 02/42] qemu-iotests: Introduce _unsupported_imgopts Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 04/42] qemu-iotests: Clean up all extents for vmdk Kevin Wolf
                   ` (38 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

Some cases are not applicable for vmdk subformats those don't support
certain features, e.g. backing file, and some others can't run on
mult-file image, e.g. monolithicFlat. This adds declaration in test
cases to skip them automatically, so that iotests on vmdk can go
more smoothly (without manually picking of cases for each subformat).

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/017 | 1 +
 tests/qemu-iotests/018 | 1 +
 tests/qemu-iotests/019 | 3 +++
 tests/qemu-iotests/020 | 3 +++
 tests/qemu-iotests/034 | 3 +++
 tests/qemu-iotests/037 | 3 +++
 tests/qemu-iotests/059 | 3 +++
 tests/qemu-iotests/063 | 3 +++
 tests/qemu-iotests/069 | 1 +
 9 files changed, 21 insertions(+)

diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017
index aba3faf..3af3cdf 100755
--- a/tests/qemu-iotests/017
+++ b/tests/qemu-iotests/017
@@ -43,6 +43,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow qcow2 vmdk qed
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
 
 TEST_OFFSETS="0 4294967296"
 
diff --git a/tests/qemu-iotests/018 b/tests/qemu-iotests/018
index 15fcfe5..6f7f054 100755
--- a/tests/qemu-iotests/018
+++ b/tests/qemu-iotests/018
@@ -43,6 +43,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow qcow2 vmdk qed
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
 
 TEST_OFFSETS="0 4294967296"
 
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
index 5bb18d0..b43e70f 100755
--- a/tests/qemu-iotests/019
+++ b/tests/qemu-iotests/019
@@ -47,6 +47,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow qcow2 vmdk qed
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" \
+                     "subformat=twoGbMaxExtentFlat" \
+                     "subformat=twoGbMaxExtentSparse"
 
 TEST_OFFSETS="0 4294967296"
 CLUSTER_SIZE=65536
diff --git a/tests/qemu-iotests/020 b/tests/qemu-iotests/020
index b3c86d8..73a0429 100755
--- a/tests/qemu-iotests/020
+++ b/tests/qemu-iotests/020
@@ -45,6 +45,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow qcow2 vmdk qed
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" \
+                     "subformat=twoGbMaxExtentFlat" \
+                     "subformat=twoGbMaxExtentSparse"
 
 TEST_OFFSETS="0 4294967296"
 
diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034
index 67f1959..7349789 100755
--- a/tests/qemu-iotests/034
+++ b/tests/qemu-iotests/034
@@ -41,6 +41,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow qcow2 vmdk qed
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" \
+                     "subformat=twoGbMaxExtentFlat" \
+                     "subformat=twoGbMaxExtentSparse"
 
 CLUSTER_SIZE=4k
 size=128M
diff --git a/tests/qemu-iotests/037 b/tests/qemu-iotests/037
index 743bae3..e444349 100755
--- a/tests/qemu-iotests/037
+++ b/tests/qemu-iotests/037
@@ -41,6 +41,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow qcow2 vmdk qed
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" \
+                     "subformat=twoGbMaxExtentFlat" \
+                     "subformat=twoGbMaxExtentSparse"
 
 CLUSTER_SIZE=4k
 size=128M
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index 65bea1d..d8215ae 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -42,6 +42,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt vmdk
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" \
+                     "subformat=twoGbMaxExtentFlat" \
+                     "subformat=twoGbMaxExtentSparse"
 
 capacity_offset=16
 granularity_offset=20
diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063
index 2ab8f20..77503a2 100755
--- a/tests/qemu-iotests/063
+++ b/tests/qemu-iotests/063
@@ -44,6 +44,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow qcow2 vmdk qed raw
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" \
+                     "subformat=twoGbMaxExtentFlat" \
+                     "subformat=twoGbMaxExtentSparse"
 
 _make_test_img 4M
 
diff --git a/tests/qemu-iotests/069 b/tests/qemu-iotests/069
index 3042803..50347d9 100755
--- a/tests/qemu-iotests/069
+++ b/tests/qemu-iotests/069
@@ -41,6 +41,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt cow qed qcow qcow2 vmdk
 _supported_proto generic
 _supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
 
 IMG_SIZE=128K
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 04/42] qemu-iotests: Clean up all extents for vmdk
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (2 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 03/42] qemu-iotests: Add _unsupported_imgopts for vmdk subformats Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 05/42] block/iscsi: return -ENOMEM if an async call fails immediately Kevin Wolf
                   ` (37 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

This modifies _cleanup_test_img to remove all the extent files listed by
"qemu-img info"'s format specific information.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/common.rc | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 2489c43..0f68156 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -170,6 +170,17 @@ _make_test_img()
     fi
 }
 
+_rm_test_img()
+{
+    local img=$1
+    if [ "$IMGFMT" = "vmdk" ]; then
+        # Remove all the extents for vmdk
+        $QEMU_IMG info $img 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
+            | xargs -I {} rm -f "{}"
+    fi
+    rm -f $img
+}
+
 _cleanup_test_img()
 {
     case "$IMGPROTO" in
@@ -179,9 +190,9 @@ _cleanup_test_img()
             rm -f "$TEST_IMG_FILE"
             ;;
         file)
-            rm -f "$TEST_DIR/t.$IMGFMT"
-            rm -f "$TEST_DIR/t.$IMGFMT.orig"
-            rm -f "$TEST_DIR/t.$IMGFMT.base"
+            _rm_test_img "$TEST_DIR/t.$IMGFMT"
+            _rm_test_img "$TEST_DIR/t.$IMGFMT.orig"
+            _rm_test_img "$TEST_DIR/t.$IMGFMT.base"
             if [ -n "$SAMPLE_IMG_FILE" ]
             then
                 rm -f "$TEST_DIR/$SAMPLE_IMG_FILE"
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 05/42] block/iscsi: return -ENOMEM if an async call fails immediately
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (3 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 04/42] qemu-iotests: Clean up all extents for vmdk Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 06/42] gluster: Convert aio routines into coroutines Kevin Wolf
                   ` (36 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Peter Lieven <pl@kamp.de>

if an async libiscsi call fails directly it can only be due
to an out of memory condition. All other errors are returned
through the callback.

Signed-off-by: Peter Lieven <pl@kamp.de>
Reviewed-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/iscsi.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index c0ea0c4..76b3c96 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -308,7 +308,7 @@ retry:
                                     iscsi_co_generic_cb, &iTask);
     if (iTask.task == NULL) {
         g_free(buf);
-        return -EIO;
+        return -ENOMEM;
     }
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
     scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
@@ -376,7 +376,7 @@ retry:
         break;
     }
     if (iTask.task == NULL) {
-        return -EIO;
+        return -ENOMEM;
     }
 #if defined(LIBISCSI_FEATURE_IOVECTOR)
     scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, iov->niov);
@@ -419,7 +419,7 @@ static int coroutine_fn iscsi_co_flush(BlockDriverState *bs)
 retry:
     if (iscsi_synchronizecache10_task(iscsilun->iscsi, iscsilun->lun, 0, 0, 0,
                                       0, iscsi_co_generic_cb, &iTask) == NULL) {
-        return -EIO;
+        return -ENOMEM;
     }
 
     while (!iTask.complete) {
@@ -669,7 +669,7 @@ retry:
                                   sector_qemu2lun(sector_num, iscsilun),
                                   8 + 16, iscsi_co_generic_cb,
                                   &iTask) == NULL) {
-        ret = -EIO;
+        ret = -ENOMEM;
         goto out;
     }
 
@@ -753,7 +753,7 @@ coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
 retry:
     if (iscsi_unmap_task(iscsilun->iscsi, iscsilun->lun, 0, 0, &list, 1,
                      iscsi_co_generic_cb, &iTask) == NULL) {
-        return -EIO;
+        return -ENOMEM;
     }
 
     while (!iTask.complete) {
@@ -822,7 +822,7 @@ retry:
                                iscsilun->zeroblock, iscsilun->block_size,
                                nb_blocks, 0, !!(flags & BDRV_REQ_MAY_UNMAP),
                                0, 0, iscsi_co_generic_cb, &iTask) == NULL) {
-        return -EIO;
+        return -ENOMEM;
     }
 
     while (!iTask.complete) {
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 06/42] gluster: Convert aio routines into coroutines
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (4 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 05/42] block/iscsi: return -ENOMEM if an async call fails immediately Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 07/42] gluster: Implement .bdrv_co_write_zeroes for gluster Kevin Wolf
                   ` (35 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Bharata B Rao <bharata@linux.vnet.ibm.com>

Convert the read, write, flush and discard implementations from aio-based
ones to coroutine based ones.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/gluster.c | 221 +++++++++++++++++++-------------------------------------
 1 file changed, 74 insertions(+), 147 deletions(-)

diff --git a/block/gluster.c b/block/gluster.c
index 563d497..f9aea0e 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -21,19 +21,15 @@
 #include "qemu/uri.h"
 
 typedef struct GlusterAIOCB {
-    BlockDriverAIOCB common;
     int64_t size;
     int ret;
-    bool *finished;
     QEMUBH *bh;
+    Coroutine *coroutine;
 } GlusterAIOCB;
 
 typedef struct BDRVGlusterState {
     struct glfs *glfs;
-    int fds[2];
     struct glfs_fd *fd;
-    int event_reader_pos;
-    GlusterAIOCB *event_acb;
 } BDRVGlusterState;
 
 #define GLUSTER_FD_READ  0
@@ -231,46 +227,13 @@ out:
     return NULL;
 }
 
-static void qemu_gluster_complete_aio(GlusterAIOCB *acb, BDRVGlusterState *s)
+static void qemu_gluster_complete_aio(void *opaque)
 {
-    int ret;
-    bool *finished = acb->finished;
-    BlockDriverCompletionFunc *cb = acb->common.cb;
-    void *opaque = acb->common.opaque;
-
-    if (!acb->ret || acb->ret == acb->size) {
-        ret = 0; /* Success */
-    } else if (acb->ret < 0) {
-        ret = acb->ret; /* Read/Write failed */
-    } else {
-        ret = -EIO; /* Partial read/write - fail it */
-    }
+    GlusterAIOCB *acb = (GlusterAIOCB *)opaque;
 
-    qemu_aio_release(acb);
-    cb(opaque, ret);
-    if (finished) {
-        *finished = true;
-    }
-}
-
-static void qemu_gluster_aio_event_reader(void *opaque)
-{
-    BDRVGlusterState *s = opaque;
-    ssize_t ret;
-
-    do {
-        char *p = (char *)&s->event_acb;
-
-        ret = read(s->fds[GLUSTER_FD_READ], p + s->event_reader_pos,
-                   sizeof(s->event_acb) - s->event_reader_pos);
-        if (ret > 0) {
-            s->event_reader_pos += ret;
-            if (s->event_reader_pos == sizeof(s->event_acb)) {
-                s->event_reader_pos = 0;
-                qemu_gluster_complete_aio(s->event_acb, s);
-            }
-        }
-    } while (ret < 0 && errno == EINTR);
+    qemu_bh_delete(acb->bh);
+    acb->bh = NULL;
+    qemu_coroutine_enter(acb->coroutine, NULL);
 }
 
 /* TODO Convert to fine grained options */
@@ -309,7 +272,6 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
 
     filename = qemu_opt_get(opts, "filename");
 
-
     s->glfs = qemu_gluster_init(gconf, filename);
     if (!s->glfs) {
         ret = -errno;
@@ -329,17 +291,7 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,
     s->fd = glfs_open(s->glfs, gconf->image, open_flags);
     if (!s->fd) {
         ret = -errno;
-        goto out;
-    }
-
-    ret = qemu_pipe(s->fds);
-    if (ret < 0) {
-        ret = -errno;
-        goto out;
     }
-    fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK);
-    qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ],
-        qemu_gluster_aio_event_reader, NULL, s);
 
 out:
     qemu_opts_del(opts);
@@ -398,58 +350,37 @@ out:
     return ret;
 }
 
-static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb)
-{
-    GlusterAIOCB *acb = (GlusterAIOCB *)blockacb;
-    bool finished = false;
-
-    acb->finished = &finished;
-    while (!finished) {
-        qemu_aio_wait();
-    }
-}
-
-static const AIOCBInfo gluster_aiocb_info = {
-    .aiocb_size = sizeof(GlusterAIOCB),
-    .cancel = qemu_gluster_aio_cancel,
-};
-
+/*
+ * AIO callback routine called from GlusterFS thread.
+ */
 static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
 {
     GlusterAIOCB *acb = (GlusterAIOCB *)arg;
-    BlockDriverState *bs = acb->common.bs;
-    BDRVGlusterState *s = bs->opaque;
-    int retval;
-
-    acb->ret = ret;
-    retval = qemu_write_full(s->fds[GLUSTER_FD_WRITE], &acb, sizeof(acb));
-    if (retval != sizeof(acb)) {
-        /*
-         * Gluster AIO callback thread failed to notify the waiting
-         * QEMU thread about IO completion.
-         */
-        error_report("Gluster AIO completion failed: %s", strerror(errno));
-        abort();
+
+    if (!ret || ret == acb->size) {
+        acb->ret = 0; /* Success */
+    } else if (ret < 0) {
+        acb->ret = ret; /* Read/Write failed */
+    } else {
+        acb->ret = -EIO; /* Partial read/write - fail it */
     }
+
+    acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
+    qemu_bh_schedule(acb->bh);
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int write)
+static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int write)
 {
     int ret;
-    GlusterAIOCB *acb;
+    GlusterAIOCB *acb = g_slice_new(GlusterAIOCB);
     BDRVGlusterState *s = bs->opaque;
-    size_t size;
-    off_t offset;
+    size_t size = nb_sectors * BDRV_SECTOR_SIZE;
+    off_t offset = sector_num * BDRV_SECTOR_SIZE;
 
-    offset = sector_num * BDRV_SECTOR_SIZE;
-    size = nb_sectors * BDRV_SECTOR_SIZE;
-
-    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = size;
     acb->ret = 0;
-    acb->finished = NULL;
+    acb->coroutine = qemu_coroutine_self();
 
     if (write) {
         ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
@@ -460,13 +391,16 @@ static BlockDriverAIOCB *qemu_gluster_aio_rw(BlockDriverState *bs,
     }
 
     if (ret < 0) {
+        ret = -errno;
         goto out;
     }
-    return &acb->common;
+
+    qemu_coroutine_yield();
+    ret = acb->ret;
 
 out:
-    qemu_aio_release(acb);
-    return NULL;
+    g_slice_free(GlusterAIOCB, acb);
+    return ret;
 }
 
 static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
@@ -482,71 +416,68 @@ static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
     return 0;
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_readv(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
-    return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
+    return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 0);
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_writev(BlockDriverState *bs,
-        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
 {
-    return qemu_gluster_aio_rw(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
+    return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
 }
 
-static BlockDriverAIOCB *qemu_gluster_aio_flush(BlockDriverState *bs,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
 {
     int ret;
-    GlusterAIOCB *acb;
+    GlusterAIOCB *acb = g_slice_new(GlusterAIOCB);
     BDRVGlusterState *s = bs->opaque;
 
-    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = 0;
     acb->ret = 0;
-    acb->finished = NULL;
+    acb->coroutine = qemu_coroutine_self();
 
     ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
     if (ret < 0) {
+        ret = -errno;
         goto out;
     }
-    return &acb->common;
+
+    qemu_coroutine_yield();
+    ret = acb->ret;
 
 out:
-    qemu_aio_release(acb);
-    return NULL;
+    g_slice_free(GlusterAIOCB, acb);
+    return ret;
 }
 
 #ifdef CONFIG_GLUSTERFS_DISCARD
-static BlockDriverAIOCB *qemu_gluster_aio_discard(BlockDriverState *bs,
-        int64_t sector_num, int nb_sectors, BlockDriverCompletionFunc *cb,
-        void *opaque)
+static coroutine_fn int qemu_gluster_co_discard(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors)
 {
     int ret;
-    GlusterAIOCB *acb;
+    GlusterAIOCB *acb = g_slice_new(GlusterAIOCB);
     BDRVGlusterState *s = bs->opaque;
-    size_t size;
-    off_t offset;
-
-    offset = sector_num * BDRV_SECTOR_SIZE;
-    size = nb_sectors * BDRV_SECTOR_SIZE;
+    size_t size = nb_sectors * BDRV_SECTOR_SIZE;
+    off_t offset = sector_num * BDRV_SECTOR_SIZE;
 
-    acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
     acb->size = 0;
     acb->ret = 0;
-    acb->finished = NULL;
+    acb->coroutine = qemu_coroutine_self();
 
     ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
     if (ret < 0) {
+        ret = -errno;
         goto out;
     }
-    return &acb->common;
+
+    qemu_coroutine_yield();
+    ret = acb->ret;
 
 out:
-    qemu_aio_release(acb);
-    return NULL;
+    g_slice_free(GlusterAIOCB, acb);
+    return ret;
 }
 #endif
 
@@ -581,10 +512,6 @@ static void qemu_gluster_close(BlockDriverState *bs)
 {
     BDRVGlusterState *s = bs->opaque;
 
-    close(s->fds[GLUSTER_FD_READ]);
-    close(s->fds[GLUSTER_FD_WRITE]);
-    qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL);
-
     if (s->fd) {
         glfs_close(s->fd);
         s->fd = NULL;
@@ -618,12 +545,12 @@ static BlockDriver bdrv_gluster = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
@@ -639,12 +566,12 @@ static BlockDriver bdrv_gluster_tcp = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
@@ -660,12 +587,12 @@ static BlockDriver bdrv_gluster_unix = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
@@ -681,12 +608,12 @@ static BlockDriver bdrv_gluster_rdma = {
     .bdrv_getlength               = qemu_gluster_getlength,
     .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
     .bdrv_truncate                = qemu_gluster_truncate,
-    .bdrv_aio_readv               = qemu_gluster_aio_readv,
-    .bdrv_aio_writev              = qemu_gluster_aio_writev,
-    .bdrv_aio_flush               = qemu_gluster_aio_flush,
+    .bdrv_co_readv                = qemu_gluster_co_readv,
+    .bdrv_co_writev               = qemu_gluster_co_writev,
+    .bdrv_co_flush_to_disk        = qemu_gluster_co_flush_to_disk,
     .bdrv_has_zero_init           = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
-    .bdrv_aio_discard             = qemu_gluster_aio_discard,
+    .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
     .create_options               = qemu_gluster_create_options,
 };
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 07/42] gluster: Implement .bdrv_co_write_zeroes for gluster
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (5 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 06/42] gluster: Convert aio routines into coroutines Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 08/42] gluster: Add support for creating zero-filled image Kevin Wolf
                   ` (34 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Bharata B Rao <bharata@linux.vnet.ibm.com>

Support .bdrv_co_write_zeroes() from gluster driver by using GlusterFS API
glfs_zerofill() that off-loads the writing of zeroes to GlusterFS server.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/gluster.c | 79 +++++++++++++++++++++++++++++++++++++++++++--------------
 configure       |  8 ++++++
 2 files changed, 68 insertions(+), 19 deletions(-)

diff --git a/block/gluster.c b/block/gluster.c
index f9aea0e..c11f60c 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -236,6 +236,25 @@ static void qemu_gluster_complete_aio(void *opaque)
     qemu_coroutine_enter(acb->coroutine, NULL);
 }
 
+/*
+ * AIO callback routine called from GlusterFS thread.
+ */
+static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
+{
+    GlusterAIOCB *acb = (GlusterAIOCB *)arg;
+
+    if (!ret || ret == acb->size) {
+        acb->ret = 0; /* Success */
+    } else if (ret < 0) {
+        acb->ret = ret; /* Read/Write failed */
+    } else {
+        acb->ret = -EIO; /* Partial read/write - fail it */
+    }
+
+    acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
+    qemu_bh_schedule(acb->bh);
+}
+
 /* TODO Convert to fine grained options */
 static QemuOptsList runtime_opts = {
     .name = "gluster",
@@ -308,6 +327,35 @@ out:
     return ret;
 }
 
+#ifdef CONFIG_GLUSTERFS_ZEROFILL
+static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
+        int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
+{
+    int ret;
+    GlusterAIOCB *acb = g_slice_new(GlusterAIOCB);
+    BDRVGlusterState *s = bs->opaque;
+    off_t size = nb_sectors * BDRV_SECTOR_SIZE;
+    off_t offset = sector_num * BDRV_SECTOR_SIZE;
+
+    acb->size = size;
+    acb->ret = 0;
+    acb->coroutine = qemu_coroutine_self();
+
+    ret = glfs_zerofill_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
+    if (ret < 0) {
+        ret = -errno;
+        goto out;
+    }
+
+    qemu_coroutine_yield();
+    ret = acb->ret;
+
+out:
+    g_slice_free(GlusterAIOCB, acb);
+    return ret;
+}
+#endif
+
 static int qemu_gluster_create(const char *filename,
         QEMUOptionParameter *options, Error **errp)
 {
@@ -350,25 +398,6 @@ out:
     return ret;
 }
 
-/*
- * AIO callback routine called from GlusterFS thread.
- */
-static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
-{
-    GlusterAIOCB *acb = (GlusterAIOCB *)arg;
-
-    if (!ret || ret == acb->size) {
-        acb->ret = 0; /* Success */
-    } else if (ret < 0) {
-        acb->ret = ret; /* Read/Write failed */
-    } else {
-        acb->ret = -EIO; /* Partial read/write - fail it */
-    }
-
-    acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
-    qemu_bh_schedule(acb->bh);
-}
-
 static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int write)
 {
@@ -552,6 +581,9 @@ static BlockDriver bdrv_gluster = {
 #ifdef CONFIG_GLUSTERFS_DISCARD
     .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
+#ifdef CONFIG_GLUSTERFS_ZEROFILL
+    .bdrv_co_write_zeroes         = qemu_gluster_co_write_zeroes,
+#endif
     .create_options               = qemu_gluster_create_options,
 };
 
@@ -573,6 +605,9 @@ static BlockDriver bdrv_gluster_tcp = {
 #ifdef CONFIG_GLUSTERFS_DISCARD
     .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
+#ifdef CONFIG_GLUSTERFS_ZEROFILL
+    .bdrv_co_write_zeroes         = qemu_gluster_co_write_zeroes,
+#endif
     .create_options               = qemu_gluster_create_options,
 };
 
@@ -594,6 +629,9 @@ static BlockDriver bdrv_gluster_unix = {
 #ifdef CONFIG_GLUSTERFS_DISCARD
     .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
+#ifdef CONFIG_GLUSTERFS_ZEROFILL
+    .bdrv_co_write_zeroes         = qemu_gluster_co_write_zeroes,
+#endif
     .create_options               = qemu_gluster_create_options,
 };
 
@@ -615,6 +653,9 @@ static BlockDriver bdrv_gluster_rdma = {
 #ifdef CONFIG_GLUSTERFS_DISCARD
     .bdrv_co_discard              = qemu_gluster_co_discard,
 #endif
+#ifdef CONFIG_GLUSTERFS_ZEROFILL
+    .bdrv_co_write_zeroes         = qemu_gluster_co_write_zeroes,
+#endif
     .create_options               = qemu_gluster_create_options,
 };
 
diff --git a/configure b/configure
index 3782a6a..b472694 100755
--- a/configure
+++ b/configure
@@ -256,6 +256,7 @@ coroutine_pool=""
 seccomp=""
 glusterfs=""
 glusterfs_discard="no"
+glusterfs_zerofill="no"
 virtio_blk_data_plane=""
 gtk=""
 gtkabi="2.0"
@@ -2701,6 +2702,9 @@ if test "$glusterfs" != "no" ; then
     if $pkg_config --atleast-version=5 glusterfs-api; then
       glusterfs_discard="yes"
     fi
+    if $pkg_config --atleast-version=6 glusterfs-api; then
+      glusterfs_zerofill="yes"
+    fi
   else
     if test "$glusterfs" = "yes" ; then
       feature_not_found "GlusterFS backend support"
@@ -4229,6 +4233,10 @@ if test "$glusterfs_discard" = "yes" ; then
   echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak
 fi
 
+if test "$glusterfs_zerofill" = "yes" ; then
+  echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak
+fi
+
 if test "$libssh2" = "yes" ; then
   echo "CONFIG_LIBSSH2=y" >> $config_host_mak
 fi
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 08/42] gluster: Add support for creating zero-filled image
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (6 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 07/42] gluster: Implement .bdrv_co_write_zeroes for gluster Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 09/42] sheepdog: fix clone operation by 'qemu-img create -b' Kevin Wolf
                   ` (33 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Bharata B Rao <bharata@linux.vnet.ibm.com>

GlusterFS supports creation of zero-filled file on GlusterFS volume
by means of an API called glfs_zerofill(). Use this API from QEMU to
create an image that is filled with zeroes by using the preallocation
option of qemu-img.

qemu-img create gluster://server/volume/image -o preallocation=full 10G

The allowed values for preallocation are 'full' and 'off'. By default
preallocation is off and image is not zero-filled.

glfs_zerofill() offloads the writing of zeroes to the server and if
the storage supports SCSI WRITESAME, GlusterFS server can issue
BLKZEROOUT ioctl to achieve the zeroing.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/gluster.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/block/gluster.c b/block/gluster.c
index c11f60c..a009b15 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -354,6 +354,29 @@ out:
     g_slice_free(GlusterAIOCB, acb);
     return ret;
 }
+
+static inline bool gluster_supports_zerofill(void)
+{
+    return 1;
+}
+
+static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
+        int64_t size)
+{
+    return glfs_zerofill(fd, offset, size);
+}
+
+#else
+static inline bool gluster_supports_zerofill(void)
+{
+    return 0;
+}
+
+static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
+        int64_t size)
+{
+    return 0;
+}
 #endif
 
 static int qemu_gluster_create(const char *filename,
@@ -362,6 +385,7 @@ static int qemu_gluster_create(const char *filename,
     struct glfs *glfs;
     struct glfs_fd *fd;
     int ret = 0;
+    int prealloc = 0;
     int64_t total_size = 0;
     GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));
 
@@ -374,6 +398,19 @@ static int qemu_gluster_create(const char *filename,
     while (options && options->name) {
         if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
             total_size = options->value.n / BDRV_SECTOR_SIZE;
+        } else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
+            if (!options->value.s || !strcmp(options->value.s, "off")) {
+                prealloc = 0;
+            } else if (!strcmp(options->value.s, "full") &&
+                    gluster_supports_zerofill()) {
+                prealloc = 1;
+            } else {
+                error_setg(errp, "Invalid preallocation mode: '%s'"
+                    " or GlusterFS doesn't support zerofill API",
+                           options->value.s);
+                ret = -EINVAL;
+                goto out;
+            }
         }
         options++;
     }
@@ -383,9 +420,15 @@ static int qemu_gluster_create(const char *filename,
     if (!fd) {
         ret = -errno;
     } else {
-        if (glfs_ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
+        if (!glfs_ftruncate(fd, total_size * BDRV_SECTOR_SIZE)) {
+            if (prealloc && qemu_gluster_zerofill(fd, 0,
+                    total_size * BDRV_SECTOR_SIZE)) {
+                ret = -errno;
+            }
+        } else {
             ret = -errno;
         }
+
         if (glfs_close(fd) != 0) {
             ret = -errno;
         }
@@ -560,6 +603,11 @@ static QEMUOptionParameter qemu_gluster_create_options[] = {
         .type = OPT_SIZE,
         .help = "Virtual disk size"
     },
+    {
+        .name = BLOCK_OPT_PREALLOC,
+        .type = OPT_STRING,
+        .help = "Preallocation mode (allowed values: off, full)"
+    },
     { NULL }
 };
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 09/42] sheepdog: fix clone operation by 'qemu-img create -b'
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (7 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 08/42] gluster: Add support for creating zero-filled image Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail Kevin Wolf
                   ` (32 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Liu Yuan <namei.unix@gmail.com>

We should pass base_inode->vdi_id to base_vdi_id of SheepdogVdiReq so that sheep
can create a clone instead a fresh volume.

This fixes following command:

qemu-create -b sheepdog:base sheepdog:clone

so users can boot sheepdog:clone as a normal volume.

Cc: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Liu Yuan <namei.unix@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/sheepdog.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/block/sheepdog.c b/block/sheepdog.c
index b94ab6e..6088fa5 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -161,7 +161,7 @@ typedef struct SheepdogVdiReq {
     uint32_t id;
     uint32_t data_length;
     uint64_t vdi_size;
-    uint32_t vdi_id;
+    uint32_t base_vdi_id;
     uint8_t copies;
     uint8_t copy_policy;
     uint8_t reserved[2];
@@ -1493,7 +1493,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot)
 
     memset(&hdr, 0, sizeof(hdr));
     hdr.opcode = SD_OP_NEW_VDI;
-    hdr.vdi_id = s->inode.vdi_id;
+    hdr.base_vdi_id = s->inode.vdi_id;
 
     wlen = SD_MAX_VDI_LEN;
 
@@ -1684,7 +1684,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
 
     if (backing_file) {
         BlockDriverState *bs;
-        BDRVSheepdogState *s;
+        BDRVSheepdogState *base;
         BlockDriver *drv;
 
         /* Currently, only Sheepdog backing image is supported. */
@@ -1702,15 +1702,15 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
             goto out;
         }
 
-        s = bs->opaque;
+        base = bs->opaque;
 
-        if (!is_snapshot(&s->inode)) {
+        if (!is_snapshot(&base->inode)) {
             error_report("cannot clone from a non snapshot vdi");
             bdrv_unref(bs);
             ret = -EINVAL;
             goto out;
         }
-
+        s->inode.vdi_id = base->inode.vdi_id;
         bdrv_unref(bs);
     }
 
@@ -1743,7 +1743,7 @@ static void sd_close(BlockDriverState *bs)
     memset(&hdr, 0, sizeof(hdr));
 
     hdr.opcode = SD_OP_RELEASE_VDI;
-    hdr.vdi_id = s->inode.vdi_id;
+    hdr.base_vdi_id = s->inode.vdi_id;
     wlen = strlen(s->name) + 1;
     hdr.data_length = wlen;
     hdr.flags = SD_FLAG_CMD_WRITE;
@@ -1846,7 +1846,7 @@ static bool sd_delete(BDRVSheepdogState *s)
     unsigned int wlen = SD_MAX_VDI_LEN, rlen = 0;
     SheepdogVdiReq hdr = {
         .opcode = SD_OP_DEL_VDI,
-        .vdi_id = s->inode.vdi_id,
+        .base_vdi_id = s->inode.vdi_id,
         .data_length = wlen,
         .flags = SD_FLAG_CMD_WRITE,
     };
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (8 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 09/42] sheepdog: fix clone operation by 'qemu-img create -b' Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-17 15:06   ` Andreas Färber
  2014-01-15 10:22 ` [Qemu-devel] [PULL 11/42] docs: qcow2 compat=1.1 is now the default Kevin Wolf
                   ` (31 subsequent siblings)
  41 siblings, 1 reply; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Kewei Yu <keweihk@gmail.com>

When we disable vnc from "./configure", QEMU can't use the vnc option.
So qtest can't use the "vnc -none ", otherwise "make check" fails.
If QEMU uses "-display none", "-vnc none" is excrescent, So we just need to drop it.

Signed-off-by: Kewei Yu <keweihk@gmail.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/fdc-test.c | 5 +----
 tests/ide-test.c | 3 ---
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 38b5b17..37096dc 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -518,7 +518,6 @@ static void fuzz_registers(void)
 int main(int argc, char **argv)
 {
     const char *arch = qtest_get_arch();
-    char *cmdline;
     int fd;
     int ret;
 
@@ -538,9 +537,7 @@ int main(int argc, char **argv)
     /* Run the tests */
     g_test_init(&argc, &argv, NULL);
 
-    cmdline = g_strdup_printf("-vnc none ");
-
-    qtest_start(cmdline);
+    qtest_start(NULL);
     qtest_irq_intercept_in(global_qtest, "ioapic");
     qtest_add_func("/fdc/cmos", test_cmos);
     qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start);
diff --git a/tests/ide-test.c b/tests/ide-test.c
index d5cec5a..4a0d97f 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -380,7 +380,6 @@ static void test_bmdma_no_busmaster(void)
 static void test_bmdma_setup(void)
 {
     ide_test_start(
-        "-vnc none "
         "-drive file=%s,if=ide,serial=%s,cache=writeback "
         "-global ide-hd.ver=%s",
         tmp_path, "testdisk", "version");
@@ -410,7 +409,6 @@ static void test_identify(void)
     int ret;
 
     ide_test_start(
-        "-vnc none "
         "-drive file=%s,if=ide,serial=%s,cache=writeback "
         "-global ide-hd.ver=%s",
         tmp_path, "testdisk", "version");
@@ -455,7 +453,6 @@ static void test_flush(void)
     uint8_t data;
 
     ide_test_start(
-        "-vnc none "
         "-drive file=blkdebug::%s,if=ide,cache=writeback",
         tmp_path);
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 11/42] docs: qcow2 compat=1.1 is now the default
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (9 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 12/42] vmdk: Fix big flat extent IO Kevin Wolf
                   ` (30 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Commit 9117b47717ad208b12786ce88eacb013f9b3dd1c ("qcow2: Change default
for new images to compat=1.1") changed the default qcow2 image format
version but forgot to update qemu-doc.texi and qemu-img.texi.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-doc.texi | 8 ++++----
 qemu-img.texi | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/qemu-doc.texi b/qemu-doc.texi
index 4e9c6e9..ce61f30 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -536,11 +536,11 @@ support of multiple VM snapshots.
 Supported options:
 @table @code
 @item compat
-Determines the qcow2 version to use. @code{compat=0.10} uses the traditional
-image format that can be read by any QEMU since 0.10 (this is the default).
+Determines the qcow2 version to use. @code{compat=0.10} uses the
+traditional image format that can be read by any QEMU since 0.10.
 @code{compat=1.1} enables image format extensions that only QEMU 1.1 and
-newer understand. Amongst others, this includes zero clusters, which allow
-efficient copy-on-read for sparse images.
+newer understand (this is the default). Amongst others, this includes
+zero clusters, which allow efficient copy-on-read for sparse images.
 
 @item backing_file
 File name of a base image (see @option{create} subcommand)
diff --git a/qemu-img.texi b/qemu-img.texi
index 1bba91e..778e967 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -391,11 +391,11 @@ support of multiple VM snapshots.
 Supported options:
 @table @code
 @item compat
-Determines the qcow2 version to use. @code{compat=0.10} uses the traditional
-image format that can be read by any QEMU since 0.10 (this is the default).
+Determines the qcow2 version to use. @code{compat=0.10} uses the
+traditional image format that can be read by any QEMU since 0.10.
 @code{compat=1.1} enables image format extensions that only QEMU 1.1 and
-newer understand. Amongst others, this includes zero clusters, which allow
-efficient copy-on-read for sparse images.
+newer understand (this is the default). Amongst others, this includes zero
+clusters, which allow efficient copy-on-read for sparse images.
 
 @item backing_file
 File name of a base image (see @option{create} subcommand)
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 12/42] vmdk: Fix big flat extent IO
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (10 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 11/42] docs: qcow2 compat=1.1 is now the default Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 13/42] readline: decouple readline from the monitor Kevin Wolf
                   ` (29 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Fam Zheng <famz@redhat.com>

Local variable "n" as int64_t avoids overflow with large sector number
calculation. See test case change for failure case.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vmdk.c               |  4 +--
 tests/qemu-iotests/059     |  7 +++++
 tests/qemu-iotests/059.out | 74 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index c6b60b4..22b99b0 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1325,8 +1325,8 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
 {
     BDRVVmdkState *s = bs->opaque;
     VmdkExtent *extent = NULL;
-    int n, ret;
-    int64_t index_in_cluster;
+    int ret;
+    int64_t index_in_cluster, n;
     uint64_t extent_begin_sector, extent_relative_sector_num;
     uint64_t cluster_offset;
     VmdkMetaData m_data;
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index d8215ae..64ed04c 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -102,6 +102,13 @@ echo "=== Testing version 3 ==="
 _use_sample_img iotest-version3.vmdk.bz2
 _img_info
 
+echo
+echo "=== Testing 4TB monolithicFlat creation and IO ==="
+IMGOPTS="subformat=monolithicFlat" _make_test_img 4T
+_img_info
+$QEMU_IO -c "write -P 0xa 900G 512" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -v 900G 1024" "$TEST_IMG" | _filter_qemu_io
+
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 16ab7c6..5e30e69 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -2047,4 +2047,78 @@ RW 12582912 VMFS "dummy.IMGFMT" 1
 image: TEST_DIR/iotest-version3.IMGFMT
 file format: IMGFMT
 virtual size: 1.0G (1073741824 bytes)
+
+=== Testing 4TB monolithicFlat creation and IO ===
+Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=4398046511104
+image: TEST_DIR/iotest-version3.IMGFMT
+file format: IMGFMT
+virtual size: 4.0T (4398046511104 bytes)
+wrote 512/512 bytes at offset 966367641600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+e100000000:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000010:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000020:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000030:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000040:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000050:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000060:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000070:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000080:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000090:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000000a0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000000b0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000000c0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000000d0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000000e0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000000f0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000100:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000110:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000120:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000130:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000140:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000150:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000160:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000170:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000180:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000190:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000001a0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000001b0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000001c0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000001d0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000001e0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e1000001f0:  0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a  ................
+e100000200:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000210:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000220:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000230:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000240:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000250:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000260:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000270:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000280:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000290:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000002a0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000002b0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000002c0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000002d0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000002e0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000002f0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000300:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000310:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000320:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000330:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000340:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000350:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000360:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000370:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000380:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e100000390:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000003a0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000003b0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000003c0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000003d0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000003e0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+e1000003f0:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+read 1024/1024 bytes at offset 966367641600
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 *** done
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 13/42] readline: decouple readline from the monitor
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (11 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 12/42] vmdk: Fix big flat extent IO Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 14/42] readline: move readline to a generic location Kevin Wolf
                   ` (28 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Make the readline.c functionality reusable.  Instead of calling
monitor_printf() and monitor_flush() directly, invoke function pointers
provided by the user.

This way readline.c does not know about Monitor and other users will be
able to make use of readline.c.

Note that there is already an "opaque" argument to the ReadLineFunc
callback.  Consistently call it "readline_opaque" from now on to
distinguish from the ReadLinePrintfFunc/ReadLineFlushFunc "opaque"
argument.

I also dropped the printf macro trickery since it's now highly unlikely
that anyone modifying readline.c would call printf(3) directly.  We no
longer need this protection.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 hmp.c                      |  6 +++---
 include/monitor/readline.h | 20 +++++++++++++-------
 monitor.c                  | 39 ++++++++++++++++++++++++++++++++-------
 readline.c                 | 44 +++++++++++++++++++++++---------------------
 4 files changed, 71 insertions(+), 38 deletions(-)

diff --git a/hmp.c b/hmp.c
index 79f9c7d..468f97d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1092,11 +1092,11 @@ void hmp_eject(Monitor *mon, const QDict *qdict)
     hmp_handle_error(mon, &err);
 }
 
-static void hmp_change_read_arg(Monitor *mon, const char *password,
-                                void *opaque)
+static void hmp_change_read_arg(void *opaque, const char *password,
+                                void *readline_opaque)
 {
     qmp_change_vnc_password(password, NULL);
-    monitor_read_command(mon, 1);
+    monitor_read_command(opaque, 1);
 }
 
 void hmp_change(Monitor *mon, const QDict *qdict)
diff --git a/include/monitor/readline.h b/include/monitor/readline.h
index 0faf6e1..a89fe4a 100644
--- a/include/monitor/readline.h
+++ b/include/monitor/readline.h
@@ -1,14 +1,15 @@
 #ifndef READLINE_H
 #define READLINE_H
 
-#include "qemu-common.h"
-
 #define READLINE_CMD_BUF_SIZE 4095
 #define READLINE_MAX_CMDS 64
 #define READLINE_MAX_COMPLETIONS 256
 
-typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque);
-typedef void ReadLineCompletionFunc(Monitor *mon,
+typedef void ReadLinePrintfFunc(void *opaque, const char *fmt, ...);
+typedef void ReadLineFlushFunc(void *opaque);
+typedef void ReadLineFunc(void *opaque, const char *str,
+                          void *readline_opaque);
+typedef void ReadLineCompletionFunc(void *opaque,
                                     const char *cmdline);
 
 typedef struct ReadLineState {
@@ -35,7 +36,10 @@ typedef struct ReadLineState {
     void *readline_opaque;
     int read_password;
     char prompt[256];
-    Monitor *mon;
+
+    ReadLinePrintfFunc *printf_func;
+    ReadLineFlushFunc *flush_func;
+    void *opaque;
 } ReadLineState;
 
 void readline_add_completion(ReadLineState *rs, const char *str);
@@ -46,11 +50,13 @@ const char *readline_get_history(ReadLineState *rs, unsigned int index);
 void readline_handle_byte(ReadLineState *rs, int ch);
 
 void readline_start(ReadLineState *rs, const char *prompt, int read_password,
-                    ReadLineFunc *readline_func, void *opaque);
+                    ReadLineFunc *readline_func, void *readline_opaque);
 void readline_restart(ReadLineState *rs);
 void readline_show_prompt(ReadLineState *rs);
 
-ReadLineState *readline_init(Monitor *mon,
+ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
+                             ReadLineFlushFunc *flush_func,
+                             void *opaque,
                              ReadLineCompletionFunc *completion_finder);
 
 #endif /* !READLINE_H */
diff --git a/monitor.c b/monitor.c
index 845f608..32d0264 100644
--- a/monitor.c
+++ b/monitor.c
@@ -217,8 +217,8 @@ static const mon_cmd_t qmp_cmds[];
 Monitor *cur_mon;
 Monitor *default_mon;
 
-static void monitor_command_cb(Monitor *mon, const char *cmdline,
-                               void *opaque);
+static void monitor_command_cb(void *opaque, const char *cmdline,
+                               void *readline_opaque);
 
 static inline int qmp_cmd_mode(const Monitor *mon)
 {
@@ -4338,9 +4338,10 @@ static void monitor_find_completion_by_table(Monitor *mon,
     }
 }
 
-static void monitor_find_completion(Monitor *mon,
+static void monitor_find_completion(void *opaque,
                                     const char *cmdline)
 {
+    Monitor *mon = opaque;
     char *args[MAX_ARGS];
     int nb_args, len;
 
@@ -4751,8 +4752,11 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size)
     cur_mon = old_mon;
 }
 
-static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque)
+static void monitor_command_cb(void *opaque, const char *cmdline,
+                               void *readline_opaque)
 {
+    Monitor *mon = opaque;
+
     monitor_suspend(mon);
     handle_user_command(mon, cmdline);
     monitor_resume(mon);
@@ -4881,6 +4885,22 @@ static void sortcmdlist(void)
  * End:
  */
 
+/* These functions just adapt the readline interface in a typesafe way.  We
+ * could cast function pointers but that discards compiler checks.
+ */
+static void monitor_readline_printf(void *opaque, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    monitor_vprintf(opaque, fmt, ap);
+    va_end(ap);
+}
+
+static void monitor_readline_flush(void *opaque)
+{
+    monitor_flush(opaque);
+}
+
 void monitor_init(CharDriverState *chr, int flags)
 {
     static int is_first_init = 1;
@@ -4898,7 +4918,10 @@ void monitor_init(CharDriverState *chr, int flags)
     mon->chr = chr;
     mon->flags = flags;
     if (flags & MONITOR_USE_READLINE) {
-        mon->rs = readline_init(mon, monitor_find_completion);
+        mon->rs = readline_init(monitor_readline_printf,
+                                monitor_readline_flush,
+                                mon,
+                                monitor_find_completion);
         monitor_read_command(mon, 0);
     }
 
@@ -4920,9 +4943,11 @@ void monitor_init(CharDriverState *chr, int flags)
         default_mon = mon;
 }
 
-static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
+static void bdrv_password_cb(void *opaque, const char *password,
+                             void *readline_opaque)
 {
-    BlockDriverState *bs = opaque;
+    Monitor *mon = opaque;
+    BlockDriverState *bs = readline_opaque;
     int ret = 0;
 
     if (bdrv_set_key(bs, password) != 0) {
diff --git a/readline.c b/readline.c
index abf27dd..ca894d1 100644
--- a/readline.c
+++ b/readline.c
@@ -21,21 +21,19 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+#include "qemu-common.h"
 #include "monitor/readline.h"
-#include "monitor/monitor.h"
 
 #define IS_NORM 0
 #define IS_ESC  1
 #define IS_CSI  2
 #define IS_SS3  3
 
-#undef printf
-#define printf do_not_use_printf
-
 void readline_show_prompt(ReadLineState *rs)
 {
-    monitor_printf(rs->mon, "%s", rs->prompt);
-    monitor_flush(rs->mon);
+    rs->printf_func(rs->opaque, "%s", rs->prompt);
+    rs->flush_func(rs->opaque);
     rs->last_cmd_buf_index = 0;
     rs->last_cmd_buf_size = 0;
     rs->esc_state = IS_NORM;
@@ -49,17 +47,17 @@ static void readline_update(ReadLineState *rs)
     if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
         memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
         for(i = 0; i < rs->last_cmd_buf_index; i++) {
-            monitor_printf(rs->mon, "\033[D");
+            rs->printf_func(rs->opaque, "\033[D");
         }
         rs->cmd_buf[rs->cmd_buf_size] = '\0';
         if (rs->read_password) {
             len = strlen(rs->cmd_buf);
             for(i = 0; i < len; i++)
-                monitor_printf(rs->mon, "*");
+                rs->printf_func(rs->opaque, "*");
         } else {
-            monitor_printf(rs->mon, "%s", rs->cmd_buf);
+            rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
         }
-        monitor_printf(rs->mon, "\033[K");
+        rs->printf_func(rs->opaque, "\033[K");
         memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
         rs->last_cmd_buf_size = rs->cmd_buf_size;
         rs->last_cmd_buf_index = rs->cmd_buf_size;
@@ -68,17 +66,17 @@ static void readline_update(ReadLineState *rs)
         delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
         if (delta > 0) {
             for(i = 0;i < delta; i++) {
-                monitor_printf(rs->mon, "\033[C");
+                rs->printf_func(rs->opaque, "\033[C");
             }
         } else {
             delta = -delta;
             for(i = 0;i < delta; i++) {
-                monitor_printf(rs->mon, "\033[D");
+                rs->printf_func(rs->opaque, "\033[D");
             }
         }
         rs->last_cmd_buf_index = rs->cmd_buf_index;
     }
-    monitor_flush(rs->mon);
+    rs->flush_func(rs->opaque);
 }
 
 static void readline_insert_char(ReadLineState *rs, int ch)
@@ -284,7 +282,7 @@ static void readline_completion(ReadLineState *rs)
     cmdline = g_malloc(rs->cmd_buf_index + 1);
     memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);
     cmdline[rs->cmd_buf_index] = '\0';
-    rs->completion_finder(rs->mon, cmdline);
+    rs->completion_finder(rs->opaque, cmdline);
     g_free(cmdline);
 
     /* no completion found */
@@ -299,7 +297,7 @@ static void readline_completion(ReadLineState *rs)
         if (len > 0 && rs->completions[0][len - 1] != '/')
             readline_insert_char(rs, ' ');
     } else {
-        monitor_printf(rs->mon, "\n");
+        rs->printf_func(rs->opaque, "\n");
         max_width = 0;
         max_prefix = 0;	
         for(i = 0; i < rs->nb_completions; i++) {
@@ -329,9 +327,9 @@ static void readline_completion(ReadLineState *rs)
         nb_cols = 80 / max_width;
         j = 0;
         for(i = 0; i < rs->nb_completions; i++) {
-            monitor_printf(rs->mon, "%-*s", max_width, rs->completions[i]);
+            rs->printf_func(rs->opaque, "%-*s", max_width, rs->completions[i]);
             if (++j == nb_cols || i == (rs->nb_completions - 1)) {
-                monitor_printf(rs->mon, "\n");
+                rs->printf_func(rs->opaque, "\n");
                 j = 0;
             }
         }
@@ -365,12 +363,12 @@ void readline_handle_byte(ReadLineState *rs, int ch)
             rs->cmd_buf[rs->cmd_buf_size] = '\0';
             if (!rs->read_password)
                 readline_hist_add(rs, rs->cmd_buf);
-            monitor_printf(rs->mon, "\n");
+            rs->printf_func(rs->opaque, "\n");
             rs->cmd_buf_index = 0;
             rs->cmd_buf_size = 0;
             rs->last_cmd_buf_index = 0;
             rs->last_cmd_buf_size = 0;
-            rs->readline_func(rs->mon, rs->cmd_buf, rs->readline_opaque);
+            rs->readline_func(rs->opaque, rs->cmd_buf, rs->readline_opaque);
             break;
         case 23:
             /* ^W */
@@ -480,13 +478,17 @@ const char *readline_get_history(ReadLineState *rs, unsigned int index)
     return rs->history[index];
 }
 
-ReadLineState *readline_init(Monitor *mon,
+ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
+                             ReadLineFlushFunc *flush_func,
+                             void *opaque,
                              ReadLineCompletionFunc *completion_finder)
 {
     ReadLineState *rs = g_malloc0(sizeof(*rs));
 
     rs->hist_entry = -1;
-    rs->mon = mon;
+    rs->opaque = opaque;
+    rs->printf_func = printf_func;
+    rs->flush_func = flush_func;
     rs->completion_finder = completion_finder;
 
     return rs;
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 14/42] readline: move readline to a generic location
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (12 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 13/42] readline: decouple readline from the monitor Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 15/42] osdep: add qemu_set_tty_echo() Kevin Wolf
                   ` (27 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Now that the monitor and readline are decoupled, readline.h no longer
belongs in include/monitor/.  Put the header into include/qemu/.

Move the source file into util/ so it can be linked as part of
libqemuutil.a.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 Makefile.objs              |   1 -
 include/monitor/monitor.h  |   2 +-
 include/monitor/readline.h |  62 ------
 include/qemu/readline.h    |  62 ++++++
 monitor.c                  |   2 +-
 readline.c                 | 495 ---------------------------------------------
 util/Makefile.objs         |   1 +
 util/readline.c            | 495 +++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 560 insertions(+), 560 deletions(-)
 delete mode 100644 include/monitor/readline.h
 create mode 100644 include/qemu/readline.h
 delete mode 100644 readline.c
 create mode 100644 util/readline.c

diff --git a/Makefile.objs b/Makefile.objs
index 857bb53..ac1d0e1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -43,7 +43,6 @@ libcacard-y += libcacard/vcardt.o
 ifeq ($(CONFIG_SOFTMMU),y)
 common-obj-y = $(block-obj-y) blockdev.o blockdev-nbd.o block/
 common-obj-y += net/
-common-obj-y += readline.o
 common-obj-y += qdev-monitor.o device-hotplug.o
 common-obj-$(CONFIG_WIN32) += os-win32.o
 common-obj-$(CONFIG_POSIX) += os-posix.o
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 22d8b8f..7e5f752 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -5,7 +5,7 @@
 #include "qapi/qmp/qerror.h"
 #include "qapi/qmp/qdict.h"
 #include "block/block.h"
-#include "monitor/readline.h"
+#include "qemu/readline.h"
 
 extern Monitor *cur_mon;
 extern Monitor *default_mon;
diff --git a/include/monitor/readline.h b/include/monitor/readline.h
deleted file mode 100644
index a89fe4a..0000000
--- a/include/monitor/readline.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef READLINE_H
-#define READLINE_H
-
-#define READLINE_CMD_BUF_SIZE 4095
-#define READLINE_MAX_CMDS 64
-#define READLINE_MAX_COMPLETIONS 256
-
-typedef void ReadLinePrintfFunc(void *opaque, const char *fmt, ...);
-typedef void ReadLineFlushFunc(void *opaque);
-typedef void ReadLineFunc(void *opaque, const char *str,
-                          void *readline_opaque);
-typedef void ReadLineCompletionFunc(void *opaque,
-                                    const char *cmdline);
-
-typedef struct ReadLineState {
-    char cmd_buf[READLINE_CMD_BUF_SIZE + 1];
-    int cmd_buf_index;
-    int cmd_buf_size;
-
-    char last_cmd_buf[READLINE_CMD_BUF_SIZE + 1];
-    int last_cmd_buf_index;
-    int last_cmd_buf_size;
-
-    int esc_state;
-    int esc_param;
-
-    char *history[READLINE_MAX_CMDS];
-    int hist_entry;
-
-    ReadLineCompletionFunc *completion_finder;
-    char *completions[READLINE_MAX_COMPLETIONS];
-    int nb_completions;
-    int completion_index;
-
-    ReadLineFunc *readline_func;
-    void *readline_opaque;
-    int read_password;
-    char prompt[256];
-
-    ReadLinePrintfFunc *printf_func;
-    ReadLineFlushFunc *flush_func;
-    void *opaque;
-} ReadLineState;
-
-void readline_add_completion(ReadLineState *rs, const char *str);
-void readline_set_completion_index(ReadLineState *rs, int completion_index);
-
-const char *readline_get_history(ReadLineState *rs, unsigned int index);
-
-void readline_handle_byte(ReadLineState *rs, int ch);
-
-void readline_start(ReadLineState *rs, const char *prompt, int read_password,
-                    ReadLineFunc *readline_func, void *readline_opaque);
-void readline_restart(ReadLineState *rs);
-void readline_show_prompt(ReadLineState *rs);
-
-ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
-                             ReadLineFlushFunc *flush_func,
-                             void *opaque,
-                             ReadLineCompletionFunc *completion_finder);
-
-#endif /* !READLINE_H */
diff --git a/include/qemu/readline.h b/include/qemu/readline.h
new file mode 100644
index 0000000..a89fe4a
--- /dev/null
+++ b/include/qemu/readline.h
@@ -0,0 +1,62 @@
+#ifndef READLINE_H
+#define READLINE_H
+
+#define READLINE_CMD_BUF_SIZE 4095
+#define READLINE_MAX_CMDS 64
+#define READLINE_MAX_COMPLETIONS 256
+
+typedef void ReadLinePrintfFunc(void *opaque, const char *fmt, ...);
+typedef void ReadLineFlushFunc(void *opaque);
+typedef void ReadLineFunc(void *opaque, const char *str,
+                          void *readline_opaque);
+typedef void ReadLineCompletionFunc(void *opaque,
+                                    const char *cmdline);
+
+typedef struct ReadLineState {
+    char cmd_buf[READLINE_CMD_BUF_SIZE + 1];
+    int cmd_buf_index;
+    int cmd_buf_size;
+
+    char last_cmd_buf[READLINE_CMD_BUF_SIZE + 1];
+    int last_cmd_buf_index;
+    int last_cmd_buf_size;
+
+    int esc_state;
+    int esc_param;
+
+    char *history[READLINE_MAX_CMDS];
+    int hist_entry;
+
+    ReadLineCompletionFunc *completion_finder;
+    char *completions[READLINE_MAX_COMPLETIONS];
+    int nb_completions;
+    int completion_index;
+
+    ReadLineFunc *readline_func;
+    void *readline_opaque;
+    int read_password;
+    char prompt[256];
+
+    ReadLinePrintfFunc *printf_func;
+    ReadLineFlushFunc *flush_func;
+    void *opaque;
+} ReadLineState;
+
+void readline_add_completion(ReadLineState *rs, const char *str);
+void readline_set_completion_index(ReadLineState *rs, int completion_index);
+
+const char *readline_get_history(ReadLineState *rs, unsigned int index);
+
+void readline_handle_byte(ReadLineState *rs, int ch);
+
+void readline_start(ReadLineState *rs, const char *prompt, int read_password,
+                    ReadLineFunc *readline_func, void *readline_opaque);
+void readline_restart(ReadLineState *rs);
+void readline_show_prompt(ReadLineState *rs);
+
+ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
+                             ReadLineFlushFunc *flush_func,
+                             void *opaque,
+                             ReadLineCompletionFunc *completion_finder);
+
+#endif /* !READLINE_H */
diff --git a/monitor.c b/monitor.c
index 32d0264..80456fb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -37,7 +37,7 @@
 #include "ui/qemu-spice.h"
 #include "sysemu/sysemu.h"
 #include "monitor/monitor.h"
-#include "monitor/readline.h"
+#include "qemu/readline.h"
 #include "ui/console.h"
 #include "sysemu/blockdev.h"
 #include "audio/audio.h"
diff --git a/readline.c b/readline.c
deleted file mode 100644
index ca894d1..0000000
--- a/readline.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * QEMU readline utility
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "qemu-common.h"
-#include "monitor/readline.h"
-
-#define IS_NORM 0
-#define IS_ESC  1
-#define IS_CSI  2
-#define IS_SS3  3
-
-void readline_show_prompt(ReadLineState *rs)
-{
-    rs->printf_func(rs->opaque, "%s", rs->prompt);
-    rs->flush_func(rs->opaque);
-    rs->last_cmd_buf_index = 0;
-    rs->last_cmd_buf_size = 0;
-    rs->esc_state = IS_NORM;
-}
-
-/* update the displayed command line */
-static void readline_update(ReadLineState *rs)
-{
-    int i, delta, len;
-
-    if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
-        memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
-        for(i = 0; i < rs->last_cmd_buf_index; i++) {
-            rs->printf_func(rs->opaque, "\033[D");
-        }
-        rs->cmd_buf[rs->cmd_buf_size] = '\0';
-        if (rs->read_password) {
-            len = strlen(rs->cmd_buf);
-            for(i = 0; i < len; i++)
-                rs->printf_func(rs->opaque, "*");
-        } else {
-            rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
-        }
-        rs->printf_func(rs->opaque, "\033[K");
-        memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
-        rs->last_cmd_buf_size = rs->cmd_buf_size;
-        rs->last_cmd_buf_index = rs->cmd_buf_size;
-    }
-    if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
-        delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
-        if (delta > 0) {
-            for(i = 0;i < delta; i++) {
-                rs->printf_func(rs->opaque, "\033[C");
-            }
-        } else {
-            delta = -delta;
-            for(i = 0;i < delta; i++) {
-                rs->printf_func(rs->opaque, "\033[D");
-            }
-        }
-        rs->last_cmd_buf_index = rs->cmd_buf_index;
-    }
-    rs->flush_func(rs->opaque);
-}
-
-static void readline_insert_char(ReadLineState *rs, int ch)
-{
-    if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
-        memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
-                rs->cmd_buf + rs->cmd_buf_index,
-                rs->cmd_buf_size - rs->cmd_buf_index);
-        rs->cmd_buf[rs->cmd_buf_index] = ch;
-        rs->cmd_buf_size++;
-        rs->cmd_buf_index++;
-    }
-}
-
-static void readline_backward_char(ReadLineState *rs)
-{
-    if (rs->cmd_buf_index > 0) {
-        rs->cmd_buf_index--;
-    }
-}
-
-static void readline_forward_char(ReadLineState *rs)
-{
-    if (rs->cmd_buf_index < rs->cmd_buf_size) {
-        rs->cmd_buf_index++;
-    }
-}
-
-static void readline_delete_char(ReadLineState *rs)
-{
-    if (rs->cmd_buf_index < rs->cmd_buf_size) {
-        memmove(rs->cmd_buf + rs->cmd_buf_index,
-                rs->cmd_buf + rs->cmd_buf_index + 1,
-                rs->cmd_buf_size - rs->cmd_buf_index - 1);
-        rs->cmd_buf_size--;
-    }
-}
-
-static void readline_backspace(ReadLineState *rs)
-{
-    if (rs->cmd_buf_index > 0) {
-        readline_backward_char(rs);
-        readline_delete_char(rs);
-    }
-}
-
-static void readline_backword(ReadLineState *rs)
-{
-    int start;
-
-    if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
-        return;
-    }
-
-    start = rs->cmd_buf_index - 1;
-
-    /* find first word (backwards) */
-    while (start > 0) {
-        if (!qemu_isspace(rs->cmd_buf[start])) {
-            break;
-        }
-
-        --start;
-    }
-
-    /* find first space (backwards) */
-    while (start > 0) {
-        if (qemu_isspace(rs->cmd_buf[start])) {
-            ++start;
-            break;
-        }
-
-        --start;
-    }
-
-    /* remove word */
-    if (start < rs->cmd_buf_index) {
-        memmove(rs->cmd_buf + start,
-                rs->cmd_buf + rs->cmd_buf_index,
-                rs->cmd_buf_size - rs->cmd_buf_index);
-        rs->cmd_buf_size -= rs->cmd_buf_index - start;
-        rs->cmd_buf_index = start;
-    }
-}
-
-static void readline_bol(ReadLineState *rs)
-{
-    rs->cmd_buf_index = 0;
-}
-
-static void readline_eol(ReadLineState *rs)
-{
-    rs->cmd_buf_index = rs->cmd_buf_size;
-}
-
-static void readline_up_char(ReadLineState *rs)
-{
-    int idx;
-
-    if (rs->hist_entry == 0)
-	return;
-    if (rs->hist_entry == -1) {
-	/* Find latest entry */
-	for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
-	    if (rs->history[idx] == NULL)
-		break;
-	}
-	rs->hist_entry = idx;
-    }
-    rs->hist_entry--;
-    if (rs->hist_entry >= 0) {
-	pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
-                rs->history[rs->hist_entry]);
-	rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
-    }
-}
-
-static void readline_down_char(ReadLineState *rs)
-{
-    if (rs->hist_entry == -1)
-        return;
-    if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
-        rs->history[++rs->hist_entry] != NULL) {
-	pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
-                rs->history[rs->hist_entry]);
-    } else {
-        rs->cmd_buf[0] = 0;
-	rs->hist_entry = -1;
-    }
-    rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
-}
-
-static void readline_hist_add(ReadLineState *rs, const char *cmdline)
-{
-    char *hist_entry, *new_entry;
-    int idx;
-
-    if (cmdline[0] == '\0')
-	return;
-    new_entry = NULL;
-    if (rs->hist_entry != -1) {
-	/* We were editing an existing history entry: replace it */
-	hist_entry = rs->history[rs->hist_entry];
-	idx = rs->hist_entry;
-	if (strcmp(hist_entry, cmdline) == 0) {
-	    goto same_entry;
-	}
-    }
-    /* Search cmdline in history buffers */
-    for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
-	hist_entry = rs->history[idx];
-	if (hist_entry == NULL)
-	    break;
-	if (strcmp(hist_entry, cmdline) == 0) {
-	same_entry:
-	    new_entry = hist_entry;
-	    /* Put this entry at the end of history */
-	    memmove(&rs->history[idx], &rs->history[idx + 1],
-		    (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
-	    rs->history[READLINE_MAX_CMDS - 1] = NULL;
-	    for (; idx < READLINE_MAX_CMDS; idx++) {
-		if (rs->history[idx] == NULL)
-		    break;
-	    }
-	    break;
-	}
-    }
-    if (idx == READLINE_MAX_CMDS) {
-	/* Need to get one free slot */
-        g_free(rs->history[0]);
-	memmove(rs->history, &rs->history[1],
-	        (READLINE_MAX_CMDS - 1) * sizeof(char *));
-	rs->history[READLINE_MAX_CMDS - 1] = NULL;
-	idx = READLINE_MAX_CMDS - 1;
-    }
-    if (new_entry == NULL)
-        new_entry = g_strdup(cmdline);
-    rs->history[idx] = new_entry;
-    rs->hist_entry = -1;
-}
-
-/* completion support */
-
-void readline_add_completion(ReadLineState *rs, const char *str)
-{
-    if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
-        rs->completions[rs->nb_completions++] = g_strdup(str);
-    }
-}
-
-void readline_set_completion_index(ReadLineState *rs, int index)
-{
-    rs->completion_index = index;
-}
-
-static void readline_completion(ReadLineState *rs)
-{
-    int len, i, j, max_width, nb_cols, max_prefix;
-    char *cmdline;
-
-    rs->nb_completions = 0;
-
-    cmdline = g_malloc(rs->cmd_buf_index + 1);
-    memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);
-    cmdline[rs->cmd_buf_index] = '\0';
-    rs->completion_finder(rs->opaque, cmdline);
-    g_free(cmdline);
-
-    /* no completion found */
-    if (rs->nb_completions <= 0)
-        return;
-    if (rs->nb_completions == 1) {
-        len = strlen(rs->completions[0]);
-        for(i = rs->completion_index; i < len; i++) {
-            readline_insert_char(rs, rs->completions[0][i]);
-        }
-        /* extra space for next argument. XXX: make it more generic */
-        if (len > 0 && rs->completions[0][len - 1] != '/')
-            readline_insert_char(rs, ' ');
-    } else {
-        rs->printf_func(rs->opaque, "\n");
-        max_width = 0;
-        max_prefix = 0;	
-        for(i = 0; i < rs->nb_completions; i++) {
-            len = strlen(rs->completions[i]);
-            if (i==0) {
-                max_prefix = len;
-            } else {
-                if (len < max_prefix)
-                    max_prefix = len;
-                for(j=0; j<max_prefix; j++) {
-                    if (rs->completions[i][j] != rs->completions[0][j])
-                        max_prefix = j;
-                }
-            }
-            if (len > max_width)
-                max_width = len;
-        }
-        if (max_prefix > 0) 
-            for(i = rs->completion_index; i < max_prefix; i++) {
-                readline_insert_char(rs, rs->completions[0][i]);
-            }
-        max_width += 2;
-        if (max_width < 10)
-            max_width = 10;
-        else if (max_width > 80)
-            max_width = 80;
-        nb_cols = 80 / max_width;
-        j = 0;
-        for(i = 0; i < rs->nb_completions; i++) {
-            rs->printf_func(rs->opaque, "%-*s", max_width, rs->completions[i]);
-            if (++j == nb_cols || i == (rs->nb_completions - 1)) {
-                rs->printf_func(rs->opaque, "\n");
-                j = 0;
-            }
-        }
-        readline_show_prompt(rs);
-    }
-    for (i = 0; i < rs->nb_completions; i++) {
-        g_free(rs->completions[i]);
-    }
-}
-
-/* return true if command handled */
-void readline_handle_byte(ReadLineState *rs, int ch)
-{
-    switch(rs->esc_state) {
-    case IS_NORM:
-        switch(ch) {
-        case 1:
-            readline_bol(rs);
-            break;
-        case 4:
-            readline_delete_char(rs);
-            break;
-        case 5:
-            readline_eol(rs);
-            break;
-        case 9:
-            readline_completion(rs);
-            break;
-        case 10:
-        case 13:
-            rs->cmd_buf[rs->cmd_buf_size] = '\0';
-            if (!rs->read_password)
-                readline_hist_add(rs, rs->cmd_buf);
-            rs->printf_func(rs->opaque, "\n");
-            rs->cmd_buf_index = 0;
-            rs->cmd_buf_size = 0;
-            rs->last_cmd_buf_index = 0;
-            rs->last_cmd_buf_size = 0;
-            rs->readline_func(rs->opaque, rs->cmd_buf, rs->readline_opaque);
-            break;
-        case 23:
-            /* ^W */
-            readline_backword(rs);
-            break;
-        case 27:
-            rs->esc_state = IS_ESC;
-            break;
-        case 127:
-        case 8:
-            readline_backspace(rs);
-            break;
-	case 155:
-            rs->esc_state = IS_CSI;
-	    break;
-        default:
-            if (ch >= 32) {
-                readline_insert_char(rs, ch);
-            }
-            break;
-        }
-        break;
-    case IS_ESC:
-        if (ch == '[') {
-            rs->esc_state = IS_CSI;
-            rs->esc_param = 0;
-        } else if (ch == 'O') {
-            rs->esc_state = IS_SS3;
-            rs->esc_param = 0;
-        } else {
-            rs->esc_state = IS_NORM;
-        }
-        break;
-    case IS_CSI:
-        switch(ch) {
-	case 'A':
-	case 'F':
-	    readline_up_char(rs);
-	    break;
-	case 'B':
-	case 'E':
-	    readline_down_char(rs);
-	    break;
-        case 'D':
-            readline_backward_char(rs);
-            break;
-        case 'C':
-            readline_forward_char(rs);
-            break;
-        case '0' ... '9':
-            rs->esc_param = rs->esc_param * 10 + (ch - '0');
-            goto the_end;
-        case '~':
-            switch(rs->esc_param) {
-            case 1:
-                readline_bol(rs);
-                break;
-            case 3:
-                readline_delete_char(rs);
-                break;
-            case 4:
-                readline_eol(rs);
-                break;
-            }
-            break;
-        default:
-            break;
-        }
-        rs->esc_state = IS_NORM;
-    the_end:
-        break;
-    case IS_SS3:
-        switch(ch) {
-        case 'F':
-            readline_eol(rs);
-            break;
-        case 'H':
-            readline_bol(rs);
-            break;
-        }
-        rs->esc_state = IS_NORM;
-        break;
-    }
-    readline_update(rs);
-}
-
-void readline_start(ReadLineState *rs, const char *prompt, int read_password,
-                    ReadLineFunc *readline_func, void *opaque)
-{
-    pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
-    rs->readline_func = readline_func;
-    rs->readline_opaque = opaque;
-    rs->read_password = read_password;
-    readline_restart(rs);
-}
-
-void readline_restart(ReadLineState *rs)
-{
-    rs->cmd_buf_index = 0;
-    rs->cmd_buf_size = 0;
-}
-
-const char *readline_get_history(ReadLineState *rs, unsigned int index)
-{
-    if (index >= READLINE_MAX_CMDS)
-        return NULL;
-    return rs->history[index];
-}
-
-ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
-                             ReadLineFlushFunc *flush_func,
-                             void *opaque,
-                             ReadLineCompletionFunc *completion_finder)
-{
-    ReadLineState *rs = g_malloc0(sizeof(*rs));
-
-    rs->hist_entry = -1;
-    rs->opaque = opaque;
-    rs->printf_func = printf_func;
-    rs->flush_func = flush_func;
-    rs->completion_finder = completion_finder;
-
-    return rs;
-}
diff --git a/util/Makefile.objs b/util/Makefile.objs
index af3e5cb..937376b 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -13,3 +13,4 @@ util-obj-y += hexdump.o
 util-obj-y += crc32c.o
 util-obj-y += throttle.o
 util-obj-y += getauxval.o
+util-obj-y += readline.o
diff --git a/util/readline.c b/util/readline.c
new file mode 100644
index 0000000..8441be4
--- /dev/null
+++ b/util/readline.c
@@ -0,0 +1,495 @@
+/*
+ * QEMU readline utility
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu-common.h"
+#include "qemu/readline.h"
+
+#define IS_NORM 0
+#define IS_ESC  1
+#define IS_CSI  2
+#define IS_SS3  3
+
+void readline_show_prompt(ReadLineState *rs)
+{
+    rs->printf_func(rs->opaque, "%s", rs->prompt);
+    rs->flush_func(rs->opaque);
+    rs->last_cmd_buf_index = 0;
+    rs->last_cmd_buf_size = 0;
+    rs->esc_state = IS_NORM;
+}
+
+/* update the displayed command line */
+static void readline_update(ReadLineState *rs)
+{
+    int i, delta, len;
+
+    if (rs->cmd_buf_size != rs->last_cmd_buf_size ||
+        memcmp(rs->cmd_buf, rs->last_cmd_buf, rs->cmd_buf_size) != 0) {
+        for(i = 0; i < rs->last_cmd_buf_index; i++) {
+            rs->printf_func(rs->opaque, "\033[D");
+        }
+        rs->cmd_buf[rs->cmd_buf_size] = '\0';
+        if (rs->read_password) {
+            len = strlen(rs->cmd_buf);
+            for(i = 0; i < len; i++)
+                rs->printf_func(rs->opaque, "*");
+        } else {
+            rs->printf_func(rs->opaque, "%s", rs->cmd_buf);
+        }
+        rs->printf_func(rs->opaque, "\033[K");
+        memcpy(rs->last_cmd_buf, rs->cmd_buf, rs->cmd_buf_size);
+        rs->last_cmd_buf_size = rs->cmd_buf_size;
+        rs->last_cmd_buf_index = rs->cmd_buf_size;
+    }
+    if (rs->cmd_buf_index != rs->last_cmd_buf_index) {
+        delta = rs->cmd_buf_index - rs->last_cmd_buf_index;
+        if (delta > 0) {
+            for(i = 0;i < delta; i++) {
+                rs->printf_func(rs->opaque, "\033[C");
+            }
+        } else {
+            delta = -delta;
+            for(i = 0;i < delta; i++) {
+                rs->printf_func(rs->opaque, "\033[D");
+            }
+        }
+        rs->last_cmd_buf_index = rs->cmd_buf_index;
+    }
+    rs->flush_func(rs->opaque);
+}
+
+static void readline_insert_char(ReadLineState *rs, int ch)
+{
+    if (rs->cmd_buf_index < READLINE_CMD_BUF_SIZE) {
+        memmove(rs->cmd_buf + rs->cmd_buf_index + 1,
+                rs->cmd_buf + rs->cmd_buf_index,
+                rs->cmd_buf_size - rs->cmd_buf_index);
+        rs->cmd_buf[rs->cmd_buf_index] = ch;
+        rs->cmd_buf_size++;
+        rs->cmd_buf_index++;
+    }
+}
+
+static void readline_backward_char(ReadLineState *rs)
+{
+    if (rs->cmd_buf_index > 0) {
+        rs->cmd_buf_index--;
+    }
+}
+
+static void readline_forward_char(ReadLineState *rs)
+{
+    if (rs->cmd_buf_index < rs->cmd_buf_size) {
+        rs->cmd_buf_index++;
+    }
+}
+
+static void readline_delete_char(ReadLineState *rs)
+{
+    if (rs->cmd_buf_index < rs->cmd_buf_size) {
+        memmove(rs->cmd_buf + rs->cmd_buf_index,
+                rs->cmd_buf + rs->cmd_buf_index + 1,
+                rs->cmd_buf_size - rs->cmd_buf_index - 1);
+        rs->cmd_buf_size--;
+    }
+}
+
+static void readline_backspace(ReadLineState *rs)
+{
+    if (rs->cmd_buf_index > 0) {
+        readline_backward_char(rs);
+        readline_delete_char(rs);
+    }
+}
+
+static void readline_backword(ReadLineState *rs)
+{
+    int start;
+
+    if (rs->cmd_buf_index == 0 || rs->cmd_buf_index > rs->cmd_buf_size) {
+        return;
+    }
+
+    start = rs->cmd_buf_index - 1;
+
+    /* find first word (backwards) */
+    while (start > 0) {
+        if (!qemu_isspace(rs->cmd_buf[start])) {
+            break;
+        }
+
+        --start;
+    }
+
+    /* find first space (backwards) */
+    while (start > 0) {
+        if (qemu_isspace(rs->cmd_buf[start])) {
+            ++start;
+            break;
+        }
+
+        --start;
+    }
+
+    /* remove word */
+    if (start < rs->cmd_buf_index) {
+        memmove(rs->cmd_buf + start,
+                rs->cmd_buf + rs->cmd_buf_index,
+                rs->cmd_buf_size - rs->cmd_buf_index);
+        rs->cmd_buf_size -= rs->cmd_buf_index - start;
+        rs->cmd_buf_index = start;
+    }
+}
+
+static void readline_bol(ReadLineState *rs)
+{
+    rs->cmd_buf_index = 0;
+}
+
+static void readline_eol(ReadLineState *rs)
+{
+    rs->cmd_buf_index = rs->cmd_buf_size;
+}
+
+static void readline_up_char(ReadLineState *rs)
+{
+    int idx;
+
+    if (rs->hist_entry == 0)
+	return;
+    if (rs->hist_entry == -1) {
+	/* Find latest entry */
+	for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
+	    if (rs->history[idx] == NULL)
+		break;
+	}
+	rs->hist_entry = idx;
+    }
+    rs->hist_entry--;
+    if (rs->hist_entry >= 0) {
+	pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
+                rs->history[rs->hist_entry]);
+	rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
+    }
+}
+
+static void readline_down_char(ReadLineState *rs)
+{
+    if (rs->hist_entry == -1)
+        return;
+    if (rs->hist_entry < READLINE_MAX_CMDS - 1 &&
+        rs->history[++rs->hist_entry] != NULL) {
+	pstrcpy(rs->cmd_buf, sizeof(rs->cmd_buf),
+                rs->history[rs->hist_entry]);
+    } else {
+        rs->cmd_buf[0] = 0;
+	rs->hist_entry = -1;
+    }
+    rs->cmd_buf_index = rs->cmd_buf_size = strlen(rs->cmd_buf);
+}
+
+static void readline_hist_add(ReadLineState *rs, const char *cmdline)
+{
+    char *hist_entry, *new_entry;
+    int idx;
+
+    if (cmdline[0] == '\0')
+	return;
+    new_entry = NULL;
+    if (rs->hist_entry != -1) {
+	/* We were editing an existing history entry: replace it */
+	hist_entry = rs->history[rs->hist_entry];
+	idx = rs->hist_entry;
+	if (strcmp(hist_entry, cmdline) == 0) {
+	    goto same_entry;
+	}
+    }
+    /* Search cmdline in history buffers */
+    for (idx = 0; idx < READLINE_MAX_CMDS; idx++) {
+	hist_entry = rs->history[idx];
+	if (hist_entry == NULL)
+	    break;
+	if (strcmp(hist_entry, cmdline) == 0) {
+	same_entry:
+	    new_entry = hist_entry;
+	    /* Put this entry at the end of history */
+	    memmove(&rs->history[idx], &rs->history[idx + 1],
+		    (READLINE_MAX_CMDS - (idx + 1)) * sizeof(char *));
+	    rs->history[READLINE_MAX_CMDS - 1] = NULL;
+	    for (; idx < READLINE_MAX_CMDS; idx++) {
+		if (rs->history[idx] == NULL)
+		    break;
+	    }
+	    break;
+	}
+    }
+    if (idx == READLINE_MAX_CMDS) {
+	/* Need to get one free slot */
+        g_free(rs->history[0]);
+	memmove(rs->history, &rs->history[1],
+	        (READLINE_MAX_CMDS - 1) * sizeof(char *));
+	rs->history[READLINE_MAX_CMDS - 1] = NULL;
+	idx = READLINE_MAX_CMDS - 1;
+    }
+    if (new_entry == NULL)
+        new_entry = g_strdup(cmdline);
+    rs->history[idx] = new_entry;
+    rs->hist_entry = -1;
+}
+
+/* completion support */
+
+void readline_add_completion(ReadLineState *rs, const char *str)
+{
+    if (rs->nb_completions < READLINE_MAX_COMPLETIONS) {
+        rs->completions[rs->nb_completions++] = g_strdup(str);
+    }
+}
+
+void readline_set_completion_index(ReadLineState *rs, int index)
+{
+    rs->completion_index = index;
+}
+
+static void readline_completion(ReadLineState *rs)
+{
+    int len, i, j, max_width, nb_cols, max_prefix;
+    char *cmdline;
+
+    rs->nb_completions = 0;
+
+    cmdline = g_malloc(rs->cmd_buf_index + 1);
+    memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index);
+    cmdline[rs->cmd_buf_index] = '\0';
+    rs->completion_finder(rs->opaque, cmdline);
+    g_free(cmdline);
+
+    /* no completion found */
+    if (rs->nb_completions <= 0)
+        return;
+    if (rs->nb_completions == 1) {
+        len = strlen(rs->completions[0]);
+        for(i = rs->completion_index; i < len; i++) {
+            readline_insert_char(rs, rs->completions[0][i]);
+        }
+        /* extra space for next argument. XXX: make it more generic */
+        if (len > 0 && rs->completions[0][len - 1] != '/')
+            readline_insert_char(rs, ' ');
+    } else {
+        rs->printf_func(rs->opaque, "\n");
+        max_width = 0;
+        max_prefix = 0;	
+        for(i = 0; i < rs->nb_completions; i++) {
+            len = strlen(rs->completions[i]);
+            if (i==0) {
+                max_prefix = len;
+            } else {
+                if (len < max_prefix)
+                    max_prefix = len;
+                for(j=0; j<max_prefix; j++) {
+                    if (rs->completions[i][j] != rs->completions[0][j])
+                        max_prefix = j;
+                }
+            }
+            if (len > max_width)
+                max_width = len;
+        }
+        if (max_prefix > 0) 
+            for(i = rs->completion_index; i < max_prefix; i++) {
+                readline_insert_char(rs, rs->completions[0][i]);
+            }
+        max_width += 2;
+        if (max_width < 10)
+            max_width = 10;
+        else if (max_width > 80)
+            max_width = 80;
+        nb_cols = 80 / max_width;
+        j = 0;
+        for(i = 0; i < rs->nb_completions; i++) {
+            rs->printf_func(rs->opaque, "%-*s", max_width, rs->completions[i]);
+            if (++j == nb_cols || i == (rs->nb_completions - 1)) {
+                rs->printf_func(rs->opaque, "\n");
+                j = 0;
+            }
+        }
+        readline_show_prompt(rs);
+    }
+    for (i = 0; i < rs->nb_completions; i++) {
+        g_free(rs->completions[i]);
+    }
+}
+
+/* return true if command handled */
+void readline_handle_byte(ReadLineState *rs, int ch)
+{
+    switch(rs->esc_state) {
+    case IS_NORM:
+        switch(ch) {
+        case 1:
+            readline_bol(rs);
+            break;
+        case 4:
+            readline_delete_char(rs);
+            break;
+        case 5:
+            readline_eol(rs);
+            break;
+        case 9:
+            readline_completion(rs);
+            break;
+        case 10:
+        case 13:
+            rs->cmd_buf[rs->cmd_buf_size] = '\0';
+            if (!rs->read_password)
+                readline_hist_add(rs, rs->cmd_buf);
+            rs->printf_func(rs->opaque, "\n");
+            rs->cmd_buf_index = 0;
+            rs->cmd_buf_size = 0;
+            rs->last_cmd_buf_index = 0;
+            rs->last_cmd_buf_size = 0;
+            rs->readline_func(rs->opaque, rs->cmd_buf, rs->readline_opaque);
+            break;
+        case 23:
+            /* ^W */
+            readline_backword(rs);
+            break;
+        case 27:
+            rs->esc_state = IS_ESC;
+            break;
+        case 127:
+        case 8:
+            readline_backspace(rs);
+            break;
+	case 155:
+            rs->esc_state = IS_CSI;
+	    break;
+        default:
+            if (ch >= 32) {
+                readline_insert_char(rs, ch);
+            }
+            break;
+        }
+        break;
+    case IS_ESC:
+        if (ch == '[') {
+            rs->esc_state = IS_CSI;
+            rs->esc_param = 0;
+        } else if (ch == 'O') {
+            rs->esc_state = IS_SS3;
+            rs->esc_param = 0;
+        } else {
+            rs->esc_state = IS_NORM;
+        }
+        break;
+    case IS_CSI:
+        switch(ch) {
+	case 'A':
+	case 'F':
+	    readline_up_char(rs);
+	    break;
+	case 'B':
+	case 'E':
+	    readline_down_char(rs);
+	    break;
+        case 'D':
+            readline_backward_char(rs);
+            break;
+        case 'C':
+            readline_forward_char(rs);
+            break;
+        case '0' ... '9':
+            rs->esc_param = rs->esc_param * 10 + (ch - '0');
+            goto the_end;
+        case '~':
+            switch(rs->esc_param) {
+            case 1:
+                readline_bol(rs);
+                break;
+            case 3:
+                readline_delete_char(rs);
+                break;
+            case 4:
+                readline_eol(rs);
+                break;
+            }
+            break;
+        default:
+            break;
+        }
+        rs->esc_state = IS_NORM;
+    the_end:
+        break;
+    case IS_SS3:
+        switch(ch) {
+        case 'F':
+            readline_eol(rs);
+            break;
+        case 'H':
+            readline_bol(rs);
+            break;
+        }
+        rs->esc_state = IS_NORM;
+        break;
+    }
+    readline_update(rs);
+}
+
+void readline_start(ReadLineState *rs, const char *prompt, int read_password,
+                    ReadLineFunc *readline_func, void *opaque)
+{
+    pstrcpy(rs->prompt, sizeof(rs->prompt), prompt);
+    rs->readline_func = readline_func;
+    rs->readline_opaque = opaque;
+    rs->read_password = read_password;
+    readline_restart(rs);
+}
+
+void readline_restart(ReadLineState *rs)
+{
+    rs->cmd_buf_index = 0;
+    rs->cmd_buf_size = 0;
+}
+
+const char *readline_get_history(ReadLineState *rs, unsigned int index)
+{
+    if (index >= READLINE_MAX_CMDS)
+        return NULL;
+    return rs->history[index];
+}
+
+ReadLineState *readline_init(ReadLinePrintfFunc *printf_func,
+                             ReadLineFlushFunc *flush_func,
+                             void *opaque,
+                             ReadLineCompletionFunc *completion_finder)
+{
+    ReadLineState *rs = g_malloc0(sizeof(*rs));
+
+    rs->hist_entry = -1;
+    rs->opaque = opaque;
+    rs->printf_func = printf_func;
+    rs->flush_func = flush_func;
+    rs->completion_finder = completion_finder;
+
+    return rs;
+}
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 15/42] osdep: add qemu_set_tty_echo()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (13 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 14/42] readline: move readline to a generic location Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 16/42] qemu-io: use readline.c Kevin Wolf
                   ` (26 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Using stdin with readline.c requires disabling echo and line buffering.
Add a portable wrapper to set the terminal attributes under Linux and
Windows.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/qemu/osdep.h |  2 ++
 util/oslib-posix.c   | 18 ++++++++++++++++++
 util/oslib-win32.c   | 19 +++++++++++++++++++
 3 files changed, 39 insertions(+)

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index b3e2b6d..eac7172 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -240,4 +240,6 @@ static inline void qemu_init_auxval(char **envp) { }
 void qemu_init_auxval(char **envp);
 #endif
 
+void qemu_set_tty_echo(int fd, bool echo);
+
 #endif
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index e00a44c..f5c4016 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -47,6 +47,9 @@ extern int daemon(int, int);
 #  define QEMU_VMALLOC_ALIGN getpagesize()
 #endif
 
+#include <termios.h>
+#include <unistd.h>
+
 #include <glib/gprintf.h>
 
 #include "config-host.h"
@@ -251,3 +254,18 @@ qemu_get_local_state_pathname(const char *relative_pathname)
     return g_strdup_printf("%s/%s", CONFIG_QEMU_LOCALSTATEDIR,
                            relative_pathname);
 }
+
+void qemu_set_tty_echo(int fd, bool echo)
+{
+    struct termios tty;
+
+    tcgetattr(fd, &tty);
+
+    if (echo) {
+        tty.c_lflag |= ECHO | ECHONL | ICANON | IEXTEN;
+    } else {
+        tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
+    }
+
+    tcsetattr(fd, TCSANOW, &tty);
+}
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 776ccfa..50be044 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -189,3 +189,22 @@ qemu_get_local_state_pathname(const char *relative_pathname)
     return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path,
                            relative_pathname);
 }
+
+void qemu_set_tty_echo(int fd, bool echo)
+{
+    HANDLE handle = (HANDLE)_get_osfhandle(fd);
+    DWORD dwMode = 0;
+
+    if (handle == INVALID_HANDLE_VALUE) {
+        return;
+    }
+
+    GetConsoleMode(handle, &dwMode);
+
+    if (echo) {
+        SetConsoleMode(handle, dwMode | ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
+    } else {
+        SetConsoleMode(handle,
+                       dwMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT));
+    }
+}
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 16/42] qemu-io: use readline.c
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (14 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 15/42] osdep: add qemu_set_tty_echo() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 17/42] qemu-io: add command completion Kevin Wolf
                   ` (25 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Use readline.c for command-line history.  There was support for GNU
Readline and BSD Editline but it was never compiled in.  Since QEMU has
its own readline.c, just use that when qemu-io runs with stdin attached
to a terminal.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-io.c | 103 +++++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 58 insertions(+), 45 deletions(-)

diff --git a/qemu-io.c b/qemu-io.c
index 3b3340a..d7c26d3 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -18,6 +18,7 @@
 #include "qemu/main-loop.h"
 #include "qemu/option.h"
 #include "qemu/config-file.h"
+#include "qemu/readline.h"
 #include "block/block_int.h"
 #include "trace/control.h"
 
@@ -32,6 +33,8 @@ extern int qemuio_misalign;
 static int ncmdline;
 static char **cmdline;
 
+static ReadLineState *readline_state;
+
 static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_unref(bs);
@@ -203,14 +206,6 @@ static void usage(const char *name)
     name);
 }
 
-
-#if defined(ENABLE_READLINE)
-# include <readline/history.h>
-# include <readline/readline.h>
-#elif defined(ENABLE_EDITLINE)
-# include <histedit.h>
-#endif
-
 static char *get_prompt(void)
 {
     static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
@@ -222,52 +217,47 @@ static char *get_prompt(void)
     return prompt;
 }
 
-#if defined(ENABLE_READLINE)
-static char *fetchline(void)
+static void readline_printf_func(void *opaque, const char *fmt, ...)
 {
-    char *line = readline(get_prompt());
-    if (line && *line) {
-        add_history(line);
-    }
-    return line;
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    va_end(ap);
 }
-#elif defined(ENABLE_EDITLINE)
-static char *el_get_prompt(EditLine *e)
+
+static void readline_flush_func(void *opaque)
 {
-    return get_prompt();
+    fflush(stdout);
 }
 
-static char *fetchline(void)
+static void readline_func(void *opaque, const char *str, void *readline_opaque)
 {
-    static EditLine *el;
-    static History *hist;
-    HistEvent hevent;
-    char *line;
-    int count;
-
-    if (!el) {
-        hist = history_init();
-        history(hist, &hevent, H_SETSIZE, 100);
-        el = el_init(progname, stdin, stdout, stderr);
-        el_source(el, NULL);
-        el_set(el, EL_SIGNAL, 1);
-        el_set(el, EL_PROMPT, el_get_prompt);
-        el_set(el, EL_HIST, history, (const char *)hist);
-    }
-    line = strdup(el_gets(el, &count));
-    if (line) {
-        if (count > 0) {
-            line[count-1] = '\0';
-        }
-        if (*line) {
-            history(hist, &hevent, H_ENTER, line);
+    char **line = readline_opaque;
+    *line = g_strdup(str);
+}
+
+static void readline_completion_func(void *opaque, const char *str)
+{
+    /* No command or argument completion implemented yet */
+}
+
+static char *fetchline_readline(void)
+{
+    char *line = NULL;
+
+    readline_start(readline_state, get_prompt(), 0, readline_func, &line);
+    while (!line) {
+        int ch = getchar();
+        if (ch == EOF) {
+            break;
         }
+        readline_handle_byte(readline_state, ch);
     }
     return line;
 }
-#else
-# define MAXREADLINESZ 1024
-static char *fetchline(void)
+
+#define MAXREADLINESZ 1024
+static char *fetchline_fgets(void)
 {
     char *p, *line = g_malloc(MAXREADLINESZ);
 
@@ -283,7 +273,15 @@ static char *fetchline(void)
 
     return line;
 }
-#endif
+
+static char *fetchline(void)
+{
+    if (readline_state) {
+        return fetchline_readline();
+    } else {
+        return fetchline_fgets();
+    }
+}
 
 static void prep_fetchline(void *opaque)
 {
@@ -339,6 +337,11 @@ static void add_user_command(char *optarg)
     cmdline[ncmdline-1] = optarg;
 }
 
+static void reenable_tty_echo(void)
+{
+    qemu_set_tty_echo(STDIN_FILENO, true);
+}
+
 int main(int argc, char **argv)
 {
     int readonly = 0;
@@ -435,6 +438,15 @@ int main(int argc, char **argv)
     qemuio_add_command(&open_cmd);
     qemuio_add_command(&close_cmd);
 
+    if (isatty(STDIN_FILENO)) {
+        readline_state = readline_init(readline_printf_func,
+                                       readline_flush_func,
+                                       NULL,
+                                       readline_completion_func);
+        qemu_set_tty_echo(STDIN_FILENO, false);
+        atexit(reenable_tty_echo);
+    }
+
     /* open the device */
     if (!readonly) {
         flags |= BDRV_O_RDWR;
@@ -453,5 +465,6 @@ int main(int argc, char **argv)
     if (qemuio_bs) {
         bdrv_unref(qemuio_bs);
     }
+    g_free(readline_state);
     return 0;
 }
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 17/42] qemu-io: add command completion
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (15 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 16/42] qemu-io: use readline.c Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 18/42] blkdebug: Use errp for read_config() Kevin Wolf
                   ` (24 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Stefan Hajnoczi <stefanha@redhat.com>

Autocomplete qemu-io commands at the interactive prompt.

Note this only completes command names and not their options.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/qemu-io.h |  3 +++
 qemu-io-cmds.c    | 15 +++++++++++++++
 qemu-io.c         |  8 +++++++-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/include/qemu-io.h b/include/qemu-io.h
index a418b46..7e7c07c 100644
--- a/include/qemu-io.h
+++ b/include/qemu-io.h
@@ -42,5 +42,8 @@ bool qemuio_command(BlockDriverState *bs, const char *cmd);
 
 void qemuio_add_command(const cmdinfo_t *ci);
 int qemuio_command_usage(const cmdinfo_t *ci);
+void qemuio_complete_command(const char *input,
+                             void (*fn)(const char *cmd, void *opaque),
+                             void *opaque);
 
 #endif /* QEMU_IO_H */
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 85e4982..6dfb4a5 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -94,6 +94,21 @@ static const cmdinfo_t *find_command(const char *cmd)
     return NULL;
 }
 
+/* Invoke fn() for commands with a matching prefix */
+void qemuio_complete_command(const char *input,
+                             void (*fn)(const char *cmd, void *opaque),
+                             void *opaque)
+{
+    cmdinfo_t *ct;
+    size_t input_len = strlen(input);
+
+    for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
+        if (strncmp(input, ct->name, input_len) == 0) {
+            fn(ct->name, opaque);
+        }
+    }
+}
+
 static char **breakline(char *input, int *count)
 {
     int c = 0;
diff --git a/qemu-io.c b/qemu-io.c
index d7c26d3..fdc46a9 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -236,9 +236,15 @@ static void readline_func(void *opaque, const char *str, void *readline_opaque)
     *line = g_strdup(str);
 }
 
+static void completion_match(const char *cmd, void *opaque)
+{
+    readline_add_completion(readline_state, cmd);
+}
+
 static void readline_completion_func(void *opaque, const char *str)
 {
-    /* No command or argument completion implemented yet */
+    readline_set_completion_index(readline_state, strlen(str));
+    qemuio_complete_command(str, completion_match, NULL);
 }
 
 static char *fetchline_readline(void)
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 18/42] blkdebug: Use errp for read_config()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (16 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 17/42] qemu-io: add command completion Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 19/42] blkdebug: Don't require sophisticated filename Kevin Wolf
                   ` (23 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Use an Error variable in the read_config() function.

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

diff --git a/block/blkdebug.c b/block/blkdebug.c
index ebc5f13..2eb2e8b 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -271,7 +271,7 @@ static void remove_rule(BlkdebugRule *rule)
     g_free(rule);
 }
 
-static int read_config(BDRVBlkdebugState *s, const char *filename)
+static int read_config(BDRVBlkdebugState *s, const char *filename, Error **errp)
 {
     FILE *f;
     int ret;
@@ -279,11 +279,14 @@ static int read_config(BDRVBlkdebugState *s, const char *filename)
 
     f = fopen(filename, "r");
     if (f == NULL) {
+        error_setg_errno(errp, errno, "Could not read blkdebug config file");
         return -errno;
     }
 
     ret = qemu_config_parse(f, config_groups, filename);
     if (ret < 0) {
+        error_setg(errp, "Could not parse blkdebug config file");
+        ret = -EINVAL;
         goto fail;
     }
 
@@ -370,9 +373,8 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     /* Read rules from config file */
     config = qemu_opt_get(opts, "config");
     if (config) {
-        ret = read_config(s, config);
-        if (ret < 0) {
-            error_setg_errno(errp, -ret, "Could not read blkdebug config file");
+        ret = read_config(s, config, errp);
+        if (ret) {
             goto fail;
         }
     }
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 19/42] blkdebug: Don't require sophisticated filename
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (17 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 18/42] blkdebug: Use errp for read_config() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 20/42] qdict: Add qdict_array_split() Kevin Wolf
                   ` (22 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

If the filename is not prefixed by "blkdebug:" in
blkdebug_parse_filename(), the blkdebug driver was not selected through
that protocol prefix, but by an explicit command line option
(file.driver=blkdebug or something similar). Contrary to the current
reaction, this is not a problem at all; we just need to store the
filename (in the x-image option) and can go on; the user just has to
manually specify the config option.

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

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 2eb2e8b..fab76ce 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -313,7 +313,9 @@ static void blkdebug_parse_filename(const char *filename, QDict *options,
 
     /* Parse the blkdebug: prefix */
     if (!strstart(filename, "blkdebug:", &filename)) {
-        error_setg(errp, "File name string must start with 'blkdebug:'");
+        /* There was no prefix; therefore, all options have to be already
+           present in the QDict (except for the filename) */
+        qdict_put(options, "x-image", qstring_from_str(filename));
         return;
     }
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 20/42] qdict: Add qdict_array_split()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (18 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 19/42] blkdebug: Don't require sophisticated filename Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 21/42] qapi: extend qdict_flatten() for QLists Kevin Wolf
                   ` (21 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

This function splits a QDict consisting of entries prefixed by
incrementally enumerated indices into a QList of QDicts.

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

diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 5cefd80..1ddf97b 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -68,5 +68,6 @@ QDict *qdict_clone_shallow(const QDict *src);
 void qdict_flatten(QDict *qdict);
 
 void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
+void qdict_array_split(QDict *src, QList **dst);
 
 #endif /* QDICT_H */
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 17e14f0..2d5848d 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -554,3 +554,40 @@ void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
         entry = next;
     }
 }
+
+/**
+ * qdict_array_split(): This function moves array-like elements of a QDict into
+ * a new QList of QDicts. Every entry in the original QDict with a key prefixed
+ * "%u.", where %u designates an unsigned integer starting at 0 and
+ * incrementally counting up, will be moved to a new QDict at index %u in the
+ * output QList with the key prefix removed. The function terminates when there
+ * is no entry in the QDict with a prefix directly (incrementally) following the
+ * last one.
+ * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "3.y": 1, "o.o": 7}
+ *      (or {"1.x": 0, "3.y": 1, "0.a": 42, "o.o": 7, "0.b": 23})
+ *       => [{"a": 42, "b": 23}, {"x": 0}]
+ *      and {"3.y": 1, "o.o": 7} (remainder of the old QDict)
+ */
+void qdict_array_split(QDict *src, QList **dst)
+{
+    unsigned i;
+
+    *dst = qlist_new();
+
+    for (i = 0; i < UINT_MAX; i++) {
+        QDict *subqdict;
+        char prefix[32];
+        size_t snprintf_ret;
+
+        snprintf_ret = snprintf(prefix, 32, "%u.", i);
+        assert(snprintf_ret < 32);
+
+        qdict_extract_subqdict(src, &subqdict, prefix);
+        if (!qdict_size(subqdict)) {
+            QDECREF(subqdict);
+            break;
+        }
+
+        qlist_append_obj(*dst, QOBJECT(subqdict));
+    }
+}
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 21/42] qapi: extend qdict_flatten() for QLists
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (19 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 20/42] qdict: Add qdict_array_split() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 22/42] qemu-option: Add qemu_config_parse_qdict() Kevin Wolf
                   ` (20 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Reversing qdict_array_split(), qdict_flatten() should flatten QLists as
well by interpreting them as QDicts where every entry's key is its
index.

This allows bringing QDicts with QLists from QMP commands to the same
form as they would be given as command-line options, thereby allowing
them to be parsed the same way.

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

diff --git a/qobject/qdict.c b/qobject/qdict.c
index 2d5848d..a3924f2 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -477,7 +477,43 @@ static void qdict_destroy_obj(QObject *obj)
     g_free(qdict);
 }
 
-static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix)
+static void qdict_flatten_qdict(QDict *qdict, QDict *target,
+                                const char *prefix);
+
+static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix)
+{
+    QObject *value;
+    const QListEntry *entry;
+    char *new_key;
+    int i;
+
+    /* This function is never called with prefix == NULL, i.e., it is always
+     * called from within qdict_flatten_q(list|dict)(). Therefore, it does not
+     * need to remove list entries during the iteration (the whole list will be
+     * deleted eventually anyway from qdict_flatten_qdict()). */
+    assert(prefix);
+
+    entry = qlist_first(qlist);
+
+    for (i = 0; entry; entry = qlist_next(entry), i++) {
+        value = qlist_entry_obj(entry);
+        new_key = g_strdup_printf("%s.%i", prefix, i);
+
+        if (qobject_type(value) == QTYPE_QDICT) {
+            qdict_flatten_qdict(qobject_to_qdict(value), target, new_key);
+        } else if (qobject_type(value) == QTYPE_QLIST) {
+            qdict_flatten_qlist(qobject_to_qlist(value), target, new_key);
+        } else {
+            /* All other types are moved to the target unchanged. */
+            qobject_incref(value);
+            qdict_put_obj(target, new_key, value);
+        }
+
+        g_free(new_key);
+    }
+}
+
+static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
 {
     QObject *value;
     const QDictEntry *entry, *next;
@@ -500,8 +536,12 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix)
         if (qobject_type(value) == QTYPE_QDICT) {
             /* Entries of QDicts are processed recursively, the QDict object
              * itself disappears. */
-            qdict_do_flatten(qobject_to_qdict(value), target,
-                             new_key ? new_key : entry->key);
+            qdict_flatten_qdict(qobject_to_qdict(value), target,
+                                new_key ? new_key : entry->key);
+            delete = true;
+        } else if (qobject_type(value) == QTYPE_QLIST) {
+            qdict_flatten_qlist(qobject_to_qlist(value), target,
+                                new_key ? new_key : entry->key);
             delete = true;
         } else if (prefix) {
             /* All other objects are moved to the target unchanged. */
@@ -526,12 +566,14 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix)
 
 /**
  * qdict_flatten(): For each nested QDict with key x, all fields with key y
- * are moved to this QDict and their key is renamed to "x.y". This operation
- * is applied recursively for nested QDicts.
+ * are moved to this QDict and their key is renamed to "x.y". For each nested
+ * QList with key x, the field at index y is moved to this QDict with the key
+ * "x.y" (i.e., the reverse of what qdict_array_split() does).
+ * This operation is applied recursively for nested QDicts and QLists.
  */
 void qdict_flatten(QDict *qdict)
 {
-    qdict_do_flatten(qdict, qdict, NULL);
+    qdict_flatten_qdict(qdict, qdict, NULL);
 }
 
 /* extract all the src QDict entries starting by start into dst */
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 22/42] qemu-option: Add qemu_config_parse_qdict()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (20 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 21/42] qapi: extend qdict_flatten() for QLists Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 23/42] blkdebug: Always call read_config() Kevin Wolf
                   ` (19 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

This function basically parses command-line options given as a QDict
replacing a config file.

For instance, the QDict {"section.opt1": 42, "section.opt2": 23}
corresponds to the config file:

[section]
opt1 = 42
opt2 = 23

It is possible to specify multiple sections and also multiple sections
of the same type. On the command line, this looks like the following:

inject-error.0.event=reftable_load,\
inject-error.1.event=l2_load,\
set-state.event=l1_update

This would correspond to the following config file:

[inject-error "inject-error.0"]
event = reftable_load

[inject-error "inject-error.1"]
event = l2_load

[set-state]
event = l1_update

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/qemu/config-file.h |   6 +++
 util/qemu-config.c         | 100 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+)

diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index 508428f..dbd97c4 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include "qemu/option.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
 
 QemuOptsList *qemu_find_opts(const char *group);
 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
@@ -18,6 +19,11 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname);
 
 int qemu_read_config_file(const char *filename);
 
+/* Parse QDict options as a replacement for a config file (allowing multiple
+   enumerated (0..(n-1)) configuration "sections") */
+void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
+                             Error **errp);
+
 /* Read default QEMU config files
  */
 int qemu_read_default_config_files(bool userconfig);
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 7973659..9298f55 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -356,3 +356,103 @@ int qemu_read_config_file(const char *filename)
         return -EINVAL;
     }
 }
+
+static void config_parse_qdict_section(QDict *options, QemuOptsList *opts,
+                                       Error **errp)
+{
+    QemuOpts *subopts;
+    QDict *subqdict;
+    QList *list = NULL;
+    Error *local_err = NULL;
+    size_t orig_size, enum_size;
+    char *prefix;
+
+    prefix = g_strdup_printf("%s.", opts->name);
+    qdict_extract_subqdict(options, &subqdict, prefix);
+    g_free(prefix);
+    orig_size = qdict_size(subqdict);
+    if (!orig_size) {
+        goto out;
+    }
+
+    subopts = qemu_opts_create(opts, NULL, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        goto out;
+    }
+
+    qemu_opts_absorb_qdict(subopts, subqdict, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        goto out;
+    }
+
+    enum_size = qdict_size(subqdict);
+    if (enum_size < orig_size && enum_size) {
+        error_setg(errp, "Unknown option '%s' for [%s]",
+                   qdict_first(subqdict)->key, opts->name);
+        goto out;
+    }
+
+    if (enum_size) {
+        /* Multiple, enumerated sections */
+        QListEntry *list_entry;
+        unsigned i = 0;
+
+        /* Not required anymore */
+        qemu_opts_del(subopts);
+
+        qdict_array_split(subqdict, &list);
+        if (qdict_size(subqdict)) {
+            error_setg(errp, "Unused option '%s' for [%s]",
+                       qdict_first(subqdict)->key, opts->name);
+            goto out;
+        }
+
+        QLIST_FOREACH_ENTRY(list, list_entry) {
+            QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry));
+            char *opt_name;
+
+            opt_name = g_strdup_printf("%s.%u", opts->name, i++);
+            subopts = qemu_opts_create(opts, opt_name, 1, &local_err);
+            g_free(opt_name);
+            if (error_is_set(&local_err)) {
+                error_propagate(errp, local_err);
+                goto out;
+            }
+
+            qemu_opts_absorb_qdict(subopts, section, &local_err);
+            if (error_is_set(&local_err)) {
+                error_propagate(errp, local_err);
+                qemu_opts_del(subopts);
+                goto out;
+            }
+
+            if (qdict_size(section)) {
+                error_setg(errp, "[%s] section doesn't support the option '%s'",
+                           opts->name, qdict_first(section)->key);
+                qemu_opts_del(subopts);
+                goto out;
+            }
+        }
+    }
+
+out:
+    QDECREF(subqdict);
+    QDECREF(list);
+}
+
+void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
+                             Error **errp)
+{
+    int i;
+    Error *local_err = NULL;
+
+    for (i = 0; lists[i]; i++) {
+        config_parse_qdict_section(options, lists[i], &local_err);
+        if (error_is_set(&local_err)) {
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+}
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 23/42] blkdebug: Always call read_config()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (21 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 22/42] qemu-option: Add qemu_config_parse_qdict() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 24/42] blkdebug: Use command-line in read_config() Kevin Wolf
                   ` (18 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Move the check whether there actually is a config file into the
read_config() function.

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

diff --git a/block/blkdebug.c b/block/blkdebug.c
index fab76ce..acf23f2 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -273,21 +273,23 @@ static void remove_rule(BlkdebugRule *rule)
 
 static int read_config(BDRVBlkdebugState *s, const char *filename, Error **errp)
 {
-    FILE *f;
+    FILE *f = NULL;
     int ret;
     struct add_rule_data d;
 
-    f = fopen(filename, "r");
-    if (f == NULL) {
-        error_setg_errno(errp, errno, "Could not read blkdebug config file");
-        return -errno;
-    }
+    if (filename) {
+        f = fopen(filename, "r");
+        if (f == NULL) {
+            error_setg_errno(errp, errno, "Could not read blkdebug config file");
+            return -errno;
+        }
 
-    ret = qemu_config_parse(f, config_groups, filename);
-    if (ret < 0) {
-        error_setg(errp, "Could not parse blkdebug config file");
-        ret = -EINVAL;
-        goto fail;
+        ret = qemu_config_parse(f, config_groups, filename);
+        if (ret < 0) {
+            error_setg(errp, "Could not parse blkdebug config file");
+            ret = -EINVAL;
+            goto fail;
+        }
     }
 
     d.s = s;
@@ -301,7 +303,9 @@ static int read_config(BDRVBlkdebugState *s, const char *filename, Error **errp)
 fail:
     qemu_opts_reset(&inject_error_opts);
     qemu_opts_reset(&set_state_opts);
-    fclose(f);
+    if (f) {
+        fclose(f);
+    }
     return ret;
 }
 
@@ -374,11 +378,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
 
     /* Read rules from config file */
     config = qemu_opt_get(opts, "config");
-    if (config) {
-        ret = read_config(s, config, errp);
-        if (ret) {
-            goto fail;
-        }
+    ret = read_config(s, config, errp);
+    if (ret) {
+        goto fail;
     }
 
     /* Set initial state */
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 24/42] blkdebug: Use command-line in read_config()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (22 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 23/42] blkdebug: Always call read_config() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 25/42] block: Allow reference for bdrv_file_open() Kevin Wolf
                   ` (17 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Use qemu_config_parse_qdict() to parse the command-line options in
addition to the config file.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/blkdebug.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index acf23f2..0bf3bb5 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -271,11 +271,13 @@ static void remove_rule(BlkdebugRule *rule)
     g_free(rule);
 }
 
-static int read_config(BDRVBlkdebugState *s, const char *filename, Error **errp)
+static int read_config(BDRVBlkdebugState *s, const char *filename,
+                       QDict *options, Error **errp)
 {
     FILE *f = NULL;
     int ret;
     struct add_rule_data d;
+    Error *local_err = NULL;
 
     if (filename) {
         f = fopen(filename, "r");
@@ -292,6 +294,13 @@ static int read_config(BDRVBlkdebugState *s, const char *filename, Error **errp)
         }
     }
 
+    qemu_config_parse_qdict(options, config_groups, &local_err);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        ret = -EINVAL;
+        goto fail;
+    }
+
     d.s = s;
     d.action = ACTION_INJECT_ERROR;
     qemu_opts_foreach(&inject_error_opts, add_rule, &d, 0);
@@ -376,9 +385,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    /* Read rules from config file */
+    /* Read rules from config file or command line options */
     config = qemu_opt_get(opts, "config");
-    ret = read_config(s, config, errp);
+    ret = read_config(s, config, options, errp);
     if (ret) {
         goto fail;
     }
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 25/42] block: Allow reference for bdrv_file_open()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (23 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 24/42] blkdebug: Use command-line in read_config() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 26/42] block: Pass reference to bdrv_file_open() Kevin Wolf
                   ` (16 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Allow specifying a reference to an existing block device (by name) for
bdrv_file_open() instead of a filename and/or options.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c               | 25 ++++++++++++++++++++++---
 block/blkdebug.c      |  2 +-
 block/blkverify.c     |  2 +-
 block/cow.c           |  3 ++-
 block/qcow.c          |  3 ++-
 block/qcow2.c         |  2 +-
 block/qed.c           |  4 ++--
 block/sheepdog.c      |  4 ++--
 block/vhdx.c          |  2 +-
 block/vmdk.c          |  8 ++++----
 include/block/block.h |  3 ++-
 qemu-io.c             |  2 +-
 12 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/block.c b/block.c
index 64e7d22..1e53b3d 100644
--- a/block.c
+++ b/block.c
@@ -858,9 +858,10 @@ free_and_fail:
  * dictionary, it needs to use QINCREF() before calling bdrv_file_open.
  */
 int bdrv_file_open(BlockDriverState **pbs, const char *filename,
-                   QDict *options, int flags, Error **errp)
+                   const char *reference, QDict *options, int flags,
+                   Error **errp)
 {
-    BlockDriverState *bs;
+    BlockDriverState *bs = NULL;
     BlockDriver *drv;
     const char *drvname;
     bool allow_protocol_prefix = false;
@@ -872,6 +873,24 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
         options = qdict_new();
     }
 
+    if (reference) {
+        if (filename || qdict_size(options)) {
+            error_setg(errp, "Cannot reference an existing block device with "
+                       "additional options or a new filename");
+            return -EINVAL;
+        }
+        QDECREF(options);
+
+        bs = bdrv_find(reference);
+        if (!bs) {
+            error_setg(errp, "Cannot find block device '%s'", reference);
+            return -ENODEV;
+        }
+        bdrv_ref(bs);
+        *pbs = bs;
+        return 0;
+    }
+
     bs = bdrv_new("");
     bs->options = options;
     options = qdict_clone_shallow(options);
@@ -1124,7 +1143,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
 
     qdict_extract_subqdict(options, &file_options, "file.");
 
-    ret = bdrv_file_open(&file, filename, file_options,
+    ret = bdrv_file_open(&file, filename, NULL, file_options,
                          bdrv_open_flags(bs, flags | BDRV_O_UNMAP), &local_err);
     if (ret < 0) {
         goto fail;
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 0bf3bb5..21a4931 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -403,7 +403,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    ret = bdrv_file_open(&bs->file, filename, NULL, flags, &local_err);
+    ret = bdrv_file_open(&bs->file, filename, NULL, NULL, flags, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto fail;
diff --git a/block/blkverify.c b/block/blkverify.c
index 1c1637f..e15ac4c 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -141,7 +141,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    ret = bdrv_file_open(&bs->file, raw, NULL, flags, &local_err);
+    ret = bdrv_file_open(&bs->file, raw, NULL, NULL, flags, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto fail;
diff --git a/block/cow.c b/block/cow.c
index dc15e46..7fc0b12 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -351,7 +351,8 @@ static int cow_create(const char *filename, QEMUOptionParameter *options,
         return ret;
     }
 
-    ret = bdrv_file_open(&cow_bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    ret = bdrv_file_open(&cow_bs, filename, NULL, NULL, BDRV_O_RDWR,
+                         &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
diff --git a/block/qcow.c b/block/qcow.c
index c470e05..948b0c5 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -691,7 +691,8 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options,
         return ret;
     }
 
-    ret = bdrv_file_open(&qcow_bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    ret = bdrv_file_open(&qcow_bs, filename, NULL, NULL, BDRV_O_RDWR,
+                         &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
diff --git a/block/qcow2.c b/block/qcow2.c
index 8ec9db1..e15a4dd 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1483,7 +1483,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
         return ret;
     }
 
-    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         return ret;
diff --git a/block/qed.c b/block/qed.c
index 450a1fa..0dd5c58 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -563,8 +563,8 @@ static int qed_create(const char *filename, uint32_t cluster_size,
         return ret;
     }
 
-    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB,
-                         &local_err);
+    ret = bdrv_file_open(&bs, filename, NULL, NULL,
+                         BDRV_O_RDWR | BDRV_O_CACHE_WB, &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 6088fa5..2ce3d9b 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1534,7 +1534,7 @@ static int sd_prealloc(const char *filename)
     Error *local_err = NULL;
     int ret;
 
-    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err);
     if (ret < 0) {
         qerror_report_err(local_err);
         error_free(local_err);
@@ -1695,7 +1695,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options,
             goto out;
         }
 
-        ret = bdrv_file_open(&bs, backing_file, NULL, 0, &local_err);
+        ret = bdrv_file_open(&bs, backing_file, NULL, NULL, 0, &local_err);
         if (ret < 0) {
             qerror_report_err(local_err);
             error_free(local_err);
diff --git a/block/vhdx.c b/block/vhdx.c
index 1995778..9ee0a61 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1797,7 +1797,7 @@ static int vhdx_create(const char *filename, QEMUOptionParameter *options,
         goto exit;
     }
 
-    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto exit;
diff --git a/block/vmdk.c b/block/vmdk.c
index 22b99b0..599a928 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -769,8 +769,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
 
         path_combine(extent_path, sizeof(extent_path),
                 desc_file_path, fname);
-        ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags,
-                             errp);
+        ret = bdrv_file_open(&extent_file, extent_path, NULL, NULL,
+                             bs->open_flags, errp);
         if (ret) {
             return ret;
         }
@@ -1469,7 +1469,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize,
         goto exit;
     }
 
-    ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    ret = bdrv_file_open(&bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto exit;
@@ -1807,7 +1807,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options,
             goto exit;
         }
     }
-    ret = bdrv_file_open(&new_bs, filename, NULL, BDRV_O_RDWR, &local_err);
+    ret = bdrv_file_open(&new_bs, filename, NULL, NULL, BDRV_O_RDWR, &local_err);
     if (ret < 0) {
         error_setg_errno(errp, -ret, "Could not write description");
         goto exit;
diff --git a/include/block/block.h b/include/block/block.h
index 36efaea..e2b2a15 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -184,7 +184,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_file_open(BlockDriverState **pbs, const char *filename,
-                   QDict *options, int flags, Error **errp);
+                   const char *reference, QDict *options, int flags,
+                   Error **errp);
 int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
 int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
               int flags, BlockDriver *drv, Error **errp);
diff --git a/qemu-io.c b/qemu-io.c
index fdc46a9..bfb773e 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -59,7 +59,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
     }
 
     if (growable) {
-        if (bdrv_file_open(&qemuio_bs, name, opts, flags, &local_err)) {
+        if (bdrv_file_open(&qemuio_bs, name, NULL, opts, flags, &local_err)) {
             fprintf(stderr, "%s: can't open device %s: %s\n", progname, name,
                     error_get_pretty(local_err));
             error_free(local_err);
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 26/42] block: Pass reference to bdrv_file_open()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (24 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 25/42] block: Allow reference for bdrv_file_open() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 27/42] block: Allow block devices without files Kevin Wolf
                   ` (15 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

With that now being possible, bdrv_open() should try to extract a block
device reference from the options and pass it to bdrv_file_open().

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

diff --git a/block.c b/block.c
index 1e53b3d..bef4f82 100644
--- a/block.c
+++ b/block.c
@@ -1056,6 +1056,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     char tmp_filename[PATH_MAX + 1];
     BlockDriverState *file = NULL;
     QDict *file_options = NULL;
+    const char *file_reference;
     const char *drvname;
     Error *local_err = NULL;
 
@@ -1142,9 +1143,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     }
 
     qdict_extract_subqdict(options, &file_options, "file.");
+    file_reference = qdict_get_try_str(options, "file");
 
-    ret = bdrv_file_open(&file, filename, NULL, file_options,
+    ret = bdrv_file_open(&file, filename, file_reference, file_options,
                          bdrv_open_flags(bs, flags | BDRV_O_UNMAP), &local_err);
+    qdict_del(options, "file");
     if (ret < 0) {
         goto fail;
     }
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 27/42] block: Allow block devices without files
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (25 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 26/42] block: Pass reference to bdrv_file_open() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 28/42] block: Add bdrv_open_image() Kevin Wolf
                   ` (14 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

blkdebug and blkverify will, in order to retain compatibility, not
support the field "file" implicitly through bdrv_open(). In order to be
able to use those drivers without giving a filename anyway, it is
necessary to be able to have block devices without files implicitly
opened by bdrv_open(). This is the case, if there was neither a file
name, a reference to an existing block device to use as a file nor
options specific to the file.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/block.c b/block.c
index bef4f82..7464fb2 100644
--- a/block.c
+++ b/block.c
@@ -1145,11 +1145,14 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     qdict_extract_subqdict(options, &file_options, "file.");
     file_reference = qdict_get_try_str(options, "file");
 
-    ret = bdrv_file_open(&file, filename, file_reference, file_options,
-                         bdrv_open_flags(bs, flags | BDRV_O_UNMAP), &local_err);
-    qdict_del(options, "file");
-    if (ret < 0) {
-        goto fail;
+    if (filename || file_reference || qdict_size(file_options)) {
+        ret = bdrv_file_open(&file, filename, file_reference, file_options,
+                             bdrv_open_flags(bs, flags | BDRV_O_UNMAP),
+                             &local_err);
+        qdict_del(options, "file");
+        if (ret < 0) {
+            goto fail;
+        }
     }
 
     /* Find the right image format driver */
@@ -1165,7 +1168,13 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     }
 
     if (!drv) {
-        ret = find_image_format(file, filename, &drv, &local_err);
+        if (file) {
+            ret = find_image_format(file, filename, &drv, &local_err);
+        } else {
+            error_setg(errp, "Must specify either driver or file");
+            ret = -EINVAL;
+            goto unlink_and_fail;
+        }
     }
 
     if (!drv) {
@@ -1178,7 +1187,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         goto unlink_and_fail;
     }
 
-    if (bs->file != file) {
+    if (file && (bs->file != file)) {
         bdrv_unref(file);
         file = NULL;
     }
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 28/42] block: Add bdrv_open_image()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (26 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 27/42] block: Allow block devices without files Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 29/42] block: Use bdrv_open_image() in bdrv_open() Kevin Wolf
                   ` (13 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Add a common function for opening images to be used for block drivers
specified through BlockdevRefs in an option QDict. The difference from
bdrv_file_open() is that this function may invoke bdrv_open() instead,
allowing auto-detection of the driver to be used; and second, it
automatically extracts the BlockdevRef from the option QDict.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c               | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/block/block.h |  3 +++
 2 files changed, 76 insertions(+)

diff --git a/block.c b/block.c
index 7464fb2..76b6c25 100644
--- a/block.c
+++ b/block.c
@@ -1041,6 +1041,79 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
 }
 
 /*
+ * Opens a disk image whose options are given as BlockdevRef in another block
+ * device's options.
+ *
+ * If force_raw is true, bdrv_file_open() will be used, thereby preventing any
+ * image format auto-detection. If it is false and a filename is given,
+ * bdrv_open() will be used for auto-detection.
+ *
+ * If allow_none is true, no image will be opened if filename is false and no
+ * BlockdevRef is given. *pbs will remain unchanged and 0 will be returned.
+ *
+ * bdrev_key specifies the key for the image's BlockdevRef in the options QDict.
+ * That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
+ * itself, all options starting with "${bdref_key}." are considered part of the
+ * BlockdevRef.
+ *
+ * The BlockdevRef will be removed from the options QDict.
+ */
+int bdrv_open_image(BlockDriverState **pbs, const char *filename,
+                    QDict *options, const char *bdref_key, int flags,
+                    bool force_raw, bool allow_none, Error **errp)
+{
+    QDict *image_options;
+    int ret;
+    char *bdref_key_dot;
+    const char *reference;
+
+    bdref_key_dot = g_strdup_printf("%s.", bdref_key);
+    qdict_extract_subqdict(options, &image_options, bdref_key_dot);
+    g_free(bdref_key_dot);
+
+    reference = qdict_get_try_str(options, bdref_key);
+    if (!filename && !reference && !qdict_size(image_options)) {
+        if (allow_none) {
+            ret = 0;
+        } else {
+            error_setg(errp, "A block device must be specified for \"%s\"",
+                       bdref_key);
+            ret = -EINVAL;
+        }
+        goto done;
+    }
+
+    if (filename && !force_raw) {
+        /* If a filename is given and the block driver should be detected
+           automatically (instead of using none), use bdrv_open() in order to do
+           that auto-detection. */
+        BlockDriverState *bs;
+
+        if (reference) {
+            error_setg(errp, "Cannot reference an existing block device while "
+                       "giving a filename");
+            ret = -EINVAL;
+            goto done;
+        }
+
+        bs = bdrv_new("");
+        ret = bdrv_open(bs, filename, image_options, flags, NULL, errp);
+        if (ret < 0) {
+            bdrv_unref(bs);
+        } else {
+            *pbs = bs;
+        }
+    } else {
+        ret = bdrv_file_open(pbs, filename, reference, image_options, flags,
+                             errp);
+    }
+
+done:
+    qdict_del(options, bdref_key);
+    return ret;
+}
+
+/*
  * Opens a disk image (raw, qcow2, vmdk, ...)
  *
  * options is a QDict of options to pass to the block drivers, or NULL for an
diff --git a/include/block/block.h b/include/block/block.h
index e2b2a15..a47f3d4 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -186,6 +186,9 @@ int bdrv_parse_discard_flags(const char *mode, int *flags);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename,
                    const char *reference, QDict *options, int flags,
                    Error **errp);
+int bdrv_open_image(BlockDriverState **pbs, const char *filename,
+                    QDict *options, const char *bdref_key, int flags,
+                    bool force_raw, bool allow_none, Error **errp);
 int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
 int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
               int flags, BlockDriver *drv, Error **errp);
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 29/42] block: Use bdrv_open_image() in bdrv_open()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (27 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 28/42] block: Add bdrv_open_image() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 30/42] block: Allow recursive "file"s Kevin Wolf
                   ` (12 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Using bdrv_open_image() instead of bdrv_file_open() directly in
bdrv_open() is easier.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/block.c b/block.c
index 76b6c25..9e4e85f 100644
--- a/block.c
+++ b/block.c
@@ -1128,8 +1128,6 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
     /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
     char tmp_filename[PATH_MAX + 1];
     BlockDriverState *file = NULL;
-    QDict *file_options = NULL;
-    const char *file_reference;
     const char *drvname;
     Error *local_err = NULL;
 
@@ -1215,17 +1213,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,
         flags |= BDRV_O_ALLOW_RDWR;
     }
 
-    qdict_extract_subqdict(options, &file_options, "file.");
-    file_reference = qdict_get_try_str(options, "file");
-
-    if (filename || file_reference || qdict_size(file_options)) {
-        ret = bdrv_file_open(&file, filename, file_reference, file_options,
-                             bdrv_open_flags(bs, flags | BDRV_O_UNMAP),
-                             &local_err);
-        qdict_del(options, "file");
-        if (ret < 0) {
-            goto fail;
-        }
+    ret = bdrv_open_image(&file, filename, options, "file",
+                          bdrv_open_flags(bs, flags | BDRV_O_UNMAP), true, true,
+                          &local_err);
+    if (ret < 0) {
+        goto fail;
     }
 
     /* Find the right image format driver */
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 30/42] block: Allow recursive "file"s
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (28 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 29/42] block: Use bdrv_open_image() in bdrv_open() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 31/42] blockdev: Move "file" to legacy_opts Kevin Wolf
                   ` (11 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

It should be possible to use a format as a driver for a file which in
turn requires another file, i.e., nesting file formats.

Allowing nested file formats results in e.g. qcow2 BlockDriverStates
never being directly passed to bdrv_open_common() from bdrv_file_open(),
but instead being handed through bdrv_open(). This changes the error
message when trying to give a filename to qcow2, i.e. trying to use it
as a driver for the protocol level. Therefore, change the reference
output of I/O test 051 accordingly.

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

diff --git a/block.c b/block.c
index 9e4e85f..6af5f6e 100644
--- a/block.c
+++ b/block.c
@@ -948,14 +948,19 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
         goto fail;
     }
 
-    ret = bdrv_open_common(bs, NULL, options, flags, drv, &local_err);
+    if (!drv->bdrv_file_open) {
+        ret = bdrv_open(bs, filename, options, flags, drv, &local_err);
+        options = NULL;
+    } else {
+        ret = bdrv_open_common(bs, NULL, options, flags, drv, &local_err);
+    }
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto fail;
     }
 
     /* Check if any unknown options were used */
-    if (qdict_size(options) != 0) {
+    if (options && (qdict_size(options) != 0)) {
         const QDictEntry *entry = qdict_first(options);
         error_setg(errp, "Block protocol '%s' doesn't support the option '%s'",
                    drv->format_name, entry->key);
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index c2cadba..d0c5173 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -222,7 +222,7 @@ 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: could not open disk image TEST_DIR/t.qcow2: Can't use 'qcow2' as a block driver for the protocol level
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device '' doesn't support the option 'filename'
 
 
 === Parsing protocol from file name ===
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 31/42] blockdev: Move "file" to legacy_opts
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (29 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 30/42] block: Allow recursive "file"s Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 32/42] blkdebug: Allow command-line file configuration Kevin Wolf
                   ` (10 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Specifying the image filename through the "file" option is a legacy
option and should not be supported by blockdev-add (in that case, giving
a string for "file" references an existing block device).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 blockdev.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index e457494..386109a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -307,12 +307,11 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
 typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
 
 /* Takes the ownership of bs_opts */
-static DriveInfo *blockdev_init(QDict *bs_opts,
+static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
                                 BlockInterfaceType type,
                                 Error **errp)
 {
     const char *buf;
-    const char *file = NULL;
     const char *serial;
     int ro = 0;
     int bdrv_flags = 0;
@@ -354,7 +353,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts,
     ro = qemu_opt_get_bool(opts, "read-only", 0);
     copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
 
-    file = qemu_opt_get(opts, "file");
     serial = qemu_opt_get(opts, "serial");
 
     if ((buf = qemu_opt_get(opts, "discard")) != NULL) {
@@ -599,6 +597,10 @@ QemuOptsList qemu_legacy_drive_opts = {
             .name = "addr",
             .type = QEMU_OPT_STRING,
             .help = "pci address (virtio only)",
+        },{
+            .name = "file",
+            .type = QEMU_OPT_STRING,
+            .help = "file name",
         },
 
         /* Options that are passed on, but have special semantics with -drive */
@@ -629,6 +631,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     const char *devaddr;
     bool read_only = false;
     bool copy_on_read;
+    const char *filename;
     Error *local_err = NULL;
 
     /* Change legacy command line options into QMP ones */
@@ -867,8 +870,10 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
         }
     }
 
+    filename = qemu_opt_get(legacy_opts, "file");
+
     /* Actual block device init: Functionality shared with blockdev-add */
-    dinfo = blockdev_init(bs_opts, type, &local_err);
+    dinfo = blockdev_init(filename, bs_opts, type, &local_err);
     if (dinfo == NULL) {
         if (error_is_set(&local_err)) {
             qerror_report_err(local_err);
@@ -2210,7 +2215,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    blockdev_init(qdict, IF_NONE, &local_err);
+    blockdev_init(NULL, qdict, IF_NONE, &local_err);
     if (error_is_set(&local_err)) {
         error_propagate(errp, local_err);
         goto fail;
@@ -2251,10 +2256,6 @@ QemuOptsList qemu_common_drive_opts = {
             .type = QEMU_OPT_BOOL,
             .help = "enable/disable snapshot mode",
         },{
-            .name = "file",
-            .type = QEMU_OPT_STRING,
-            .help = "disk image",
-        },{
             .name = "discard",
             .type = QEMU_OPT_STRING,
             .help = "discard operation (ignore/off, unmap/on)",
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 32/42] blkdebug: Allow command-line file configuration
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (30 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 31/42] blockdev: Move "file" to legacy_opts Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 33/42] blkverify: Allow command-line configuration Kevin Wolf
                   ` (9 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Introduce the "image" option as an alternative to specifying the image
through the filename.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/blkdebug.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 21a4931..c8f8d56 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -374,7 +374,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     BDRVBlkdebugState *s = bs->opaque;
     QemuOpts *opts;
     Error *local_err = NULL;
-    const char *filename, *config;
+    const char *config;
     int ret;
 
     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
@@ -396,14 +396,8 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
     s->state = 1;
 
     /* Open the backing file */
-    filename = qemu_opt_get(opts, "x-image");
-    if (filename == NULL) {
-        error_setg(errp, "Could not retrieve image file name");
-        ret = -EINVAL;
-        goto fail;
-    }
-
-    ret = bdrv_file_open(&bs->file, filename, NULL, NULL, flags, &local_err);
+    ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-image"), options, "image",
+                          flags, true, false, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto fail;
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 33/42] blkverify: Allow command-line configuration
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (31 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 32/42] blkdebug: Allow command-line file configuration Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 34/42] blkverify: Don't require protocol filename Kevin Wolf
                   ` (8 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Introduce the "test" and "raw" options for specifying images.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/blkverify.c | 25 +++++--------------------
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/block/blkverify.c b/block/blkverify.c
index e15ac4c..dc14290 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -122,7 +122,6 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
     BDRVBlkverifyState *s = bs->opaque;
     QemuOpts *opts;
     Error *local_err = NULL;
-    const char *filename, *raw;
     int ret;
 
     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
@@ -133,33 +132,19 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
         goto fail;
     }
 
-    /* Parse the raw image filename */
-    raw = qemu_opt_get(opts, "x-raw");
-    if (raw == NULL) {
-        error_setg(errp, "Could not retrieve raw image filename");
-        ret = -EINVAL;
-        goto fail;
-    }
-
-    ret = bdrv_file_open(&bs->file, raw, NULL, NULL, flags, &local_err);
+    /* Open the raw file */
+    ret = bdrv_open_image(&bs->file, qemu_opt_get(opts, "x-raw"), options,
+                          "raw", flags, true, false, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
         goto fail;
     }
 
     /* Open the test file */
-    filename = qemu_opt_get(opts, "x-image");
-    if (filename == NULL) {
-        error_setg(errp, "Could not retrieve test image filename");
-        ret = -EINVAL;
-        goto fail;
-    }
-
-    s->test_file = bdrv_new("");
-    ret = bdrv_open(s->test_file, filename, NULL, flags, NULL, &local_err);
+    ret = bdrv_open_image(&s->test_file, qemu_opt_get(opts, "x-image"), options,
+                          "test", flags, false, false, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
-        bdrv_unref(s->test_file);
         s->test_file = NULL;
         goto fail;
     }
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 34/42] blkverify: Don't require protocol filename
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (32 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 33/42] blkverify: Allow command-line configuration Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 35/42] qapi: Add "errno" to the list of polluted words Kevin Wolf
                   ` (7 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

If the filename is not prefixed by "blkverify:" in
blkverify_parse_filename(), the blkverify driver was not selected
through that protocol prefix, but by an explicit command line (or QMP)
option (like driver=blkverify).

If blkverify_parse_filename() has been called, a filename has been
given. If it is not prefixed, it is probably really just a plain
filename. This is no problem, since we can use it as the test image
filename and rely on the user to specify the raw image filename through
the new corresponding option.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/blkverify.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/block/blkverify.c b/block/blkverify.c
index dc14290..a2e8f5f 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -78,7 +78,9 @@ static void blkverify_parse_filename(const char *filename, QDict *options,
 
     /* Parse the blkverify: prefix */
     if (!strstart(filename, "blkverify:", &filename)) {
-        error_setg(errp, "File name string must start with 'blkverify:'");
+        /* There was no prefix; therefore, all options have to be already
+           present in the QDict (except for the filename) */
+        qdict_put(options, "x-image", qstring_from_str(filename));
         return;
     }
 
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 35/42] qapi: Add "errno" to the list of polluted words
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (33 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 34/42] blkverify: Don't require protocol filename Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify Kevin Wolf
                   ` (6 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Using "errno" directly as an identifier results in various syntax
errors; therefore it should be added to the list of polluted words.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 scripts/qapi.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qapi.py b/scripts/qapi.py
index 750e9fb..9b3de4c 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -247,7 +247,7 @@ def c_var(name, protect=True):
                      'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
                      'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
     # namespace pollution:
-    polluted_words = set(['unix'])
+    polluted_words = set(['unix', 'errno'])
     if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words):
         return "q_" + name
     return name.replace('-', '_').lstrip("*")
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (34 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 35/42] qapi: Add "errno" to the list of polluted words Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 15:19   ` Eric Blake
  2014-01-15 10:22 ` [Qemu-devel] [PULL 37/42] qemu-io: Make filename optional Kevin Wolf
                   ` (5 subsequent siblings)
  41 siblings, 1 reply; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Add structures to support blkdebug and blkverify in blockdev-add.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi-schema.json | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 109 insertions(+), 4 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index f27c48a..35f7b34 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4201,6 +4201,113 @@
             '*pass-discard-other': 'bool' } }
 
 ##
+# @BlkdebugEvent
+#
+# Trigger events supported by blkdebug.
+##
+{ 'enum': 'BlkdebugEvent',
+  'data': [ 'l1_update', 'l1_grow.alloc_table', 'l1_grow.write_table',
+            'l1_grow.activate_table', 'l2_load', 'l2_update',
+            'l2_update_compressed', 'l2_alloc.cow_read', 'l2_alloc.write',
+            'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio',
+            'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read',
+            'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update',
+            'refblock_load', 'refblock_update', 'refblock_update_part',
+            'refblock_alloc', 'refblock_alloc.hookup', 'refblock_alloc.write',
+            'refblock_alloc.write_blocks', 'refblock_alloc.write_table',
+            'refblock_alloc.switch_table', 'cluster_alloc',
+            'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
+            'flush_to_disk' ] }
+
+##
+# @BlkdebugInjectErrorOptions
+#
+# Describes a single error injection for blkdebug.
+#
+# @event:       trigger event
+#
+# @state:       #optional the state identifier blkdebug needs to be in to
+#               actually trigger the event; defaults to "any"
+#
+# @errno:       #optional error identifier (errno) to be returned; defaults to
+#               EIO
+#
+# @sector:      #optional specifies the sector index which has to be affected
+#               in order to actually trigger the event; defaults to "any
+#               sector"
+#
+# @once:        #optional disables further events after this one has been
+#               triggered; defaults to false
+#
+# @immediately: #optional fail immediately; defaults to false
+#
+# Since: 2.0
+##
+{ 'type': 'BlkdebugInjectErrorOptions',
+  'data': { 'event': 'BlkdebugEvent',
+            '*state': 'int',
+            '*errno': 'int',
+            '*sector': 'int',
+            '*once': 'bool',
+            '*immediately': 'bool' } }
+
+##
+# @BlkdebugSetStateOptions
+#
+# Describes a single state-change event for blkdebug.
+#
+# @event:       trigger event
+#
+# @state:       #optional the current state identifier blkdebug needs to be in;
+#               defaults to "any"
+#
+# @new_state:   the state identifier blkdebug is supposed to assume if
+#               this event is triggered
+#
+# Since: 2.0
+##
+{ 'type': 'BlkdebugSetStateOptions',
+  'data': { 'event': 'BlkdebugEvent',
+            '*state': 'int',
+            'new_state': 'int' } }
+
+##
+# @BlockdevOptionsBlkdebug
+#
+# Driver specific block device options for blkdebug.
+#
+# @image:           underlying raw block device (or image file)
+#
+# @config:          #optional filename of the configuration file
+#
+# @inject-error:    #optional array of error injection descriptions
+#
+# @set-state:       #optional array of state-change descriptions
+#
+# Since: 2.0
+##
+{ 'type': 'BlockdevOptionsBlkdebug',
+  'data': { 'image': 'BlockdevRef',
+            '*config': 'str',
+            '*inject-error': ['BlkdebugInjectErrorOptions'],
+            '*set-state': ['BlkdebugSetStateOptions'] } }
+
+##
+# @BlockdevOptionsBlkverify
+#
+# Driver specific block device options for blkverify.
+#
+# @test:    block device to be tested
+#
+# @raw:     raw image used for verification
+#
+# Since: 2.0
+##
+{ 'type': 'BlockdevOptionsBlkverify',
+  'data': { 'test': 'BlockdevRef',
+            'raw': 'BlockdevRef' } }
+
+##
 # @BlockdevOptions
 #
 # Options for creating a block device.
@@ -4224,10 +4331,8 @@
 # TODO sheepdog: Wait for structured options
 # TODO ssh: Should take InetSocketAddress for 'host'?
       'vvfat':      'BlockdevOptionsVVFAT',
-
-# TODO blkdebug: Wait for structured options
-# TODO blkverify: Wait for structured options
-
+      'blkdebug':   'BlockdevOptionsBlkdebug',
+      'blkverify':  'BlockdevOptionsBlkverify',
       'bochs':      'BlockdevOptionsGenericFormat',
       'cloop':      'BlockdevOptionsGenericFormat',
       'cow':        'BlockdevOptionsGenericCOWFormat',
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 37/42] qemu-io: Make filename optional
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (35 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 38/42] tests: Add test for qdict_array_split() Kevin Wolf
                   ` (4 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Giving a filename is actually not essential, since it can be specified
through the options as well - on the contrary: Sometimes a filename must
not be given.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-io.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/qemu-io.c b/qemu-io.c
index bfb773e..d669028 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -163,11 +163,13 @@ static int open_f(BlockDriverState *bs, int argc, char **argv)
         flags |= BDRV_O_RDWR;
     }
 
-    if (optind != argc - 1) {
+    if (optind == argc - 1) {
+        return openfile(argv[optind], flags, growable, opts);
+    } else if (optind == argc) {
+        return openfile(NULL, flags, growable, opts);
+    } else {
         return qemuio_command_usage(&open_cmd);
     }
-
-    return openfile(argv[optind], flags, growable, opts);
 }
 
 static int quit_f(BlockDriverState *bs, int argc, char **argv)
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 38/42] tests: Add test for qdict_array_split()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (36 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 37/42] qemu-io: Make filename optional Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 39/42] tests: Add test for qdict_flatten() Kevin Wolf
                   ` (3 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Add a test case for qdict_array_split() in tests/check-qdict.c.

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

diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index dc5f05a..cab7dd0 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -227,6 +227,85 @@ static void qdict_iterapi_test(void)
     QDECREF(tests_dict);
 }
 
+static void qdict_array_split_test(void)
+{
+    QDict *test_dict = qdict_new();
+    QDict *dict1, *dict2;
+    QList *test_list;
+
+    /*
+     * Test the split of
+     *
+     * {
+     *     "1.x": 0,
+     *     "3.y": 1,
+     *     "0.a": 42,
+     *     "o.o": 7,
+     *     "0.b": 23
+     * }
+     *
+     * to
+     *
+     * [
+     *     {
+     *         "a": 42,
+     *         "b": 23
+     *     },
+     *     {
+     *         "x": 0
+     *     }
+     * ]
+     *
+     * and
+     *
+     * {
+     *     "3.y": 1,
+     *     "o.o": 7
+     * }
+     *
+     * (remaining in the old QDict)
+     *
+     * This example is given in the comment of qdict_array_split().
+     */
+
+    qdict_put(test_dict, "1.x", qint_from_int(0));
+    qdict_put(test_dict, "3.y", qint_from_int(1));
+    qdict_put(test_dict, "0.a", qint_from_int(42));
+    qdict_put(test_dict, "o.o", qint_from_int(7));
+    qdict_put(test_dict, "0.b", qint_from_int(23));
+
+    qdict_array_split(test_dict, &test_list);
+
+    dict1 = qobject_to_qdict(qlist_pop(test_list));
+    dict2 = qobject_to_qdict(qlist_pop(test_list));
+
+    g_assert(dict1);
+    g_assert(dict2);
+    g_assert(qlist_empty(test_list));
+
+    QDECREF(test_list);
+
+    g_assert(qdict_get_int(dict1, "a") == 42);
+    g_assert(qdict_get_int(dict1, "b") == 23);
+
+    g_assert(qdict_size(dict1) == 2);
+
+    QDECREF(dict1);
+
+    g_assert(qdict_get_int(dict2, "x") == 0);
+
+    g_assert(qdict_size(dict2) == 1);
+
+    QDECREF(dict2);
+
+    g_assert(qdict_get_int(test_dict, "3.y") == 1);
+    g_assert(qdict_get_int(test_dict, "o.o") == 7);
+
+    g_assert(qdict_size(test_dict) == 2);
+
+    QDECREF(test_dict);
+}
+
 /*
  * Errors test-cases
  */
@@ -365,6 +444,7 @@ int main(int argc, char **argv)
     g_test_add_func("/public/del", qdict_del_test);
     g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
     g_test_add_func("/public/iterapi", qdict_iterapi_test);
+    g_test_add_func("/public/array_split", qdict_array_split_test);
 
     g_test_add_func("/errors/put_exists", qdict_put_exists_test);
     g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 39/42] tests: Add test for qdict_flatten()
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (37 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 38/42] tests: Add test for qdict_array_split() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 40/42] iotests: Test new blkdebug/blkverify interface Kevin Wolf
                   ` (2 subsequent siblings)
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Add a test case for qdict_flatten() in tests/check-qdict.c. This test
case covers the flattening of subordinate QLists as well.

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

diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index cab7dd0..7a7461b 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -227,6 +227,81 @@ static void qdict_iterapi_test(void)
     QDECREF(tests_dict);
 }
 
+static void qdict_flatten_test(void)
+{
+    QList *list1 = qlist_new();
+    QList *list2 = qlist_new();
+    QDict *dict1 = qdict_new();
+    QDict *dict2 = qdict_new();
+    QDict *dict3 = qdict_new();
+
+    /*
+     * Test the flattening of
+     *
+     * {
+     *     "e": [
+     *         42,
+     *         [
+     *             23,
+     *             66,
+     *             {
+     *                 "a": 0,
+     *                 "b": 1
+     *             }
+     *         ]
+     *     ],
+     *     "f": {
+     *         "c": 2,
+     *         "d": 3,
+     *     },
+     *     "g": 4
+     * }
+     *
+     * to
+     *
+     * {
+     *     "e.0": 42,
+     *     "e.1.0": 23,
+     *     "e.1.1": 66,
+     *     "e.1.2.a": 0,
+     *     "e.1.2.b": 1,
+     *     "f.c": 2,
+     *     "f.d": 3,
+     *     "g": 4
+     * }
+     */
+
+    qdict_put(dict1, "a", qint_from_int(0));
+    qdict_put(dict1, "b", qint_from_int(1));
+
+    qlist_append_obj(list1, QOBJECT(qint_from_int(23)));
+    qlist_append_obj(list1, QOBJECT(qint_from_int(66)));
+    qlist_append_obj(list1, QOBJECT(dict1));
+    qlist_append_obj(list2, QOBJECT(qint_from_int(42)));
+    qlist_append_obj(list2, QOBJECT(list1));
+
+    qdict_put(dict2, "c", qint_from_int(2));
+    qdict_put(dict2, "d", qint_from_int(3));
+    qdict_put_obj(dict3, "e", QOBJECT(list2));
+    qdict_put_obj(dict3, "f", QOBJECT(dict2));
+    qdict_put(dict3, "g", qint_from_int(4));
+
+    qdict_flatten(dict3);
+
+    g_assert(qdict_get_int(dict3, "e.0") == 42);
+    g_assert(qdict_get_int(dict3, "e.1.0") == 23);
+    g_assert(qdict_get_int(dict3, "e.1.1") == 66);
+    g_assert(qdict_get_int(dict3, "e.1.2.a") == 0);
+    g_assert(qdict_get_int(dict3, "e.1.2.b") == 1);
+    g_assert(qdict_get_int(dict3, "f.c") == 2);
+    g_assert(qdict_get_int(dict3, "f.d") == 3);
+    g_assert(qdict_get_int(dict3, "g") == 4);
+
+    g_assert(qdict_size(dict3) == 8);
+
+    QDECREF(dict3);
+}
+
 static void qdict_array_split_test(void)
 {
     QDict *test_dict = qdict_new();
@@ -444,6 +519,7 @@ int main(int argc, char **argv)
     g_test_add_func("/public/del", qdict_del_test);
     g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
     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("/errors/put_exists", qdict_put_exists_test);
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 40/42] iotests: Test new blkdebug/blkverify interface
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (38 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 39/42] tests: Add test for qdict_flatten() Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 41/42] iotests: Test file format nesting Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 42/42] block: fix backing file segfault Kevin Wolf
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Add a test for the new blkdebug/blkverify interface.

This test is not written in Python, although it uses QMP. This is
because it invokes the qemu-io HMP command, which outputs errors to
stderr instead of returning them through QMP. Filtering and testing that
output is easier in a shell script than with the Python infrastructure.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/071     | 239 +++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/071.out |  90 +++++++++++++++++
 tests/qemu-iotests/group   |   1 +
 3 files changed, 330 insertions(+)
 create mode 100755 tests/qemu-iotests/071
 create mode 100644 tests/qemu-iotests/071.out

diff --git a/tests/qemu-iotests/071 b/tests/qemu-iotests/071
new file mode 100755
index 0000000..2a22546
--- /dev/null
+++ b/tests/qemu-iotests/071
@@ -0,0 +1,239 @@
+#!/bin/bash
+#
+# Test case for the QMP blkdebug and blkverify interfaces
+#
+# Copyright (C) 2013 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 generic
+_supported_os Linux
+
+function do_run_qemu()
+{
+    echo Testing: "$@" | _filter_imgfmt
+    $QEMU -nographic -qmp stdio -serial none "$@"
+    echo
+}
+
+function run_qemu()
+{
+    do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu_io
+}
+
+IMG_SIZE=64M
+
+echo
+echo "=== Testing blkverify through filename ==="
+echo
+
+TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
+    _filter_imgfmt
+_make_test_img $IMG_SIZE
+$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \
+         -c 'read 0 512' -c 'write -P 42 0x38000 512' -c 'read -P 42 0x38000 512' | _filter_qemu_io
+
+$QEMU_IO -c 'write -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \
+         -c 'read -P 42 0 512' | _filter_qemu_io
+
+echo
+echo "=== Testing blkverify through file blockref ==="
+echo
+
+TEST_IMG="$TEST_IMG.base" IMGOPTS="" IMGFMT="raw" _make_test_img $IMG_SIZE |\
+    _filter_imgfmt
+_make_test_img $IMG_SIZE
+$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base,file.test.driver=$IMGFMT,file.test.file.filename=$TEST_IMG" \
+         -c 'read 0 512' -c 'write -P 42 0x38000 512' -c 'read -P 42 0x38000 512' | _filter_qemu_io
+
+$QEMU_IO -c 'write -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "open -o file.driver=blkverify,file.raw.filename=$TEST_IMG.base $TEST_IMG" \
+         -c 'read -P 42 0 512' | _filter_qemu_io
+
+echo
+echo "=== Testing blkdebug through filename ==="
+echo
+
+$QEMU_IO -c "open -o file.driver=blkdebug,file.inject-error.event=l2_load $TEST_IMG" \
+         -c 'read -P 42 0x38000 512'
+
+echo
+echo "=== Testing blkdebug through file blockref ==="
+echo
+
+$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=blkdebug,file.inject-error.event=l2_load,file.image.filename=$TEST_IMG" \
+         -c 'read -P 42 0x38000 512'
+
+echo
+echo "=== Testing blkdebug on existing block device ==="
+echo
+
+run_qemu -drive "file=$TEST_IMG,format=raw,if=none,id=drive0" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
+            "driver": "$IMGFMT",
+            "id": "drive0-debug",
+            "file": {
+                "driver": "blkdebug",
+                "image": "drive0",
+                "inject-error": [{
+                    "event": "l2_load"
+                }]
+            }
+        }
+    }
+}
+{ "execute": "human-monitor-command",
+    "arguments": {
+        "command-line": 'qemu-io drive0-debug "read 0 512"'
+    }
+}
+{ "execute": "quit" }
+EOF
+
+echo
+echo "=== Testing blkverify on existing block device ==="
+echo
+
+run_qemu -drive "file=$TEST_IMG,format=$IMGFMT,if=none,id=drive0" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
+            "driver": "blkverify",
+            "id": "drive0-verify",
+            "test": "drive0",
+            "raw": {
+                "driver": "raw",
+                "file": {
+                    "driver": "file",
+                    "filename": "$TEST_IMG.base"
+                }
+            }
+        }
+    }
+}
+{ "execute": "human-monitor-command",
+    "arguments": {
+        "command-line": 'qemu-io drive0-verify "read 0 512"'
+    }
+}
+{ "execute": "quit" }
+EOF
+
+echo
+echo "=== Testing blkverify on existing raw block device ==="
+echo
+
+run_qemu -drive "file=$TEST_IMG.base,if=none,id=drive0" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
+            "driver": "blkverify",
+            "id": "drive0-verify",
+            "test": {
+                "driver": "$IMGFMT",
+                "file": {
+                    "driver": "file",
+                    "filename": "$TEST_IMG"
+                }
+            },
+            "raw": "drive0"
+        }
+    }
+}
+{ "execute": "human-monitor-command",
+    "arguments": {
+        "command-line": 'qemu-io drive0-verify "read 0 512"'
+    }
+}
+{ "execute": "quit" }
+EOF
+
+echo
+echo "=== Testing blkdebug's set-state through QMP ==="
+echo
+
+run_qemu -drive "file=$TEST_IMG,format=raw,if=none,id=drive0" <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "blockdev-add",
+    "arguments": {
+        "options": {
+            "driver": "$IMGFMT",
+            "id": "drive0-debug",
+            "file": {
+                "driver": "blkdebug",
+                "image": "drive0",
+                "inject-error": [{
+                    "event": "read_aio",
+                    "state": 42
+                }],
+                "set-state": [{
+                    "event": "write_aio",
+                    "new_state": 42
+                }]
+            }
+        }
+    }
+}
+{ "execute": "human-monitor-command",
+    "arguments": {
+        "command-line": 'qemu-io drive0-debug "read 0 512"'
+    }
+}
+{ "execute": "human-monitor-command",
+    "arguments": {
+        "command-line": 'qemu-io drive0-debug "write 0 512"'
+    }
+}
+{ "execute": "human-monitor-command",
+    "arguments": {
+        "command-line": 'qemu-io drive0-debug "read 0 512"'
+    }
+}
+{ "execute": "quit" }
+EOF
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
new file mode 100644
index 0000000..5f840a9
--- /dev/null
+++ b/tests/qemu-iotests/071.out
@@ -0,0 +1,90 @@
+QA output created by 071
+
+=== Testing blkverify through filename ===
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 229376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 229376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+blkverify: read sector_num=0 nb_sectors=4 contents mismatch in sector 0
+
+=== Testing blkverify through file blockref ===
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 229376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 229376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+blkverify: read sector_num=0 nb_sectors=4 contents mismatch in sector 0
+
+=== Testing blkdebug through filename ===
+
+read failed: Input/output error
+
+=== Testing blkdebug through file blockref ===
+
+read failed: Input/output error
+
+=== Testing blkdebug on existing block device ===
+
+Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+read failed: Input/output error
+{"return": ""}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+
+
+=== Testing blkverify on existing block device ===
+
+Testing: -drive file=TEST_DIR/t.IMGFMT,format=IMGFMT,if=none,id=drive0
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0
+
+
+=== Testing blkverify on existing raw block device ===
+
+Testing: -drive file=TEST_DIR/t.IMGFMT.base,if=none,id=drive0
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0
+
+
+=== Testing blkdebug's set-state through QMP ===
+
+Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+read failed: Input/output error
+{"return": ""}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index cc750c9..1194339 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -77,5 +77,6 @@
 068 rw auto
 069 rw auto
 070 rw auto
+071 rw auto
 073 rw auto
 074 rw auto
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 41/42] iotests: Test file format nesting
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (39 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 40/42] iotests: Test new blkdebug/blkverify interface Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  2014-01-15 10:22 ` [Qemu-devel] [PULL 42/42] block: fix backing file segfault Kevin Wolf
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Max Reitz <mreitz@redhat.com>

Add a test for nested image formats.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/072     | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/072.out | 21 ++++++++++++++
 tests/qemu-iotests/group   |  1 +
 3 files changed, 91 insertions(+)
 create mode 100755 tests/qemu-iotests/072
 create mode 100644 tests/qemu-iotests/072.out

diff --git a/tests/qemu-iotests/072 b/tests/qemu-iotests/072
new file mode 100755
index 0000000..a3876c2
--- /dev/null
+++ b/tests/qemu-iotests/072
@@ -0,0 +1,69 @@
+#!/bin/bash
+#
+# Test case for nested image formats
+#
+# Copyright (C) 2013 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 vpc vmdk vhdx vdi qed qcow2 qcow cow
+_supported_proto generic
+_supported_os Linux
+
+IMG_SIZE=64M
+
+echo
+echo "=== Testing nested image formats ==="
+echo
+
+TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE
+
+$QEMU_IO -c 'write -P 42 0 512' -c 'write -P 23 512 512' \
+         -c 'write -P 66 1024 512' "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IMG convert -f raw -O $IMGFMT "$TEST_IMG.base" "$TEST_IMG"
+
+$QEMU_IO -c "open -o driver=$IMGFMT,file.driver=$IMGFMT,file.file.filename=$TEST_IMG" \
+         -c 'read -P 42 0 512' -c 'read -P 23 512 512' \
+         -c 'read -P 66 1024 512' | _filter_qemu_io
+
+# When not giving any format, qemu should open only one "layer". Therefore, this
+# should not work for any image formats with a header.
+$QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/072.out b/tests/qemu-iotests/072.out
new file mode 100644
index 0000000..efe577c
--- /dev/null
+++ b/tests/qemu-iotests/072.out
@@ -0,0 +1,21 @@
+QA output created by 072
+
+=== Testing nested image formats ===
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 1024
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 1024
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Pattern verification failed at offset 0, 512 bytes
+read 512/512 bytes at offset 0
+512 bytes, 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 1194339..5860c40 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -78,5 +78,6 @@
 069 rw auto
 070 rw auto
 071 rw auto
+072 rw auto
 073 rw auto
 074 rw auto
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 42/42] block: fix backing file segfault
  2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
                   ` (40 preceding siblings ...)
  2014-01-15 10:22 ` [Qemu-devel] [PULL 41/42] iotests: Test file format nesting Kevin Wolf
@ 2014-01-15 10:22 ` Kevin Wolf
  41 siblings, 0 replies; 51+ messages in thread
From: Kevin Wolf @ 2014-01-15 10:22 UTC (permalink / raw)
  To: anthony; +Cc: kwolf, qemu-devel

From: Peter Feiner <peter@gridcentric.ca>

When a backing file is opened such that (1) a protocol is directly
used as the block driver and (2) the block driver has bdrv_file_open,
bdrv_open_backing_file segfaults. The problem arises because
bdrv_open_common returns without setting bd->backing_hd->file.

To effect (1), you seem to have to use the -F flag in qemu-img. There
are several block drivers that satisfy (2), such as "file" and "nbd".
Here are some concrete examples:

    #!/bin/bash

    echo Test file format
    ./qemu-img create -f file base.file 1m
    ./qemu-img create -f qcow2 -F file -o backing_file=base.file\
        file-overlay.qcow2
    ./qemu-img convert -O raw file-overlay.qcow2 file-convert.raw

    echo Test nbd format
    SOCK=$PWD/nbd.sock
    ./qemu-img create -f raw base.raw 1m
    ./qemu-nbd -t -k $SOCK base.raw &
    trap "kill $!" EXIT
    while ! test -e $SOCK; do sleep 1; done
    ./qemu-img create -f qcow2 -F nbd -o backing_file=nbd:unix:$SOCK\
        nbd-overlay.qcow2
    ./qemu-img convert -O raw nbd-overlay.qcow2 nbd-convert.raw

Without this patch, the two qemu-img convert commands segfault.

This is a regression that was introduced in v1.7 by
dbecebddfa4932d1c83915bcb9b5ba5984eb91be.

Signed-off-by: Peter Feiner <peter@gridcentric.ca>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/block.c b/block.c
index 6af5f6e..418dbe9 100644
--- a/block.c
+++ b/block.c
@@ -1040,8 +1040,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
         error_free(local_err);
         return ret;
     }
-    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
-            bs->backing_hd->file->filename);
+    if (bs->backing_hd->file)
+        pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+                bs->backing_hd->file->filename);
     return 0;
 }
 
-- 
1.8.1.4

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

* Re: [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify
  2014-01-15 10:22 ` [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify Kevin Wolf
@ 2014-01-15 15:19   ` Eric Blake
  2014-01-15 17:11     ` Paolo Bonzini
  2014-01-16 10:03     ` Kevin Wolf
  0 siblings, 2 replies; 51+ messages in thread
From: Eric Blake @ 2014-01-15 15:19 UTC (permalink / raw)
  To: Kevin Wolf, anthony; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 4424 bytes --]

On 01/15/2014 03:22 AM, Kevin Wolf wrote:
> From: Max Reitz <mreitz@redhat.com>
> 
> Add structures to support blkdebug and blkverify in blockdev-add.
> 
> Signed-off-by: Max Reitz <mreitz@redhat.com>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  qapi-schema.json | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 109 insertions(+), 4 deletions(-)

Sorry for not noticing this sooner, but we still have some interface
problems that need to be ironed out.

> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index f27c48a..35f7b34 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -4201,6 +4201,113 @@
>              '*pass-discard-other': 'bool' } }
>  
>  ##
> +# @BlkdebugEvent
> +#
> +# Trigger events supported by blkdebug.
> +##
> +{ 'enum': 'BlkdebugEvent',

Missing a 'Since: 2.0' designation; would be worth adding that in a
followup patch.

> +  'data': [ 'l1_update', 'l1_grow.alloc_table', 'l1_grow.write_table',
> +            'l1_grow.activate_table', 'l2_load', 'l2_update',
> +            'l2_update_compressed', 'l2_alloc.cow_read', 'l2_alloc.write',
> +            'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio',
> +            'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read',
> +            'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update',
> +            'refblock_load', 'refblock_update', 'refblock_update_part',
> +            'refblock_alloc', 'refblock_alloc.hookup', 'refblock_alloc.write',
> +            'refblock_alloc.write_blocks', 'refblock_alloc.write_table',
> +            'refblock_alloc.switch_table', 'cluster_alloc',
> +            'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
> +            'flush_to_disk' ] }

Do we want to prefer '-' over '_' in all these names?

> +
> +##
> +# @BlkdebugInjectErrorOptions
> +#
> +# Describes a single error injection for blkdebug.
> +#
> +# @event:       trigger event
> +#
> +# @state:       #optional the state identifier blkdebug needs to be in to
> +#               actually trigger the event; defaults to "any"

This sounds like it is a finite set of states, and therefore should be
an enum rather than an 'int'.

> +#
> +# @errno:       #optional error identifier (errno) to be returned; defaults to
> +#               EIO

errno is not a portable.  The values of errno on one machine may not
match the values of errno on the other machine using the QMP connection
via a remote socket.  It might be cleaner to have an enum of named error
values, rather than integer errno values.

> +#
> +# @sector:      #optional specifies the sector index which has to be affected
> +#               in order to actually trigger the event; defaults to "any
> +#               sector"
> +#
> +# @once:        #optional disables further events after this one has been
> +#               triggered; defaults to false
> +#
> +# @immediately: #optional fail immediately; defaults to false
> +#
> +# Since: 2.0
> +##
> +{ 'type': 'BlkdebugInjectErrorOptions',
> +  'data': { 'event': 'BlkdebugEvent',
> +            '*state': 'int',
> +            '*errno': 'int',
> +            '*sector': 'int',
> +            '*once': 'bool',
> +            '*immediately': 'bool' } }
> +
> +##
> +# @BlkdebugSetStateOptions
> +#
> +# Describes a single state-change event for blkdebug.
> +#
> +# @event:       trigger event
> +#
> +# @state:       #optional the current state identifier blkdebug needs to be in;
> +#               defaults to "any"
> +#

Again, this should be an enum, not an int.

> +# @new_state:   the state identifier blkdebug is supposed to assume if
> +#               this event is triggered

s/new_state/new-state/

> @@ -4224,10 +4331,8 @@
>  # TODO sheepdog: Wait for structured options
>  # TODO ssh: Should take InetSocketAddress for 'host'?
>        'vvfat':      'BlockdevOptionsVVFAT',
> -
> -# TODO blkdebug: Wait for structured options
> -# TODO blkverify: Wait for structured options
> -
> +      'blkdebug':   'BlockdevOptionsBlkdebug',
> +      'blkverify':  'BlockdevOptionsBlkverify',

As we are adding new arms to the union, we should document that these
values are available since 2.0.

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


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

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

* Re: [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify
  2014-01-15 15:19   ` Eric Blake
@ 2014-01-15 17:11     ` Paolo Bonzini
  2014-01-16 10:03     ` Kevin Wolf
  1 sibling, 0 replies; 51+ messages in thread
From: Paolo Bonzini @ 2014-01-15 17:11 UTC (permalink / raw)
  To: Eric Blake; +Cc: Kevin Wolf, qemu-devel, anthony

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 15/01/2014 16:19, Eric Blake ha scritto:
>> +# +# @errno:       #optional error identifier (errno) to be
>> returned; defaults to +#               EIO
> 
> errno is not a portable.  The values of errno on one machine may
> not match the values of errno on the other machine using the QMP
> connection via a remote socket.  It might be cleaner to have an
> enum of named error values, rather than integer errno values.

This has been on my todo list for a huge time.  I'll try to set aside
some time.

Paolo
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJS1sFDAAoJEBvWZb6bTYbycoIQAIB2bonsqfY2jcr+weibAotc
26t8+JY9jcQTs392+7naoHYLxgGzqVsas18tZO4rdX+8/qyhKxNT1gY5IsAmBvmV
raI3pU69QJfvEWgjpGY5GeYMxRlVH4Pxw+XOaJARoghMx2IpeHiPqFU7Kkc1YwJ+
reFysBNEXaAheOopeWI2xKz8r+gVNeiKDMDoQ7yOpGKp5t9p/qBSLhSjL/utGxOQ
rx1lSmGExRiG5wQF8rxOA2JDRYpJzGAGi2aYHP+vJDleaYAzEoHnbm5DUVEKs5ro
6vefj/Es5T3YKOfJAxtQfq3PQ62CTfkX/+hJD451moAlHLlc8WPzNfDQYm0iD6Bv
M4GbSjDZB6rU/ngHcxO462VQqd9sl2WbdDeE0hdWkL2ZzVcR+SJ+Uf50FXAHCna0
hRWqES+k6Bl6wcHoCt8yF9UkBS8Ac6/puJzHl2jQT1GK8HC0+at9UU+5lArPo3kj
Nsq930WjOmjeYQrH7qsn96ecBBTW/hD+PoYz/er5xjdmUNXiG3OKr/0Q3uTalyKE
PNZAzFmLBx0GalmiTLySwAxB0xx+to0wl4+qwhNfSenBsM2n4Mv0YHdKFEVND40I
WNVvJigkjb9lSzpdXJvoIMd860F1SHDhRf4+fjOI8pneWmZKmfNBeobtPUntyVY7
Z2HaUHDIGo6qKqvQS6zQ
=p34S
-----END PGP SIGNATURE-----

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

* Re: [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify
  2014-01-15 15:19   ` Eric Blake
  2014-01-15 17:11     ` Paolo Bonzini
@ 2014-01-16 10:03     ` Kevin Wolf
  2014-01-17 15:01       ` Andreas Färber
  1 sibling, 1 reply; 51+ messages in thread
From: Kevin Wolf @ 2014-01-16 10:03 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-devel, anthony

[-- Attachment #1: Type: text/plain, Size: 5530 bytes --]

Am 15.01.2014 um 16:19 hat Eric Blake geschrieben:
> On 01/15/2014 03:22 AM, Kevin Wolf wrote:
> > From: Max Reitz <mreitz@redhat.com>
> > 
> > Add structures to support blkdebug and blkverify in blockdev-add.
> > 
> > Signed-off-by: Max Reitz <mreitz@redhat.com>
> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > ---
> >  qapi-schema.json | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 109 insertions(+), 4 deletions(-)
> 
> Sorry for not noticing this sooner, but we still have some interface
> problems that need to be ironed out.

Nothing that should hold up this pull request, there are just a few
improvements that can be done in a follow-up.

> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index f27c48a..35f7b34 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -4201,6 +4201,113 @@
> >              '*pass-discard-other': 'bool' } }
> >  
> >  ##
> > +# @BlkdebugEvent
> > +#
> > +# Trigger events supported by blkdebug.
> > +##
> > +{ 'enum': 'BlkdebugEvent',
> 
> Missing a 'Since: 2.0' designation; would be worth adding that in a
> followup patch.

Ack.

> > +  'data': [ 'l1_update', 'l1_grow.alloc_table', 'l1_grow.write_table',
> > +            'l1_grow.activate_table', 'l2_load', 'l2_update',
> > +            'l2_update_compressed', 'l2_alloc.cow_read', 'l2_alloc.write',
> > +            'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio',
> > +            'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read',
> > +            'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update',
> > +            'refblock_load', 'refblock_update', 'refblock_update_part',
> > +            'refblock_alloc', 'refblock_alloc.hookup', 'refblock_alloc.write',
> > +            'refblock_alloc.write_blocks', 'refblock_alloc.write_table',
> > +            'refblock_alloc.switch_table', 'cluster_alloc',
> > +            'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
> > +            'flush_to_disk' ] }
> 
> Do we want to prefer '-' over '_' in all these names?

These are existing names from the blkdebug configuration file. If we
wanted to have '-' in QMP and '_' in the config file, we'd have to have
some conversion somewhere. Uglier than having underscores here, imho.

> > +
> > +##
> > +# @BlkdebugInjectErrorOptions
> > +#
> > +# Describes a single error injection for blkdebug.
> > +#
> > +# @event:       trigger event
> > +#
> > +# @state:       #optional the state identifier blkdebug needs to be in to
> > +#               actually trigger the event; defaults to "any"
> 
> This sounds like it is a finite set of states, and therefore should be
> an enum rather than an 'int'.

No, these are user-defined states.

> > +#
> > +# @errno:       #optional error identifier (errno) to be returned; defaults to
> > +#               EIO
> 
> errno is not a portable.  The values of errno on one machine may not
> match the values of errno on the other machine using the QMP connection
> via a remote socket.  It might be cleaner to have an enum of named error
> values, rather than integer errno values.

That's true. On the other hand this is only blkdebug, which is used for
testing and debugging and nothing else. I know what the errno values are
on my machine, so in practice this is good enough for me.

If someone feels bored and wants to clean it up later, be my guest, but
as far as I am concerned, in this specific place it's a non-problem.

> > +#
> > +# @sector:      #optional specifies the sector index which has to be affected
> > +#               in order to actually trigger the event; defaults to "any
> > +#               sector"
> > +#
> > +# @once:        #optional disables further events after this one has been
> > +#               triggered; defaults to false
> > +#
> > +# @immediately: #optional fail immediately; defaults to false
> > +#
> > +# Since: 2.0
> > +##
> > +{ 'type': 'BlkdebugInjectErrorOptions',
> > +  'data': { 'event': 'BlkdebugEvent',
> > +            '*state': 'int',
> > +            '*errno': 'int',
> > +            '*sector': 'int',
> > +            '*once': 'bool',
> > +            '*immediately': 'bool' } }
> > +
> > +##
> > +# @BlkdebugSetStateOptions
> > +#
> > +# Describes a single state-change event for blkdebug.
> > +#
> > +# @event:       trigger event
> > +#
> > +# @state:       #optional the current state identifier blkdebug needs to be in;
> > +#               defaults to "any"
> > +#
> 
> Again, this should be an enum, not an int.

See above.

> > +# @new_state:   the state identifier blkdebug is supposed to assume if
> > +#               this event is triggered
> 
> s/new_state/new-state/

Again, existing blkdebug config stuff.

> > @@ -4224,10 +4331,8 @@
> >  # TODO sheepdog: Wait for structured options
> >  # TODO ssh: Should take InetSocketAddress for 'host'?
> >        'vvfat':      'BlockdevOptionsVVFAT',
> > -
> > -# TODO blkdebug: Wait for structured options
> > -# TODO blkverify: Wait for structured options
> > -
> > +      'blkdebug':   'BlockdevOptionsBlkdebug',
> > +      'blkverify':  'BlockdevOptionsBlkverify',
> 
> As we are adding new arms to the union, we should document that these
> values are available since 2.0.

Hm, yes, I think this request makes sense. Do we have an existing example
of such documentation? Because I'm not quite sure where to put it.

Kevin

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify
  2014-01-16 10:03     ` Kevin Wolf
@ 2014-01-17 15:01       ` Andreas Färber
  0 siblings, 0 replies; 51+ messages in thread
From: Andreas Färber @ 2014-01-17 15:01 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, anthony

Am 16.01.2014 11:03, schrieb Kevin Wolf:
> Am 15.01.2014 um 16:19 hat Eric Blake geschrieben:
>> On 01/15/2014 03:22 AM, Kevin Wolf wrote:
>>> From: Max Reitz <mreitz@redhat.com>
>>>
>>> Add structures to support blkdebug and blkverify in blockdev-add.
>>>
>>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>>> ---
>>>  qapi-schema.json | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>>>  1 file changed, 109 insertions(+), 4 deletions(-)
>>
>> Sorry for not noticing this sooner, but we still have some interface
>> problems that need to be ironed out.
> 
> Nothing that should hold up this pull request, there are just a few
> improvements that can be done in a follow-up.
> 
>>> diff --git a/qapi-schema.json b/qapi-schema.json
>>> index f27c48a..35f7b34 100644
>>> --- a/qapi-schema.json
>>> +++ b/qapi-schema.json
>>> @@ -4201,6 +4201,113 @@
>>>              '*pass-discard-other': 'bool' } }
>>>  
>>>  ##
>>> +# @BlkdebugEvent
>>> +#
>>> +# Trigger events supported by blkdebug.
>>> +##
>>> +{ 'enum': 'BlkdebugEvent',
>>
>> Missing a 'Since: 2.0' designation; would be worth adding that in a
>> followup patch.
> 
> Ack.
> 
>>> +  'data': [ 'l1_update', 'l1_grow.alloc_table', 'l1_grow.write_table',
>>> +            'l1_grow.activate_table', 'l2_load', 'l2_update',
>>> +            'l2_update_compressed', 'l2_alloc.cow_read', 'l2_alloc.write',
>>> +            'read_aio', 'read_backing_aio', 'read_compressed', 'write_aio',
>>> +            'write_compressed', 'vmstate_load', 'vmstate_save', 'cow_read',
>>> +            'cow_write', 'reftable_load', 'reftable_grow', 'reftable_update',
>>> +            'refblock_load', 'refblock_update', 'refblock_update_part',
>>> +            'refblock_alloc', 'refblock_alloc.hookup', 'refblock_alloc.write',
>>> +            'refblock_alloc.write_blocks', 'refblock_alloc.write_table',
>>> +            'refblock_alloc.switch_table', 'cluster_alloc',
>>> +            'cluster_alloc_bytes', 'cluster_free', 'flush_to_os',
>>> +            'flush_to_disk' ] }
>>
>> Do we want to prefer '-' over '_' in all these names?
> 
> These are existing names from the blkdebug configuration file. If we
> wanted to have '-' in QMP and '_' in the config file, we'd have to have
> some conversion somewhere. Uglier than having underscores here, imho.
[snip]

FWIW for -cpu we added code to do an automatic conversion from '_' to
'-' so that we could name QOM properties the new way while keeping
command line compatibility. As a side-effect, both became possible IIUC.

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail
  2014-01-15 10:22 ` [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail Kevin Wolf
@ 2014-01-17 15:06   ` Andreas Färber
  2014-01-18 11:54     ` Kewei Yu
  0 siblings, 1 reply; 51+ messages in thread
From: Andreas Färber @ 2014-01-17 15:06 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, anthony

Am 15.01.2014 11:22, schrieb Kevin Wolf:
> From: Kewei Yu <keweihk@gmail.com>
> 
> When we disable vnc from "./configure", QEMU can't use the vnc option.
> So qtest can't use the "vnc -none ", otherwise "make check" fails.
> If QEMU uses "-display none", "-vnc none" is excrescent, So we just need to drop it.
> 
> Signed-off-by: Kewei Yu <keweihk@gmail.com>
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

If the pull does get respun, 'Fix "make check" failing for
--disable-vnc' would be better English. ;)

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail
  2014-01-17 15:06   ` Andreas Färber
@ 2014-01-18 11:54     ` Kewei Yu
  2014-01-26  0:06       ` Andreas Färber
  0 siblings, 1 reply; 51+ messages in thread
From: Kewei Yu @ 2014-01-18 11:54 UTC (permalink / raw)
  To: Andreas Färber; +Cc: Kevin Wolf, qemu-devel@nongnu.org Developers, anthony

[-- Attachment #1: Type: text/plain, Size: 887 bytes --]

2014/1/17 Andreas Färber <afaerber@suse.de>

> Am 15.01.2014 11:22, schrieb Kevin Wolf:
> > From: Kewei Yu <keweihk@gmail.com>
> >
> > When we disable vnc from "./configure", QEMU can't use the vnc option.
> > So qtest can't use the "vnc -none ", otherwise "make check" fails.
> > If QEMU uses "-display none", "-vnc none" is excrescent, So we just need
> to drop it.
> >
> > Signed-off-by: Kewei Yu <keweihk@gmail.com>
> > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>
> If the pull does get respun, 'Fix "make check" failing for
> --disable-vnc' would be better English. ;)
>
 Yes, It is more accurate. So.... I should re-submit it?

>
> Andreas
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
>
> Kewei

[-- Attachment #2: Type: text/html, Size: 1984 bytes --]

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

* Re: [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail
  2014-01-18 11:54     ` Kewei Yu
@ 2014-01-26  0:06       ` Andreas Färber
  2014-01-26  8:04         ` Kewei Yu
  0 siblings, 1 reply; 51+ messages in thread
From: Andreas Färber @ 2014-01-26  0:06 UTC (permalink / raw)
  To: Kewei Yu; +Cc: Kevin Wolf, qemu-devel@nongnu.org Developers, anthony

Am 18.01.2014 12:54, schrieb Kewei Yu:
> 
> 2014/1/17 Andreas Färber <afaerber@suse.de <mailto:afaerber@suse.de>>
> 
>     Am 15.01.2014 11:22, schrieb Kevin Wolf:
>     > From: Kewei Yu <keweihk@gmail.com <mailto:keweihk@gmail.com>>
>     >
>     > When we disable vnc from "./configure", QEMU can't use the vnc option.
>     > So qtest can't use the "vnc -none ", otherwise "make check" fails.
>     > If QEMU uses "-display none", "-vnc none" is excrescent, So we
>     just need to drop it.
>     >
>     > Signed-off-by: Kewei Yu <keweihk@gmail.com <mailto:keweihk@gmail.com>>
>     > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com
>     <mailto:pbonzini@redhat.com>>
>     > Signed-off-by: Kevin Wolf <kwolf@redhat.com <mailto:kwolf@redhat.com>>
> 
>     If the pull does get respun, 'Fix "make check" failing for
>     --disable-vnc' would be better English. ;)
> 
>  Yes, It is more accurate. So.... I should re-submit it?

Sorry for the late answer. Since it was already in the maintainer's
queue and just about the commit message, it's not necessary for you to
resubmit, my comment was addressed to Kevin. When a "PULL" has been
sent, only major reasons (like build breakages, missing/wrong Sob, etc.)
lead to a resubmission by the maintainer.

Apart from the grammar issues ("causes ... to fail" or "... failure",
"disabling ... causes"), please keep in mind that many commits fix bugs,
so it will be more useful to the reader of patch/commit to read
prominently what is changing (and why) to determine whether he/she is
affected. Hope that explains.

Regards,
Andreas

> 
> 
>     Andreas
> 
>     --
>     SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
>     GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
> 
> Kewei

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail
  2014-01-26  0:06       ` Andreas Färber
@ 2014-01-26  8:04         ` Kewei Yu
  0 siblings, 0 replies; 51+ messages in thread
From: Kewei Yu @ 2014-01-26  8:04 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Kevin Wolf, qemu-devel@nongnu.org Developers, Anthony Liguori

[-- Attachment #1: Type: text/plain, Size: 2192 bytes --]

2014/1/26 Andreas Färber <afaerber@suse.de>

> Am 18.01.2014 12:54, schrieb Kewei Yu:
> >
> > 2014/1/17 Andreas Färber <afaerber@suse.de <mailto:afaerber@suse.de>>
> >
> >     Am 15.01.2014 11:22, schrieb Kevin Wolf:
> >     > From: Kewei Yu <keweihk@gmail.com <mailto:keweihk@gmail.com>>
> >     >
> >     > When we disable vnc from "./configure", QEMU can't use the vnc
> option.
> >     > So qtest can't use the "vnc -none ", otherwise "make check" fails.
> >     > If QEMU uses "-display none", "-vnc none" is excrescent, So we
> >     just need to drop it.
> >     >
> >     > Signed-off-by: Kewei Yu <keweihk@gmail.com <mailto:
> keweihk@gmail.com>>
> >     > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com
> >     <mailto:pbonzini@redhat.com>>
> >     > Signed-off-by: Kevin Wolf <kwolf@redhat.com <mailto:
> kwolf@redhat.com>>
> >
> >     If the pull does get respun, 'Fix "make check" failing for
> >     --disable-vnc' would be better English. ;)
> >
> >  Yes, It is more accurate. So.... I should re-submit it?
>
> Sorry for the late answer. Since it was already in the maintainer's
> queue and just about the commit message, it's not necessary for you to
> resubmit, my comment was addressed to Kevin. When a "PULL" has been
> sent, only major reasons (like build breakages, missing/wrong Sob, etc.)
> lead to a resubmission by the maintainer.
>
> Apart from the grammar issues ("causes ... to fail" or "... failure",
> "disabling ... causes"), please keep in mind that many commits fix bugs,
> so it will be more useful to the reader of patch/commit to read
> prominently what is changing (and why) to determine whether he/she is
> affected. Hope that explains.
>
Thank you for your patient explains, I will. ^ ^

Regards,
Kewei


>
> Regards,
> Andreas
>
> >
> >
> >     Andreas
> >
> >     --
> >     SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> >     GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG
> Nürnberg
> >
> > Kewei
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
>

[-- Attachment #2: Type: text/html, Size: 3858 bytes --]

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

end of thread, other threads:[~2014-01-26  8:05 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-15 10:22 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 01/42] rbd: switch from pipe to QEMUBH completion notification Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 02/42] qemu-iotests: Introduce _unsupported_imgopts Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 03/42] qemu-iotests: Add _unsupported_imgopts for vmdk subformats Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 04/42] qemu-iotests: Clean up all extents for vmdk Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 05/42] block/iscsi: return -ENOMEM if an async call fails immediately Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 06/42] gluster: Convert aio routines into coroutines Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 07/42] gluster: Implement .bdrv_co_write_zeroes for gluster Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 08/42] gluster: Add support for creating zero-filled image Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 09/42] sheepdog: fix clone operation by 'qemu-img create -b' Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 10/42] qtest: Fix the bug about disable vnc causes "make check" fail Kevin Wolf
2014-01-17 15:06   ` Andreas Färber
2014-01-18 11:54     ` Kewei Yu
2014-01-26  0:06       ` Andreas Färber
2014-01-26  8:04         ` Kewei Yu
2014-01-15 10:22 ` [Qemu-devel] [PULL 11/42] docs: qcow2 compat=1.1 is now the default Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 12/42] vmdk: Fix big flat extent IO Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 13/42] readline: decouple readline from the monitor Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 14/42] readline: move readline to a generic location Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 15/42] osdep: add qemu_set_tty_echo() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 16/42] qemu-io: use readline.c Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 17/42] qemu-io: add command completion Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 18/42] blkdebug: Use errp for read_config() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 19/42] blkdebug: Don't require sophisticated filename Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 20/42] qdict: Add qdict_array_split() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 21/42] qapi: extend qdict_flatten() for QLists Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 22/42] qemu-option: Add qemu_config_parse_qdict() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 23/42] blkdebug: Always call read_config() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 24/42] blkdebug: Use command-line in read_config() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 25/42] block: Allow reference for bdrv_file_open() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 26/42] block: Pass reference to bdrv_file_open() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 27/42] block: Allow block devices without files Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 28/42] block: Add bdrv_open_image() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 29/42] block: Use bdrv_open_image() in bdrv_open() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 30/42] block: Allow recursive "file"s Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 31/42] blockdev: Move "file" to legacy_opts Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 32/42] blkdebug: Allow command-line file configuration Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 33/42] blkverify: Allow command-line configuration Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 34/42] blkverify: Don't require protocol filename Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 35/42] qapi: Add "errno" to the list of polluted words Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 36/42] qapi: QMP interface for blkdebug and blkverify Kevin Wolf
2014-01-15 15:19   ` Eric Blake
2014-01-15 17:11     ` Paolo Bonzini
2014-01-16 10:03     ` Kevin Wolf
2014-01-17 15:01       ` Andreas Färber
2014-01-15 10:22 ` [Qemu-devel] [PULL 37/42] qemu-io: Make filename optional Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 38/42] tests: Add test for qdict_array_split() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 39/42] tests: Add test for qdict_flatten() Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 40/42] iotests: Test new blkdebug/blkverify interface Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 41/42] iotests: Test file format nesting Kevin Wolf
2014-01-15 10:22 ` [Qemu-devel] [PULL 42/42] block: fix backing file segfault Kevin Wolf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.