Home | History | Annotate | Download | only in rpc
      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	"@(#)mt_rpcinit.c	1.24	06/10/17 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 (at) 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