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