From patchwork Wed Jul 18 15:07:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 1211561 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 9EE68DFFFD for ; Wed, 18 Jul 2012 15:08:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754803Ab2GRPIo (ORCPT ); Wed, 18 Jul 2012 11:08:44 -0400 Received: from e06smtp13.uk.ibm.com ([195.75.94.109]:56870 "EHLO e06smtp13.uk.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754633Ab2GRPIf (ORCPT ); Wed, 18 Jul 2012 11:08:35 -0400 Received: from /spool/local by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 18 Jul 2012 16:08:34 +0100 Received: from d06nrmr1806.portsmouth.uk.ibm.com (9.149.39.193) by e06smtp13.uk.ibm.com (192.168.101.143) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 18 Jul 2012 16:08:31 +0100 Received: from d06av10.portsmouth.uk.ibm.com (d06av10.portsmouth.uk.ibm.com [9.149.37.251]) by d06nrmr1806.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q6IF8Vvg2842858 for ; Wed, 18 Jul 2012 16:08:31 +0100 Received: from d06av10.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av10.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q6IEk37n012826 for ; Wed, 18 Jul 2012 10:46:04 -0400 Received: from localhost (sig-9-145-185-169.de.ibm.com [9.145.185.169]) by d06av10.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q6IEk3TH012815; Wed, 18 Jul 2012 10:46:03 -0400 From: Stefan Hajnoczi To: Cc: , Anthony Liguori , Kevin Wolf , Paolo Bonzini , "Michael S. Tsirkin" , Asias He , Khoa Huynh , Stefan Hajnoczi Subject: [RFC v9 08/27] virtio-blk: Read requests from the vring Date: Wed, 18 Jul 2012 16:07:35 +0100 Message-Id: <1342624074-24650-9-git-send-email-stefanha@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1342624074-24650-1-git-send-email-stefanha@linux.vnet.ibm.com> References: <1342624074-24650-1-git-send-email-stefanha@linux.vnet.ibm.com> x-cbid: 12071815-2966-0000-0000-000004C240C3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Stefan Hajnoczi --- hw/dataplane/vring.h | 8 +++++-- hw/virtio-blk.c | 62 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/hw/dataplane/vring.h b/hw/dataplane/vring.h index 7099a99..b07d4f6 100644 --- a/hw/dataplane/vring.h +++ b/hw/dataplane/vring.h @@ -76,7 +76,7 @@ static void vring_setup(Vring *vring, VirtIODevice *vdev, int n) * Stolen from linux-2.6/drivers/vhost/vhost.c. */ static unsigned int vring_pop(Vring *vring, - struct iovec iov[], unsigned int iov_size, + struct iovec iov[], struct iovec *iov_end, unsigned int *out_num, unsigned int *in_num) { struct vring_desc desc; @@ -138,10 +138,14 @@ static unsigned int vring_pop(Vring *vring, return ret; } continue; */ - fprintf(stderr, "virtio-blk indirect vring not supported\n"); + fprintf(stderr, "Indirect vring not supported\n"); exit(1); } + if (iov >= iov_end) { + fprintf(stderr, "Not enough vring iovecs\n"); + exit(1); + } iov->iov_base = phys_to_host(vring, desc.addr); iov->iov_len = desc.len; iov++; diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 2c1cce8..91f1bab 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -24,6 +24,7 @@ enum { SEG_MAX = 126, /* maximum number of I/O segments */ VRING_MAX = SEG_MAX + 2, /* maximum number of vring descriptors */ + REQ_MAX = VRING_MAX / 2, /* maximum number of requests in the vring */ }; typedef struct VirtIOBlock @@ -58,20 +59,63 @@ static void handle_io(EventHandler *handler) fprintf(stderr, "io completion happened\n"); } +static void process_request(struct iovec iov[], unsigned int out_num, unsigned int in_num) +{ + /* Virtio block requests look like this: */ + struct virtio_blk_outhdr *outhdr; /* iov[0] */ + /* data[] ... */ + struct virtio_blk_inhdr *inhdr; /* iov[out_num + in_num - 1] */ + + if (unlikely(out_num == 0 || in_num == 0 || + iov[0].iov_len != sizeof *outhdr || + iov[out_num + in_num - 1].iov_len != sizeof *inhdr)) { + fprintf(stderr, "virtio-blk invalid request\n"); + exit(1); + } + + outhdr = iov[0].iov_base; + inhdr = iov[out_num + in_num - 1].iov_base; + + fprintf(stderr, "virtio-blk request type=%#x sector=%#lx\n", + outhdr->type, outhdr->sector); +} + static void handle_notify(EventHandler *handler) { VirtIOBlock *s = container_of(handler, VirtIOBlock, notify_handler); - struct iovec iov[VRING_MAX]; - unsigned int out_num, in_num; - int head; - head = vring_pop(&s->vring, iov, ARRAY_SIZE(iov), &out_num, &in_num); - if (unlikely(head >= vring_get_num(&s->vring))) { - fprintf(stderr, "false alarm, nothing on vring\n"); - return; - } + /* There is one array of iovecs into which all new requests are extracted + * from the vring. Requests are read from the vring and the translated + * descriptors are written to the iovecs array. The iovecs do not have to + * persist across handle_notify() calls because the kernel copies the + * iovecs on io_submit(). + * + * Handling io_submit() EAGAIN may require storing the requests across + * handle_notify() calls until the kernel has sufficient resources to + * accept more I/O. This is not implemented yet. + */ + struct iovec iovec[VRING_MAX]; + struct iovec *iov, *end = &iovec[VRING_MAX]; + + /* When a request is read from the vring, the index of the first descriptor + * (aka head) is returned so that the completed request can be pushed onto + * the vring later. + * + * The number of hypervisor read-only iovecs is out_num. The number of + * hypervisor write-only iovecs is in_num. + */ + unsigned int head, out_num = 0, in_num = 0; + + for (iov = iovec; ; iov += out_num + in_num) { + head = vring_pop(&s->vring, iov, end, &out_num, &in_num); + if (head >= vring_get_num(&s->vring)) { + break; /* no more requests */ + } + + fprintf(stderr, "head=%u out_num=%u in_num=%u\n", head, out_num, in_num); - fprintf(stderr, "head=%u out_num=%u in_num=%u\n", head, out_num, in_num); + process_request(iov, out_num, in_num); + } } static void *data_plane_thread(void *opaque)