summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/rpc
diff options
context:
space:
mode:
authorDai Ngo <dai.ngo@sun.com>2009-05-20 11:23:22 -0700
committerDai Ngo <dai.ngo@sun.com>2009-05-20 11:23:22 -0700
commite280ed373e7a3152deb093649e841edea237022f (patch)
tree8b74c3ad2425d82b624ffb0f5a476ed5b232c797 /usr/src/uts/common/rpc
parentc1d90a7f5657ab4d599b769861a5495af7a253b0 (diff)
downloadillumos-joyent-e280ed373e7a3152deb093649e841edea237022f.tar.gz
6831781 "[NFS4] NFS server not responding - still trying" messages during heavy TCP traffic
Diffstat (limited to 'usr/src/uts/common/rpc')
-rw-r--r--usr/src/uts/common/rpc/clnt_cots.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/usr/src/uts/common/rpc/clnt_cots.c b/usr/src/uts/common/rpc/clnt_cots.c
index 58c946b15a..85874c885a 100644
--- a/usr/src/uts/common/rpc/clnt_cots.c
+++ b/usr/src/uts/common/rpc/clnt_cots.c
@@ -763,7 +763,7 @@ clnt_cots_kcallit(CLIENT *h, rpcproc_t procnum, xdrproc_t xdr_args,
struct netbuf *retryaddr;
struct cm_xprt *cm_entry = NULL;
queue_t *wq;
- int len;
+ int len, waitsecs, max_waitsecs;
int mpsize;
int refreshes = REFRESHES;
int interrupted;
@@ -778,7 +778,6 @@ clnt_cots_kcallit(CLIENT *h, rpcproc_t procnum, xdrproc_t xdr_args,
RPCLOG(2, "clnt_cots_kcallit: wait.tv_sec: %ld\n", wait.tv_sec);
RPCLOG(2, "clnt_cots_kcallit: wait.tv_usec: %ld\n", wait.tv_usec);
-
/*
* Bug ID 1240234:
* Look out for zero length timeouts. We don't want to
@@ -1081,23 +1080,53 @@ call_again:
tidu_size);
wq = cm_entry->x_wq;
+ waitsecs = 0;
+
+dispatch_again:
status = clnt_dispatch_send(wq, mp, call, p->cku_xid,
(p->cku_flags & CKU_ONQUEUE));
- if (status == RPC_CANTSEND) {
- p->cku_err.re_status = status;
- p->cku_err.re_errno = EIO;
- DTRACE_PROBE(krpc__e__clntcots__kcallit__cantsend);
-
+ if ((status == RPC_CANTSEND) && (call->call_reason == ENOBUFS)) {
/*
- * Allow for processing of the QFULL queue.
+ * QFULL condition, allow some time for queue to drain
+ * and try again. Give up after waiting for all timeout
+ * specified for the call, or zone is going away.
*/
- delay_first = TRUE;
- ticks = clnt_cots_min_tout * drv_usectohz(1000000);
+ max_waitsecs = wait.tv_sec ? wait.tv_sec : clnt_cots_min_tout;
+ if ((waitsecs++ < max_waitsecs) &&
+ !(zone_status_get(curproc->p_zone) >=
+ ZONE_IS_SHUTTING_DOWN)) {
+
+ /* wait 1 sec for queue to drain */
+ if (clnt_delay(drv_usectohz(1000000),
+ h->cl_nosignal) == EINTR) {
+ p->cku_err.re_errno = EINTR;
+ p->cku_err.re_status = RPC_INTR;
+
+ goto cots_done;
+ }
+
+ /* and try again */
+ goto dispatch_again;
+ }
+ p->cku_err.re_status = status;
+ p->cku_err.re_errno = call->call_reason;
+ DTRACE_PROBE(krpc__e__clntcots__kcallit__cantsend);
goto cots_done;
}
+ if (waitsecs) {
+ /* adjust timeout to account for time wait to send */
+ wait.tv_sec -= waitsecs;
+ if (wait.tv_sec < 0) {
+ /* pick up reply on next retry */
+ wait.tv_sec = 0;
+ }
+ DTRACE_PROBE2(clnt_cots__sendwait, CLIENT *, h,
+ int, waitsecs);
+ }
+
RPCLOG(64, "clnt_cots_kcallit: sent call for xid 0x%x\n",
(uint_t)p->cku_xid);
p->cku_flags = (CKU_ONQUEUE|CKU_SENT);
@@ -2888,7 +2917,7 @@ clnt_dispatch_send(queue_t *q, mblk_t *mp, calllist_t *e, uint_t xid,
if (!canput(q)) {
e->call_status = RPC_CANTSEND;
- e->call_reason = EIO;
+ e->call_reason = ENOBUFS;
return (RPC_CANTSEND);
}