Re: RPC retransmission of write requests containing bogus data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



(I've dropped Michael to bcc, since I think it's relatively clear this
isn't a NIC driver issue, apologies for the noise Michael)
(sorry to anyone who gets this twice, evolution had a bit of a fit and
I'm not sure if it went out properly)

On Mon, 2008-10-20 at 17:39 +0100, Ian Campbell wrote:
> 
> Actually, that was NFSv4 on 2.6.18, I guess I should test with
> something newer since it looks like the TCP connection reset stuff is
> newer (it's 43d78ef2ba5bec26d0315859e8324bfc0be23766 right?)

As expected 2.6.27 appears to be fine when using NFSv4. I used the patch
below with NFSv3 and the problem also went away, although I appreciate
you have concerns with this approach.

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 5ee23e7..759589e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -623,7 +623,8 @@ static int nfs_init_client(struct nfs_client *clp,
 	 * Create a client RPC handle for doing FSSTAT with UNIX auth only
 	 * - RFC 2623, sec 2.3.2
 	 */
-	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX, 0);
+	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
+				      RPC_CLNT_CREATE_DISCRTRY);
 	if (error < 0)
 		goto error;
 	nfs_mark_client_ready(clp, NFS_CS_READY);

FYI I've also been experimenting with patches along the lines of the
below. I've not got it to actually work yet though :-/

Ian.

diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 64981a2..5c57112 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -89,6 +89,7 @@ struct rpc_task {
 #ifdef RPC_DEBUG
 	unsigned short		tk_pid;		/* debugging aid */
 #endif
+	int			tk_nrtrans;	/* number of times this task has transmitted */
 };
 #define tk_xprt			tk_client->cl_xprt
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 99a52aa..72d1ceb 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -884,6 +884,8 @@ void xprt_transmit(struct rpc_task *task)
 		xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs;
 		xprt->stat.bklog_u += xprt->backlog.qlen;
 
+		task->tk_nrtrans++;
+
 		/* Don't race with disconnect */
 		if (!xprt_connected(xprt))
 			task->tk_status = -ENOTCONN;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4486c59..1fb5310 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -423,8 +423,9 @@ static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen,
 	return kernel_sendmsg(sock, &msg, NULL, 0, 0);
 }
 
-static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more)
+static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, int copy)
 {
+	static int once = 0;
 	struct page **ppage;
 	unsigned int remainder;
 	int err, sent = 0;
@@ -440,7 +441,14 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i
 		remainder -= len;
 		if (remainder != 0 || more)
 			flags |= MSG_MORE;
-		err = sock->ops->sendpage(sock, *ppage, base, len, flags);
+		if (!once && copy) {
+			once = 1;
+			printk("using sock_no_sendpage for retransmit\n");
+		}
+		if (copy)
+			err = sock_no_sendpage(sock, *ppage, base, len, flags);
+		else
+			err = sock->ops->sendpage(sock, *ppage, base, len, flags);
 		if (remainder == 0 || err != len)
 			break;
 		sent += err;
@@ -463,7 +471,7 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i
  * @base: starting position in the buffer
  *
  */
-static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
+static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, int copy)
 {
 	unsigned int remainder = xdr->len - base;
 	int err, sent = 0;
@@ -491,7 +499,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
 	if (base < xdr->page_len) {
 		unsigned int len = xdr->page_len - base;
 		remainder -= len;
-		err = xs_send_pagedata(sock, xdr, base, remainder != 0);
+		err = xs_send_pagedata(sock, xdr, base, remainder != 0, copy);
 		if (remainder == 0 || err != len)
 			goto out;
 		sent += err;
@@ -582,7 +590,7 @@ static int xs_udp_send_request(struct rpc_task *task)
 	status = xs_sendpages(transport->sock,
 			      xs_addr(xprt),
 			      xprt->addrlen, xdr,
-			      req->rq_bytes_sent);
+			      req->rq_bytes_sent, task->tk_nrtrans);
 
 	dprintk("RPC:       xs_udp_send_request(%u) = %d\n",
 			xdr->len - req->rq_bytes_sent, status);
@@ -671,7 +679,7 @@ static int xs_tcp_send_request(struct rpc_task *task)
 	 * called sendmsg(). */
 	while (1) {
 		status = xs_sendpages(transport->sock,
-					NULL, 0, xdr, req->rq_bytes_sent);
+				      NULL, 0, xdr, req->rq_bytes_sent, task->tk_nrtrans);
 
 		dprintk("RPC:       xs_tcp_send_request(%u) = %d\n",
 				xdr->len - req->rq_bytes_sent, status);


--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux