1 /* 2 * CDDL HEADER START 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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 30 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 */ 31 32 /* 33 * Define and initialize MT client/server data. 34 */ 35 36 #include <sys/types.h> 37 #include <sys/t_lock.h> 38 #include <sys/kstat.h> 39 #include <sys/systm.h> 40 #include <sys/zone.h> 41 42 #include <rpc/types.h> 43 #include <rpc/auth.h> 44 #include <rpc/clnt.h> 45 46 kmutex_t xid_lock; /* XID allocation */ 47 kmutex_t clnt_pending_lock; /* for list of pending calls awaiting replies */ 48 kmutex_t clnt_max_msg_lock; /* updating max message sanity check for cots */ 49 50 zone_key_t rpcstat_zone_key; 51 52 /* 53 * rpcstat_zone_[init|fini]_common() ends up being nearly identical to 54 * nfsstat_zone_[init|fini]_common(). Due to them necessarily being in 55 * different modules, however, we end up needing to duplicate the code. 56 */ 57 kstat_named_t * 58 rpcstat_zone_init_common(zoneid_t zoneid, const char *module, const char *name, 59 const kstat_named_t *template, size_t template_size) 60 { 61 kstat_t *ksp; 62 kstat_named_t *ks_data; 63 64 65 /* 66 * PSARC 2001/697 Contract Private Interface 67 * rpc_clts_client 68 * rpc_cots_client 69 * Changes must be reviewed by Solaris File Sharing 70 * Changes must be communicated to contract-2001-697@sun.com 71 * 72 */ 73 ks_data = kmem_alloc(template_size, KM_SLEEP); 74 bcopy(template, ks_data, template_size); 75 if ((ksp = kstat_create_zone(module, 0, name, "rpc", 76 KSTAT_TYPE_NAMED, template_size / sizeof (kstat_named_t), 77 KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE, zoneid)) != NULL) { 78 ksp->ks_data = ks_data; 79 kstat_install(ksp); 80 } 81 return (ks_data); 82 } 83 84 void 85 rpcstat_zone_fini_common(zoneid_t zoneid, const char *module, const char *name) 86 { 87 kstat_delete_byname_zone(module, 0, name, zoneid); 88 } 89 90 static void * 91 mt_kstat_zone_init(zoneid_t zoneid) 92 { 93 struct rpcstat *rpcstat; 94 95 rpcstat = kmem_alloc(sizeof (*rpcstat), KM_SLEEP); 96 97 clnt_clts_stats_init(zoneid, &rpcstat->rpc_clts_client); 98 svc_clts_stats_init(zoneid, &rpcstat->rpc_clts_server); 99 100 clnt_cots_stats_init(zoneid, &rpcstat->rpc_cots_client); 101 svc_cots_stats_init(zoneid, &rpcstat->rpc_cots_server); 102 103 return (rpcstat); 104 } 105 106 /* 107 * Deletes the previously allocated "rpc" kstats 108 */ 109 static void 110 mt_kstat_zone_fini(zoneid_t zoneid, void *data) 111 { 112 struct rpcstat *rpcstat = data; 113 114 clnt_cots_stats_fini(zoneid, &rpcstat->rpc_cots_client); 115 svc_cots_stats_fini(zoneid, &rpcstat->rpc_cots_server); 116 117 clnt_clts_stats_fini(zoneid, &rpcstat->rpc_clts_client); 118 svc_clts_stats_fini(zoneid, &rpcstat->rpc_clts_server); 119 120 kmem_free(rpcstat, sizeof (*rpcstat)); 121 } 122 123 void 124 mt_kstat_init(void) 125 { 126 zone_key_create(&rpcstat_zone_key, mt_kstat_zone_init, NULL, 127 mt_kstat_zone_fini); 128 } 129 130 void 131 mt_kstat_fini(void) 132 { 133 (void) zone_key_delete(rpcstat_zone_key); 134 } 135 136 static bool_t clnt_xid_initialized = FALSE; 137 static uint32_t clnt_xid = 0; /* transaction id used by all clients */ 138 139 uint32_t 140 alloc_xid(void) 141 { 142 uint32_t xid; 143 timestruc_t now; 144 145 /* 146 * Do a one time initialzation to better utilize the number 147 * space. 148 */ 149 mutex_enter(&xid_lock); 150 if (clnt_xid_initialized == FALSE) { 151 clnt_xid_initialized = TRUE; 152 gethrestime(&now); 153 clnt_xid = (uint32_t)((now.tv_sec << 20) | 154 (now.tv_nsec >> 10)); 155 } 156 157 xid = clnt_xid++; 158 159 /* 160 * Don't return a zero xid. This could happen if the initialization 161 * happens to return zero or if clnt_xid wraps. 162 */ 163 if (xid == 0) 164 xid = clnt_xid++; 165 166 mutex_exit(&xid_lock); 167 return (xid); 168 } 169 170 /* 171 * These functions are temporary and designed for the upgrade-workaround only. 172 * They cannot be used for general zone-crossing RPC client support, and will 173 * be removed shortly. 174 */ 175 struct zone * 176 rpc_zone(void) 177 { 178 return (nfs_global_client_only != 0 ? global_zone : curproc->p_zone); 179 } 180 181 zoneid_t 182 rpc_zoneid(void) 183 { 184 return (nfs_global_client_only != 0 ? GLOBAL_ZONEID : getzoneid()); 185 } 186