diff options
Diffstat (limited to 'net/rds/message.c')
| -rw-r--r-- | net/rds/message.c | 24 | 
1 files changed, 18 insertions, 6 deletions
diff --git a/net/rds/message.c b/net/rds/message.c index 4b00b1152a5f..f139420ba1f6 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -308,16 +308,27 @@ out:  /*   * RDS ops use this to grab SG entries from the rm's sg pool.   */ -struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents) +struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents, +					  int *ret)  {  	struct scatterlist *sg_first = (struct scatterlist *) &rm[1];  	struct scatterlist *sg_ret; -	WARN_ON(rm->m_used_sgs + nents > rm->m_total_sgs); -	WARN_ON(!nents); +	if (WARN_ON(!ret)) +		return NULL; -	if (rm->m_used_sgs + nents > rm->m_total_sgs) +	if (nents <= 0) { +		pr_warn("rds: alloc sgs failed! nents <= 0\n"); +		*ret = -EINVAL;  		return NULL; +	} + +	if (rm->m_used_sgs + nents > rm->m_total_sgs) { +		pr_warn("rds: alloc sgs failed! total %d used %d nents %d\n", +			rm->m_total_sgs, rm->m_used_sgs, nents); +		*ret = -ENOMEM; +		return NULL; +	}  	sg_ret = &sg_first[rm->m_used_sgs];  	sg_init_table(sg_ret, nents); @@ -332,6 +343,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in  	unsigned int i;  	int num_sgs = ceil(total_len, PAGE_SIZE);  	int extra_bytes = num_sgs * sizeof(struct scatterlist); +	int ret;  	rm = rds_message_alloc(extra_bytes, GFP_NOWAIT);  	if (!rm) @@ -340,10 +352,10 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in  	set_bit(RDS_MSG_PAGEVEC, &rm->m_flags);  	rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);  	rm->data.op_nents = ceil(total_len, PAGE_SIZE); -	rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs); +	rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs, &ret);  	if (!rm->data.op_sg) {  		rds_message_put(rm); -		return ERR_PTR(-ENOMEM); +		return ERR_PTR(ret);  	}  	for (i = 0; i < rm->data.op_nents; ++i) {  | 
