aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSimon Derr <simon.derr@bull.net>2012-09-17 09:16:30 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2012-09-17 15:54:11 -0400
commit584a8c13d58423462680907d4cc40d9929c9030a (patch)
tree17191b8555e06f8f62aaea1c5a76fde040980e00 /net
parent1957b3a86f8eb5ceab32e3aae99e2822258aa530 (diff)
9P: Fix race in p9_write_work()
See previous commit about p9_read_work() for details. This fixes a similar race between p9_write_work() and p9_poll_mux() Signed-off-by: Simon Derr <simon.derr@bull.net> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net')
-rw-r--r--net/9p/trans_fd.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 7088a94b2601..b2c308fffb8a 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -476,10 +476,9 @@ static void p9_write_work(struct work_struct *work)
476 clear_bit(Wpending, &m->wsched); 476 clear_bit(Wpending, &m->wsched);
477 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos); 477 err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
478 p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err); 478 p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
479 if (err == -EAGAIN) { 479 if (err == -EAGAIN)
480 clear_bit(Wworksched, &m->wsched); 480 goto end_clear;
481 return; 481
482 }
483 482
484 if (err < 0) 483 if (err < 0)
485 goto error; 484 goto error;
@@ -492,19 +491,21 @@ static void p9_write_work(struct work_struct *work)
492 if (m->wpos == m->wsize) 491 if (m->wpos == m->wsize)
493 m->wpos = m->wsize = 0; 492 m->wpos = m->wsize = 0;
494 493
494end_clear:
495 clear_bit(Wworksched, &m->wsched);
496
495 if (m->wsize || !list_empty(&m->unsent_req_list)) { 497 if (m->wsize || !list_empty(&m->unsent_req_list)) {
496 if (test_and_clear_bit(Wpending, &m->wsched)) 498 if (test_and_clear_bit(Wpending, &m->wsched))
497 n = POLLOUT; 499 n = POLLOUT;
498 else 500 else
499 n = p9_fd_poll(m->client, NULL); 501 n = p9_fd_poll(m->client, NULL);
500 502
501 if (n & POLLOUT) { 503 if ((n & POLLOUT) &&
504 !test_and_set_bit(Wworksched, &m->wsched)) {
502 p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m); 505 p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m);
503 schedule_work(&m->wq); 506 schedule_work(&m->wq);
504 } else 507 }
505 clear_bit(Wworksched, &m->wsched); 508 }
506 } else
507 clear_bit(Wworksched, &m->wsched);
508 509
509 return; 510 return;
510 511