summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>2011-03-14 14:12:49 -0700
committerEric Van Hensbergen <ericvh@gmail.com>2011-03-22 16:32:47 -0500
commita01a984035ea799b14aa5e874dcaeb122f09c4b4 (patch)
tree7998ac0aab9c53c25dde38710a4ab60ac7d2935f
parent53bda3e5b4e91763224ecb7d05dab94d281fd41d (diff)
downloadlinux-stable-a01a984035ea799b14aa5e874dcaeb122f09c4b4.tar.gz
linux-stable-a01a984035ea799b14aa5e874dcaeb122f09c4b4.tar.bz2
linux-stable-a01a984035ea799b14aa5e874dcaeb122f09c4b4.zip
[net/9p] Set the condition just before waking up.
Given that the sprious wake-ups are common, we need to move the condition setting right next to the wake_up(). After setting the condition to req->status = REQ_STATUS_RCVD, sprious wakeups may cause the virtqueue back on the free list for someone else to use. This may result in kernel panic while relasing the pinned pages in p9_release_req_pages(). Also rearranged the while loop in req_done() for better redability. Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
-rw-r--r--net/9p/trans_virtio.c44
1 files changed, 22 insertions, 22 deletions
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 961e025957ae..cb98af9367ab 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -141,33 +141,33 @@ static void req_done(struct virtqueue *vq)
P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
- do {
+ while (1) {
spin_lock_irqsave(&chan->lock, flags);
rc = virtqueue_get_buf(chan->vq, &len);
- if (rc != NULL) {
- chan->ring_bufs_avail = 1;
- spin_unlock_irqrestore(&chan->lock, flags);
- /* Wakeup if anyone waiting for VirtIO ring space. */
- wake_up(chan->vc_wq);
- 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;
- if (req->tc->private) {
- struct trans_rpage_info *rp = req->tc->private;
- /*Release pages */
- p9_release_req_pages(rp);
- if (rp->rp_alloc)
- kfree(rp);
- req->tc->private = NULL;
- }
- p9_client_cb(chan->client, req);
- } else {
+ if (rc == NULL) {
spin_unlock_irqrestore(&chan->lock, flags);
+ break;
}
- } while (rc != NULL);
+
+ chan->ring_bufs_avail = 1;
+ spin_unlock_irqrestore(&chan->lock, flags);
+ /* Wakeup if anyone waiting for VirtIO ring space. */
+ wake_up(chan->vc_wq);
+ 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);
+ if (req->tc->private) {
+ struct trans_rpage_info *rp = req->tc->private;
+ /*Release pages */
+ p9_release_req_pages(rp);
+ if (rp->rp_alloc)
+ kfree(rp);
+ req->tc->private = NULL;
+ }
+ req->status = REQ_STATUS_RCVD;
+ p9_client_cb(chan->client, req);
+ }
}
/**