aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p')
-rw-r--r--net/9p/trans_fd.c129
1 files changed, 66 insertions, 63 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index cc9bc739e9d3..627e3f097fc5 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -111,7 +111,9 @@ struct p9_poll_wait {
111 * @err: error state 111 * @err: error state
112 * @req_list: accounting for requests which have been sent 112 * @req_list: accounting for requests which have been sent
113 * @unsent_req_list: accounting for requests that haven't been sent 113 * @unsent_req_list: accounting for requests that haven't been sent
114 * @rcall: current response &p9_fcall structure 114 * @req: current request being processed (if any)
115 * @tmp_buf: temporary buffer to read in header
116 * @rsize: amount to read for current frame
115 * @rpos: read position in current frame 117 * @rpos: read position in current frame
116 * @rbuf: current read buffer 118 * @rbuf: current read buffer
117 * @wpos: write position for current frame 119 * @wpos: write position for current frame
@@ -132,7 +134,9 @@ struct p9_conn {
132 int err; 134 int err;
133 struct list_head req_list; 135 struct list_head req_list;
134 struct list_head unsent_req_list; 136 struct list_head unsent_req_list;
135 struct p9_fcall *rcall; 137 struct p9_req_t *req;
138 char tmp_buf[7];
139 int rsize;
136 int rpos; 140 int rpos;
137 char *rbuf; 141 char *rbuf;
138 int wpos; 142 int wpos;
@@ -346,34 +350,25 @@ static void p9_read_work(struct work_struct *work)
346{ 350{
347 int n, err; 351 int n, err;
348 struct p9_conn *m; 352 struct p9_conn *m;
349 struct p9_req_t *req;
350 struct p9_fcall *rcall;
351 char *rbuf;
352 353
353 m = container_of(work, struct p9_conn, rq); 354 m = container_of(work, struct p9_conn, rq);
354 355
355 if (m->err < 0) 356 if (m->err < 0)
356 return; 357 return;
357 358
358 rcall = NULL;
359 P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos); 359 P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
360 360
361 if (!m->rcall) { 361 if (!m->rbuf) {
362 m->rcall = 362 m->rbuf = m->tmp_buf;
363 kmalloc(sizeof(struct p9_fcall) + m->client->msize,
364 GFP_KERNEL);
365 if (!m->rcall) {
366 err = -ENOMEM;
367 goto error;
368 }
369
370 m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
371 m->rpos = 0; 363 m->rpos = 0;
364 m->rsize = 7; /* start by reading header */
372 } 365 }
373 366
374 clear_bit(Rpending, &m->wsched); 367 clear_bit(Rpending, &m->wsched);
368 P9_DPRINTK(P9_DEBUG_MUX, "read mux %p pos %d size: %d = %d\n", m,
369 m->rpos, m->rsize, m->rsize-m->rpos);
375 err = p9_fd_read(m->client, m->rbuf + m->rpos, 370 err = p9_fd_read(m->client, m->rbuf + m->rpos,
376 m->client->msize - m->rpos); 371 m->rsize - m->rpos);
377 P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err); 372 P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err);
378 if (err == -EAGAIN) { 373 if (err == -EAGAIN) {
379 clear_bit(Rworksched, &m->wsched); 374 clear_bit(Rworksched, &m->wsched);
@@ -384,8 +379,12 @@ static void p9_read_work(struct work_struct *work)
384 goto error; 379 goto error;
385 380
386 m->rpos += err; 381 m->rpos += err;
387 while (m->rpos > 4) { 382
388 n = le32_to_cpu(*(__le32 *) m->rbuf); 383 if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */
384 u16 tag;
385 P9_DPRINTK(P9_DEBUG_MUX, "got new header\n");
386
387 n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */
389 if (n >= m->client->msize) { 388 if (n >= m->client->msize) {
390 P9_DPRINTK(P9_DEBUG_ERROR, 389 P9_DPRINTK(P9_DEBUG_ERROR,
391 "requested packet size too big: %d\n", n); 390 "requested packet size too big: %d\n", n);
@@ -393,66 +392,71 @@ static void p9_read_work(struct work_struct *work)
393 goto error; 392 goto error;
394 } 393 }
395 394
396 if (m->rpos < n) 395 tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */
397 break; 396 P9_DPRINTK(P9_DEBUG_MUX, "mux %p pkt: size: %d bytes tag: %d\n",
397 m, n, tag);
398 398
399 err = 399 m->req = p9_tag_lookup(m->client, tag);
400 p9_deserialize_fcall(m->rbuf, n, m->rcall, m->client->dotu); 400 if (!m->req) {
401 if (err < 0) 401 P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
402 tag);
403 err = -EIO;
402 goto error; 404 goto error;
405 }
406
407 if (m->req->rc == NULL) {
408 m->req->rc = kmalloc(sizeof(struct p9_fcall) +
409 m->client->msize, GFP_KERNEL);
410 if (!m->req->rc) {
411 m->req = NULL;
412 err = -ENOMEM;
413 goto error;
414 }
415 }
416 m->rbuf = (char *)m->req->rc + sizeof(struct p9_fcall);
417 memcpy(m->rbuf, m->tmp_buf, m->rsize);
418 m->rsize = n;
419 }
420
421 /* not an else because some packets (like clunk) have no payload */
422 if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */
423 P9_DPRINTK(P9_DEBUG_MUX, "got new packet\n");
424 m->rbuf = (char *)m->req->rc + sizeof(struct p9_fcall);
425 err = p9_deserialize_fcall(m->rbuf, m->rsize, m->req->rc,
426 m->client->dotu);
427 if (err < 0) {
428 m->req = NULL;
429 goto error;
430 }
403 431
404#ifdef CONFIG_NET_9P_DEBUG 432#ifdef CONFIG_NET_9P_DEBUG
405 if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { 433 if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
406 char buf[150]; 434 char buf[150];
407 435
408 p9_printfcall(buf, sizeof(buf), m->rcall, 436 p9_printfcall(buf, sizeof(buf), m->req->rc,
409 m->client->dotu); 437 m->client->dotu);
410 printk(KERN_NOTICE ">>> %p %s\n", m, buf); 438 printk(KERN_NOTICE ">>> %p %s\n", m, buf);
411 } 439 }
412#endif 440#endif
413 441
414 rcall = m->rcall; 442 P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m,
415 rbuf = m->rbuf; 443 m->req->rc->id, m->req->rc->tag);
416 if (m->rpos > n) {
417 m->rcall = kmalloc(sizeof(struct p9_fcall) +
418 m->client->msize, GFP_KERNEL);
419 if (!m->rcall) {
420 err = -ENOMEM;
421 goto error;
422 }
423 444
424 m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall); 445 m->rbuf = NULL;
425 memmove(m->rbuf, rbuf + n, m->rpos - n); 446 m->rpos = 0;
426 m->rpos -= n; 447 m->rsize = 0;
427 } else {
428 m->rcall = NULL;
429 m->rbuf = NULL;
430 m->rpos = 0;
431 }
432 448
433 P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, 449 if (m->req->status != REQ_STATUS_FLSH) {
434 rcall->id, rcall->tag); 450 list_del(&m->req->req_list);
451 m->req->status = REQ_STATUS_RCVD;
452 }
435 453
436 req = p9_tag_lookup(m->client, rcall->tag); 454 process_request(m, m->req);
437 455
438 if (req) { 456 if (m->req->status != REQ_STATUS_FLSH)
439 if (req->status != REQ_STATUS_FLSH) { 457 p9_conn_rpc_cb(m->client, m->req);
440 list_del(&req->req_list);
441 req->status = REQ_STATUS_RCVD;
442 }
443 458
444 req->rc = rcall; 459 m->req = NULL;
445 process_request(m, req);
446
447 if (req->status != REQ_STATUS_FLSH)
448 p9_conn_rpc_cb(m->client, req);
449 } else {
450 if (err >= 0 && rcall->id != P9_RFLUSH)
451 P9_DPRINTK(P9_DEBUG_ERROR,
452 "unexpected response mux %p id %d tag %d\n",
453 m, rcall->id, rcall->tag);
454 kfree(rcall);
455 }
456 } 460 }
457 461
458 if (!list_empty(&m->req_list)) { 462 if (!list_empty(&m->req_list)) {
@@ -470,7 +474,6 @@ static void p9_read_work(struct work_struct *work)
470 clear_bit(Rworksched, &m->wsched); 474 clear_bit(Rworksched, &m->wsched);
471 475
472 return; 476 return;
473
474error: 477error:
475 p9_conn_cancel(m, err); 478 p9_conn_cancel(m, err);
476 clear_bit(Rworksched, &m->wsched); 479 clear_bit(Rworksched, &m->wsched);