diff options
author | Venkateswararao Jujjuri (JV) <jvrao@linux.vnet.ibm.com> | 2010-09-29 21:06:54 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2010-10-28 10:08:48 -0400 |
commit | 419b39561e698d73a42f8010655d22e0134486da (patch) | |
tree | 76b6bd98dcaaa89d27b2d804d1ed67f049f070bd /net/9p | |
parent | 329176cc2c50e63c580ddaabb385876db5af1360 (diff) |
[net/9p]Serialize virtqueue operations to make VirtIO transport SMP safe.
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net/9p')
-rw-r--r-- | net/9p/trans_virtio.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index b88515936e4b..8ae08596aad8 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -134,16 +134,24 @@ static void req_done(struct virtqueue *vq) | |||
134 | struct p9_fcall *rc; | 134 | struct p9_fcall *rc; |
135 | unsigned int len; | 135 | unsigned int len; |
136 | struct p9_req_t *req; | 136 | struct p9_req_t *req; |
137 | unsigned long flags; | ||
137 | 138 | ||
138 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); | 139 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); |
139 | 140 | ||
140 | while ((rc = virtqueue_get_buf(chan->vq, &len)) != NULL) { | 141 | do { |
141 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); | 142 | spin_lock_irqsave(&chan->lock, flags); |
142 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); | 143 | rc = virtqueue_get_buf(chan->vq, &len); |
143 | req = p9_tag_lookup(chan->client, rc->tag); | 144 | spin_unlock_irqrestore(&chan->lock, flags); |
144 | req->status = REQ_STATUS_RCVD; | 145 | |
145 | p9_client_cb(chan->client, req); | 146 | if (rc != NULL) { |
146 | } | 147 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); |
148 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", | ||
149 | rc->tag); | ||
150 | req = p9_tag_lookup(chan->client, rc->tag); | ||
151 | req->status = REQ_STATUS_RCVD; | ||
152 | p9_client_cb(chan->client, req); | ||
153 | } | ||
154 | } while (rc != NULL); | ||
147 | } | 155 | } |
148 | 156 | ||
149 | /** | 157 | /** |
@@ -199,23 +207,29 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) | |||
199 | int in, out; | 207 | int in, out; |
200 | struct virtio_chan *chan = client->trans; | 208 | struct virtio_chan *chan = client->trans; |
201 | char *rdata = (char *)req->rc+sizeof(struct p9_fcall); | 209 | char *rdata = (char *)req->rc+sizeof(struct p9_fcall); |
210 | unsigned long flags; | ||
211 | int err; | ||
202 | 212 | ||
203 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); | 213 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); |
204 | 214 | ||
215 | req->status = REQ_STATUS_SENT; | ||
216 | |||
217 | spin_lock_irqsave(&chan->lock, flags); | ||
205 | out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, | 218 | out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata, |
206 | req->tc->size); | 219 | req->tc->size); |
207 | in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, | 220 | in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, |
208 | client->msize); | 221 | client->msize); |
209 | 222 | ||
210 | req->status = REQ_STATUS_SENT; | 223 | err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc); |
211 | 224 | if (err < 0) { | |
212 | if (virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc) < 0) { | 225 | spin_unlock_irqrestore(&chan->lock, flags); |
213 | P9_DPRINTK(P9_DEBUG_TRANS, | 226 | P9_DPRINTK(P9_DEBUG_TRANS, |
214 | "9p debug: virtio rpc add_buf returned failure"); | 227 | "9p debug: virtio rpc add_buf returned failure"); |
215 | return -EIO; | 228 | return -EIO; |
216 | } | 229 | } |
217 | 230 | ||
218 | virtqueue_kick(chan->vq); | 231 | virtqueue_kick(chan->vq); |
232 | spin_unlock_irqrestore(&chan->lock, flags); | ||
219 | 233 | ||
220 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); | 234 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request kicked\n"); |
221 | return 0; | 235 | return 0; |