diff options
author | Dominique Martinet <dominique.martinet@cea.fr> | 2014-01-17 21:31:00 +0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2014-03-26 01:37:59 +0400 |
commit | 2b6e72ed747f68a038df616efd86744b3644d694 (patch) | |
tree | d781427484432608a74ccc44fd4a7a3296751f23 /net/9p/client.c | |
parent | 38dbfb59d1175ef458d006556061adeaa8751b72 (diff) | |
download | linux-2b6e72ed747f68a038df616efd86744b3644d694.tar.xz |
9P: Add memory barriers to protect request fields over cb/rpc threads handoff
We need barriers to guarantee this pattern works as intended:
[w] req->rc, 1 [r] req->status, 1
wmb rmb
[w] req->status, 1 [r] req->rc
Where the wmb ensures that rc gets written before status,
and the rmb ensures that if you observe status == 1, rc is the new value.
Signed-off-by: Dominique Martinet <dominique.martinet@cea.fr>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net/9p/client.c')
-rw-r--r-- | net/9p/client.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index a5e4d2dcb03e..95b1836173e1 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -415,9 +415,17 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) * req: request received * */ -void p9_client_cb(struct p9_client *c, struct p9_req_t *req) +void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) { p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); + + /* + * This barrier is needed to make sure any change made to req before + * the other thread wakes up will indeed be seen by the waiting side. + */ + smp_wmb(); + req->status = status; + wake_up(req->wq); p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); } @@ -751,6 +759,12 @@ again: err = wait_event_interruptible(*req->wq, req->status >= REQ_STATUS_RCVD); + /* + * Make sure our req is coherent with regard to updates in other + * threads - echoes to wmb() in the callback + */ + smp_rmb(); + if ((err == -ERESTARTSYS) && (c->status == Connected) && (type == P9_TFLUSH)) { sigpending = 1; |