diff options
Diffstat (limited to 'net/sunrpc/xprtsock.c')
| -rw-r--r-- | net/sunrpc/xprtsock.c | 190 | 
1 files changed, 30 insertions, 160 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d86c664ea6af..0bda8a73e8a8 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -54,6 +54,7 @@  #include <trace/events/sunrpc.h> +#include "socklib.h"  #include "sunrpc.h"  static void xs_close(struct rpc_xprt *xprt); @@ -749,125 +750,6 @@ xs_stream_start_connect(struct sock_xprt *transport)  #define XS_SENDMSG_FLAGS	(MSG_DONTWAIT | MSG_NOSIGNAL) -static int xs_sendmsg(struct socket *sock, struct msghdr *msg, size_t seek) -{ -	if (seek) -		iov_iter_advance(&msg->msg_iter, seek); -	return sock_sendmsg(sock, msg); -} - -static int xs_send_kvec(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t seek) -{ -	iov_iter_kvec(&msg->msg_iter, WRITE, vec, 1, vec->iov_len); -	return xs_sendmsg(sock, msg, seek); -} - -static int xs_send_pagedata(struct socket *sock, struct msghdr *msg, struct xdr_buf *xdr, size_t base) -{ -	int err; - -	err = xdr_alloc_bvec(xdr, GFP_KERNEL); -	if (err < 0) -		return err; - -	iov_iter_bvec(&msg->msg_iter, WRITE, xdr->bvec, -			xdr_buf_pagecount(xdr), -			xdr->page_len + xdr->page_base); -	return xs_sendmsg(sock, msg, base + xdr->page_base); -} - -#define xs_record_marker_len() sizeof(rpc_fraghdr) - -/* Common case: - *  - stream transport - *  - sending from byte 0 of the message - *  - the message is wholly contained in @xdr's head iovec - */ -static int xs_send_rm_and_kvec(struct socket *sock, struct msghdr *msg, -		rpc_fraghdr marker, struct kvec *vec, size_t base) -{ -	struct kvec iov[2] = { -		[0] = { -			.iov_base	= &marker, -			.iov_len	= sizeof(marker) -		}, -		[1] = *vec, -	}; -	size_t len = iov[0].iov_len + iov[1].iov_len; - -	iov_iter_kvec(&msg->msg_iter, WRITE, iov, 2, len); -	return xs_sendmsg(sock, msg, base); -} - -/** - * xs_sendpages - write pages directly to a socket - * @sock: socket to send on - * @addr: UDP only -- address of destination - * @addrlen: UDP only -- length of destination address - * @xdr: buffer containing this request - * @base: starting position in the buffer - * @rm: stream record marker field - * @sent_p: return the total number of bytes successfully queued for sending - * - */ -static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, rpc_fraghdr rm, int *sent_p) -{ -	struct msghdr msg = { -		.msg_name = addr, -		.msg_namelen = addrlen, -		.msg_flags = XS_SENDMSG_FLAGS | MSG_MORE, -	}; -	unsigned int rmsize = rm ? sizeof(rm) : 0; -	unsigned int remainder = rmsize + xdr->len - base; -	unsigned int want; -	int err = 0; - -	if (unlikely(!sock)) -		return -ENOTSOCK; - -	want = xdr->head[0].iov_len + rmsize; -	if (base < want) { -		unsigned int len = want - base; -		remainder -= len; -		if (remainder == 0) -			msg.msg_flags &= ~MSG_MORE; -		if (rmsize) -			err = xs_send_rm_and_kvec(sock, &msg, rm, -					&xdr->head[0], base); -		else -			err = xs_send_kvec(sock, &msg, &xdr->head[0], base); -		if (remainder == 0 || err != len) -			goto out; -		*sent_p += err; -		base = 0; -	} else -		base -= want; - -	if (base < xdr->page_len) { -		unsigned int len = xdr->page_len - base; -		remainder -= len; -		if (remainder == 0) -			msg.msg_flags &= ~MSG_MORE; -		err = xs_send_pagedata(sock, &msg, xdr, base); -		if (remainder == 0 || err != len) -			goto out; -		*sent_p += err; -		base = 0; -	} else -		base -= xdr->page_len; - -	if (base >= xdr->tail[0].iov_len) -		return 0; -	msg.msg_flags &= ~MSG_MORE; -	err = xs_send_kvec(sock, &msg, &xdr->tail[0], base); -out: -	if (err > 0) { -		*sent_p += err; -		err = 0; -	} -	return err; -} -  /**   * xs_nospace - handle transmit was incomplete   * @req: pointer to RPC request @@ -959,8 +841,11 @@ static int xs_local_send_request(struct rpc_rqst *req)  	struct xdr_buf *xdr = &req->rq_snd_buf;  	rpc_fraghdr rm = xs_stream_record_marker(xdr);  	unsigned int msglen = rm ? req->rq_slen + sizeof(rm) : req->rq_slen; +	struct msghdr msg = { +		.msg_flags	= XS_SENDMSG_FLAGS, +	}; +	unsigned int uninitialized_var(sent);  	int status; -	int sent = 0;  	/* Close the stream if the previous transmission was incomplete */  	if (xs_send_request_was_aborted(transport, req)) { @@ -972,8 +857,8 @@ static int xs_local_send_request(struct rpc_rqst *req)  			req->rq_svec->iov_base, req->rq_svec->iov_len);  	req->rq_xtime = ktime_get(); -	status = xs_sendpages(transport->sock, NULL, 0, xdr, -			      transport->xmit.offset, rm, &sent); +	status = xprt_sock_sendmsg(transport->sock, &msg, xdr, +				   transport->xmit.offset, rm, &sent);  	dprintk("RPC:       %s(%u) = %d\n",  			__func__, xdr->len - transport->xmit.offset, status); @@ -1025,7 +910,12 @@ static int xs_udp_send_request(struct rpc_rqst *req)  	struct rpc_xprt *xprt = req->rq_xprt;  	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);  	struct xdr_buf *xdr = &req->rq_snd_buf; -	int sent = 0; +	struct msghdr msg = { +		.msg_name	= xs_addr(xprt), +		.msg_namelen	= xprt->addrlen, +		.msg_flags	= XS_SENDMSG_FLAGS, +	}; +	unsigned int uninitialized_var(sent);  	int status;  	xs_pktdump("packet data:", @@ -1039,8 +929,7 @@ static int xs_udp_send_request(struct rpc_rqst *req)  		return -EBADSLT;  	req->rq_xtime = ktime_get(); -	status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, -			      xdr, 0, 0, &sent); +	status = xprt_sock_sendmsg(transport->sock, &msg, xdr, 0, 0, &sent);  	dprintk("RPC:       xs_udp_send_request(%u) = %d\n",  			xdr->len, status); @@ -1106,9 +995,12 @@ static int xs_tcp_send_request(struct rpc_rqst *req)  	struct xdr_buf *xdr = &req->rq_snd_buf;  	rpc_fraghdr rm = xs_stream_record_marker(xdr);  	unsigned int msglen = rm ? req->rq_slen + sizeof(rm) : req->rq_slen; +	struct msghdr msg = { +		.msg_flags	= XS_SENDMSG_FLAGS, +	};  	bool vm_wait = false; +	unsigned int uninitialized_var(sent);  	int status; -	int sent;  	/* Close the stream if the previous transmission was incomplete */  	if (xs_send_request_was_aborted(transport, req)) { @@ -1129,9 +1021,8 @@ static int xs_tcp_send_request(struct rpc_rqst *req)  	 * called sendmsg(). */  	req->rq_xtime = ktime_get();  	while (1) { -		sent = 0; -		status = xs_sendpages(transport->sock, NULL, 0, xdr, -				      transport->xmit.offset, rm, &sent); +		status = xprt_sock_sendmsg(transport->sock, &msg, xdr, +					   transport->xmit.offset, rm, &sent);  		dprintk("RPC:       xs_tcp_send_request(%u) = %d\n",  				xdr->len - transport->xmit.offset, status); @@ -1970,7 +1861,7 @@ static int xs_local_setup_socket(struct sock_xprt *transport)  	struct rpc_xprt *xprt = &transport->xprt;  	struct file *filp;  	struct socket *sock; -	int status = -EIO; +	int status;  	status = __sock_create(xprt->xprt_net, AF_LOCAL,  					SOCK_STREAM, 0, &sock, 1); @@ -2636,46 +2527,25 @@ static void bc_free(struct rpc_task *task)  	free_page((unsigned long)buf);  } -/* - * Use the svc_sock to send the callback. Must be called with svsk->sk_mutex - * held. Borrows heavily from svc_tcp_sendto and xs_tcp_send_request. - */  static int bc_sendto(struct rpc_rqst *req)  { -	int len; -	struct xdr_buf *xbufp = &req->rq_snd_buf; +	struct xdr_buf *xdr = &req->rq_snd_buf;  	struct sock_xprt *transport =  			container_of(req->rq_xprt, struct sock_xprt, xprt); -	unsigned long headoff; -	unsigned long tailoff; -	struct page *tailpage;  	struct msghdr msg = { -		.msg_flags	= MSG_MORE +		.msg_flags	= 0,  	};  	rpc_fraghdr marker = cpu_to_be32(RPC_LAST_STREAM_FRAGMENT | -					 (u32)xbufp->len); -	struct kvec iov = { -		.iov_base	= &marker, -		.iov_len	= sizeof(marker), -	}; +					 (u32)xdr->len); +	unsigned int sent = 0; +	int err;  	req->rq_xtime = ktime_get(); - -	len = kernel_sendmsg(transport->sock, &msg, &iov, 1, iov.iov_len); -	if (len != iov.iov_len) +	err = xprt_sock_sendmsg(transport->sock, &msg, xdr, 0, marker, &sent); +	xdr_free_bvec(xdr); +	if (err < 0 || sent != (xdr->len + sizeof(marker)))  		return -EAGAIN; - -	tailpage = NULL; -	if (xbufp->tail[0].iov_len) -		tailpage = virt_to_page(xbufp->tail[0].iov_base); -	tailoff = (unsigned long)xbufp->tail[0].iov_base & ~PAGE_MASK; -	headoff = (unsigned long)xbufp->head[0].iov_base & ~PAGE_MASK; -	len = svc_send_common(transport->sock, xbufp, -			      virt_to_page(xbufp->head[0].iov_base), headoff, -			      tailpage, tailoff); -	if (len != xbufp->len) -		return -EAGAIN; -	return len; +	return sent;  }  /*  |