aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/send.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/send.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/send.c')
-rw-r--r--net/rds/send.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/net/rds/send.c b/net/rds/send.c
index 19dfd025498e..28d09447207b 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -758,6 +758,19 @@ out:
758 return *queued; 758 return *queued;
759} 759}
760 760
761/*
762 * rds_message is getting to be quite complicated, and we'd like to allocate
763 * it all in one go. This figures out how big it needs to be up front.
764 */
765static int rds_rm_size(struct msghdr *msg, int data_len)
766{
767 int size = 0;
768
769 size += ceil(data_len, PAGE_SIZE) * sizeof(struct scatterlist);
770
771 return size;
772}
773
761static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm, 774static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm,
762 struct msghdr *msg, int *allocated_mr) 775 struct msghdr *msg, int *allocated_mr)
763{ 776{
@@ -845,13 +858,23 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
845 goto out; 858 goto out;
846 } 859 }
847 860
848 rm = rds_message_copy_from_user(msg->msg_iov, payload_len); 861 /* size of rm including all sgs */
849 if (IS_ERR(rm)) { 862 ret = rds_rm_size(msg, payload_len);
850 ret = PTR_ERR(rm); 863 if (ret < 0)
851 rm = NULL; 864 goto out;
865
866 rm = rds_message_alloc(ret, GFP_KERNEL);
867 if (!rm) {
868 ret = -ENOMEM;
852 goto out; 869 goto out;
853 } 870 }
854 871
872 rm->data.m_sg = rds_message_alloc_sgs(rm, ceil(payload_len, PAGE_SIZE));
873 /* XXX fix this to not allocate memory */
874 ret = rds_message_copy_from_user(rm, msg->msg_iov, payload_len);
875 if (ret)
876 goto out;
877
855 rm->m_daddr = daddr; 878 rm->m_daddr = daddr;
856 879
857 /* rds_conn_create has a spinlock that runs with IRQ off. 880 /* rds_conn_create has a spinlock that runs with IRQ off.