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 /*
44 * Implements a kernel based, client side RPC over Connection Oriented
1919 RPCLOG(8, "connmgr_get: too many conns, dooming entry"
1920 " %p\n", (void *)lru_entry->x_tiptr);
1921 lru_entry->x_doomed = TRUE;
1922 goto use_new_conn;
1923 }
1924
1925 /*
1926 * If we are at the maximum number of connections to
1927 * the server, hand back the least recently used one.
1928 */
1929 if (i == clnt_max_conns) {
1930 /*
1931 * Copy into the handle the source address of
1932 * the connection, which we will use in case of
1933 * a later retry.
1934 */
1935 if (srcaddr->len != lru_entry->x_src.len) {
1936 if (srcaddr->len > 0)
1937 kmem_free(srcaddr->buf,
1938 srcaddr->maxlen);
1939 srcaddr->buf = kmem_zalloc(
1940 lru_entry->x_src.len, KM_SLEEP);
1941 srcaddr->maxlen = srcaddr->len =
1942 lru_entry->x_src.len;
1943 }
1944 bcopy(lru_entry->x_src.buf, srcaddr->buf, srcaddr->len);
1945 RPCLOG(2, "connmgr_get: call going out on %p\n",
1946 (void *)lru_entry);
1947 lru_entry->x_time = ddi_get_lbolt();
1948 CONN_HOLD(lru_entry);
1949
1950 if ((i > 1) && (prev != &cm_hd)) {
1951 /*
1952 * remove and re-insert entry at head of list.
1953 */
1954 *prev = lru_entry->x_next;
1955 lru_entry->x_next = cm_hd;
1956 cm_hd = lru_entry;
1957 }
1958
1959 mutex_exit(&connmgr_lock);
2074
2075 /*
2076 * We cannot find an entry in the list for this retry.
2077 * Either the entry has been removed temporarily to be
2078 * reconnected by another thread, or the original call
2079 * got a port but never got connected,
2080 * and hence the transport never got put in the
2081 * list. Fall through to the "create new connection" code -
2082 * the former case will fail there trying to rebind the port,
2083 * and the later case (and any other pathological cases) will
2084 * rebind and reconnect and not hang the client machine.
2085 */
2086 RPCLOG0(8, "connmgr_get: no entry in list for retry\n");
2087 }
2088 /*
2089 * Set up a transport entry in the connection manager's list.
2090 */
2091 cm_entry = (struct cm_xprt *)
2092 kmem_zalloc(sizeof (struct cm_xprt), KM_SLEEP);
2093
2094 cm_entry->x_server.buf = kmem_zalloc(destaddr->len, KM_SLEEP);
2095 bcopy(destaddr->buf, cm_entry->x_server.buf, destaddr->len);
2096 cm_entry->x_server.len = cm_entry->x_server.maxlen = destaddr->len;
2097
2098 cm_entry->x_state_flags = X_THREAD;
2099 cm_entry->x_ref = 1;
2100 cm_entry->x_family = addrfmly;
2101 cm_entry->x_rdev = device;
2102 cm_entry->x_zoneid = zoneid;
2103 mutex_init(&cm_entry->x_lock, NULL, MUTEX_DEFAULT, NULL);
2104 cv_init(&cm_entry->x_cv, NULL, CV_DEFAULT, NULL);
2105 cv_init(&cm_entry->x_conn_cv, NULL, CV_DEFAULT, NULL);
2106 cv_init(&cm_entry->x_dis_cv, NULL, CV_DEFAULT, NULL);
2107
2108 /*
2109 * Note that we add this partially initialized entry to the
2110 * connection list. This is so that we don't have connections to
2111 * the same server.
2112 *
2113 * Note that x_src is not initialized at this point. This is because
2114 * retryaddr might be NULL in which case x_src is whatever
2239 calllist_t call;
2240
2241 bzero(&call, sizeof (call));
2242 cv_init(&call.call_cv, NULL, CV_DEFAULT, NULL);
2243
2244 /*
2245 * This is a bound end-point so don't close it's stream.
2246 */
2247 connected = connmgr_connect(cm_entry, wq, destaddr, addrfmly,
2248 &call, &tidu_size, FALSE, waitp, nosignal, cr);
2249 *rpcerr = call.call_err;
2250 cv_destroy(&call.call_cv);
2251
2252 }
2253
2254 mutex_enter(&connmgr_lock);
2255
2256 /*
2257 * Set up a transport entry in the connection manager's list.
2258 */
2259 cm_entry->x_src.buf = kmem_zalloc(srcaddr->len, KM_SLEEP);
2260 bcopy(srcaddr->buf, cm_entry->x_src.buf, srcaddr->len);
2261 cm_entry->x_src.len = cm_entry->x_src.maxlen = srcaddr->len;
2262
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;
2423
2424 cv_broadcast(&cm_entry->x_conn_cv);
2425
2426 if (cm_entry->x_connected == FALSE) {
2427 mutex_exit(&connmgr_lock);
2428 connmgr_release(cm_entry);
2429 return (NULL);
2430 }
2431 }
2432
2433 if (srcaddr != NULL) {
2434 /*
2435 * Copy into the handle the
2436 * source address of the
2437 * connection, which we will use
2438 * in case of a later retry.
2439 */
2440 if (srcaddr->len != cm_entry->x_src.len) {
2441 if (srcaddr->maxlen > 0)
2442 kmem_free(srcaddr->buf, srcaddr->maxlen);
2443 srcaddr->buf = kmem_zalloc(cm_entry->x_src.len,
2444 KM_SLEEP);
2445 srcaddr->maxlen = srcaddr->len =
2446 cm_entry->x_src.len;
2447 }
2448 bcopy(cm_entry->x_src.buf, srcaddr->buf, srcaddr->len);
2449 }
2450 cm_entry->x_time = ddi_get_lbolt();
2451 mutex_exit(&connmgr_lock);
2452 return (cm_entry);
2453 }
2454
2455 /*
2456 * If we need to send a T_DISCON_REQ, send one.
2457 */
2458 static void
2459 connmgr_dis_and_wait(struct cm_xprt *cm_entry)
2460 {
2461 ASSERT(MUTEX_HELD(&connmgr_lock));
2462 for (;;) {
2463 while (cm_entry->x_needdis == TRUE) {
2464 RPCLOG(8, "connmgr_dis_and_wait: need "
2465 "T_DISCON_REQ for connection 0x%p\n",
2466 (void *)cm_entry);
|
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 * Copyright 2019 Joyent, Inc.
26 */
27
28 /*
29 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
30 * Use is subject to license terms.
31 */
32
33 /*
34 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
35 * All Rights Reserved
36 */
37
38 /*
39 * Portions of this source code were derived from Berkeley 4.3 BSD
40 * under license from the Regents of the University of California.
41 */
42
43
44 /*
45 * Implements a kernel based, client side RPC over Connection Oriented
1920 RPCLOG(8, "connmgr_get: too many conns, dooming entry"
1921 " %p\n", (void *)lru_entry->x_tiptr);
1922 lru_entry->x_doomed = TRUE;
1923 goto use_new_conn;
1924 }
1925
1926 /*
1927 * If we are at the maximum number of connections to
1928 * the server, hand back the least recently used one.
1929 */
1930 if (i == clnt_max_conns) {
1931 /*
1932 * Copy into the handle the source address of
1933 * the connection, which we will use in case of
1934 * a later retry.
1935 */
1936 if (srcaddr->len != lru_entry->x_src.len) {
1937 if (srcaddr->len > 0)
1938 kmem_free(srcaddr->buf,
1939 srcaddr->maxlen);
1940 ASSERT(lru_entry->x_src.len != 0);
1941 srcaddr->buf = kmem_alloc(
1942 lru_entry->x_src.len, KM_SLEEP);
1943 srcaddr->maxlen = srcaddr->len =
1944 lru_entry->x_src.len;
1945 }
1946 bcopy(lru_entry->x_src.buf, srcaddr->buf, srcaddr->len);
1947 RPCLOG(2, "connmgr_get: call going out on %p\n",
1948 (void *)lru_entry);
1949 lru_entry->x_time = ddi_get_lbolt();
1950 CONN_HOLD(lru_entry);
1951
1952 if ((i > 1) && (prev != &cm_hd)) {
1953 /*
1954 * remove and re-insert entry at head of list.
1955 */
1956 *prev = lru_entry->x_next;
1957 lru_entry->x_next = cm_hd;
1958 cm_hd = lru_entry;
1959 }
1960
1961 mutex_exit(&connmgr_lock);
2076
2077 /*
2078 * We cannot find an entry in the list for this retry.
2079 * Either the entry has been removed temporarily to be
2080 * reconnected by another thread, or the original call
2081 * got a port but never got connected,
2082 * and hence the transport never got put in the
2083 * list. Fall through to the "create new connection" code -
2084 * the former case will fail there trying to rebind the port,
2085 * and the later case (and any other pathological cases) will
2086 * rebind and reconnect and not hang the client machine.
2087 */
2088 RPCLOG0(8, "connmgr_get: no entry in list for retry\n");
2089 }
2090 /*
2091 * Set up a transport entry in the connection manager's list.
2092 */
2093 cm_entry = (struct cm_xprt *)
2094 kmem_zalloc(sizeof (struct cm_xprt), KM_SLEEP);
2095
2096 cm_entry->x_server.buf = kmem_alloc(destaddr->len, KM_SLEEP);
2097 bcopy(destaddr->buf, cm_entry->x_server.buf, destaddr->len);
2098 cm_entry->x_server.len = cm_entry->x_server.maxlen = destaddr->len;
2099
2100 cm_entry->x_state_flags = X_THREAD;
2101 cm_entry->x_ref = 1;
2102 cm_entry->x_family = addrfmly;
2103 cm_entry->x_rdev = device;
2104 cm_entry->x_zoneid = zoneid;
2105 mutex_init(&cm_entry->x_lock, NULL, MUTEX_DEFAULT, NULL);
2106 cv_init(&cm_entry->x_cv, NULL, CV_DEFAULT, NULL);
2107 cv_init(&cm_entry->x_conn_cv, NULL, CV_DEFAULT, NULL);
2108 cv_init(&cm_entry->x_dis_cv, NULL, CV_DEFAULT, NULL);
2109
2110 /*
2111 * Note that we add this partially initialized entry to the
2112 * connection list. This is so that we don't have connections to
2113 * the same server.
2114 *
2115 * Note that x_src is not initialized at this point. This is because
2116 * retryaddr might be NULL in which case x_src is whatever
2241 calllist_t call;
2242
2243 bzero(&call, sizeof (call));
2244 cv_init(&call.call_cv, NULL, CV_DEFAULT, NULL);
2245
2246 /*
2247 * This is a bound end-point so don't close it's stream.
2248 */
2249 connected = connmgr_connect(cm_entry, wq, destaddr, addrfmly,
2250 &call, &tidu_size, FALSE, waitp, nosignal, cr);
2251 *rpcerr = call.call_err;
2252 cv_destroy(&call.call_cv);
2253
2254 }
2255
2256 mutex_enter(&connmgr_lock);
2257
2258 /*
2259 * Set up a transport entry in the connection manager's list.
2260 */
2261 if (srcaddr->len > 0) {
2262 cm_entry->x_src.buf = kmem_alloc(srcaddr->len, KM_SLEEP);
2263 bcopy(srcaddr->buf, cm_entry->x_src.buf, srcaddr->len);
2264 cm_entry->x_src.len = cm_entry->x_src.maxlen = srcaddr->len;
2265 } /* Else kmem_zalloc() of cm_entry already sets its x_src to NULL. */
2266
2267 cm_entry->x_tiptr = tiptr;
2268 cm_entry->x_time = ddi_get_lbolt();
2269
2270 if (tiptr->tp_info.servtype == T_COTS_ORD)
2271 cm_entry->x_ordrel = TRUE;
2272 else
2273 cm_entry->x_ordrel = FALSE;
2274
2275 cm_entry->x_tidu_size = tidu_size;
2276
2277 if (cm_entry->x_early_disc) {
2278 /*
2279 * We need to check if a disconnect request has come
2280 * while we are connected, if so, then we need to
2281 * set rpcerr->re_status appropriately before returning
2282 * NULL to caller.
2283 */
2284 if (rpcerr->re_status == RPC_SUCCESS)
2285 rpcerr->re_status = RPC_XPRTFAILED;
2427
2428 cv_broadcast(&cm_entry->x_conn_cv);
2429
2430 if (cm_entry->x_connected == FALSE) {
2431 mutex_exit(&connmgr_lock);
2432 connmgr_release(cm_entry);
2433 return (NULL);
2434 }
2435 }
2436
2437 if (srcaddr != NULL) {
2438 /*
2439 * Copy into the handle the
2440 * source address of the
2441 * connection, which we will use
2442 * in case of a later retry.
2443 */
2444 if (srcaddr->len != cm_entry->x_src.len) {
2445 if (srcaddr->maxlen > 0)
2446 kmem_free(srcaddr->buf, srcaddr->maxlen);
2447 ASSERT(cm_entry->x_src.len != 0);
2448 srcaddr->buf = kmem_alloc(cm_entry->x_src.len,
2449 KM_SLEEP);
2450 srcaddr->maxlen = srcaddr->len = cm_entry->x_src.len;
2451 }
2452 bcopy(cm_entry->x_src.buf, srcaddr->buf, srcaddr->len);
2453 }
2454 cm_entry->x_time = ddi_get_lbolt();
2455 mutex_exit(&connmgr_lock);
2456 return (cm_entry);
2457 }
2458
2459 /*
2460 * If we need to send a T_DISCON_REQ, send one.
2461 */
2462 static void
2463 connmgr_dis_and_wait(struct cm_xprt *cm_entry)
2464 {
2465 ASSERT(MUTEX_HELD(&connmgr_lock));
2466 for (;;) {
2467 while (cm_entry->x_needdis == TRUE) {
2468 RPCLOG(8, "connmgr_dis_and_wait: need "
2469 "T_DISCON_REQ for connection 0x%p\n",
2470 (void *)cm_entry);
|