diff options
Diffstat (limited to 'net/9p/client.c')
| -rw-r--r-- | net/9p/client.c | 70 | 
1 files changed, 43 insertions, 27 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 01f1779eba80..8b93cae2d11d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -204,6 +204,17 @@ free_and_return:  	return ret;  } +struct p9_fcall *p9_fcall_alloc(int alloc_msize) +{ +	struct p9_fcall *fc; +	fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); +	if (!fc) +		return NULL; +	fc->capacity = alloc_msize; +	fc->sdata = (char *) fc + sizeof(struct p9_fcall); +	return fc; +} +  /**   * p9_tag_alloc - lookup/allocate a request by tag   * @c: client session to lookup tag within @@ -256,39 +267,36 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size)  	col = tag % P9_ROW_MAXTAG;  	req = &c->reqs[row][col]; -	if (!req->tc) { +	if (!req->wq) {  		req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); -		if (!req->wq) { -			pr_err("Couldn't grow tag array\n"); -			return ERR_PTR(-ENOMEM); -		} +		if (!req->wq) +			goto grow_failed;  		init_waitqueue_head(req->wq); -		req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, -				  GFP_NOFS); -		req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, -				  GFP_NOFS); -		if ((!req->tc) || (!req->rc)) { -			pr_err("Couldn't grow tag array\n"); -			kfree(req->tc); -			kfree(req->rc); -			kfree(req->wq); -			req->tc = req->rc = NULL; -			req->wq = NULL; -			return ERR_PTR(-ENOMEM); -		} -		req->tc->capacity = alloc_msize; -		req->rc->capacity = alloc_msize; -		req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); -		req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);  	} +	if (!req->tc) +		req->tc = p9_fcall_alloc(alloc_msize); +	if (!req->rc) +		req->rc = p9_fcall_alloc(alloc_msize); +	if (!req->tc || !req->rc) +		goto grow_failed; +  	p9pdu_reset(req->tc);  	p9pdu_reset(req->rc);  	req->tc->tag = tag-1;  	req->status = REQ_STATUS_ALLOC; -	return &c->reqs[row][col]; +	return req; + +grow_failed: +	pr_err("Couldn't grow tag array\n"); +	kfree(req->tc); +	kfree(req->rc); +	kfree(req->wq); +	req->tc = req->rc = NULL; +	req->wq = NULL; +	return ERR_PTR(-ENOMEM);  }  /** @@ -648,12 +656,20 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)  		return PTR_ERR(req); -	/* if we haven't received a response for oldreq, -	   remove it from the list. */ +	/* +	 * if we haven't received a response for oldreq, +	 * remove it from the list, and notify the transport +	 * layer that the reply will never arrive. +	 */  	spin_lock(&c->lock); -	if (oldreq->status == REQ_STATUS_FLSH) +	if (oldreq->status == REQ_STATUS_FLSH) {  		list_del(&oldreq->req_list); -	spin_unlock(&c->lock); +		spin_unlock(&c->lock); +		if (c->trans_mod->cancelled) +			c->trans_mod->cancelled(c, req); +	} else { +		spin_unlock(&c->lock); +	}  	p9_free_req(c, req);  	return 0;  | 
