From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:56153) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RDCJW-00022w-F7 for qemu-devel@nongnu.org; Mon, 10 Oct 2011 05:38:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RDCJP-00014N-UJ for qemu-devel@nongnu.org; Mon, 10 Oct 2011 05:38:26 -0400 Received: from mail-bw0-f45.google.com ([209.85.214.45]:57071) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RDCJO-0000ul-D1 for qemu-devel@nongnu.org; Mon, 10 Oct 2011 05:38:19 -0400 Received: by mail-bw0-f45.google.com with SMTP id zv15so8235447bkb.4 for ; Mon, 10 Oct 2011 02:38:17 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Mon, 10 Oct 2011 11:37:57 +0200 Message-Id: <1318239477-31451-16-git-send-email-pbonzini@redhat.com> In-Reply-To: <1318239477-31451-1-git-send-email-pbonzini@redhat.com> References: <1318239477-31451-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 15/15] qemu-nbd: throttle requests List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Limiting the number of in-flight requests is implemented very simply with a can_read callback. It does not require a semaphore, unlike the client side in block/nbd.c, because we can throttle directly the creation of coroutines. The client side can have a coroutine created at any time when an I/O request is made. Signed-off-by: Paolo Bonzini --- nbd.c | 23 ++++++++++++++++++++--- 1 files changed, 20 insertions(+), 3 deletions(-) diff --git a/nbd.c b/nbd.c index 01d3a85..1869212 100644 --- a/nbd.c +++ b/nbd.c @@ -589,6 +589,8 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply) return 0; } +#define MAX_NBD_REQUESTS 16 + typedef struct NBDRequest NBDRequest; struct NBDRequest { @@ -616,6 +618,8 @@ struct NBDClient { CoMutex send_lock; Coroutine *send_coroutine; + + int nb_requests; }; static void nbd_client_get(NBDClient *client) @@ -646,6 +650,9 @@ static NBDRequest *nbd_request_get(NBDClient *client) NBDRequest *req; NBDExport *exp = client->exp; + assert(client->nb_requests < MAX_NBD_REQUESTS); + client->nb_requests++; + if (QSIMPLEQ_EMPTY(&exp->requests)) { req = g_malloc0(sizeof(NBDRequest)); req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE); @@ -662,6 +669,7 @@ static void nbd_request_put(NBDRequest *req) { NBDClient *client = req->client; QSIMPLEQ_INSERT_HEAD(&client->exp->requests, req, entry); + client->nb_requests--; nbd_client_put(client); } @@ -690,6 +698,7 @@ void nbd_export_close(NBDExport *exp) g_free(exp); } +static int nbd_can_read(void *opaque); static void nbd_read(void *opaque); static void nbd_restart_write(void *opaque); @@ -701,7 +710,8 @@ static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, int rc, ret; qemu_co_mutex_lock(&client->send_lock); - qemu_set_fd_handler2(csock, NULL, nbd_read, nbd_restart_write, client); + qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, + nbd_restart_write, client); client->send_coroutine = qemu_coroutine_self(); if (!len) { @@ -726,7 +736,7 @@ static int nbd_co_send_reply(NBDRequest *req, struct nbd_reply *reply, } client->send_coroutine = NULL; - qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client); + qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); qemu_co_mutex_unlock(&client->send_lock); return rc; } @@ -902,6 +912,13 @@ out: nbd_client_close(client); } +static int nbd_can_read(void *opaque) +{ + NBDClient *client = opaque; + + return client->recv_coroutine || client->nb_requests < MAX_NBD_REQUESTS; +} + static void nbd_read(void *opaque) { NBDClient *client = opaque; @@ -933,6 +950,6 @@ NBDClient *nbd_client_new(NBDExport *exp, int csock, client->sock = csock; client->close = close; qemu_co_mutex_init(&client->send_lock); - qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client); + qemu_set_fd_handler2(csock, nbd_can_read, nbd_read, NULL, client); return client; } -- 1.7.6