Print this page
NEX-16052 NFS clients cannot reconnect to server after network loss (autofs)
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-4123 xdrmblk_getpos() is unreliable
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
re #13613 rb4516 Tunables needs volatile keyword


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.
  25  */
  26 
  27 /*
  28  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  29  * Use is subject to license terms.
  30  */
  31 
  32 /*
  33  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
  34  *              All Rights Reserved
  35  */
  36 
  37 /*
  38  * Portions of this source code were derived from Berkeley 4.3 BSD
  39  * under license from the Regents of the University of California.
  40  */
  41 
  42 
  43 /*


 457         kstat_named_t   rccantconn;
 458         kstat_named_t   rcnomem;
 459         kstat_named_t   rcintrs;
 460 } cots_rcstat_tmpl = {
 461         { "calls",      KSTAT_DATA_UINT64 },
 462         { "badcalls",   KSTAT_DATA_UINT64 },
 463         { "badxids",    KSTAT_DATA_UINT64 },
 464         { "timeouts",   KSTAT_DATA_UINT64 },
 465         { "newcreds",   KSTAT_DATA_UINT64 },
 466         { "badverfs",   KSTAT_DATA_UINT64 },
 467         { "timers",     KSTAT_DATA_UINT64 },
 468         { "cantconn",   KSTAT_DATA_UINT64 },
 469         { "nomem",      KSTAT_DATA_UINT64 },
 470         { "interrupts", KSTAT_DATA_UINT64 }
 471 };
 472 
 473 #define COTSRCSTAT_INCR(p, x)   \
 474         atomic_inc_64(&(p)->x.value.ui64)
 475 
 476 #define CLNT_MAX_CONNS  1       /* concurrent connections between clnt/srvr */
 477 int clnt_max_conns = CLNT_MAX_CONNS;
 478 
 479 #define CLNT_MIN_TIMEOUT        10      /* seconds to wait after we get a */
 480                                         /* connection reset */
 481 #define CLNT_MIN_CONNTIMEOUT    5       /* seconds to wait for a connection */
 482 
 483 
 484 int clnt_cots_min_tout = CLNT_MIN_TIMEOUT;
 485 int clnt_cots_min_conntout = CLNT_MIN_CONNTIMEOUT;
 486 
 487 /*
 488  * Limit the number of times we will attempt to receive a reply without
 489  * re-sending a response.
 490  */
 491 #define CLNT_MAXRECV_WITHOUT_RETRY      3
 492 uint_t clnt_cots_maxrecv        = CLNT_MAXRECV_WITHOUT_RETRY;
 493 
 494 uint_t *clnt_max_msg_sizep;
 495 void (*clnt_stop_idle)(queue_t *wq);
 496 
 497 #define ptoh(p)         (&((p)->cku_client))


2263         cm_entry->x_tiptr = tiptr;
2264         cm_entry->x_time = ddi_get_lbolt();
2265 
2266         if (tiptr->tp_info.servtype == T_COTS_ORD)
2267                 cm_entry->x_ordrel = TRUE;
2268         else
2269                 cm_entry->x_ordrel = FALSE;
2270 
2271         cm_entry->x_tidu_size = tidu_size;
2272 
2273         if (cm_entry->x_early_disc) {
2274                 /*
2275                  * We need to check if a disconnect request has come
2276                  * while we are connected, if so, then we need to
2277                  * set rpcerr->re_status appropriately before returning
2278                  * NULL to caller.
2279                  */
2280                 if (rpcerr->re_status == RPC_SUCCESS)
2281                         rpcerr->re_status = RPC_XPRTFAILED;
2282                 cm_entry->x_connected = FALSE;

2283         } else
2284                 cm_entry->x_connected = connected;
2285 
2286         /*
2287          * There could be a discrepancy here such that
2288          * x_early_disc is TRUE yet connected is TRUE as well
2289          * and the connection is actually connected. In that case
2290          * lets be conservative and declare the connection as not
2291          * connected.
2292          */
2293         cm_entry->x_early_disc = FALSE;
2294         cm_entry->x_needdis = (cm_entry->x_connected == FALSE);
2295         cm_entry->x_ctime = ddi_get_lbolt();
2296 
2297         /*
2298          * Notify any threads waiting that the connection attempt is done.
2299          */
2300         cm_entry->x_thread = FALSE;
2301         cv_broadcast(&cm_entry->x_conn_cv);
2302 


2381                 connected = connmgr_connect(cm_entry, cm_entry->x_wq,
2382                     destaddr, addrfmly, &call, &cm_entry->x_tidu_size,
2383                     reconnect, waitp, nosignal, cr);
2384 
2385                 *rpcerr = call.call_err;
2386                 cv_destroy(&call.call_cv);
2387 
2388                 mutex_enter(&connmgr_lock);
2389 
2390 
2391                 if (cm_entry->x_early_disc) {
2392                         /*
2393                          * We need to check if a disconnect request has come
2394                          * while we are connected, if so, then we need to
2395                          * set rpcerr->re_status appropriately before returning
2396                          * NULL to caller.
2397                          */
2398                         if (rpcerr->re_status == RPC_SUCCESS)
2399                                 rpcerr->re_status = RPC_XPRTFAILED;
2400                         cm_entry->x_connected = FALSE;

2401                 } else
2402                         cm_entry->x_connected = connected;
2403 
2404                 /*
2405                  * There could be a discrepancy here such that
2406                  * x_early_disc is TRUE yet connected is TRUE as well
2407                  * and the connection is actually connected. In that case
2408                  * lets be conservative and declare the connection as not
2409                  * connected.
2410                  */
2411 
2412                 cm_entry->x_early_disc = FALSE;
2413                 cm_entry->x_needdis = (cm_entry->x_connected == FALSE);
2414 
2415 
2416                 /*
2417                  * connmgr_connect() may have given up before the connection
2418                  * actually timed out. So ensure that before the next
2419                  * connection attempt we do a disconnect.
2420                  */




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.
  25  */
  26 
  27 /*
  28  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  29  * Use is subject to license terms.
  30  */
  31 
  32 /*
  33  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
  34  *              All Rights Reserved
  35  */
  36 
  37 /*
  38  * Portions of this source code were derived from Berkeley 4.3 BSD
  39  * under license from the Regents of the University of California.
  40  */
  41 
  42 
  43 /*


 457         kstat_named_t   rccantconn;
 458         kstat_named_t   rcnomem;
 459         kstat_named_t   rcintrs;
 460 } cots_rcstat_tmpl = {
 461         { "calls",      KSTAT_DATA_UINT64 },
 462         { "badcalls",   KSTAT_DATA_UINT64 },
 463         { "badxids",    KSTAT_DATA_UINT64 },
 464         { "timeouts",   KSTAT_DATA_UINT64 },
 465         { "newcreds",   KSTAT_DATA_UINT64 },
 466         { "badverfs",   KSTAT_DATA_UINT64 },
 467         { "timers",     KSTAT_DATA_UINT64 },
 468         { "cantconn",   KSTAT_DATA_UINT64 },
 469         { "nomem",      KSTAT_DATA_UINT64 },
 470         { "interrupts", KSTAT_DATA_UINT64 }
 471 };
 472 
 473 #define COTSRCSTAT_INCR(p, x)   \
 474         atomic_inc_64(&(p)->x.value.ui64)
 475 
 476 #define CLNT_MAX_CONNS  1       /* concurrent connections between clnt/srvr */
 477 volatile int clnt_max_conns = CLNT_MAX_CONNS;
 478 
 479 #define CLNT_MIN_TIMEOUT        10      /* seconds to wait after we get a */
 480                                         /* connection reset */
 481 #define CLNT_MIN_CONNTIMEOUT    5       /* seconds to wait for a connection */
 482 
 483 
 484 int clnt_cots_min_tout = CLNT_MIN_TIMEOUT;
 485 int clnt_cots_min_conntout = CLNT_MIN_CONNTIMEOUT;
 486 
 487 /*
 488  * Limit the number of times we will attempt to receive a reply without
 489  * re-sending a response.
 490  */
 491 #define CLNT_MAXRECV_WITHOUT_RETRY      3
 492 uint_t clnt_cots_maxrecv        = CLNT_MAXRECV_WITHOUT_RETRY;
 493 
 494 uint_t *clnt_max_msg_sizep;
 495 void (*clnt_stop_idle)(queue_t *wq);
 496 
 497 #define ptoh(p)         (&((p)->cku_client))


2263         cm_entry->x_tiptr = tiptr;
2264         cm_entry->x_time = ddi_get_lbolt();
2265 
2266         if (tiptr->tp_info.servtype == T_COTS_ORD)
2267                 cm_entry->x_ordrel = TRUE;
2268         else
2269                 cm_entry->x_ordrel = FALSE;
2270 
2271         cm_entry->x_tidu_size = tidu_size;
2272 
2273         if (cm_entry->x_early_disc) {
2274                 /*
2275                  * We need to check if a disconnect request has come
2276                  * while we are connected, if so, then we need to
2277                  * set rpcerr->re_status appropriately before returning
2278                  * NULL to caller.
2279                  */
2280                 if (rpcerr->re_status == RPC_SUCCESS)
2281                         rpcerr->re_status = RPC_XPRTFAILED;
2282                 cm_entry->x_connected = FALSE;
2283                 cm_entry->x_dead = TRUE;
2284         } else
2285                 cm_entry->x_connected = connected;
2286 
2287         /*
2288          * There could be a discrepancy here such that
2289          * x_early_disc is TRUE yet connected is TRUE as well
2290          * and the connection is actually connected. In that case
2291          * lets be conservative and declare the connection as not
2292          * connected.
2293          */
2294         cm_entry->x_early_disc = FALSE;
2295         cm_entry->x_needdis = (cm_entry->x_connected == FALSE);
2296         cm_entry->x_ctime = ddi_get_lbolt();
2297 
2298         /*
2299          * Notify any threads waiting that the connection attempt is done.
2300          */
2301         cm_entry->x_thread = FALSE;
2302         cv_broadcast(&cm_entry->x_conn_cv);
2303 


2382                 connected = connmgr_connect(cm_entry, cm_entry->x_wq,
2383                     destaddr, addrfmly, &call, &cm_entry->x_tidu_size,
2384                     reconnect, waitp, nosignal, cr);
2385 
2386                 *rpcerr = call.call_err;
2387                 cv_destroy(&call.call_cv);
2388 
2389                 mutex_enter(&connmgr_lock);
2390 
2391 
2392                 if (cm_entry->x_early_disc) {
2393                         /*
2394                          * We need to check if a disconnect request has come
2395                          * while we are connected, if so, then we need to
2396                          * set rpcerr->re_status appropriately before returning
2397                          * NULL to caller.
2398                          */
2399                         if (rpcerr->re_status == RPC_SUCCESS)
2400                                 rpcerr->re_status = RPC_XPRTFAILED;
2401                         cm_entry->x_connected = FALSE;
2402                         cm_entry->x_dead = TRUE;
2403                 } else
2404                         cm_entry->x_connected = connected;
2405 
2406                 /*
2407                  * There could be a discrepancy here such that
2408                  * x_early_disc is TRUE yet connected is TRUE as well
2409                  * and the connection is actually connected. In that case
2410                  * lets be conservative and declare the connection as not
2411                  * connected.
2412                  */
2413 
2414                 cm_entry->x_early_disc = FALSE;
2415                 cm_entry->x_needdis = (cm_entry->x_connected == FALSE);
2416 
2417 
2418                 /*
2419                  * connmgr_connect() may have given up before the connection
2420                  * actually timed out. So ensure that before the next
2421                  * connection attempt we do a disconnect.
2422                  */