diff options
Diffstat (limited to 'net/rds/send.c')
-rw-r--r-- | net/rds/send.c | 31 |
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 | */ | ||
765 | static 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 | |||
761 | static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm, | 774 | static 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. |