aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/message.c
diff options
context:
space:
mode:
authorAndy Grover <andy.grover@oracle.com>2010-01-12 15:56:06 -0500
committerAndy Grover <andy.grover@oracle.com>2010-09-08 21:11:36 -0400
commitfc445084f185cdd877bec323bfe724a361e2292a (patch)
treeeda014c09872cbbacc411ea3b89f359291ccb577 /net/rds/message.c
parent3ef13f3c22aaea28aff383cb0883481d24885456 (diff)
RDS: Explicitly allocate rm in sendmsg()
r_m_copy_from_user used to allocate the rm as well as kernel buffers for the data, and then copy the data in. Now, sendmsg() allocates the rm, although the data buffer alloc still happens in r_m_copy_from_user. SGs are still allocated with rm, but now r_m_alloc_sgs() is used to reserve them. This allows multiple SG lists to be allocated from the one rm -- this is important once we also want to alloc our rdma sgl from this pool. Signed-off-by: Andy Grover <andy.grover@oracle.com>
Diffstat (limited to 'net/rds/message.c')
-rw-r--r--net/rds/message.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/net/rds/message.c b/net/rds/message.c
index 4421d160b1a4..3498cbcc7542 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -214,17 +214,22 @@ int rds_message_add_rdma_dest_extension(struct rds_header *hdr, u32 r_key, u32 o
214} 214}
215EXPORT_SYMBOL_GPL(rds_message_add_rdma_dest_extension); 215EXPORT_SYMBOL_GPL(rds_message_add_rdma_dest_extension);
216 216
217struct rds_message *rds_message_alloc(unsigned int nents, gfp_t gfp) 217/*
218 * Each rds_message is allocated with extra space for the scatterlist entries
219 * rds ops will need. This is to minimize memory allocation count. Then, each rds op
220 * can grab SGs when initializing its part of the rds_message.
221 */
222struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)
218{ 223{
219 struct rds_message *rm; 224 struct rds_message *rm;
220 225
221 rm = kzalloc(sizeof(struct rds_message) + 226 rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp);
222 (nents * sizeof(struct scatterlist)), gfp);
223 if (!rm) 227 if (!rm)
224 goto out; 228 goto out;
225 229
226 if (nents) 230 rm->m_used_sgs = 0;
227 sg_init_table(rm->data.m_sg, nents); 231 rm->m_total_sgs = extra_len / sizeof(struct scatterlist);
232
228 atomic_set(&rm->m_refcount, 1); 233 atomic_set(&rm->m_refcount, 1);
229 INIT_LIST_HEAD(&rm->m_sock_item); 234 INIT_LIST_HEAD(&rm->m_sock_item);
230 INIT_LIST_HEAD(&rm->m_conn_item); 235 INIT_LIST_HEAD(&rm->m_conn_item);
@@ -234,6 +239,23 @@ out:
234 return rm; 239 return rm;
235} 240}
236 241
242/*
243 * RDS ops use this to grab SG entries from the rm's sg pool.
244 */
245struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
246{
247 struct scatterlist *sg_first = (struct scatterlist *) &rm[1];
248 struct scatterlist *sg_ret;
249
250 WARN_ON(rm->m_used_sgs + nents > rm->m_total_sgs);
251
252 sg_ret = &sg_first[rm->m_used_sgs];
253
254 rm->m_used_sgs += nents;
255
256 return sg_ret;
257}
258
237struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len) 259struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned int total_len)
238{ 260{
239 struct rds_message *rm; 261 struct rds_message *rm;
@@ -256,22 +278,15 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
256 return rm; 278 return rm;
257} 279}
258 280
259struct rds_message *rds_message_copy_from_user(struct iovec *first_iov, 281int rds_message_copy_from_user(struct rds_message *rm, struct iovec *first_iov,
260 size_t total_len) 282 size_t total_len)
261{ 283{
262 unsigned long to_copy; 284 unsigned long to_copy;
263 unsigned long iov_off; 285 unsigned long iov_off;
264 unsigned long sg_off; 286 unsigned long sg_off;
265 struct rds_message *rm;
266 struct iovec *iov; 287 struct iovec *iov;
267 struct scatterlist *sg; 288 struct scatterlist *sg;
268 int ret; 289 int ret = 0;
269
270 rm = rds_message_alloc(ceil(total_len, PAGE_SIZE), GFP_KERNEL);
271 if (rm == NULL) {
272 ret = -ENOMEM;
273 goto out;
274 }
275 290
276 rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len); 291 rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
277 292
@@ -320,14 +335,8 @@ struct rds_message *rds_message_copy_from_user(struct iovec *first_iov,
320 sg++; 335 sg++;
321 } 336 }
322 337
323 ret = 0;
324out: 338out:
325 if (ret) { 339 return ret;
326 if (rm)
327 rds_message_put(rm);
328 rm = ERR_PTR(ret);
329 }
330 return rm;
331} 340}
332 341
333int rds_message_inc_copy_to_user(struct rds_incoming *inc, 342int rds_message_inc_copy_to_user(struct rds_incoming *inc,