From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:38243) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXwxR-0003Es-Gb for qemu-devel@nongnu.org; Tue, 06 Dec 2011 10:29:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RXwxP-0000gN-G1 for qemu-devel@nongnu.org; Tue, 06 Dec 2011 10:29:25 -0500 Received: from mail-iy0-f173.google.com ([209.85.210.173]:40617) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXwxP-0000A8-2E for qemu-devel@nongnu.org; Tue, 06 Dec 2011 10:29:23 -0500 Received: by mail-iy0-f173.google.com with SMTP id j26so193361iaf.4 for ; Tue, 06 Dec 2011 07:29:22 -0800 (PST) Sender: Paolo Bonzini From: Paolo Bonzini Date: Tue, 6 Dec 2011 16:27:52 +0100 Message-Id: <1323185272-2610-26-git-send-email-pbonzini@redhat.com> In-Reply-To: <1323185272-2610-1-git-send-email-pbonzini@redhat.com> References: <1323185272-2610-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 25/25] 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 7eaaf88..0374d02 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