svn commit: r362354 - projects/nfs-over-tls/sys/rpc
Rick Macklem
rmacklem at FreeBSD.org
Fri Jun 19 00:26:31 UTC 2020
Author: rmacklem
Date: Fri Jun 19 00:26:30 2020
New Revision: 362354
URL: https://svnweb.freebsd.org/changeset/base/362354
Log:
Modify handling of EOF on socket and m_split() returning NULL.
This patch modifies the behaviour of the krpc TCP client side socket
upcall function for certain failure scenarios.
When the soreceive() returns a fatal error or EOF on the socket,
the unpatched code would fail RPCs in progress immediately.
This patch modifies the behaviour so that it processes the ct_raw mbuf
list (data already received) before failing RPCs in progress, in case
the reply for an RPC is already in ct_raw.
For the case where m_split() returns NULL, the code now just returns
instead of failing RPCs in progress.
If the lack of mbufs is transient, a subsequent TCP segment might be
received so that progress on parsing RPC messages from the ct_raw
list can continue.
If not, clnt_reconnect_call() will eventually time out and try to
establish a new TCP connection to retry RPCs on.
Hopefully the transient lack of mbufs will be resolved so that a
new TCP connection can be established.
Modified:
projects/nfs-over-tls/sys/rpc/clnt_vc.c
Modified: projects/nfs-over-tls/sys/rpc/clnt_vc.c
==============================================================================
--- projects/nfs-over-tls/sys/rpc/clnt_vc.c Thu Jun 18 23:57:10 2020 (r362353)
+++ projects/nfs-over-tls/sys/rpc/clnt_vc.c Fri Jun 19 00:26:30 2020 (r362354)
@@ -941,8 +941,6 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
struct cmsghdr *cmsg;
struct tls_get_record tgr;
- CTASSERT(sizeof(xid_plus_direction) == 2 * sizeof(uint32_t));
-
/*
* RPC-over-TLS needs to block reception during
* upcalls since the upcall will be doing I/O on
@@ -998,6 +996,9 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
* after our call to soreceive fails with
* EWOULDBLOCK.
*/
+if (so->so_rcv.sb_lowat > 1)
+printf("lowat=%d\n", so->so_rcv.sb_lowat);
+ error = 0;
if (!soreadable(so))
break;
continue;
@@ -1030,19 +1031,8 @@ clnt_vc_soupcall(struct socket *so, void *arg, int wai
printf("Mark upcallneeded\n");
break;
}
- if (error != 0) {
- wakeup_all:
-printf("wakeup_all err=%d\n", error);
- mtx_lock(&ct->ct_lock);
- ct->ct_error.re_status = RPC_CANTRECV;
- ct->ct_error.re_errno = error;
- TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
- cr->cr_error = error;
- wakeup(cr);
- }
- mtx_unlock(&ct->ct_lock);
- goto out;
- }
+ if (error != 0)
+ break;
/* Process any record header(s). */
if (m2 != NULL) {
@@ -1093,22 +1083,6 @@ printf("Got weird type=%d\n", tgr.tls_type);
header = ntohl(header);
ct->ct_record_resid = header & 0x7fffffff;
ct->ct_record_eor = ((header & 0x80000000) != 0);
- if (ct->ct_record_resid < 20 ||
- ct->ct_record_resid > 150000 ||
- !ct->ct_record_eor) {
- printf("clnt_vc_soupcall: bogus record "
- "mark recres=%zd eor=%d\n",
- ct->ct_record_resid, ct->ct_record_eor);
- /*
- * Connection is messed up. All we can
- * do now is shut it down and let
- * clnt_reconnect_XXX establish a new
- * connection.
- * This should never happen, but??
- */
- error = ECONNRESET;
- goto wakeup_all;
- }
m_adj(ct->ct_raw, sizeof(uint32_t));
rawlen -= sizeof(uint32_t);
} else {
@@ -1130,22 +1104,10 @@ printf("Got weird type=%d\n", tgr.tls_type);
} else {
m = m_split(ct->ct_raw, ct->ct_record_resid,
M_NOWAIT);
- if (m == NULL) {
-printf("soup m_split returned NULL\n");
- /*
- * What to do now?
- * The system is out of mbufs.
- * I think it best to close this
- * connection and allow
- * clnt_reconnect_XXX() to try
- * and establish a new one.
- * If we just return and there is
- * no more data received, the
- * connection will be hung.
- */
- error = ECONNRESET;
- goto wakeup_all;
- }
+ if (m == NULL)
+{ printf("soup m_split returned NULL\n");
+ break;
+}
if (ct->ct_record != NULL)
m_last(ct->ct_record)->m_next =
ct->ct_raw;
@@ -1266,7 +1228,24 @@ printf("backxprt=%p\n", xprt);
}
}
}
-out:
+ if (error != 0) {
+ wakeup_all:
+ /*
+ * This socket is broken, so mark that it cannot
+ * receive and fail all RPCs waiting for a reply
+ * on it, so that they will be retried on a new
+ * TCP connection created by clnt_reconnect_X().
+ */
+ mtx_lock(&ct->ct_lock);
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = error;
+ TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
+ cr->cr_error = error;
+ wakeup(cr);
+ }
+ mtx_unlock(&ct->ct_lock);
+ }
+
ct->ct_upcallrefs--;
if (ct->ct_upcallrefs < 0)
panic("rpcvc upcall refcnt");
More information about the svn-src-projects
mailing list