diff options
author | Simon Derr <simon.derr@bull.net> | 2013-06-21 09:32:34 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2013-07-07 23:02:26 -0400 |
commit | ea071aa1365eaf8a79b33bd8699cb0811dcddf34 (patch) | |
tree | c948ded09d3e1b10bf75abde352b50b13f2581a2 /net | |
parent | d9a738597faf7cd2edeec82ce8fd81969fed8390 (diff) |
9P: Fix fcall allocation for rdma
The current code assumes that when a request in the request array
does have a tc, it also has a rc.
This is normally true, but not always : when using RDMA, req->rc
will temporarily be set to NULL after the request has been sent.
That is usually OK though, as when the reply arrives, req->rc will be
reassigned to a sane value before the request is recycled.
But there is a catch : if the request is flushed, the reply will never
arrive, and req->rc will be NULL, but not req->tc.
This patch fixes p9_tag_alloc to take this into account.
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/client.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 01f1779eba80..5828769d1f3d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -258,27 +258,25 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) | |||
258 | req = &c->reqs[row][col]; | 258 | req = &c->reqs[row][col]; |
259 | if (!req->tc) { | 259 | if (!req->tc) { |
260 | req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); | 260 | req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); |
261 | if (!req->wq) { | 261 | if (!req->wq) |
262 | pr_err("Couldn't grow tag array\n"); | 262 | goto grow_failed; |
263 | return ERR_PTR(-ENOMEM); | 263 | |
264 | } | ||
265 | init_waitqueue_head(req->wq); | 264 | init_waitqueue_head(req->wq); |
266 | req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, | 265 | req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, |
267 | GFP_NOFS); | 266 | GFP_NOFS); |
267 | if (!req->tc) | ||
268 | goto grow_failed; | ||
269 | |||
270 | req->tc->capacity = alloc_msize; | ||
271 | req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); | ||
272 | } | ||
273 | if (!req->rc) { | ||
268 | req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, | 274 | req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, |
269 | GFP_NOFS); | 275 | GFP_NOFS); |
270 | if ((!req->tc) || (!req->rc)) { | 276 | if (!req->rc) |
271 | pr_err("Couldn't grow tag array\n"); | 277 | goto grow_failed; |
272 | kfree(req->tc); | 278 | |
273 | kfree(req->rc); | ||
274 | kfree(req->wq); | ||
275 | req->tc = req->rc = NULL; | ||
276 | req->wq = NULL; | ||
277 | return ERR_PTR(-ENOMEM); | ||
278 | } | ||
279 | req->tc->capacity = alloc_msize; | ||
280 | req->rc->capacity = alloc_msize; | 279 | req->rc->capacity = alloc_msize; |
281 | req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); | ||
282 | req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); | 280 | req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); |
283 | } | 281 | } |
284 | 282 | ||
@@ -288,7 +286,16 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) | |||
288 | req->tc->tag = tag-1; | 286 | req->tc->tag = tag-1; |
289 | req->status = REQ_STATUS_ALLOC; | 287 | req->status = REQ_STATUS_ALLOC; |
290 | 288 | ||
291 | return &c->reqs[row][col]; | 289 | return req; |
290 | |||
291 | grow_failed: | ||
292 | pr_err("Couldn't grow tag array\n"); | ||
293 | kfree(req->tc); | ||
294 | kfree(req->rc); | ||
295 | kfree(req->wq); | ||
296 | req->tc = req->rc = NULL; | ||
297 | req->wq = NULL; | ||
298 | return ERR_PTR(-ENOMEM); | ||
292 | } | 299 | } |
293 | 300 | ||
294 | /** | 301 | /** |