* [Qemu-devel] [PATCH 0/3] nbd: Drop BDS backpointer @ 2015-02-02 21:40 Max Reitz 2015-02-02 21:40 ` [Qemu-devel] [PATCH 1/3] " Max Reitz ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Max Reitz @ 2015-02-02 21:40 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. For the iotest to succeed, this series relies on "iotests: Specify format for qemu-nbd". 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). 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 | 95 ++++++++++++++++++++++-------------------- block/nbd-client.h | 20 ++++----- block/nbd.c | 37 +++++++--------- tests/qemu-iotests/094 | 81 +++++++++++++++++++++++++++++++++++ tests/qemu-iotests/094.out | 11 +++++ tests/qemu-iotests/common.qemu | 12 +++++- tests/qemu-iotests/group | 1 + 7 files changed, 177 insertions(+), 80 deletions(-) create mode 100755 tests/qemu-iotests/094 create mode 100644 tests/qemu-iotests/094.out -- 2.1.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 1/3] nbd: Drop BDS backpointer 2015-02-02 21:40 [Qemu-devel] [PATCH 0/3] nbd: Drop BDS backpointer Max Reitz @ 2015-02-02 21:40 ` Max Reitz 2015-02-03 8:37 ` Paolo Bonzini 2015-02-02 21:40 ` [Qemu-devel] [PATCH 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz 2015-02-02 21:40 ` [Qemu-devel] [PATCH 3/3] iotests: Add test for drive-mirror with NBD target Max Reitz 2 siblings, 1 reply; 8+ messages in thread From: Max Reitz @ 2015-02-02 21:40 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 | 95 ++++++++++++++++++++++++++++-------------------------- block/nbd-client.h | 20 ++++++------ block/nbd.c | 37 ++++++++------------- 3 files changed, 73 insertions(+), 79 deletions(-) diff --git a/block/nbd-client.c b/block/nbd-client.c index 28bfb62..4ede714 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_session_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_session_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 nbd_client_session_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_session_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_session_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_session_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, +void nbd_client_session_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_session_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 nbd_client_session_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_session_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..49daccc 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, +NbdClientSession *nbd_get_client_session(BlockDriverState *bs); + +int nbd_client_session_init(BlockDriverState *bs, int sock, const char *export_name, Error **errp); -void nbd_client_session_close(NbdClientSession *client); +void nbd_client_session_close(BlockDriverState *bs); -int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num, +int nbd_client_session_co_discard(BlockDriverState *bs, 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 nbd_client_session_co_flush(BlockDriverState *bs); +int nbd_client_session_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors, QEMUIOVector *qiov); -int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num, +int nbd_client_session_co_readv(BlockDriverState *bs, 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, +void nbd_client_session_detach_aio_context(BlockDriverState *bs); +void nbd_client_session_attach_aio_context(BlockDriverState *bs, AioContext *new_context); #endif /* NBD_CLIENT_H */ diff --git a/block/nbd.c b/block/nbd.c index 2e20831..f71fba0 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_session_init(bs, sock, export, errp); g_free(export); return result; } @@ -279,35 +285,24 @@ 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_session_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_session_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_session_co_flush(bs); } 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_session_co_discard(bs, sector_num, nb_sectors); } static void nbd_close(BlockDriverState *bs) @@ -315,7 +310,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_session_close(bs); } static int64_t nbd_getlength(BlockDriverState *bs) @@ -327,17 +322,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_session_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_session_attach_aio_context(bs, new_context); } static void nbd_refresh_filename(BlockDriverState *bs) -- 2.1.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] nbd: Drop BDS backpointer 2015-02-02 21:40 ` [Qemu-devel] [PATCH 1/3] " Max Reitz @ 2015-02-03 8:37 ` Paolo Bonzini 2015-02-03 13:54 ` Max Reitz 0 siblings, 1 reply; 8+ messages in thread From: Paolo Bonzini @ 2015-02-03 8:37 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi On 02/02/2015 22:40, Max Reitz wrote: > 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. Looks good, but please change function names from nbd_client_session_foo to nbd_client_foo or even just nbd_foo if they do not take an NbdClientSession* as the first parameter. Thanks, Paolo > Signed-off-by: Max Reitz <mreitz@redhat.com> > --- > block/nbd-client.c | 95 ++++++++++++++++++++++++++++-------------------------- > block/nbd-client.h | 20 ++++++------ > block/nbd.c | 37 ++++++++------------- > 3 files changed, 73 insertions(+), 79 deletions(-) > > diff --git a/block/nbd-client.c b/block/nbd-client.c > index 28bfb62..4ede714 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_session_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_session_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 nbd_client_session_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_session_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_session_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_session_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, > +void nbd_client_session_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_session_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 nbd_client_session_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_session_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..49daccc 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, > +NbdClientSession *nbd_get_client_session(BlockDriverState *bs); > + > +int nbd_client_session_init(BlockDriverState *bs, > int sock, const char *export_name, Error **errp); > -void nbd_client_session_close(NbdClientSession *client); > +void nbd_client_session_close(BlockDriverState *bs); > > -int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num, > +int nbd_client_session_co_discard(BlockDriverState *bs, 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 nbd_client_session_co_flush(BlockDriverState *bs); > +int nbd_client_session_co_writev(BlockDriverState *bs, int64_t sector_num, > int nb_sectors, QEMUIOVector *qiov); > -int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num, > +int nbd_client_session_co_readv(BlockDriverState *bs, 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, > +void nbd_client_session_detach_aio_context(BlockDriverState *bs); > +void nbd_client_session_attach_aio_context(BlockDriverState *bs, > AioContext *new_context); > > #endif /* NBD_CLIENT_H */ > diff --git a/block/nbd.c b/block/nbd.c > index 2e20831..f71fba0 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_session_init(bs, sock, export, errp); > g_free(export); > return result; > } > @@ -279,35 +285,24 @@ 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_session_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_session_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_session_co_flush(bs); > } > > 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_session_co_discard(bs, sector_num, nb_sectors); > } > > static void nbd_close(BlockDriverState *bs) > @@ -315,7 +310,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_session_close(bs); > } > > static int64_t nbd_getlength(BlockDriverState *bs) > @@ -327,17 +322,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_session_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_session_attach_aio_context(bs, new_context); > } > > static void nbd_refresh_filename(BlockDriverState *bs) > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 1/3] nbd: Drop BDS backpointer 2015-02-03 8:37 ` Paolo Bonzini @ 2015-02-03 13:54 ` Max Reitz 0 siblings, 0 replies; 8+ messages in thread From: Max Reitz @ 2015-02-03 13:54 UTC (permalink / raw) To: Paolo Bonzini, qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi On 2015-02-03 at 03:37, Paolo Bonzini wrote: > > On 02/02/2015 22:40, Max Reitz wrote: >> 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. > Looks good, but please change function names from nbd_client_session_foo > to nbd_client_foo or even just nbd_foo if they do not take an > NbdClientSession* as the first parameter. Ah, that makes a lot of sense, especially concerning the callback functions (albeit they were named nbd_foo already, but well...) which only take a void pointer. Will do, thanks, Max > Thanks, > > Paolo ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 2/3] iotests: Add "wait" functionality to _cleanup_qemu 2015-02-02 21:40 [Qemu-devel] [PATCH 0/3] nbd: Drop BDS backpointer Max Reitz 2015-02-02 21:40 ` [Qemu-devel] [PATCH 1/3] " Max Reitz @ 2015-02-02 21:40 ` Max Reitz 2015-02-03 8:38 ` Paolo Bonzini 2015-02-02 21:40 ` [Qemu-devel] [PATCH 3/3] iotests: Add test for drive-mirror with NBD target Max Reitz 2 siblings, 1 reply; 8+ messages in thread From: Max Reitz @ 2015-02-02 21:40 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> --- 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] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 2/3] iotests: Add "wait" functionality to _cleanup_qemu 2015-02-02 21:40 ` [Qemu-devel] [PATCH 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz @ 2015-02-03 8:38 ` Paolo Bonzini 0 siblings, 0 replies; 8+ messages in thread From: Paolo Bonzini @ 2015-02-03 8:38 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi On 02/02/2015 22:40, Max Reitz wrote: > 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> > --- > 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]}<&-" > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [PATCH 3/3] iotests: Add test for drive-mirror with NBD target 2015-02-02 21:40 [Qemu-devel] [PATCH 0/3] nbd: Drop BDS backpointer Max Reitz 2015-02-02 21:40 ` [Qemu-devel] [PATCH 1/3] " Max Reitz 2015-02-02 21:40 ` [Qemu-devel] [PATCH 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz @ 2015-02-02 21:40 ` Max Reitz 2015-02-03 8:38 ` Paolo Bonzini 2 siblings, 1 reply; 8+ messages in thread From: Max Reitz @ 2015-02-02 21:40 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> --- 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] 8+ messages in thread
* Re: [Qemu-devel] [PATCH 3/3] iotests: Add test for drive-mirror with NBD target 2015-02-02 21:40 ` [Qemu-devel] [PATCH 3/3] iotests: Add test for drive-mirror with NBD target Max Reitz @ 2015-02-03 8:38 ` Paolo Bonzini 0 siblings, 0 replies; 8+ messages in thread From: Paolo Bonzini @ 2015-02-03 8:38 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi On 02/02/2015 22:40, Max Reitz wrote: > 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> > --- > 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 > Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-02-03 13:54 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-02-02 21:40 [Qemu-devel] [PATCH 0/3] nbd: Drop BDS backpointer Max Reitz 2015-02-02 21:40 ` [Qemu-devel] [PATCH 1/3] " Max Reitz 2015-02-03 8:37 ` Paolo Bonzini 2015-02-03 13:54 ` Max Reitz 2015-02-02 21:40 ` [Qemu-devel] [PATCH 2/3] iotests: Add "wait" functionality to _cleanup_qemu Max Reitz 2015-02-03 8:38 ` Paolo Bonzini 2015-02-02 21:40 ` [Qemu-devel] [PATCH 3/3] iotests: Add test for drive-mirror with NBD target Max Reitz 2015-02-03 8:38 ` Paolo Bonzini
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).