All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer
@ 2015-02-06 21:06 Max Reitz
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 1/3] " Max Reitz
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Max Reitz @ 2015-02-06 21:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Paolo Bonzini, Stefan Hajnoczi, Max Reitz

Right now, bdrv_swap() on NBD BDSs results in a segmentation fault
pretty much all of the time. This series fixes this.

Note that this is not a common case, as bdrv_swap() is generally only
performed on root BDSs (there are exceptions, though) and NBD BDSs
normally have a format BDS above them. However, due to misconfiguration
(or maybe it is not even a misconfiguration, but just a strange
configuration) these cases may indeed occur.

I took the second patch in this series from my other series
"block: Rework bdrv_close_all()" (which has 21 patches itself and
depends on 64 other patches, so making this series rely on that one
probably would not have been a very good idea).


v2:
- Rename all functions which now take a BlockDriverState * instead of an
  NbdClientSession * from nbd_client_session_* to nbd_client_* [Paolo]
- Rename nbd_client_close() in nbd.c to client_close() and make it
  static; otherwise, it would conflict with the "new" nbd_client_close()
  in block/nbd-client.c


git-backport-diff against v1:

Key:
[----] : patches are identical
[####] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/3:[0089] [FC] 'nbd: Drop BDS backpointer'
002/3:[----] [--] 'iotests: Add "wait" functionality to _cleanup_qemu'
003/3:[----] [--] 'iotests: Add test for drive-mirror with NBD target'


Max Reitz (3):
  nbd: Drop BDS backpointer
  iotests: Add "wait" functionality to _cleanup_qemu
  iotests: Add test for drive-mirror with NBD target

 block/nbd-client.c             | 101 +++++++++++++++++++++--------------------
 block/nbd-client.h             |  34 +++++++-------
 block/nbd.c                    |  37 ++++++---------
 include/block/nbd.h            |   1 -
 nbd.c                          |   8 ++--
 tests/qemu-iotests/094         |  81 +++++++++++++++++++++++++++++++++
 tests/qemu-iotests/094.out     |  11 +++++
 tests/qemu-iotests/common.qemu |  12 ++++-
 tests/qemu-iotests/group       |   1 +
 9 files changed, 191 insertions(+), 95 deletions(-)
 create mode 100755 tests/qemu-iotests/094
 create mode 100644 tests/qemu-iotests/094.out

-- 
2.1.0

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

* [Qemu-devel] [PATCH v2 1/3] nbd: Drop BDS backpointer
  2015-02-06 21:06 [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Max Reitz
@ 2015-02-06 21:06 ` Max Reitz
  2015-02-09 12:33   ` Paolo Bonzini
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Max Reitz @ 2015-02-06 21:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Paolo Bonzini, Stefan Hajnoczi, Max Reitz

Before this patch, the "opaque" pointer in an NBD BDS points to a
BDRVNBDState, which contains an NbdClientSession object, which in turn
contains a pointer to the BDS. This pointer may become invalid due to
bdrv_swap(), so drop it, and instead pass the BDS directly to the
nbd-client.c functions which then retrieve the NbdClientSession object
from there.

Signed-off-by: Max Reitz <mreitz@redhat.com>
---
 block/nbd-client.c  | 101 +++++++++++++++++++++++++++-------------------------
 block/nbd-client.h  |  34 +++++++++---------
 block/nbd.c         |  37 ++++++++-----------
 include/block/nbd.h |   1 -
 nbd.c               |   8 ++---
 5 files changed, 87 insertions(+), 94 deletions(-)

diff --git a/block/nbd-client.c b/block/nbd-client.c
index 28bfb62..a01a37f 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -43,20 +43,23 @@ static void nbd_recv_coroutines_enter_all(NbdClientSession *s)
     }
 }
 
-static void nbd_teardown_connection(NbdClientSession *client)
+static void nbd_teardown_connection(BlockDriverState *bs)
 {
+    NbdClientSession *client = nbd_get_client_session(bs);
+
     /* finish any pending coroutines */
     shutdown(client->sock, 2);
     nbd_recv_coroutines_enter_all(client);
 
-    nbd_client_session_detach_aio_context(client);
+    nbd_client_detach_aio_context(bs);
     closesocket(client->sock);
     client->sock = -1;
 }
 
 static void nbd_reply_ready(void *opaque)
 {
-    NbdClientSession *s = opaque;
+    BlockDriverState *bs = opaque;
+    NbdClientSession *s = nbd_get_client_session(bs);
     uint64_t i;
     int ret;
 
@@ -89,28 +92,29 @@ static void nbd_reply_ready(void *opaque)
     }
 
 fail:
-    nbd_teardown_connection(s);
+    nbd_teardown_connection(bs);
 }
 
 static void nbd_restart_write(void *opaque)
 {
-    NbdClientSession *s = opaque;
+    BlockDriverState *bs = opaque;
 
-    qemu_coroutine_enter(s->send_coroutine, NULL);
+    qemu_coroutine_enter(nbd_get_client_session(bs)->send_coroutine, NULL);
 }
 
-static int nbd_co_send_request(NbdClientSession *s,
-    struct nbd_request *request,
-    QEMUIOVector *qiov, int offset)
+static int nbd_co_send_request(BlockDriverState *bs,
+                               struct nbd_request *request,
+                               QEMUIOVector *qiov, int offset)
 {
+    NbdClientSession *s = nbd_get_client_session(bs);
     AioContext *aio_context;
     int rc, ret;
 
     qemu_co_mutex_lock(&s->send_mutex);
     s->send_coroutine = qemu_coroutine_self();
-    aio_context = bdrv_get_aio_context(s->bs);
+    aio_context = bdrv_get_aio_context(bs);
     aio_set_fd_handler(aio_context, s->sock,
-                       nbd_reply_ready, nbd_restart_write, s);
+                       nbd_reply_ready, nbd_restart_write, bs);
     if (qiov) {
         if (!s->is_unix) {
             socket_set_cork(s->sock, 1);
@@ -129,7 +133,7 @@ static int nbd_co_send_request(NbdClientSession *s,
     } else {
         rc = nbd_send_request(s->sock, request);
     }
-    aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, s);
+    aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, bs);
     s->send_coroutine = NULL;
     qemu_co_mutex_unlock(&s->send_mutex);
     return rc;
@@ -195,10 +199,11 @@ static void nbd_coroutine_end(NbdClientSession *s,
     }
 }
 
-static int nbd_co_readv_1(NbdClientSession *client, int64_t sector_num,
+static int nbd_co_readv_1(BlockDriverState *bs, int64_t sector_num,
                           int nb_sectors, QEMUIOVector *qiov,
                           int offset)
 {
+    NbdClientSession *client = nbd_get_client_session(bs);
     struct nbd_request request = { .type = NBD_CMD_READ };
     struct nbd_reply reply;
     ssize_t ret;
@@ -207,7 +212,7 @@ static int nbd_co_readv_1(NbdClientSession *client, int64_t sector_num,
     request.len = nb_sectors * 512;
 
     nbd_coroutine_start(client, &request);
-    ret = nbd_co_send_request(client, &request, NULL, 0);
+    ret = nbd_co_send_request(bs, &request, NULL, 0);
     if (ret < 0) {
         reply.error = -ret;
     } else {
@@ -218,15 +223,16 @@ static int nbd_co_readv_1(NbdClientSession *client, int64_t sector_num,
 
 }
 
-static int nbd_co_writev_1(NbdClientSession *client, int64_t sector_num,
+static int nbd_co_writev_1(BlockDriverState *bs, int64_t sector_num,
                            int nb_sectors, QEMUIOVector *qiov,
                            int offset)
 {
+    NbdClientSession *client = nbd_get_client_session(bs);
     struct nbd_request request = { .type = NBD_CMD_WRITE };
     struct nbd_reply reply;
     ssize_t ret;
 
-    if (!bdrv_enable_write_cache(client->bs) &&
+    if (!bdrv_enable_write_cache(bs) &&
         (client->nbdflags & NBD_FLAG_SEND_FUA)) {
         request.type |= NBD_CMD_FLAG_FUA;
     }
@@ -235,7 +241,7 @@ static int nbd_co_writev_1(NbdClientSession *client, int64_t sector_num,
     request.len = nb_sectors * 512;
 
     nbd_coroutine_start(client, &request);
-    ret = nbd_co_send_request(client, &request, qiov, offset);
+    ret = nbd_co_send_request(bs, &request, qiov, offset);
     if (ret < 0) {
         reply.error = -ret;
     } else {
@@ -249,14 +255,13 @@ static int nbd_co_writev_1(NbdClientSession *client, int64_t sector_num,
  * remain aligned to 4K. */
 #define NBD_MAX_SECTORS 2040
 
-int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num,
-    int nb_sectors, QEMUIOVector *qiov)
+int nbd_client_co_readv(BlockDriverState *bs, int64_t sector_num,
+                        int nb_sectors, QEMUIOVector *qiov)
 {
     int offset = 0;
     int ret;
     while (nb_sectors > NBD_MAX_SECTORS) {
-        ret = nbd_co_readv_1(client, sector_num,
-                             NBD_MAX_SECTORS, qiov, offset);
+        ret = nbd_co_readv_1(bs, sector_num, NBD_MAX_SECTORS, qiov, offset);
         if (ret < 0) {
             return ret;
         }
@@ -264,17 +269,16 @@ int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num,
         sector_num += NBD_MAX_SECTORS;
         nb_sectors -= NBD_MAX_SECTORS;
     }
-    return nbd_co_readv_1(client, sector_num, nb_sectors, qiov, offset);
+    return nbd_co_readv_1(bs, sector_num, nb_sectors, qiov, offset);
 }
 
-int nbd_client_session_co_writev(NbdClientSession *client, int64_t sector_num,
-                                 int nb_sectors, QEMUIOVector *qiov)
+int nbd_client_co_writev(BlockDriverState *bs, int64_t sector_num,
+                         int nb_sectors, QEMUIOVector *qiov)
 {
     int offset = 0;
     int ret;
     while (nb_sectors > NBD_MAX_SECTORS) {
-        ret = nbd_co_writev_1(client, sector_num,
-                              NBD_MAX_SECTORS, qiov, offset);
+        ret = nbd_co_writev_1(bs, sector_num, NBD_MAX_SECTORS, qiov, offset);
         if (ret < 0) {
             return ret;
         }
@@ -282,11 +286,12 @@ int nbd_client_session_co_writev(NbdClientSession *client, int64_t sector_num,
         sector_num += NBD_MAX_SECTORS;
         nb_sectors -= NBD_MAX_SECTORS;
     }
-    return nbd_co_writev_1(client, sector_num, nb_sectors, qiov, offset);
+    return nbd_co_writev_1(bs, sector_num, nb_sectors, qiov, offset);
 }
 
-int nbd_client_session_co_flush(NbdClientSession *client)
+int nbd_client_co_flush(BlockDriverState *bs)
 {
+    NbdClientSession *client = nbd_get_client_session(bs);
     struct nbd_request request = { .type = NBD_CMD_FLUSH };
     struct nbd_reply reply;
     ssize_t ret;
@@ -303,7 +308,7 @@ int nbd_client_session_co_flush(NbdClientSession *client)
     request.len = 0;
 
     nbd_coroutine_start(client, &request);
-    ret = nbd_co_send_request(client, &request, NULL, 0);
+    ret = nbd_co_send_request(bs, &request, NULL, 0);
     if (ret < 0) {
         reply.error = -ret;
     } else {
@@ -313,9 +318,10 @@ int nbd_client_session_co_flush(NbdClientSession *client)
     return -reply.error;
 }
 
-int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
-    int nb_sectors)
+int nbd_client_co_discard(BlockDriverState *bs, int64_t sector_num,
+                          int nb_sectors)
 {
+    NbdClientSession *client = nbd_get_client_session(bs);
     struct nbd_request request = { .type = NBD_CMD_TRIM };
     struct nbd_reply reply;
     ssize_t ret;
@@ -327,7 +333,7 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
     request.len = nb_sectors * 512;
 
     nbd_coroutine_start(client, &request);
-    ret = nbd_co_send_request(client, &request, NULL, 0);
+    ret = nbd_co_send_request(bs, &request, NULL, 0);
     if (ret < 0) {
         reply.error = -ret;
     } else {
@@ -338,43 +344,41 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
 
 }
 
-void nbd_client_session_detach_aio_context(NbdClientSession *client)
+void nbd_client_detach_aio_context(BlockDriverState *bs)
 {
-    aio_set_fd_handler(bdrv_get_aio_context(client->bs), client->sock,
-                       NULL, NULL, NULL);
+    aio_set_fd_handler(bdrv_get_aio_context(bs),
+                       nbd_get_client_session(bs)->sock, NULL, NULL, NULL);
 }
 
-void nbd_client_session_attach_aio_context(NbdClientSession *client,
-                                           AioContext *new_context)
+void nbd_client_attach_aio_context(BlockDriverState *bs,
+                                   AioContext *new_context)
 {
-    aio_set_fd_handler(new_context, client->sock,
-                       nbd_reply_ready, NULL, client);
+    aio_set_fd_handler(new_context, nbd_get_client_session(bs)->sock,
+                       nbd_reply_ready, NULL, bs);
 }
 
-void nbd_client_session_close(NbdClientSession *client)
+void nbd_client_close(BlockDriverState *bs)
 {
+    NbdClientSession *client = nbd_get_client_session(bs);
     struct nbd_request request = {
         .type = NBD_CMD_DISC,
         .from = 0,
         .len = 0
     };
 
-    if (!client->bs) {
-        return;
-    }
     if (client->sock == -1) {
         return;
     }
 
     nbd_send_request(client->sock, &request);
 
-    nbd_teardown_connection(client);
-    client->bs = NULL;
+    nbd_teardown_connection(bs);
 }
 
-int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
-                            int sock, const char *export, Error **errp)
+int nbd_client_init(BlockDriverState *bs, int sock, const char *export,
+                    Error **errp)
 {
+    NbdClientSession *client = nbd_get_client_session(bs);
     int ret;
 
     /* NBD handshake */
@@ -391,13 +395,12 @@ int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
 
     qemu_co_mutex_init(&client->send_mutex);
     qemu_co_mutex_init(&client->free_sema);
-    client->bs = bs;
     client->sock = sock;
 
     /* Now that we're connected, set the socket to be non-blocking and
      * kick the reply mechanism.  */
     qemu_set_nonblock(sock);
-    nbd_client_session_attach_aio_context(client, bdrv_get_aio_context(bs));
+    nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));
 
     logout("Established connection with NBD server\n");
     return 0;
diff --git a/block/nbd-client.h b/block/nbd-client.h
index cfeecc2..fa4ff42 100644
--- a/block/nbd-client.h
+++ b/block/nbd-client.h
@@ -31,24 +31,24 @@ typedef struct NbdClientSession {
     struct nbd_reply reply;
 
     bool is_unix;
-
-    BlockDriverState *bs;
 } NbdClientSession;
 
-int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
-                            int sock, const char *export_name, Error **errp);
-void nbd_client_session_close(NbdClientSession *client);
-
-int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
-                                  int nb_sectors);
-int nbd_client_session_co_flush(NbdClientSession *client);
-int nbd_client_session_co_writev(NbdClientSession *client, int64_t sector_num,
-                                 int nb_sectors, QEMUIOVector *qiov);
-int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num,
-                                int nb_sectors, QEMUIOVector *qiov);
-
-void nbd_client_session_detach_aio_context(NbdClientSession *client);
-void nbd_client_session_attach_aio_context(NbdClientSession *client,
-                                           AioContext *new_context);
+NbdClientSession *nbd_get_client_session(BlockDriverState *bs);
+
+int nbd_client_init(BlockDriverState *bs, int sock, const char *export_name,
+                    Error **errp);
+void nbd_client_close(BlockDriverState *bs);
+
+int nbd_client_co_discard(BlockDriverState *bs, int64_t sector_num,
+                          int nb_sectors);
+int nbd_client_co_flush(BlockDriverState *bs);
+int nbd_client_co_writev(BlockDriverState *bs, int64_t sector_num,
+                         int nb_sectors, QEMUIOVector *qiov);
+int nbd_client_co_readv(BlockDriverState *bs, int64_t sector_num,
+                        int nb_sectors, QEMUIOVector *qiov);
+
+void nbd_client_detach_aio_context(BlockDriverState *bs);
+void nbd_client_attach_aio_context(BlockDriverState *bs,
+                                   AioContext *new_context);
 
 #endif /* NBD_CLIENT_H */
diff --git a/block/nbd.c b/block/nbd.c
index b05d1d0..2f3b9ad 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -224,6 +224,12 @@ static void nbd_config(BDRVNBDState *s, QDict *options, char **export,
     }
 }
 
+NbdClientSession *nbd_get_client_session(BlockDriverState *bs)
+{
+    BDRVNBDState *s = bs->opaque;
+    return &s->client;
+}
+
 static int nbd_establish_connection(BlockDriverState *bs, Error **errp)
 {
     BDRVNBDState *s = bs->opaque;
@@ -271,7 +277,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
     }
 
     /* NBD handshake */
-    result = nbd_client_session_init(&s->client, bs, sock, export, errp);
+    result = nbd_client_init(bs, sock, export, errp);
     g_free(export);
     return result;
 }
@@ -279,26 +285,18 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
 static int nbd_co_readv(BlockDriverState *bs, int64_t sector_num,
                         int nb_sectors, QEMUIOVector *qiov)
 {
-    BDRVNBDState *s = bs->opaque;
-
-    return nbd_client_session_co_readv(&s->client, sector_num,
-                                       nb_sectors, qiov);
+    return nbd_client_co_readv(bs, sector_num, nb_sectors, qiov);
 }
 
 static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num,
                          int nb_sectors, QEMUIOVector *qiov)
 {
-    BDRVNBDState *s = bs->opaque;
-
-    return nbd_client_session_co_writev(&s->client, sector_num,
-                                        nb_sectors, qiov);
+    return nbd_client_co_writev(bs, sector_num, nb_sectors, qiov);
 }
 
 static int nbd_co_flush(BlockDriverState *bs)
 {
-    BDRVNBDState *s = bs->opaque;
-
-    return nbd_client_session_co_flush(&s->client);
+    return nbd_client_co_flush(bs);
 }
 
 static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
@@ -310,10 +308,7 @@ static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
 static int nbd_co_discard(BlockDriverState *bs, int64_t sector_num,
                           int nb_sectors)
 {
-    BDRVNBDState *s = bs->opaque;
-
-    return nbd_client_session_co_discard(&s->client, sector_num,
-                                         nb_sectors);
+    return nbd_client_co_discard(bs, sector_num, nb_sectors);
 }
 
 static void nbd_close(BlockDriverState *bs)
@@ -321,7 +316,7 @@ static void nbd_close(BlockDriverState *bs)
     BDRVNBDState *s = bs->opaque;
 
     qemu_opts_del(s->socket_opts);
-    nbd_client_session_close(&s->client);
+    nbd_client_close(bs);
 }
 
 static int64_t nbd_getlength(BlockDriverState *bs)
@@ -333,17 +328,13 @@ static int64_t nbd_getlength(BlockDriverState *bs)
 
 static void nbd_detach_aio_context(BlockDriverState *bs)
 {
-    BDRVNBDState *s = bs->opaque;
-
-    nbd_client_session_detach_aio_context(&s->client);
+    nbd_client_detach_aio_context(bs);
 }
 
 static void nbd_attach_aio_context(BlockDriverState *bs,
                                    AioContext *new_context)
 {
-    BDRVNBDState *s = bs->opaque;
-
-    nbd_client_session_attach_aio_context(&s->client, new_context);
+    nbd_client_attach_aio_context(bs, new_context);
 }
 
 static void nbd_refresh_filename(BlockDriverState *bs)
diff --git a/include/block/nbd.h b/include/block/nbd.h
index b759595..ca9a5ac 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -99,7 +99,6 @@ void nbd_export_close_all(void);
 
 NBDClient *nbd_client_new(NBDExport *exp, int csock,
                           void (*close)(NBDClient *));
-void nbd_client_close(NBDClient *client);
 void nbd_client_get(NBDClient *client);
 void nbd_client_put(NBDClient *client);
 
diff --git a/nbd.c b/nbd.c
index e56afbc1..71159af 100644
--- a/nbd.c
+++ b/nbd.c
@@ -874,7 +874,7 @@ void nbd_client_put(NBDClient *client)
 {
     if (--client->refcount == 0) {
         /* The last reference should be dropped by client->close,
-         * which is called by nbd_client_close.
+         * which is called by client_close.
          */
         assert(client->closing);
 
@@ -889,7 +889,7 @@ void nbd_client_put(NBDClient *client)
     }
 }
 
-void nbd_client_close(NBDClient *client)
+static void client_close(NBDClient *client)
 {
     if (client->closing) {
         return;
@@ -1026,7 +1026,7 @@ void nbd_export_close(NBDExport *exp)
 
     nbd_export_get(exp);
     QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
-        nbd_client_close(client);
+        client_close(client);
     }
     nbd_export_set_name(exp, NULL);
     nbd_export_put(exp);
@@ -1311,7 +1311,7 @@ done:
 
 out:
     nbd_request_put(req);
-    nbd_client_close(client);
+    client_close(client);
 }
 
 static void nbd_read(void *opaque)
-- 
2.1.0

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

* [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu
  2015-02-06 21:06 [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Max Reitz
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 1/3] " Max Reitz
@ 2015-02-06 21:06 ` Max Reitz
  2015-02-09 15:01   ` Stefan Hajnoczi
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 3/3] iotests: Add test for drive-mirror with NBD target Max Reitz
  2015-02-09 17:54 ` [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Stefan Hajnoczi
  3 siblings, 1 reply; 9+ messages in thread
From: Max Reitz @ 2015-02-06 21:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Paolo Bonzini, Stefan Hajnoczi, Max Reitz

The qemu process does not always need to be killed, just waiting for it
can be fine, too. This introduces a way to do so.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/qemu-iotests/common.qemu | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
index 8e618b5..4e1996c 100644
--- a/tests/qemu-iotests/common.qemu
+++ b/tests/qemu-iotests/common.qemu
@@ -187,13 +187,23 @@ function _launch_qemu()
 
 
 # Silenty kills the QEMU process
+#
+# If $wait is set to anything other than the empty string, the process will not
+# be killed but only waited for, and any output will be forwarded to stdout. If
+# $wait is empty, the process will be killed and all output will be suppressed.
 function _cleanup_qemu()
 {
     # QEMU_PID[], QEMU_IN[], QEMU_OUT[] all use same indices
     for i in "${!QEMU_OUT[@]}"
     do
-        kill -KILL ${QEMU_PID[$i]} 2>/dev/null
+        if [ -z "${wait}" ]; then
+            kill -KILL ${QEMU_PID[$i]} 2>/dev/null
+        fi
         wait ${QEMU_PID[$i]} 2>/dev/null # silent kill
+        if [ -n "${wait}" ]; then
+            cat <&${QEMU_OUT[$i]} | _filter_testdir | _filter_qemu \
+                                  | _filter_qemu_io | _filter_qmp
+        fi
         rm -f "${QEMU_FIFO_IN}_${i}" "${QEMU_FIFO_OUT}_${i}"
         eval "exec ${QEMU_IN[$i]}<&-"   # close file descriptors
         eval "exec ${QEMU_OUT[$i]}<&-"
-- 
2.1.0

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

* [Qemu-devel] [PATCH v2 3/3] iotests: Add test for drive-mirror with NBD target
  2015-02-06 21:06 [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Max Reitz
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 1/3] " Max Reitz
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz
@ 2015-02-06 21:06 ` Max Reitz
  2015-02-09 17:54 ` [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Stefan Hajnoczi
  3 siblings, 0 replies; 9+ messages in thread
From: Max Reitz @ 2015-02-06 21:06 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kevin Wolf, Paolo Bonzini, Stefan Hajnoczi, Max Reitz

When the drive-mirror block job is completed, it will call bdrv_swap()
on the source and the target BDS; this should obviously not result in a
segmentation fault.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 tests/qemu-iotests/094     | 81 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/qemu-iotests/094.out | 11 +++++++
 tests/qemu-iotests/group   |  1 +
 3 files changed, 93 insertions(+)
 create mode 100755 tests/qemu-iotests/094
 create mode 100644 tests/qemu-iotests/094.out

diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094
new file mode 100755
index 0000000..27a2be2
--- /dev/null
+++ b/tests/qemu-iotests/094
@@ -0,0 +1,81 @@
+#!/bin/bash
+#
+# Test case for drive-mirror to NBD (especially bdrv_swap() on NBD BDS)
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+tmp=/tmp/$$
+status=1	# failure is the default!
+
+trap "exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt generic
+_supported_proto nbd
+_supported_os Linux
+_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat"
+
+_make_test_img 64M
+$QEMU_IMG create -f $IMGFMT "$TEST_DIR/source.$IMGFMT" 64M | _filter_img_create
+
+_launch_qemu -drive if=none,id=src,file="$TEST_DIR/source.$IMGFMT",format=raw \
+             -nodefaults
+
+_send_qemu_cmd $QEMU_HANDLE \
+    "{'execute': 'qmp_capabilities'}" \
+    'return'
+
+# 'format': 'nbd' is not actually "correct", but this is probably the only way
+# to test bdrv_swap() on an NBD BDS
+_send_qemu_cmd $QEMU_HANDLE  \
+    "{'execute': 'drive-mirror',
+      'arguments': {'device': 'src',
+                    'target': '$TEST_IMG',
+                    'format': 'nbd',
+                    'sync':'full',
+                    'mode':'existing'}}" \
+    'BLOCK_JOB_READY'
+
+_send_qemu_cmd $QEMU_HANDLE  \
+    "{'execute': 'block-job-complete',
+      'arguments': {'device': 'src'}}" \
+    'BLOCK_JOB_COMPLETE'
+
+_send_qemu_cmd $QEMU_HANDLE \
+    "{'execute': 'quit'}" \
+    'return'
+
+wait=1 _cleanup_qemu
+
+_cleanup_test_img
+rm -f "$TEST_DIR/source.$IMGFMT"
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/094.out b/tests/qemu-iotests/094.out
new file mode 100644
index 0000000..b66dc07
--- /dev/null
+++ b/tests/qemu-iotests/094.out
@@ -0,0 +1,11 @@
+QA output created by 094
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}}
+{"return": {}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 4b2b93b..6e2447a 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -99,6 +99,7 @@
 090 rw auto quick
 091 rw auto
 092 rw auto quick
+094 rw auto quick
 095 rw auto quick
 097 rw auto backing
 098 rw auto backing quick
-- 
2.1.0

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

* Re: [Qemu-devel] [PATCH v2 1/3] nbd: Drop BDS backpointer
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 1/3] " Max Reitz
@ 2015-02-09 12:33   ` Paolo Bonzini
  0 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2015-02-09 12:33 UTC (permalink / raw)
  To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi



On 06/02/2015 22:06, Max Reitz wrote:
> @@ -889,7 +889,7 @@ void nbd_client_put(NBDClient *client)
>      }
>  }
>  
> -void nbd_client_close(NBDClient *client)
> +static void client_close(NBDClient *client)
>  {
>      if (client->closing) {
>          return;

Probably NBDClient should be renamed to NBDServerSession.  Can be done
on top.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

Paolo

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

* Re: [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz
@ 2015-02-09 15:01   ` Stefan Hajnoczi
  2015-02-09 15:37     ` Max Reitz
  0 siblings, 1 reply; 9+ messages in thread
From: Stefan Hajnoczi @ 2015-02-09 15:01 UTC (permalink / raw)
  To: Max Reitz; +Cc: Kevin Wolf, Paolo Bonzini, qemu-devel, Stefan Hajnoczi

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

On Fri, Feb 06, 2015 at 04:06:17PM -0500, Max Reitz wrote:
> diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
> index 8e618b5..4e1996c 100644
> --- a/tests/qemu-iotests/common.qemu
> +++ b/tests/qemu-iotests/common.qemu
> @@ -187,13 +187,23 @@ function _launch_qemu()
>  
>  
>  # Silenty kills the QEMU process
> +#
> +# If $wait is set to anything other than the empty string, the process will not
> +# be killed but only waited for, and any output will be forwarded to stdout. If
> +# $wait is empty, the process will be killed and all output will be suppressed.
>  function _cleanup_qemu()
>  {
>      # QEMU_PID[], QEMU_IN[], QEMU_OUT[] all use same indices
>      for i in "${!QEMU_OUT[@]}"
>      do
> -        kill -KILL ${QEMU_PID[$i]} 2>/dev/null
> +        if [ -z "${wait}" ]; then

Is the global variable (with a common name) necessary?

function _cleanup_qemu()
{
    wait=$1
...

_cleanup_qemu
OR
_cleanup_qemu --wait

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

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

* Re: [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu
  2015-02-09 15:01   ` Stefan Hajnoczi
@ 2015-02-09 15:37     ` Max Reitz
  2015-02-09 17:49       ` Stefan Hajnoczi
  0 siblings, 1 reply; 9+ messages in thread
From: Max Reitz @ 2015-02-09 15:37 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: Kevin Wolf, Paolo Bonzini, qemu-devel, Stefan Hajnoczi

On 2015-02-09 at 10:01, Stefan Hajnoczi wrote:
> On Fri, Feb 06, 2015 at 04:06:17PM -0500, Max Reitz wrote:
>> diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
>> index 8e618b5..4e1996c 100644
>> --- a/tests/qemu-iotests/common.qemu
>> +++ b/tests/qemu-iotests/common.qemu
>> @@ -187,13 +187,23 @@ function _launch_qemu()
>>   
>>   
>>   # Silenty kills the QEMU process
>> +#
>> +# If $wait is set to anything other than the empty string, the process will not
>> +# be killed but only waited for, and any output will be forwarded to stdout. If
>> +# $wait is empty, the process will be killed and all output will be suppressed.
>>   function _cleanup_qemu()
>>   {
>>       # QEMU_PID[], QEMU_IN[], QEMU_OUT[] all use same indices
>>       for i in "${!QEMU_OUT[@]}"
>>       do
>> -        kill -KILL ${QEMU_PID[$i]} 2>/dev/null
>> +        if [ -z "${wait}" ]; then
> Is the global variable (with a common name) necessary?
>
> function _cleanup_qemu()
> {
>      wait=$1
> ...
>
> _cleanup_qemu
> OR
> _cleanup_qemu --wait

Well, it's probably not necessary, but it conforms with the _launch_qemu 
($qemu_comm_method), the _send_qemu_cmd ($qemu_error_not_set), and the 
_timed_wait_for ($silent) interfaces.

Max

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

* Re: [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu
  2015-02-09 15:37     ` Max Reitz
@ 2015-02-09 17:49       ` Stefan Hajnoczi
  0 siblings, 0 replies; 9+ messages in thread
From: Stefan Hajnoczi @ 2015-02-09 17:49 UTC (permalink / raw)
  To: Max Reitz; +Cc: Kevin Wolf, Stefan Hajnoczi, qemu-devel, Paolo Bonzini

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

On Mon, Feb 09, 2015 at 10:37:22AM -0500, Max Reitz wrote:
> On 2015-02-09 at 10:01, Stefan Hajnoczi wrote:
> >On Fri, Feb 06, 2015 at 04:06:17PM -0500, Max Reitz wrote:
> >>diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
> >>index 8e618b5..4e1996c 100644
> >>--- a/tests/qemu-iotests/common.qemu
> >>+++ b/tests/qemu-iotests/common.qemu
> >>@@ -187,13 +187,23 @@ function _launch_qemu()
> >>  # Silenty kills the QEMU process
> >>+#
> >>+# If $wait is set to anything other than the empty string, the process will not
> >>+# be killed but only waited for, and any output will be forwarded to stdout. If
> >>+# $wait is empty, the process will be killed and all output will be suppressed.
> >>  function _cleanup_qemu()
> >>  {
> >>      # QEMU_PID[], QEMU_IN[], QEMU_OUT[] all use same indices
> >>      for i in "${!QEMU_OUT[@]}"
> >>      do
> >>-        kill -KILL ${QEMU_PID[$i]} 2>/dev/null
> >>+        if [ -z "${wait}" ]; then
> >Is the global variable (with a common name) necessary?
> >
> >function _cleanup_qemu()
> >{
> >     wait=$1
> >...
> >
> >_cleanup_qemu
> >OR
> >_cleanup_qemu --wait
> 
> Well, it's probably not necessary, but it conforms with the _launch_qemu
> ($qemu_comm_method), the _send_qemu_cmd ($qemu_error_not_set), and the
> _timed_wait_for ($silent) interfaces.

Okay, let's stay consistent.

Stefan

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

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

* Re: [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer
  2015-02-06 21:06 [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Max Reitz
                   ` (2 preceding siblings ...)
  2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 3/3] iotests: Add test for drive-mirror with NBD target Max Reitz
@ 2015-02-09 17:54 ` Stefan Hajnoczi
  3 siblings, 0 replies; 9+ messages in thread
From: Stefan Hajnoczi @ 2015-02-09 17:54 UTC (permalink / raw)
  To: Max Reitz; +Cc: Kevin Wolf, Paolo Bonzini, qemu-devel

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

On Fri, Feb 06, 2015 at 04:06:15PM -0500, Max Reitz wrote:
> Right now, bdrv_swap() on NBD BDSs results in a segmentation fault
> pretty much all of the time. This series fixes this.
> 
> Note that this is not a common case, as bdrv_swap() is generally only
> performed on root BDSs (there are exceptions, though) and NBD BDSs
> normally have a format BDS above them. However, due to misconfiguration
> (or maybe it is not even a misconfiguration, but just a strange
> configuration) these cases may indeed occur.
> 
> I took the second patch in this series from my other series
> "block: Rework bdrv_close_all()" (which has 21 patches itself and
> depends on 64 other patches, so making this series rely on that one
> probably would not have been a very good idea).
> 
> 
> v2:
> - Rename all functions which now take a BlockDriverState * instead of an
>   NbdClientSession * from nbd_client_session_* to nbd_client_* [Paolo]
> - Rename nbd_client_close() in nbd.c to client_close() and make it
>   static; otherwise, it would conflict with the "new" nbd_client_close()
>   in block/nbd-client.c
> 
> 
> git-backport-diff against v1:
> 
> Key:
> [----] : patches are identical
> [####] : number of functional differences between upstream/downstream patch
> [down] : patch is downstream-only
> The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively
> 
> 001/3:[0089] [FC] 'nbd: Drop BDS backpointer'
> 002/3:[----] [--] 'iotests: Add "wait" functionality to _cleanup_qemu'
> 003/3:[----] [--] 'iotests: Add test for drive-mirror with NBD target'
> 
> 
> Max Reitz (3):
>   nbd: Drop BDS backpointer
>   iotests: Add "wait" functionality to _cleanup_qemu
>   iotests: Add test for drive-mirror with NBD target
> 
>  block/nbd-client.c             | 101 +++++++++++++++++++++--------------------
>  block/nbd-client.h             |  34 +++++++-------
>  block/nbd.c                    |  37 ++++++---------
>  include/block/nbd.h            |   1 -
>  nbd.c                          |   8 ++--
>  tests/qemu-iotests/094         |  81 +++++++++++++++++++++++++++++++++
>  tests/qemu-iotests/094.out     |  11 +++++
>  tests/qemu-iotests/common.qemu |  12 ++++-
>  tests/qemu-iotests/group       |   1 +
>  9 files changed, 191 insertions(+), 95 deletions(-)
>  create mode 100755 tests/qemu-iotests/094
>  create mode 100644 tests/qemu-iotests/094.out
> 
> -- 
> 2.1.0
> 

Thanks, applied to my block tree:
https://github.com/stefanha/qemu/commits/block

Stefan

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

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

end of thread, other threads:[~2015-02-09 17:55 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-06 21:06 [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Max Reitz
2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 1/3] " Max Reitz
2015-02-09 12:33   ` Paolo Bonzini
2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz
2015-02-09 15:01   ` Stefan Hajnoczi
2015-02-09 15:37     ` Max Reitz
2015-02-09 17:49       ` Stefan Hajnoczi
2015-02-06 21:06 ` [Qemu-devel] [PATCH v2 3/3] iotests: Add test for drive-mirror with NBD target Max Reitz
2015-02-09 17:54 ` [Qemu-devel] [PATCH v2 0/3] nbd: Drop BDS backpointer Stefan Hajnoczi

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.