Skip to content

Commit

Permalink
net/9p: Add waitq to VirtIO transport.
Browse files Browse the repository at this point in the history
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 <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
  • Loading branch information
Venkateswararao Jujjuri (JV) authored and Eric Van Hensbergen committed Oct 28, 2010
1 parent 419b395 commit 52f44e0
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
3 changes: 2 additions & 1 deletion net/9p/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)

err = c->trans_mod->request(c, req);
if (err < 0) {
c->status = Disconnected;
if (err != -ERESTARTSYS)
c->status = Disconnected;
goto reterr;
}

Expand Down
46 changes: 39 additions & 7 deletions net/9p/trans_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -222,10 +231,23 @@ 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(*chan->vc_wq,
chan->ring_bufs_avail);
if (err == -ERESTARTSYS)
return err;

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);
Expand Down Expand Up @@ -304,14 +326,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);
Expand Down Expand Up @@ -385,6 +416,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);

}
Expand Down

0 comments on commit 52f44e0

Please sign in to comment.