From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:41521) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Re74X-00057V-B1 for qemu-devel@nongnu.org; Fri, 23 Dec 2011 10:30:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Re74W-0006up-5g for qemu-devel@nongnu.org; Fri, 23 Dec 2011 10:30:13 -0500 Received: from mail-iy0-f173.google.com ([209.85.210.173]:37591) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Re74W-0006jy-1D for qemu-devel@nongnu.org; Fri, 23 Dec 2011 10:30:12 -0500 Received: by mail-iy0-f173.google.com with SMTP id j37so17394063iag.4 for ; Fri, 23 Dec 2011 07:30:11 -0800 (PST) Sender: Paolo Bonzini From: Paolo Bonzini Date: Fri, 23 Dec 2011 16:26:29 +0100 Message-Id: <1324653990-20074-26-git-send-email-pbonzini@redhat.com> In-Reply-To: <1324653990-20074-1-git-send-email-pbonzini@redhat.com> References: <1324653990-20074-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 25/26] 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 | 25 ++++++++++++++++++++++--- 1 files changed, 22 insertions(+), 3 deletions(-) diff --git a/nbd.c b/nbd.c index 6d7d1f8..567e94e 100644 --- a/nbd.c +++ b/nbd.c @@ -587,6 +587,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 { @@ -614,6 +616,8 @@ struct NBDClient { CoMutex send_lock; Coroutine *send_coroutine; + + int nb_requests; }; static void nbd_client_get(NBDClient *client) @@ -644,6 +648,9 @@ static NBDRequest *nbd_request_get(NBDClient *client) NBDRequest *req; NBDExport *exp = client->exp; + assert(client->nb_requests <= MAX_NBD_REQUESTS - 1); + client->nb_requests++; + if (QSIMPLEQ_EMPTY(&exp->requests)) { req = g_malloc0(sizeof(NBDRequest)); req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE); @@ -660,6 +667,9 @@ static void nbd_request_put(NBDRequest *req) { NBDClient *client = req->client; QSIMPLEQ_INSERT_HEAD(&client->exp->requests, req, entry); + if (client->nb_requests-- == MAX_NBD_REQUESTS) { + qemu_notify_event(); + } nbd_client_put(client); } @@ -688,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); @@ -699,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) { @@ -724,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; } @@ -900,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; @@ -931,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.7.1