From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Venkateswararao Jujjuri (JV)" Subject: [PATCH 2/2] [net/9p] Add waitq to VirtIO transport. Date: Fri, 1 Oct 2010 16:56:17 -0700 Message-ID: <1285977377-28736-2-git-send-email-jvrao@linux.vnet.ibm.com> References: <1285977377-28736-1-git-send-email-jvrao@linux.vnet.ibm.com> Cc: linux-fsdevel@vger.kernel.org, "Venkateswararao Jujjuri (JV)" To: v9fs-developer@lists.sourceforge.net Return-path: Received: from e31.co.us.ibm.com ([32.97.110.149]:43357 "EHLO e31.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754516Ab0JAXkI (ORCPT ); Fri, 1 Oct 2010 19:40:08 -0400 Received: from d03relay01.boulder.ibm.com (d03relay01.boulder.ibm.com [9.17.195.226]) by e31.co.us.ibm.com (8.14.4/8.13.1) with ESMTP id o91NRdVF013090 for ; Fri, 1 Oct 2010 17:27:39 -0600 Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by d03relay01.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o91Ne7B6120910 for ; Fri, 1 Oct 2010 17:40:07 -0600 Received: from d03av02.boulder.ibm.com (loopback [127.0.0.1]) by d03av02.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id o91Ne5xj015437 for ; Fri, 1 Oct 2010 17:40:07 -0600 In-Reply-To: <1285977377-28736-1-git-send-email-jvrao@linux.vnet.ibm.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: If there is not enough space for the PDU on the VirtIO ring, current code returns -EIO propagating the error to user. This patch introduced a wqit_queue on the channel, and lets the process wait on this queue until VirtIO ring frees up. Signed-off-by: Venkateswararao Jujjuri --- net/9p/trans_virtio.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 files changed, 37 insertions(+), 7 deletions(-) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 0df84bf..2de5144 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -75,6 +75,8 @@ struct virtio_chan { struct p9_client *client; struct virtio_device *vdev; struct virtqueue *vq; + int ring_bufs_avail; + wait_queue_head_t *vc_wq; /* Scatterlist: can be too big for stack. */ struct scatterlist sg[VIRTQUEUE_NUM]; @@ -141,15 +143,21 @@ static void req_done(struct virtqueue *vq) do { spin_lock_irqsave(&chan->lock, flags); rc = virtqueue_get_buf(chan->vq, &len); - spin_unlock_irqrestore(&chan->lock, flags); if (rc != NULL) { + if (!chan->ring_bufs_avail) { + chan->ring_bufs_avail = 1; + wake_up(chan->vc_wq); + } + spin_unlock_irqrestore(&chan->lock, flags); P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); req = p9_tag_lookup(chan->client, rc->tag); req->status = REQ_STATUS_RCVD; p9_client_cb(chan->client, req); + } else { + spin_unlock_irqrestore(&chan->lock, flags); } } while (rc != NULL); } @@ -212,6 +220,7 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); +req_retry: req->status = REQ_STATUS_SENT; spin_lock_irqsave(&chan->lock, flags); @@ -222,10 +231,21 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc); if (err < 0) { - spin_unlock_irqrestore(&chan->lock, flags); - P9_DPRINTK(P9_DEBUG_TRANS, - "9p debug: virtio rpc add_buf returned failure"); - return -EIO; + if (err == -ENOSPC) { + chan->ring_bufs_avail = 0; + spin_unlock_irqrestore(&chan->lock, flags); + err = wait_event_interruptible_timeout(*chan->vc_wq, + chan->ring_bufs_avail, + HZ/4); + P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n"); + goto req_retry; + } else { + spin_unlock_irqrestore(&chan->lock, flags); + P9_DPRINTK(P9_DEBUG_TRANS, + "9p debug: " + "virtio rpc add_buf returned failure"); + return -EIO; + } } virtqueue_kick(chan->vq); @@ -304,14 +324,23 @@ static int p9_virtio_probe(struct virtio_device *vdev) chan->tag_len = tag_len; err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); if (err) { - kfree(tag); - goto out_free_vq; + goto out_free_tag; } + chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); + if (!chan->vc_wq) { + err = -ENOMEM; + goto out_free_tag; + } + init_waitqueue_head(chan->vc_wq); + chan->ring_bufs_avail = 1; + mutex_lock(&virtio_9p_lock); list_add_tail(&chan->chan_list, &virtio_chan_list); mutex_unlock(&virtio_9p_lock); return 0; +out_free_tag: + kfree(tag); out_free_vq: vdev->config->del_vqs(vdev); kfree(chan); @@ -384,6 +413,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) mutex_unlock(&virtio_9p_lock); sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); kfree(chan->tag); + kfree(chan->vc_wq); kfree(chan); } -- 1.6.5.2