From patchwork Thu Sep 8 15:25:04 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 113914 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 97B25B6F8F for ; Fri, 9 Sep 2011 01:26:21 +1000 (EST) Received: from localhost ([::1]:54346 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1gUc-0005ao-1q for incoming@patchwork.ozlabs.org; Thu, 08 Sep 2011 11:26:18 -0400 Received: from eggs.gnu.org ([140.186.70.92]:42964) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1gU0-0003v2-Q5 for qemu-devel@nongnu.org; Thu, 08 Sep 2011 11:25:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R1gTy-0000wH-Mh for qemu-devel@nongnu.org; Thu, 08 Sep 2011 11:25:40 -0400 Received: from mail-qw0-f45.google.com ([209.85.216.45]:60835) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R1gTy-0000vx-Ij for qemu-devel@nongnu.org; Thu, 08 Sep 2011 11:25:38 -0400 Received: by qwj8 with SMTP id 8so750296qwj.4 for ; Thu, 08 Sep 2011 08:25:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=bunjlcSVoea/kZDCGwKkeUYuzCH302/m5dfBZqgXdf8=; b=Ww4AgQ5ZNWRp5LmY0j+HxMjNdMq4CaKUh03IvnJvxYm2RxBwE7fMZ34xPxejhLs4jR 9fHij5jtwLIw6nImjv7wDVm24vPUrghJIGfeStrmQVD1uHzUirBYHT/ULYQkMFBT8uLZ n84pz3EpxB6ykqr8ZKl89cV1kJJmkZ1cTYLBU= Received: by 10.52.20.47 with SMTP id k15mr855883vde.296.1315495537751; Thu, 08 Sep 2011 08:25:37 -0700 (PDT) Received: from localhost.localdomain (93-34-199-31.ip51.fastwebnet.it [93.34.199.31]) by mx.google.com with ESMTPS id by14sm2810776vdb.22.2011.09.08.08.25.35 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 08 Sep 2011 08:25:36 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 8 Sep 2011 17:25:04 +0200 Message-Id: <1315495505-28906-12-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.6 In-Reply-To: <1315495505-28906-1-git-send-email-pbonzini@redhat.com> References: <1315495505-28906-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 209.85.216.45 Subject: [Qemu-devel] [PATCH 11/12] nbd: switch to asynchronous operation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Paolo Bonzini --- block/nbd.c | 167 ++++++++++++++++++++++++++++++++++++++-------------------- nbd.c | 8 +++ 2 files changed, 117 insertions(+), 58 deletions(-) diff --git a/block/nbd.c b/block/nbd.c index 964caa8..5a75263 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -52,6 +52,9 @@ typedef struct BDRVNBDState { size_t blocksize; char *export_name; /* An NBD server may export several devices */ + CoMutex mutex; + Coroutine *coroutine; + /* If it begins with '/', this is a UNIX domain socket. Otherwise, * it's a string of the form :port */ @@ -104,6 +107,37 @@ out: return err; } +static void nbd_coroutine_start(BDRVNBDState *s) +{ + qemu_co_mutex_lock(&s->mutex); + s->coroutine = qemu_coroutine_self(); +} + +static void nbd_coroutine_enter(void *opaque) +{ + BDRVNBDState *s = opaque; + qemu_coroutine_enter(s->coroutine, NULL); +} + +static int nbd_co_send_request(BDRVNBDState *s, struct nbd_request *request) +{ + qemu_aio_set_fd_handler(s->sock, NULL, nbd_coroutine_enter, NULL, NULL, s); + return nbd_send_request(s->sock, request); +} + +static int nbd_co_receive_reply(BDRVNBDState *s, struct nbd_reply *reply) +{ + qemu_aio_set_fd_handler(s->sock, nbd_coroutine_enter, NULL, NULL, NULL, s); + return nbd_receive_reply(s->sock, reply); +} + +static void nbd_coroutine_end(BDRVNBDState *s) +{ + qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL, NULL, s); + s->coroutine = NULL; + qemu_co_mutex_unlock(&s->mutex); +} + static int nbd_establish_connection(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; @@ -163,6 +197,8 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags) BDRVNBDState *s = bs->opaque; int result; + qemu_co_mutex_init(&s->mutex); + /* Pop the config into our state object. Exit if invalid. */ result = nbd_config(s, filename, flags); if (result != 0) { @@ -177,8 +213,8 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags) return result; } -static int nbd_read(BlockDriverState *bs, int64_t sector_num, - uint8_t *buf, int nb_sectors) +static int nbd_co_readv(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { BDRVNBDState *s = bs->opaque; struct nbd_request request; @@ -189,30 +225,39 @@ static int nbd_read(BlockDriverState *bs, int64_t sector_num, request.from = sector_num * 512;; request.len = nb_sectors * 512; - if (nbd_send_request(s->sock, &request) == -1) - return -errno; - - if (nbd_receive_reply(s->sock, &reply) == -1) - return -errno; - - if (reply.error !=0) - return -reply.error; - - if (reply.handle != request.handle) - return -EIO; + nbd_coroutine_start(s); + if (nbd_co_send_request(s, &request) == -1) { + reply.error = errno; + goto done; + } + if (nbd_co_receive_reply(s, &reply) == -1) { + reply.error = errno; + goto done; + } + if (reply.error != 0) { + goto done; + } + if (reply.handle != request.handle) { + reply.error = EIO; + goto done; + } + if (qemu_co_recvv(s->sock, qiov->iov, request.len, 0) != request.len) { + reply.error = EIO; + } - if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len) - return -EIO; +done: + nbd_coroutine_end(s); + return -reply.error; - return 0; } -static int nbd_write(BlockDriverState *bs, int64_t sector_num, - const uint8_t *buf, int nb_sectors) +static int nbd_co_writev(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, QEMUIOVector *qiov) { BDRVNBDState *s = bs->opaque; struct nbd_request request; struct nbd_reply reply; + int ret; request.type = NBD_CMD_WRITE; if (!bdrv_enable_write_cache(bs) && (s->nbdflags & NBD_FLAG_SEND_FUA)) { @@ -223,25 +268,30 @@ static int nbd_write(BlockDriverState *bs, int64_t sector_num, request.from = sector_num * 512;; request.len = nb_sectors * 512; - if (nbd_send_request(s->sock, &request) == -1) - return -errno; - - if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len) - return -EIO; - - if (nbd_receive_reply(s->sock, &reply) == -1) - return -errno; - - if (reply.error !=0) - return -reply.error; - - if (reply.handle != request.handle) - return -EIO; + nbd_coroutine_start(s); + if (nbd_co_send_request(s, &request) == -1) { + reply.error = errno; + goto done; + } + ret = qemu_co_sendv(s->sock, qiov->iov, request.len, 0); + if (ret != request.len) { + reply.error = EIO; + goto done; + } + if (nbd_co_receive_reply(s, &reply) == -1) { + reply.error = errno; + goto done; + } + if (reply.handle != request.handle) { + reply.error = EIO; + } - return 0; +done: + nbd_coroutine_end(s); + return -reply.error; } -static int nbd_flush(BlockDriverState *bs) +static int nbd_co_flush(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; struct nbd_request request; @@ -260,19 +310,22 @@ static int nbd_flush(BlockDriverState *bs) request.from = 0; request.len = 0; - if (nbd_send_request(s->sock, &request) == -1) - return -errno; - - if (nbd_receive_reply(s->sock, &reply) == -1) - return -errno; - - if (reply.error !=0) - return -reply.error; - - if (reply.handle != request.handle) - return -EIO; + nbd_coroutine_start(s); + if (nbd_co_send_request(s, &request) == -1) { + reply.error = errno; + goto done; + } + if (nbd_co_receive_reply(s, &reply) == -1) { + reply.error = errno; + goto done; + } + if (reply.error == 0 && reply.handle != request.handle) { + reply.error = EIO; + } - return 0; +done: + nbd_coroutine_end(s); + return -reply.error; } static int nbd_discard(BlockDriverState *bs, int64_t sector_num, @@ -290,19 +343,17 @@ static int nbd_discard(BlockDriverState *bs, int64_t sector_num, request.from = sector_num * 512;; request.len = nb_sectors * 512; - if (nbd_send_request(s->sock, &request) == -1) + if (nbd_send_request(s->sock, &request) == -1) { return -errno; - - if (nbd_receive_reply(s->sock, &reply) == -1) + } + if (nbd_receive_reply(s->sock, &reply) == -1) { return -errno; - - if (reply.error !=0) - return -reply.error; - - if (reply.handle != request.handle) + } + if (reply.error == 0 && reply.handle != request.handle) { return -EIO; + } - return 0; + return -reply.error; } static void nbd_close(BlockDriverState *bs) @@ -325,10 +376,10 @@ static BlockDriver bdrv_nbd = { .format_name = "nbd", .instance_size = sizeof(BDRVNBDState), .bdrv_file_open = nbd_open, - .bdrv_read = nbd_read, - .bdrv_write = nbd_write, + .bdrv_co_readv = nbd_co_readv, + .bdrv_co_writev = nbd_co_writev, .bdrv_close = nbd_close, - .bdrv_flush = nbd_flush, + .bdrv_co_flush = nbd_co_flush, .bdrv_discard = nbd_discard, .bdrv_getlength = nbd_getlength, .protocol_name = "nbd", diff --git a/nbd.c b/nbd.c index f089904..2f4c6b3 100644 --- a/nbd.c +++ b/nbd.c @@ -80,6 +80,14 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) { size_t offset = 0; + if (qemu_in_coroutine()) { + if (do_read) { + return qemu_co_recv(fd, buffer, size); + } else { + return qemu_co_send(fd, buffer, size); + } + } + while (offset < size) { ssize_t len;