From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: alex@alex.org.uk, Paolo Bonzini <pbonzini@redhat.com>,
Kevin Wolf <kwolf@redhat.com>,
"open list:Block layer core" <qemu-block@nongnu.org>
Subject: [Qemu-devel] [PATCH 16/18] nbd: Support NBD_CMD_CLOSE
Date: Fri, 8 Apr 2016 16:05:56 -0600 [thread overview]
Message-ID: <1460153158-21612-17-git-send-email-eblake@redhat.com> (raw)
In-Reply-To: <1460153158-21612-1-git-send-email-eblake@redhat.com>
NBD_CMD_DISC is annoying: the server is not required to reply,
so the client has no choice but to disconnect once it has sent
the message; but depending on timing, the server can see the
disconnect prior to reading the request, and treat things as
an abrupt exit rather than a clean shutdown (which may affect
whether the server properly fsync()s data to disk, and so on).
The new NBD_CMD_CLOSE adds another round of handshake, where
the client waits for the server's action before closing, to
make sure both parties know that it was a clean close rather
than an accidental early disconnect.
In nbd-client.c, nbd_client_close() is called after we have
already exited the normal coroutine context used by all the
other transmission phase handlers, so the code is a bit more
complex to build up a coroutine just for the purpose of waiting
for the server's response.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/block/nbd.h | 4 +++-
block/nbd-client.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
nbd/server.c | 19 +++++++++++++++++--
3 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/include/block/nbd.h b/include/block/nbd.h
index d261dbc..4c57754 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -70,6 +70,7 @@ typedef struct nbd_reply nbd_reply;
#define NBD_FLAG_SEND_FUA (1 << 3) /* Send FUA (Force Unit Access) */
#define NBD_FLAG_ROTATIONAL (1 << 4) /* Use elevator algorithm - rotational media */
#define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */
+#define NBD_FLAG_SEND_CLOSE (1 << 8) /* Send CLOSE */
/* New-style handshake (global) flags, sent from server to client, and
control what will happen during handshake phase. */
@@ -99,7 +100,8 @@ enum {
NBD_CMD_WRITE = 1,
NBD_CMD_DISC = 2,
NBD_CMD_FLUSH = 3,
- NBD_CMD_TRIM = 4
+ NBD_CMD_TRIM = 4,
+ NBD_CMD_CLOSE = 7,
};
#define NBD_DEFAULT_PORT 10809
diff --git a/block/nbd-client.c b/block/nbd-client.c
index 285025d..f013084 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -374,6 +374,29 @@ void nbd_client_attach_aio_context(BlockDriverState *bs,
false, nbd_reply_ready, NULL, bs);
}
+typedef struct NbdCloseCo {
+ BlockDriverState *bs;
+ nbd_request request;
+ nbd_reply reply;
+ bool done;
+} NbdCloseCo;
+
+static void coroutine_fn nbd_client_close_co(void *opaque)
+{
+ NbdCloseCo *closeco = opaque;
+ NbdClientSession *client = nbd_get_client_session(closeco->bs);
+ ssize_t ret;
+
+ nbd_coroutine_start(client, &closeco->request);
+ ret = nbd_co_send_request(closeco->bs, &closeco->request, NULL, 0);
+ if (ret >= 0) {
+ nbd_co_receive_reply(client, &closeco->request, &closeco->reply,
+ NULL, 0);
+ }
+ nbd_coroutine_end(client, &closeco->request);
+ closeco->done = true;
+}
+
void nbd_client_close(BlockDriverState *bs)
{
NbdClientSession *client = nbd_get_client_session(bs);
@@ -383,8 +406,28 @@ void nbd_client_close(BlockDriverState *bs)
return;
}
- nbd_send_request(client->ioc, &request);
+ if (client->nbdflags & NBD_FLAG_SEND_CLOSE) {
+ /* Newer server, wants us to wait for reply before we close */
+ Coroutine *co;
+ NbdCloseCo closeco = {
+ .bs = bs,
+ .request = { .type = NBD_CMD_CLOSE },
+ };
+ AioContext *aio_context;
+ g_assert(!qemu_in_coroutine());
+ aio_context = bdrv_get_aio_context(bs);
+ co = qemu_coroutine_create(nbd_client_close_co);
+ qemu_coroutine_enter(co, &closeco);
+ while (!closeco.done) {
+ aio_poll(aio_context, true);
+ }
+ } else {
+ /* Older server, send request, but no reply will come */
+ nbd_send_request(client->ioc, &request);
+ }
+
+ /* Regardless of any received errors, the connection is done. */
nbd_teardown_connection(bs);
}
diff --git a/nbd/server.c b/nbd/server.c
index e68e83c..2a6eaf2 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -624,7 +624,8 @@ static coroutine_fn int nbd_negotiate(NBDClientNewData *data)
char buf[8 + 8 + 8 + 128];
int rc;
const uint16_t myflags = (NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
- NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
+ NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
+ NBD_FLAG_SEND_CLOSE);
bool oldStyle;
size_t len;
@@ -1244,7 +1245,21 @@ static void nbd_trip(void *opaque)
break;
case NBD_CMD_DISC:
TRACE("Request type is DISCONNECT");
- errno = 0;
+ goto out;
+ case NBD_CMD_CLOSE:
+ TRACE("Request type is CLOSE");
+ if (request.flags || request.from || request.len) {
+ LOG("bad parameters, skipping flush");
+ reply.error = EINVAL;
+ } else {
+ ret = blk_co_flush(exp->blk);
+ if (ret < 0) {
+ LOG("flush failed");
+ reply.error = -ret;
+ }
+ }
+ /* Attempt to send reply, but even if it fails, we are done */
+ nbd_co_send_reply(req, &reply, 0);
goto out;
case NBD_CMD_FLUSH:
TRACE("Request type is FLUSH");
--
2.5.5
next prev parent reply other threads:[~2016-04-08 22:06 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-04-08 22:05 [Qemu-devel] [RFC PATCH 00/18] NBD protocol additions Eric Blake
2016-04-08 22:05 ` [Qemu-devel] [PATCH 01/18] nbd: Don't kill server on client that doesn't request TLS Eric Blake
2016-04-09 10:28 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 02/18] nbd: Don't fail handshake on NBD_OPT_LIST descriptions Eric Blake
2016-04-09 10:30 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 03/18] nbd: More debug typo fixes, use correct formats Eric Blake
2016-04-09 10:30 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 04/18] nbd: Detect servers that send unexpected error values Eric Blake
2016-04-09 10:31 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 05/18] nbd: Reject unknown request flags Eric Blake
2016-04-09 10:32 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 06/18] nbd: Avoid magic number for NBD max name size Eric Blake
2016-04-09 10:35 ` Alex Bligh
2016-04-09 22:07 ` Eric Blake
2016-04-08 22:05 ` [Qemu-devel] [PATCH 07/18] nbd: Treat flags vs. command type as separate fields Eric Blake
2016-04-09 10:37 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 08/18] nbd: Limit nbdflags to 16 bits Eric Blake
2016-04-09 10:37 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 09/18] nbd: Share common reply-sending code in server Eric Blake
2016-04-09 10:38 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 10/18] nbd: Share common option-sending code in client Eric Blake
2016-04-09 10:38 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 11/18] nbd: Let client skip portions of server reply Eric Blake
2016-04-09 10:39 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [PATCH 12/18] nbd: Less allocation during NBD_OPT_LIST Eric Blake
2016-04-09 10:41 ` Alex Bligh
2016-04-09 22:24 ` Eric Blake
2016-04-08 22:05 ` [Qemu-devel] [PATCH 13/18] nbd: Support shorter handshake Eric Blake
2016-04-09 10:42 ` Alex Bligh
2016-04-09 22:27 ` Eric Blake
2016-04-08 22:05 ` [Qemu-devel] [PATCH 14/18] nbd: Implement NBD_OPT_GO on client Eric Blake
2016-04-09 10:47 ` Alex Bligh
2016-04-09 22:38 ` Eric Blake
2016-04-08 22:05 ` [Qemu-devel] [PATCH 15/18] nbd: Implement NBD_OPT_GO on server Eric Blake
2016-04-09 10:48 ` Alex Bligh
2016-04-08 22:05 ` Eric Blake [this message]
2016-04-09 10:50 ` [Qemu-devel] [PATCH 16/18] nbd: Support NBD_CMD_CLOSE Alex Bligh
2016-04-09 23:12 ` Eric Blake
2016-04-10 5:28 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [RFC PATCH 17/18] nbd: Implement NBD_CMD_WRITE_ZEROES on server Eric Blake
2016-04-09 9:39 ` Pavel Borzenkov
2016-04-09 10:54 ` Alex Bligh
2016-04-08 22:05 ` [Qemu-devel] [RFC PATCH 18/18] nbd: Implement NBD_CMD_WRITE_ZEROES on client Eric Blake
2016-04-09 10:57 ` Alex Bligh
2016-04-09 11:52 ` Pavel Borzenkov
2016-04-09 23:17 ` Eric Blake
2016-04-10 5:27 ` Alex Bligh
2016-04-09 10:21 ` [Qemu-devel] [Nbd] [RFC PATCH 00/18] NBD protocol additions Wouter Verhelst
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1460153158-21612-17-git-send-email-eblake@redhat.com \
--to=eblake@redhat.com \
--cc=alex@alex.org.uk \
--cc=kwolf@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).