nbd: Refactor reply to NBD_OPT_EXPORT_NAME

Reply directly in nbd_negotiate_handle_export_name(), rather than
waiting until nbd_negotiate_options() completes.  This will make it
easier to implement NBD_OPT_GO.  Pass additional parameters around,
rather than stashing things inside NBDClient.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-6-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
master
Eric Blake 2017-07-07 15:30:45 -05:00 committed by Paolo Bonzini
parent 621c4f4eab
commit 23e099c34c
1 changed files with 28 additions and 22 deletions

View File

@ -84,7 +84,6 @@ struct NBDClient {
int refcount; int refcount;
void (*close_fn)(NBDClient *client, bool negotiated); void (*close_fn)(NBDClient *client, bool negotiated);
bool no_zeroes;
NBDExport *exp; NBDExport *exp;
QCryptoTLSCreds *tlscreds; QCryptoTLSCreds *tlscreds;
char *tlsaclname; char *tlsaclname;
@ -277,9 +276,13 @@ static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length,
} }
static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length, static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
uint16_t myflags, bool no_zeroes,
Error **errp) Error **errp)
{ {
char name[NBD_MAX_NAME_SIZE + 1]; char name[NBD_MAX_NAME_SIZE + 1];
char buf[8 + 4 + 124] = "";
size_t len;
int ret;
/* Client sends: /* Client sends:
[20 .. xx] export name (length bytes) [20 .. xx] export name (length bytes)
@ -303,6 +306,17 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length,
return -EINVAL; return -EINVAL;
} }
trace_nbd_negotiate_new_style_size_flags(client->exp->size,
client->exp->nbdflags | myflags);
stq_be_p(buf, client->exp->size);
stw_be_p(buf + 8, client->exp->nbdflags | myflags);
len = no_zeroes ? 10 : sizeof(buf);
ret = nbd_write(client->ioc, buf, len, errp);
if (ret < 0) {
error_prepend(errp, "write failed: ");
return ret;
}
QTAILQ_INSERT_TAIL(&client->exp->clients, client, next); QTAILQ_INSERT_TAIL(&client->exp->clients, client, next);
nbd_export_get(client->exp); nbd_export_get(client->exp);
@ -373,14 +387,17 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
* 1 if client sent NBD_OPT_ABORT, i.e. on valid disconnect, * 1 if client sent NBD_OPT_ABORT, i.e. on valid disconnect,
* errp is not set * errp is not set
*/ */
static int nbd_negotiate_options(NBDClient *client, Error **errp) static int nbd_negotiate_options(NBDClient *client, uint16_t myflags,
Error **errp)
{ {
uint32_t flags; uint32_t flags;
bool fixedNewstyle = false; bool fixedNewstyle = false;
bool no_zeroes = false;
/* Client sends: /* Client sends:
[ 0 .. 3] client flags [ 0 .. 3] client flags
Then we loop until NBD_OPT_EXPORT_NAME:
[ 0 .. 7] NBD_OPTS_MAGIC [ 0 .. 7] NBD_OPTS_MAGIC
[ 8 .. 11] NBD option [ 8 .. 11] NBD option
[12 .. 15] Data length [12 .. 15] Data length
@ -403,7 +420,7 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE; flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
} }
if (flags & NBD_FLAG_C_NO_ZEROES) { if (flags & NBD_FLAG_C_NO_ZEROES) {
client->no_zeroes = true; no_zeroes = true;
flags &= ~NBD_FLAG_C_NO_ZEROES; flags &= ~NBD_FLAG_C_NO_ZEROES;
} }
if (flags != 0) { if (flags != 0) {
@ -503,7 +520,9 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
return 1; return 1;
case NBD_OPT_EXPORT_NAME: case NBD_OPT_EXPORT_NAME:
return nbd_negotiate_handle_export_name(client, length, errp); return nbd_negotiate_handle_export_name(client, length,
myflags, no_zeroes,
errp);
case NBD_OPT_STARTTLS: case NBD_OPT_STARTTLS:
if (nbd_drop(client->ioc, length, errp) < 0) { if (nbd_drop(client->ioc, length, errp) < 0) {
@ -546,7 +565,9 @@ static int nbd_negotiate_options(NBDClient *client, Error **errp)
*/ */
switch (option) { switch (option) {
case NBD_OPT_EXPORT_NAME: case NBD_OPT_EXPORT_NAME:
return nbd_negotiate_handle_export_name(client, length, errp); return nbd_negotiate_handle_export_name(client, length,
myflags, no_zeroes,
errp);
default: default:
error_setg(errp, "Unsupported option 0x%" PRIx32 " (%s)", error_setg(errp, "Unsupported option 0x%" PRIx32 " (%s)",
@ -572,7 +593,6 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA |
NBD_FLAG_SEND_WRITE_ZEROES); NBD_FLAG_SEND_WRITE_ZEROES);
bool oldStyle; bool oldStyle;
size_t len;
/* Old style negotiation header without options /* Old style negotiation header without options
[ 0 .. 7] passwd ("NBDMAGIC") [ 0 .. 7] passwd ("NBDMAGIC")
@ -586,10 +606,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
[ 0 .. 7] passwd ("NBDMAGIC") [ 0 .. 7] passwd ("NBDMAGIC")
[ 8 .. 15] magic (NBD_OPTS_MAGIC) [ 8 .. 15] magic (NBD_OPTS_MAGIC)
[16 .. 17] server flags (0) [16 .. 17] server flags (0)
....options sent.... ....options sent, ending in NBD_OPT_EXPORT_NAME....
[18 .. 25] size
[26 .. 27] export flags
[28 .. 151] reserved (0, omit if no_zeroes)
*/ */
qio_channel_set_blocking(client->ioc, false, NULL); qio_channel_set_blocking(client->ioc, false, NULL);
@ -618,24 +635,13 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
error_prepend(errp, "write failed: "); error_prepend(errp, "write failed: ");
return -EINVAL; return -EINVAL;
} }
ret = nbd_negotiate_options(client, errp); ret = nbd_negotiate_options(client, myflags, errp);
if (ret != 0) { if (ret != 0) {
if (ret < 0) { if (ret < 0) {
error_prepend(errp, "option negotiation failed: "); error_prepend(errp, "option negotiation failed: ");
} }
return ret; return ret;
} }
trace_nbd_negotiate_new_style_size_flags(
client->exp->size, client->exp->nbdflags | myflags);
stq_be_p(buf + 18, client->exp->size);
stw_be_p(buf + 26, client->exp->nbdflags | myflags);
len = client->no_zeroes ? 10 : sizeof(buf) - 18;
ret = nbd_write(client->ioc, buf + 18, len, errp);
if (ret < 0) {
error_prepend(errp, "write failed: ");
return ret;
}
} }
trace_nbd_negotiate_success(); trace_nbd_negotiate_success();