diff options
-rw-r--r-- | include/net/9p/client.h | 10 | ||||
-rw-r--r-- | net/9p/client.c | 21 | ||||
-rw-r--r-- | net/9p/trans_fd.c | 262 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 5 |
4 files changed, 126 insertions, 172 deletions
diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 140cf1d58452..4fecaabd17bd 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
@@ -49,11 +49,12 @@ enum p9_trans_status { | |||
49 | * enum p9_req_status_t - virtio request status | 49 | * enum p9_req_status_t - virtio request status |
50 | * @REQ_STATUS_IDLE: request slot unused | 50 | * @REQ_STATUS_IDLE: request slot unused |
51 | * @REQ_STATUS_ALLOC: request has been allocated but not sent | 51 | * @REQ_STATUS_ALLOC: request has been allocated but not sent |
52 | * @REQ_STATUS_UNSENT: request waiting to be sent | ||
52 | * @REQ_STATUS_SENT: request sent to server | 53 | * @REQ_STATUS_SENT: request sent to server |
53 | * @REQ_STATUS_FLSH: a flush has been sent for this request | 54 | * @REQ_STATUS_FLSH: a flush has been sent for this request |
54 | * @REQ_STATUS_RCVD: response received from server | 55 | * @REQ_STATUS_RCVD: response received from server |
55 | * @REQ_STATUS_FLSHD: request has been flushed | 56 | * @REQ_STATUS_FLSHD: request has been flushed |
56 | * @REQ_STATUS_ERR: request encountered an error on the client side | 57 | * @REQ_STATUS_ERROR: request encountered an error on the client side |
57 | * | 58 | * |
58 | * The @REQ_STATUS_IDLE state is used to mark a request slot as unused | 59 | * The @REQ_STATUS_IDLE state is used to mark a request slot as unused |
59 | * but use is actually tracked by the idpool structure which handles tag | 60 | * but use is actually tracked by the idpool structure which handles tag |
@@ -64,6 +65,7 @@ enum p9_trans_status { | |||
64 | enum p9_req_status_t { | 65 | enum p9_req_status_t { |
65 | REQ_STATUS_IDLE, | 66 | REQ_STATUS_IDLE, |
66 | REQ_STATUS_ALLOC, | 67 | REQ_STATUS_ALLOC, |
68 | REQ_STATUS_UNSENT, | ||
67 | REQ_STATUS_SENT, | 69 | REQ_STATUS_SENT, |
68 | REQ_STATUS_FLSH, | 70 | REQ_STATUS_FLSH, |
69 | REQ_STATUS_RCVD, | 71 | REQ_STATUS_RCVD, |
@@ -79,6 +81,8 @@ enum p9_req_status_t { | |||
79 | * @tc: the request fcall structure | 81 | * @tc: the request fcall structure |
80 | * @rc: the response fcall structure | 82 | * @rc: the response fcall structure |
81 | * @aux: transport specific data (provided for trans_fd migration) | 83 | * @aux: transport specific data (provided for trans_fd migration) |
84 | * @tag: tag on request (BUG: redundant) | ||
85 | * @req_list: link for higher level objects to chain requests | ||
82 | * | 86 | * |
83 | * Transport use an array to track outstanding requests | 87 | * Transport use an array to track outstanding requests |
84 | * instead of a list. While this may incurr overhead during initial | 88 | * instead of a list. While this may incurr overhead during initial |
@@ -99,6 +103,9 @@ struct p9_req_t { | |||
99 | struct p9_fcall *rc; | 103 | struct p9_fcall *rc; |
100 | u16 flush_tag; | 104 | u16 flush_tag; |
101 | void *aux; | 105 | void *aux; |
106 | |||
107 | int tag; | ||
108 | struct list_head req_list; | ||
102 | }; | 109 | }; |
103 | 110 | ||
104 | /** | 111 | /** |
@@ -207,5 +214,6 @@ struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset); | |||
207 | 214 | ||
208 | struct p9_req_t *p9_tag_alloc(struct p9_client *, u16); | 215 | struct p9_req_t *p9_tag_alloc(struct p9_client *, u16); |
209 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); | 216 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); |
217 | void p9_free_req(struct p9_client *, struct p9_req_t *); | ||
210 | 218 | ||
211 | #endif /* NET_9P_CLIENT_H */ | 219 | #endif /* NET_9P_CLIENT_H */ |
diff --git a/net/9p/client.c b/net/9p/client.c index 867031934f75..f2d07ef9e6a4 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -268,6 +268,27 @@ static void p9_tag_cleanup(struct p9_client *c) | |||
268 | c->max_tag = 0; | 268 | c->max_tag = 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | /** | ||
272 | * p9_free_req - free a request and clean-up as necessary | ||
273 | * c: client state | ||
274 | * r: request to release | ||
275 | * | ||
276 | */ | ||
277 | |||
278 | void p9_free_req(struct p9_client *c, struct p9_req_t *r) | ||
279 | { | ||
280 | r->flush_tag = P9_NOTAG; | ||
281 | r->status = REQ_STATUS_IDLE; | ||
282 | if (r->tc->tag != P9_NOTAG && p9_idpool_check(r->tc->tag, c->tagpool)) | ||
283 | p9_idpool_put(r->tc->tag, c->tagpool); | ||
284 | |||
285 | /* if this was a flush request we have to free response fcall */ | ||
286 | if (r->tc->id == P9_TFLUSH) { | ||
287 | kfree(r->tc); | ||
288 | kfree(r->rc); | ||
289 | } | ||
290 | } | ||
291 | |||
271 | static struct p9_fid *p9_fid_create(struct p9_client *clnt) | 292 | static struct p9_fid *p9_fid_create(struct p9_client *clnt) |
272 | { | 293 | { |
273 | int err; | 294 | int err; |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 6243093934b2..cc9bc739e9d3 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -44,7 +44,6 @@ | |||
44 | 44 | ||
45 | #define P9_PORT 564 | 45 | #define P9_PORT 564 |
46 | #define MAX_SOCK_BUF (64*1024) | 46 | #define MAX_SOCK_BUF (64*1024) |
47 | #define ERREQFLUSH 1 | ||
48 | #define MAXPOLLWADDR 2 | 47 | #define MAXPOLLWADDR 2 |
49 | 48 | ||
50 | /** | 49 | /** |
@@ -99,38 +98,6 @@ enum { | |||
99 | Wpending = 8, /* can write */ | 98 | Wpending = 8, /* can write */ |
100 | }; | 99 | }; |
101 | 100 | ||
102 | enum { | ||
103 | None, | ||
104 | Flushing, | ||
105 | Flushed, | ||
106 | }; | ||
107 | |||
108 | /** | ||
109 | * struct p9_req - fd mux encoding of an rpc transaction | ||
110 | * @lock: protects req_list | ||
111 | * @tag: numeric tag for rpc transaction | ||
112 | * @tcall: request &p9_fcall structure | ||
113 | * @rcall: response &p9_fcall structure | ||
114 | * @err: error state | ||
115 | * @flush: flag to indicate RPC has been flushed | ||
116 | * @req_list: list link for higher level objects to chain requests | ||
117 | * @m: connection this request was issued on | ||
118 | * @wqueue: wait queue that client is blocked on for this rpc | ||
119 | * | ||
120 | */ | ||
121 | |||
122 | struct p9_req { | ||
123 | spinlock_t lock; | ||
124 | int tag; | ||
125 | struct p9_fcall *tcall; | ||
126 | struct p9_fcall *rcall; | ||
127 | int err; | ||
128 | int flush; | ||
129 | struct list_head req_list; | ||
130 | struct p9_conn *m; | ||
131 | wait_queue_head_t wqueue; | ||
132 | }; | ||
133 | |||
134 | struct p9_poll_wait { | 101 | struct p9_poll_wait { |
135 | struct p9_conn *conn; | 102 | struct p9_conn *conn; |
136 | wait_queue_t wait; | 103 | wait_queue_t wait; |
@@ -139,7 +106,6 @@ struct p9_poll_wait { | |||
139 | 106 | ||
140 | /** | 107 | /** |
141 | * struct p9_conn - fd mux connection state information | 108 | * struct p9_conn - fd mux connection state information |
142 | * @lock: protects mux_list (?) | ||
143 | * @mux_list: list link for mux to manage multiple connections (?) | 109 | * @mux_list: list link for mux to manage multiple connections (?) |
144 | * @client: reference to client instance for this connection | 110 | * @client: reference to client instance for this connection |
145 | * @err: error state | 111 | * @err: error state |
@@ -161,7 +127,6 @@ struct p9_poll_wait { | |||
161 | */ | 127 | */ |
162 | 128 | ||
163 | struct p9_conn { | 129 | struct p9_conn { |
164 | spinlock_t lock; /* protect lock structure */ | ||
165 | struct list_head mux_list; | 130 | struct list_head mux_list; |
166 | struct p9_client *client; | 131 | struct p9_client *client; |
167 | int err; | 132 | int err; |
@@ -205,64 +170,41 @@ static void p9_mux_poll_stop(struct p9_conn *m) | |||
205 | spin_unlock_irqrestore(&p9_poll_lock, flags); | 170 | spin_unlock_irqrestore(&p9_poll_lock, flags); |
206 | } | 171 | } |
207 | 172 | ||
208 | static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req) | 173 | static void p9_conn_rpc_cb(struct p9_client *, struct p9_req_t *); |
209 | { | ||
210 | if (req->tag != P9_NOTAG && | ||
211 | p9_idpool_check(req->tag, m->client->tagpool)) | ||
212 | p9_idpool_put(req->tag, m->client->tagpool); | ||
213 | kfree(req); | ||
214 | } | ||
215 | |||
216 | static void p9_conn_rpc_cb(struct p9_req *req); | ||
217 | 174 | ||
218 | static void p9_mux_flush_cb(struct p9_req *freq) | 175 | static void p9_mux_flush_cb(struct p9_client *client, struct p9_req_t *freq) |
219 | { | 176 | { |
220 | int tag; | 177 | struct p9_conn *m = client->trans; |
221 | struct p9_conn *m = freq->m; | 178 | struct p9_req_t *req; |
222 | struct p9_req *req, *rreq, *rptr; | ||
223 | 179 | ||
224 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, | 180 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, |
225 | freq->tcall, freq->rcall, freq->err, | 181 | freq->tc, freq->rc, freq->t_err, |
226 | freq->tcall->params.tflush.oldtag); | 182 | freq->tc->params.tflush.oldtag); |
227 | |||
228 | spin_lock(&m->lock); | ||
229 | tag = freq->tcall->params.tflush.oldtag; | ||
230 | req = NULL; | ||
231 | list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { | ||
232 | if (rreq->tag == tag) { | ||
233 | req = rreq; | ||
234 | list_del(&req->req_list); | ||
235 | break; | ||
236 | } | ||
237 | } | ||
238 | spin_unlock(&m->lock); | ||
239 | 183 | ||
184 | req = p9_tag_lookup(client, freq->tc->params.tflush.oldtag); | ||
240 | if (req) { | 185 | if (req) { |
241 | spin_lock(&req->lock); | 186 | req->status = REQ_STATUS_FLSHD; |
242 | req->flush = Flushed; | 187 | list_del(&req->req_list); |
243 | spin_unlock(&req->lock); | 188 | p9_conn_rpc_cb(client, req); |
244 | |||
245 | p9_conn_rpc_cb(req); | ||
246 | } | 189 | } |
247 | 190 | ||
248 | kfree(freq->tcall); | 191 | p9_free_req(client, freq); |
249 | kfree(freq->rcall); | ||
250 | p9_mux_free_request(m, freq); | ||
251 | } | 192 | } |
252 | 193 | ||
253 | static void p9_conn_rpc_cb(struct p9_req *req) | 194 | static void p9_conn_rpc_cb(struct p9_client *client, struct p9_req_t *req) |
254 | { | 195 | { |
255 | P9_DPRINTK(P9_DEBUG_MUX, "req %p\n", req); | 196 | P9_DPRINTK(P9_DEBUG_MUX, "req %p\n", req); |
256 | 197 | ||
257 | if (req->tcall->id == P9_TFLUSH) { /* flush callback */ | 198 | if (req->tc->id == P9_TFLUSH) { /* flush callback */ |
258 | P9_DPRINTK(P9_DEBUG_MUX, "flush req %p\n", req); | 199 | P9_DPRINTK(P9_DEBUG_MUX, "flush req %p\n", req); |
259 | p9_mux_flush_cb(req); | 200 | p9_mux_flush_cb(client, req); |
260 | } else { /* normal wakeup path */ | 201 | } else { /* normal wakeup path */ |
261 | P9_DPRINTK(P9_DEBUG_MUX, "normal req %p\n", req); | 202 | P9_DPRINTK(P9_DEBUG_MUX, "normal req %p\n", req); |
262 | if (req->flush != None && !req->err) | 203 | if (!req->t_err && (req->status == REQ_STATUS_FLSHD || |
263 | req->err = -ERESTARTSYS; | 204 | req->status == REQ_STATUS_FLSH)) |
205 | req->t_err = -ERESTARTSYS; | ||
264 | 206 | ||
265 | wake_up(&req->wqueue); | 207 | wake_up(req->wq); |
266 | } | 208 | } |
267 | } | 209 | } |
268 | 210 | ||
@@ -275,59 +217,62 @@ static void p9_conn_rpc_cb(struct p9_req *req) | |||
275 | 217 | ||
276 | void p9_conn_cancel(struct p9_conn *m, int err) | 218 | void p9_conn_cancel(struct p9_conn *m, int err) |
277 | { | 219 | { |
278 | struct p9_req *req, *rtmp; | 220 | struct p9_req_t *req, *rtmp; |
279 | LIST_HEAD(cancel_list); | 221 | LIST_HEAD(cancel_list); |
280 | 222 | ||
281 | P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); | 223 | P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); |
282 | m->err = err; | 224 | m->err = err; |
283 | spin_lock(&m->lock); | 225 | spin_lock(&m->client->lock); |
284 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { | 226 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { |
227 | req->status = REQ_STATUS_ERROR; | ||
228 | if (!req->t_err) | ||
229 | req->t_err = err; | ||
285 | list_move(&req->req_list, &cancel_list); | 230 | list_move(&req->req_list, &cancel_list); |
286 | } | 231 | } |
287 | list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { | 232 | list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { |
233 | req->status = REQ_STATUS_ERROR; | ||
234 | if (!req->t_err) | ||
235 | req->t_err = err; | ||
288 | list_move(&req->req_list, &cancel_list); | 236 | list_move(&req->req_list, &cancel_list); |
289 | } | 237 | } |
290 | spin_unlock(&m->lock); | 238 | spin_unlock(&m->client->lock); |
291 | 239 | ||
292 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { | 240 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { |
293 | list_del(&req->req_list); | 241 | list_del(&req->req_list); |
294 | if (!req->err) | 242 | p9_conn_rpc_cb(m->client, req); |
295 | req->err = err; | ||
296 | |||
297 | p9_conn_rpc_cb(req); | ||
298 | } | 243 | } |
299 | } | 244 | } |
300 | 245 | ||
301 | static void process_request(struct p9_conn *m, struct p9_req *req) | 246 | static void process_request(struct p9_conn *m, struct p9_req_t *req) |
302 | { | 247 | { |
303 | int ecode; | 248 | int ecode; |
304 | struct p9_str *ename; | 249 | struct p9_str *ename; |
305 | 250 | ||
306 | if (!req->err && req->rcall->id == P9_RERROR) { | 251 | if (!req->t_err && req->rc->id == P9_RERROR) { |
307 | ecode = req->rcall->params.rerror.errno; | 252 | ecode = req->rc->params.rerror.errno; |
308 | ename = &req->rcall->params.rerror.error; | 253 | ename = &req->rc->params.rerror.error; |
309 | 254 | ||
310 | P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len, | 255 | P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len, |
311 | ename->str); | 256 | ename->str); |
312 | 257 | ||
313 | if (m->client->dotu) | 258 | if (m->client->dotu) |
314 | req->err = -ecode; | 259 | req->t_err = -ecode; |
315 | 260 | ||
316 | if (!req->err) { | 261 | if (!req->t_err) { |
317 | req->err = p9_errstr2errno(ename->str, ename->len); | 262 | req->t_err = p9_errstr2errno(ename->str, ename->len); |
318 | 263 | ||
319 | /* string match failed */ | 264 | /* string match failed */ |
320 | if (!req->err) { | 265 | if (!req->t_err) { |
321 | PRINT_FCALL_ERROR("unknown error", req->rcall); | 266 | PRINT_FCALL_ERROR("unknown error", req->rc); |
322 | req->err = -ESERVERFAULT; | 267 | req->t_err = -ESERVERFAULT; |
323 | } | 268 | } |
324 | } | 269 | } |
325 | } else if (req->tcall && req->rcall->id != req->tcall->id + 1) { | 270 | } else if (req->tc && req->rc->id != req->tc->id + 1) { |
326 | P9_DPRINTK(P9_DEBUG_ERROR, | 271 | P9_DPRINTK(P9_DEBUG_ERROR, |
327 | "fcall mismatch: expected %d, got %d\n", | 272 | "fcall mismatch: expected %d, got %d\n", |
328 | req->tcall->id + 1, req->rcall->id); | 273 | req->tc->id + 1, req->rc->id); |
329 | if (!req->err) | 274 | if (!req->t_err) |
330 | req->err = -EIO; | 275 | req->t_err = -EIO; |
331 | } | 276 | } |
332 | } | 277 | } |
333 | 278 | ||
@@ -401,7 +346,7 @@ static void p9_read_work(struct work_struct *work) | |||
401 | { | 346 | { |
402 | int n, err; | 347 | int n, err; |
403 | struct p9_conn *m; | 348 | struct p9_conn *m; |
404 | struct p9_req *req, *rptr, *rreq; | 349 | struct p9_req_t *req; |
405 | struct p9_fcall *rcall; | 350 | struct p9_fcall *rcall; |
406 | char *rbuf; | 351 | char *rbuf; |
407 | 352 | ||
@@ -488,24 +433,19 @@ static void p9_read_work(struct work_struct *work) | |||
488 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, | 433 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, |
489 | rcall->id, rcall->tag); | 434 | rcall->id, rcall->tag); |
490 | 435 | ||
491 | req = NULL; | 436 | req = p9_tag_lookup(m->client, rcall->tag); |
492 | spin_lock(&m->lock); | ||
493 | list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) { | ||
494 | if (rreq->tag == rcall->tag) { | ||
495 | req = rreq; | ||
496 | if (req->flush != Flushing) | ||
497 | list_del(&req->req_list); | ||
498 | break; | ||
499 | } | ||
500 | } | ||
501 | spin_unlock(&m->lock); | ||
502 | 437 | ||
503 | if (req) { | 438 | if (req) { |
504 | req->rcall = rcall; | 439 | if (req->status != REQ_STATUS_FLSH) { |
440 | list_del(&req->req_list); | ||
441 | req->status = REQ_STATUS_RCVD; | ||
442 | } | ||
443 | |||
444 | req->rc = rcall; | ||
505 | process_request(m, req); | 445 | process_request(m, req); |
506 | 446 | ||
507 | if (req->flush != Flushing) | 447 | if (req->status != REQ_STATUS_FLSH) |
508 | p9_conn_rpc_cb(req); | 448 | p9_conn_rpc_cb(m->client, req); |
509 | } else { | 449 | } else { |
510 | if (err >= 0 && rcall->id != P9_RFLUSH) | 450 | if (err >= 0 && rcall->id != P9_RFLUSH) |
511 | P9_DPRINTK(P9_DEBUG_ERROR, | 451 | P9_DPRINTK(P9_DEBUG_ERROR, |
@@ -580,7 +520,7 @@ static void p9_write_work(struct work_struct *work) | |||
580 | { | 520 | { |
581 | int n, err; | 521 | int n, err; |
582 | struct p9_conn *m; | 522 | struct p9_conn *m; |
583 | struct p9_req *req; | 523 | struct p9_req_t *req; |
584 | 524 | ||
585 | m = container_of(work, struct p9_conn, wq); | 525 | m = container_of(work, struct p9_conn, wq); |
586 | 526 | ||
@@ -595,18 +535,16 @@ static void p9_write_work(struct work_struct *work) | |||
595 | return; | 535 | return; |
596 | } | 536 | } |
597 | 537 | ||
598 | spin_lock(&m->lock); | 538 | spin_lock(&m->client->lock); |
599 | again: | 539 | req = list_entry(m->unsent_req_list.next, struct p9_req_t, |
600 | req = list_entry(m->unsent_req_list.next, struct p9_req, | ||
601 | req_list); | 540 | req_list); |
541 | req->status = REQ_STATUS_SENT; | ||
602 | list_move_tail(&req->req_list, &m->req_list); | 542 | list_move_tail(&req->req_list, &m->req_list); |
603 | if (req->err == ERREQFLUSH) | ||
604 | goto again; | ||
605 | 543 | ||
606 | m->wbuf = req->tcall->sdata; | 544 | m->wbuf = req->tc->sdata; |
607 | m->wsize = req->tcall->size; | 545 | m->wsize = req->tc->size; |
608 | m->wpos = 0; | 546 | m->wpos = 0; |
609 | spin_unlock(&m->lock); | 547 | spin_unlock(&m->client->lock); |
610 | } | 548 | } |
611 | 549 | ||
612 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, | 550 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, |
@@ -725,7 +663,6 @@ static struct p9_conn *p9_conn_create(struct p9_client *client) | |||
725 | if (!m) | 663 | if (!m) |
726 | return ERR_PTR(-ENOMEM); | 664 | return ERR_PTR(-ENOMEM); |
727 | 665 | ||
728 | spin_lock_init(&m->lock); | ||
729 | INIT_LIST_HEAD(&m->mux_list); | 666 | INIT_LIST_HEAD(&m->mux_list); |
730 | m->client = client; | 667 | m->client = client; |
731 | 668 | ||
@@ -812,30 +749,27 @@ static void p9_poll_mux(struct p9_conn *m) | |||
812 | * | 749 | * |
813 | */ | 750 | */ |
814 | 751 | ||
815 | static struct p9_req *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) | 752 | static struct p9_req_t *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) |
816 | { | 753 | { |
754 | int tag; | ||
817 | int n; | 755 | int n; |
818 | struct p9_req *req; | 756 | struct p9_req_t *req; |
819 | 757 | ||
820 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, | 758 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current, |
821 | tc, tc->id); | 759 | tc, tc->id); |
822 | if (m->err < 0) | 760 | if (m->err < 0) |
823 | return ERR_PTR(m->err); | 761 | return ERR_PTR(m->err); |
824 | 762 | ||
825 | req = kmalloc(sizeof(struct p9_req), GFP_KERNEL); | 763 | tag = P9_NOTAG; |
826 | if (!req) | ||
827 | return ERR_PTR(-ENOMEM); | ||
828 | |||
829 | n = P9_NOTAG; | ||
830 | if (tc->id != P9_TVERSION) { | 764 | if (tc->id != P9_TVERSION) { |
831 | n = p9_idpool_get(m->client->tagpool); | 765 | tag = p9_idpool_get(m->client->tagpool); |
832 | if (n < 0) { | 766 | if (tag < 0) |
833 | kfree(req); | ||
834 | return ERR_PTR(-ENOMEM); | 767 | return ERR_PTR(-ENOMEM); |
835 | } | ||
836 | } | 768 | } |
837 | 769 | ||
838 | p9_set_tag(tc, n); | 770 | p9_set_tag(tc, tag); |
771 | |||
772 | req = p9_tag_alloc(m->client, tag); | ||
839 | 773 | ||
840 | #ifdef CONFIG_NET_9P_DEBUG | 774 | #ifdef CONFIG_NET_9P_DEBUG |
841 | if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { | 775 | if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { |
@@ -846,18 +780,15 @@ static struct p9_req *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) | |||
846 | } | 780 | } |
847 | #endif | 781 | #endif |
848 | 782 | ||
849 | spin_lock_init(&req->lock); | 783 | req->tag = tag; |
850 | req->m = m; | 784 | req->tc = tc; |
851 | init_waitqueue_head(&req->wqueue); | 785 | req->rc = NULL; |
852 | req->tag = n; | 786 | req->t_err = 0; |
853 | req->tcall = tc; | 787 | req->status = REQ_STATUS_UNSENT; |
854 | req->rcall = NULL; | ||
855 | req->err = 0; | ||
856 | req->flush = None; | ||
857 | 788 | ||
858 | spin_lock(&m->lock); | 789 | spin_lock(&m->client->lock); |
859 | list_add_tail(&req->req_list, &m->unsent_req_list); | 790 | list_add_tail(&req->req_list, &m->unsent_req_list); |
860 | spin_unlock(&m->lock); | 791 | spin_unlock(&m->client->lock); |
861 | 792 | ||
862 | if (test_and_clear_bit(Wpending, &m->wsched)) | 793 | if (test_and_clear_bit(Wpending, &m->wsched)) |
863 | n = POLLOUT; | 794 | n = POLLOUT; |
@@ -871,39 +802,36 @@ static struct p9_req *p9_send_request(struct p9_conn *m, struct p9_fcall *tc) | |||
871 | } | 802 | } |
872 | 803 | ||
873 | static int | 804 | static int |
874 | p9_mux_flush_request(struct p9_conn *m, struct p9_req *req) | 805 | p9_mux_flush_request(struct p9_conn *m, struct p9_req_t *req) |
875 | { | 806 | { |
876 | struct p9_fcall *fc; | 807 | struct p9_fcall *fc; |
877 | struct p9_req *rreq, *rptr; | 808 | struct p9_req_t *rreq, *rptr; |
878 | 809 | ||
879 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); | 810 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag); |
880 | 811 | ||
881 | /* if a response was received for a request, do nothing */ | 812 | /* if a response was received for a request, do nothing */ |
882 | spin_lock(&req->lock); | 813 | if (req->rc || req->t_err) { |
883 | if (req->rcall || req->err) { | ||
884 | spin_unlock(&req->lock); | ||
885 | P9_DPRINTK(P9_DEBUG_MUX, | 814 | P9_DPRINTK(P9_DEBUG_MUX, |
886 | "mux %p req %p response already received\n", m, req); | 815 | "mux %p req %p response already received\n", m, req); |
887 | return 0; | 816 | return 0; |
888 | } | 817 | } |
889 | 818 | ||
890 | req->flush = Flushing; | 819 | req->status = REQ_STATUS_FLSH; |
891 | spin_unlock(&req->lock); | ||
892 | 820 | ||
893 | spin_lock(&m->lock); | 821 | spin_lock(&m->client->lock); |
894 | /* if the request is not sent yet, just remove it from the list */ | 822 | /* if the request is not sent yet, just remove it from the list */ |
895 | list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { | 823 | list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) { |
896 | if (rreq->tag == req->tag) { | 824 | if (rreq->tag == req->tag) { |
897 | P9_DPRINTK(P9_DEBUG_MUX, | 825 | P9_DPRINTK(P9_DEBUG_MUX, |
898 | "mux %p req %p request is not sent yet\n", m, req); | 826 | "mux %p req %p request is not sent yet\n", m, req); |
899 | list_del(&rreq->req_list); | 827 | list_del(&rreq->req_list); |
900 | req->flush = Flushed; | 828 | req->status = REQ_STATUS_FLSHD; |
901 | spin_unlock(&m->lock); | 829 | spin_unlock(&m->client->lock); |
902 | p9_conn_rpc_cb(req); | 830 | p9_conn_rpc_cb(m->client, req); |
903 | return 0; | 831 | return 0; |
904 | } | 832 | } |
905 | } | 833 | } |
906 | spin_unlock(&m->lock); | 834 | spin_unlock(&m->client->lock); |
907 | 835 | ||
908 | clear_thread_flag(TIF_SIGPENDING); | 836 | clear_thread_flag(TIF_SIGPENDING); |
909 | fc = p9_create_tflush(req->tag); | 837 | fc = p9_create_tflush(req->tag); |
@@ -927,7 +855,7 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc) | |||
927 | struct p9_conn *m = p->conn; | 855 | struct p9_conn *m = p->conn; |
928 | int err, sigpending; | 856 | int err, sigpending; |
929 | unsigned long flags; | 857 | unsigned long flags; |
930 | struct p9_req *req; | 858 | struct p9_req_t *req; |
931 | 859 | ||
932 | if (rc) | 860 | if (rc) |
933 | *rc = NULL; | 861 | *rc = NULL; |
@@ -945,10 +873,10 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc) | |||
945 | return err; | 873 | return err; |
946 | } | 874 | } |
947 | 875 | ||
948 | err = wait_event_interruptible(req->wqueue, req->rcall != NULL || | 876 | err = wait_event_interruptible(*req->wq, req->rc != NULL || |
949 | req->err < 0); | 877 | req->t_err < 0); |
950 | if (req->err < 0) | 878 | if (req->t_err < 0) |
951 | err = req->err; | 879 | err = req->t_err; |
952 | 880 | ||
953 | if (err == -ERESTARTSYS && client->status == Connected | 881 | if (err == -ERESTARTSYS && client->status == Connected |
954 | && m->err == 0) { | 882 | && m->err == 0) { |
@@ -956,9 +884,9 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc) | |||
956 | /* wait until we get response of the flush message */ | 884 | /* wait until we get response of the flush message */ |
957 | do { | 885 | do { |
958 | clear_thread_flag(TIF_SIGPENDING); | 886 | clear_thread_flag(TIF_SIGPENDING); |
959 | err = wait_event_interruptible(req->wqueue, | 887 | err = wait_event_interruptible(*req->wq, |
960 | req->rcall || req->err); | 888 | req->rc || req->t_err); |
961 | } while (!req->rcall && !req->err && | 889 | } while (!req->rc && !req->t_err && |
962 | err == -ERESTARTSYS && | 890 | err == -ERESTARTSYS && |
963 | client->status == Connected && !m->err); | 891 | client->status == Connected && !m->err); |
964 | 892 | ||
@@ -974,11 +902,11 @@ p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc) | |||
974 | } | 902 | } |
975 | 903 | ||
976 | if (rc) | 904 | if (rc) |
977 | *rc = req->rcall; | 905 | *rc = req->rc; |
978 | else | 906 | else |
979 | kfree(req->rcall); | 907 | kfree(req->rc); |
980 | 908 | ||
981 | p9_mux_free_request(m, req); | 909 | p9_free_req(client, req); |
982 | if (err > 0) | 910 | if (err > 0) |
983 | err = -EIO; | 911 | err = -EIO; |
984 | 912 | ||
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 36bce45e4e44..e18de14c30d5 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -247,10 +247,7 @@ p9_virtio_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc) | |||
247 | } | 247 | } |
248 | #endif | 248 | #endif |
249 | 249 | ||
250 | if (n != P9_NOTAG && p9_idpool_check(n, c->tagpool)) | 250 | p9_free_req(c, req); |
251 | p9_idpool_put(n, c->tagpool); | ||
252 | |||
253 | req->status = REQ_STATUS_IDLE; | ||
254 | 251 | ||
255 | return 0; | 252 | return 0; |
256 | } | 253 | } |