|
@@ -81,7 +81,7 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
|
|
|
|
|
|
struct NBDClient {
|
|
struct NBDClient {
|
|
int refcount;
|
|
int refcount;
|
|
- void (*close)(NBDClient *client);
|
|
|
|
|
|
+ void (*close_fn)(NBDClient *client, bool negotiated);
|
|
|
|
|
|
bool no_zeroes;
|
|
bool no_zeroes;
|
|
NBDExport *exp;
|
|
NBDExport *exp;
|
|
@@ -778,7 +778,7 @@ void nbd_client_put(NBDClient *client)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void client_close(NBDClient *client)
|
|
|
|
|
|
+static void client_close(NBDClient *client, bool negotiated)
|
|
{
|
|
{
|
|
if (client->closing) {
|
|
if (client->closing) {
|
|
return;
|
|
return;
|
|
@@ -793,8 +793,8 @@ static void client_close(NBDClient *client)
|
|
NULL);
|
|
NULL);
|
|
|
|
|
|
/* Also tell the client, so that they release their reference. */
|
|
/* Also tell the client, so that they release their reference. */
|
|
- if (client->close) {
|
|
|
|
- client->close(client);
|
|
|
|
|
|
+ if (client->close_fn) {
|
|
|
|
+ client->close_fn(client, negotiated);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -975,7 +975,7 @@ void nbd_export_close(NBDExport *exp)
|
|
|
|
|
|
nbd_export_get(exp);
|
|
nbd_export_get(exp);
|
|
QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
|
|
QTAILQ_FOREACH_SAFE(client, &exp->clients, next, next) {
|
|
- client_close(client);
|
|
|
|
|
|
+ client_close(client, true);
|
|
}
|
|
}
|
|
nbd_export_set_name(exp, NULL);
|
|
nbd_export_set_name(exp, NULL);
|
|
nbd_export_set_description(exp, NULL);
|
|
nbd_export_set_description(exp, NULL);
|
|
@@ -1337,7 +1337,7 @@ done:
|
|
|
|
|
|
out:
|
|
out:
|
|
nbd_request_put(req);
|
|
nbd_request_put(req);
|
|
- client_close(client);
|
|
|
|
|
|
+ client_close(client, true);
|
|
nbd_client_put(client);
|
|
nbd_client_put(client);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1363,7 +1363,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
|
|
qemu_co_mutex_init(&client->send_lock);
|
|
qemu_co_mutex_init(&client->send_lock);
|
|
|
|
|
|
if (nbd_negotiate(data)) {
|
|
if (nbd_negotiate(data)) {
|
|
- client_close(client);
|
|
|
|
|
|
+ client_close(client, false);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1373,11 +1373,17 @@ out:
|
|
g_free(data);
|
|
g_free(data);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Create a new client listener on the given export @exp, using the
|
|
|
|
+ * given channel @sioc. Begin servicing it in a coroutine. When the
|
|
|
|
+ * connection closes, call @close_fn with an indication of whether the
|
|
|
|
+ * client completed negotiation.
|
|
|
|
+ */
|
|
void nbd_client_new(NBDExport *exp,
|
|
void nbd_client_new(NBDExport *exp,
|
|
QIOChannelSocket *sioc,
|
|
QIOChannelSocket *sioc,
|
|
QCryptoTLSCreds *tlscreds,
|
|
QCryptoTLSCreds *tlscreds,
|
|
const char *tlsaclname,
|
|
const char *tlsaclname,
|
|
- void (*close_fn)(NBDClient *))
|
|
|
|
|
|
+ void (*close_fn)(NBDClient *, bool))
|
|
{
|
|
{
|
|
NBDClient *client;
|
|
NBDClient *client;
|
|
NBDClientNewData *data = g_new(NBDClientNewData, 1);
|
|
NBDClientNewData *data = g_new(NBDClientNewData, 1);
|
|
@@ -1394,7 +1400,7 @@ void nbd_client_new(NBDExport *exp,
|
|
object_ref(OBJECT(client->sioc));
|
|
object_ref(OBJECT(client->sioc));
|
|
client->ioc = QIO_CHANNEL(sioc);
|
|
client->ioc = QIO_CHANNEL(sioc);
|
|
object_ref(OBJECT(client->ioc));
|
|
object_ref(OBJECT(client->ioc));
|
|
- client->close = close_fn;
|
|
|
|
|
|
+ client->close_fn = close_fn;
|
|
|
|
|
|
data->client = client;
|
|
data->client = client;
|
|
data->co = qemu_coroutine_create(nbd_co_client_start, data);
|
|
data->co = qemu_coroutine_create(nbd_co_client_start, data);
|