qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 05/12] nbd: do not leak nbd_trip coroutines when a connection is torn down
Date: Wed, 19 Sep 2012 15:49:49 +0200	[thread overview]
Message-ID: <1348062596-30446-6-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1348062596-30446-1-git-send-email-pbonzini@redhat.com>

Because nbd_client_close removes the I/O handlers for the client
socket, there is no way that any suspended coroutines are restarted.
This will be a problem with the QEMU embedded NBD server, because
we will have a QMP command to forcibly close all connections with
the clients.

Instead, we can exploit the reference counting of NBDClients; shutdown the
client socket, which will make it readable and writeable.  Also call the
close callback, which will release the user's reference.  The coroutines
then will fail and exit cleanly, and release all remaining references,
until the last refcount finally triggers the closure of the client.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 nbd.c | 33 +++++++++++++++++++++++++++------
 nbd.h |  1 +
 2 file modificati, 28 inserzioni(+), 6 rimozioni(-)

diff --git a/nbd.c b/nbd.c
index 4aeb80a..eb72f4a 100644
--- a/nbd.c
+++ b/nbd.c
@@ -109,6 +109,7 @@ struct NBDClient {
     Coroutine *send_coroutine;
 
     int nb_requests;
+    bool closing;
 };
 
 /* That's all folks */
@@ -655,19 +656,35 @@ void nbd_client_get(NBDClient *client)
 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.
+         */
+        assert(client->closing);
+
+        qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL);
+        close(client->sock);
+        client->sock = -1;
         g_free(client);
     }
 }
 
-static void nbd_client_close(NBDClient *client)
+void nbd_client_close(NBDClient *client)
 {
-    qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL);
-    close(client->sock);
-    client->sock = -1;
+    if (client->closing) {
+        return;
+    }
+
+    client->closing = true;
+
+    /* Force requests to finish.  They will drop their own references,
+     * then we'll close the socket and free the NBDClient.
+     */
+    shutdown(client->sock, 2);
+
+    /* Also tell the client, so that they release their reference.  */
     if (client->close) {
         client->close(client);
     }
-    nbd_client_put(client);
 }
 
 static NBDRequest *nbd_request_get(NBDClient *client)
@@ -810,14 +827,18 @@ out:
 static void nbd_trip(void *opaque)
 {
     NBDClient *client = opaque;
-    NBDRequest *req = nbd_request_get(client);
     NBDExport *exp = client->exp;
+    NBDRequest *req;
     struct nbd_request request;
     struct nbd_reply reply;
     ssize_t ret;
 
     TRACE("Reading request.");
+    if (client->closing) {
+        return;
+    }
 
+    req = nbd_request_get(client);
     ret = nbd_co_receive_request(req, &request);
     if (ret == -EAGAIN) {
         goto done;
diff --git a/nbd.h b/nbd.h
index a9038dc..8b84a50 100644
--- a/nbd.h
+++ b/nbd.h
@@ -84,6 +84,7 @@ void nbd_export_close(NBDExport *exp);
 
 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);
 
-- 
1.7.12

  parent reply	other threads:[~2012-09-19 13:50 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-19 13:49 [Qemu-devel] [PULL 00/12] NBD patches for 2012-09-22 Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 01/12] nbd: add more constants Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 02/12] nbd: pass NBDClient to nbd_send_negotiate Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 03/12] nbd: do not close BlockDriverState in nbd_export_close Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 04/12] nbd: make refcount interface public Paolo Bonzini
2012-09-19 13:49 ` Paolo Bonzini [this message]
2012-09-19 13:49 ` [Qemu-devel] [PATCH 06/12] nbd: add reference counting to NBDExport Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 07/12] nbd: track clients into NBDExport Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 08/12] nbd: add notification for closing an NBDExport Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 09/12] qemu-nbd: rewrite termination conditions to use a state machine Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 10/12] nbd: register named exports Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 11/12] nbd: negotiate with " Paolo Bonzini
2012-09-19 13:49 ` [Qemu-devel] [PATCH 12/12] nbd: add nbd_export_get_blockdev Paolo Bonzini
2012-09-25 23:27 ` [Qemu-devel] [PULL 00/12] NBD patches for 2012-09-22 Anthony Liguori

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=1348062596-30446-6-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --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).