aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com>2011-03-14 17:12:49 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2011-03-22 17:32:47 -0400
commita01a984035ea799b14aa5e874dcaeb122f09c4b4 (patch)
tree7998ac0aab9c53c25dde38710a4ab60ac7d2935f
parent53bda3e5b4e91763224ecb7d05dab94d281fd41d (diff)
[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)
141 141
142 P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); 142 P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
143 143
144 do { 144 while (1) {
145 spin_lock_irqsave(&chan->lock, flags); 145 spin_lock_irqsave(&chan->lock, flags);
146 rc = virtqueue_get_buf(chan->vq, &len); 146 rc = virtqueue_get_buf(chan->vq, &len);
147 147
148 if (rc != NULL) { 148 if (rc == NULL) {
149 chan->ring_bufs_avail = 1;
150 spin_unlock_irqrestore(&chan->lock, flags);
151 /* Wakeup if anyone waiting for VirtIO ring space. */
152 wake_up(chan->vc_wq);
153 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
154 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n",
155 rc->tag);
156 req = p9_tag_lookup(chan->client, rc->tag);
157 req->status = REQ_STATUS_RCVD;
158 if (req->tc->private) {
159 struct trans_rpage_info *rp = req->tc->private;
160 /*Release pages */
161 p9_release_req_pages(rp);
162 if (rp->rp_alloc)
163 kfree(rp);
164 req->tc->private = NULL;
165 }
166 p9_client_cb(chan->client, req);
167 } else {
168 spin_unlock_irqrestore(&chan->lock, flags); 149 spin_unlock_irqrestore(&chan->lock, flags);
150 break;
169 } 151 }
170 } while (rc != NULL); 152
153 chan->ring_bufs_avail = 1;
154 spin_unlock_irqrestore(&chan->lock, flags);
155 /* Wakeup if anyone waiting for VirtIO ring space. */
156 wake_up(chan->vc_wq);
157 P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
158 P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
159 req = p9_tag_lookup(chan->client, rc->tag);
160 if (req->tc->private) {
161 struct trans_rpage_info *rp = req->tc->private;
162 /*Release pages */
163 p9_release_req_pages(rp);
164 if (rp->rp_alloc)
165 kfree(rp);
166 req->tc->private = NULL;
167 }
168 req->status = REQ_STATUS_RCVD;
169 p9_client_cb(chan->client, req);
170 }
171} 171}
172 172
173/** 173/**