aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/send.c
diff options
context:
space:
mode:
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.