1bbaa8b60SDan Kruchinin /* 2bbaa8b60SDan Kruchinin * CDDL HEADER START 3bbaa8b60SDan Kruchinin * 4bbaa8b60SDan Kruchinin * The contents of this file are subject to the terms of the 5bbaa8b60SDan Kruchinin * Common Development and Distribution License (the "License"). 6bbaa8b60SDan Kruchinin * You may not use this file except in compliance with the License. 7bbaa8b60SDan Kruchinin * 8bbaa8b60SDan Kruchinin * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9bbaa8b60SDan Kruchinin * or http://www.opensolaris.org/os/licensing. 10bbaa8b60SDan Kruchinin * See the License for the specific language governing permissions 11bbaa8b60SDan Kruchinin * and limitations under the License. 12bbaa8b60SDan Kruchinin * 13bbaa8b60SDan Kruchinin * When distributing Covered Code, include this CDDL HEADER in each 14bbaa8b60SDan Kruchinin * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15bbaa8b60SDan Kruchinin * If applicable, add the following below this CDDL HEADER, with the 16bbaa8b60SDan Kruchinin * fields enclosed by brackets "[]" replaced with your own identifying 17bbaa8b60SDan Kruchinin * information: Portions Copyright [yyyy] [name of copyright owner] 18bbaa8b60SDan Kruchinin * 19bbaa8b60SDan Kruchinin * CDDL HEADER END 20bbaa8b60SDan Kruchinin */ 21bbaa8b60SDan Kruchinin 22bbaa8b60SDan Kruchinin /* 23bbaa8b60SDan Kruchinin * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24bbaa8b60SDan Kruchinin * Copyright (c) 2012 by Delphix. All rights reserved. 25bbaa8b60SDan Kruchinin */ 26bbaa8b60SDan Kruchinin 27bbaa8b60SDan Kruchinin #include <sys/param.h> 28bbaa8b60SDan Kruchinin #include <sys/systm.h> 29bbaa8b60SDan Kruchinin #include <sys/socket.h> 30bbaa8b60SDan Kruchinin #include <sys/syslog.h> 31bbaa8b60SDan Kruchinin #include <sys/systm.h> 32bbaa8b60SDan Kruchinin #include <sys/unistd.h> 33bbaa8b60SDan Kruchinin #include <sys/queue.h> 34bbaa8b60SDan Kruchinin #include <sys/sdt.h> 35bbaa8b60SDan Kruchinin #include <netinet/in.h> 36bbaa8b60SDan Kruchinin 37bbaa8b60SDan Kruchinin #include <rpc/rpc.h> 38bbaa8b60SDan Kruchinin #include <rpc/xdr.h> 39bbaa8b60SDan Kruchinin #include <rpc/pmap_prot.h> 40bbaa8b60SDan Kruchinin #include <rpc/pmap_clnt.h> 41bbaa8b60SDan Kruchinin #include <rpc/rpcb_prot.h> 42bbaa8b60SDan Kruchinin 43bbaa8b60SDan Kruchinin #include <rpcsvc/nlm_prot.h> 44bbaa8b60SDan Kruchinin #include <rpcsvc/sm_inter.h> 45bbaa8b60SDan Kruchinin 46bbaa8b60SDan Kruchinin #include "nlm_impl.h" 47bbaa8b60SDan Kruchinin 48bbaa8b60SDan Kruchinin /* 49bbaa8b60SDan Kruchinin * The following errors codes from nlm_null_rpc indicate that the port we have 50bbaa8b60SDan Kruchinin * cached for the client's NLM service is stale and that we need to establish 51bbaa8b60SDan Kruchinin * a new RPC client. 52bbaa8b60SDan Kruchinin */ 53bbaa8b60SDan Kruchinin #define NLM_STALE_CLNT(_status) \ 54bbaa8b60SDan Kruchinin ((_status) == RPC_PROGUNAVAIL || \ 55bbaa8b60SDan Kruchinin (_status) == RPC_PROGVERSMISMATCH || \ 56bbaa8b60SDan Kruchinin (_status) == RPC_PROCUNAVAIL || \ 57bbaa8b60SDan Kruchinin (_status) == RPC_CANTCONNECT || \ 58bbaa8b60SDan Kruchinin (_status) == RPC_XPRTFAILED) 59bbaa8b60SDan Kruchinin 60bbaa8b60SDan Kruchinin static struct kmem_cache *nlm_rpch_cache = NULL; 61bbaa8b60SDan Kruchinin 62bbaa8b60SDan Kruchinin static int nlm_rpch_ctor(void *, void *, int); 63bbaa8b60SDan Kruchinin static void nlm_rpch_dtor(void *, void *); 64bbaa8b60SDan Kruchinin static void destroy_rpch(nlm_rpc_t *); 65bbaa8b60SDan Kruchinin static nlm_rpc_t *get_nlm_rpc_fromcache(struct nlm_host *, int); 66bbaa8b60SDan Kruchinin static void update_host_rpcbinding(struct nlm_host *, int); 67bbaa8b60SDan Kruchinin static int refresh_nlm_rpc(struct nlm_host *, nlm_rpc_t *); 68bbaa8b60SDan Kruchinin static void nlm_host_rele_rpc_locked(struct nlm_host *, nlm_rpc_t *); 69bbaa8b60SDan Kruchinin 70bbaa8b60SDan Kruchinin static nlm_rpc_t * 71bbaa8b60SDan Kruchinin get_nlm_rpc_fromcache(struct nlm_host *hostp, int vers) 72bbaa8b60SDan Kruchinin { 73bbaa8b60SDan Kruchinin nlm_rpc_t *rpcp; 74bbaa8b60SDan Kruchinin bool_t found = FALSE; 75bbaa8b60SDan Kruchinin 76bbaa8b60SDan Kruchinin ASSERT(MUTEX_HELD(&hostp->nh_lock)); 77bbaa8b60SDan Kruchinin if (TAILQ_EMPTY(&hostp->nh_rpchc)) 78bbaa8b60SDan Kruchinin return (NULL); 79bbaa8b60SDan Kruchinin 80bbaa8b60SDan Kruchinin TAILQ_FOREACH(rpcp, &hostp->nh_rpchc, nr_link) { 81bbaa8b60SDan Kruchinin if (rpcp->nr_vers == vers) { 82bbaa8b60SDan Kruchinin found = TRUE; 83bbaa8b60SDan Kruchinin break; 84bbaa8b60SDan Kruchinin } 85bbaa8b60SDan Kruchinin } 86bbaa8b60SDan Kruchinin 87bbaa8b60SDan Kruchinin if (!found) 88bbaa8b60SDan Kruchinin return (NULL); 89bbaa8b60SDan Kruchinin 90bbaa8b60SDan Kruchinin TAILQ_REMOVE(&hostp->nh_rpchc, rpcp, nr_link); 91bbaa8b60SDan Kruchinin return (rpcp); 92bbaa8b60SDan Kruchinin } 93bbaa8b60SDan Kruchinin 94bbaa8b60SDan Kruchinin /* 95bbaa8b60SDan Kruchinin * Update host's RPC binding (host->nh_addr). 96bbaa8b60SDan Kruchinin * The function is executed by only one thread at time. 97bbaa8b60SDan Kruchinin */ 98bbaa8b60SDan Kruchinin static void 99bbaa8b60SDan Kruchinin update_host_rpcbinding(struct nlm_host *hostp, int vers) 100bbaa8b60SDan Kruchinin { 101bbaa8b60SDan Kruchinin enum clnt_stat stat; 102bbaa8b60SDan Kruchinin 103bbaa8b60SDan Kruchinin ASSERT(MUTEX_HELD(&hostp->nh_lock)); 104bbaa8b60SDan Kruchinin 105bbaa8b60SDan Kruchinin /* 106bbaa8b60SDan Kruchinin * Mark RPC binding state as "update in progress" in order 107bbaa8b60SDan Kruchinin * to say other threads that they need to wait until binding 108bbaa8b60SDan Kruchinin * is fully updated. 109bbaa8b60SDan Kruchinin */ 110bbaa8b60SDan Kruchinin hostp->nh_rpcb_state = NRPCB_UPDATE_INPROGRESS; 111bbaa8b60SDan Kruchinin hostp->nh_rpcb_ustat = RPC_SUCCESS; 112bbaa8b60SDan Kruchinin mutex_exit(&hostp->nh_lock); 113bbaa8b60SDan Kruchinin 114bbaa8b60SDan Kruchinin stat = rpcbind_getaddr(&hostp->nh_knc, NLM_PROG, vers, &hostp->nh_addr); 115bbaa8b60SDan Kruchinin mutex_enter(&hostp->nh_lock); 116bbaa8b60SDan Kruchinin 117bbaa8b60SDan Kruchinin hostp->nh_rpcb_state = ((stat == RPC_SUCCESS) ? 118bbaa8b60SDan Kruchinin NRPCB_UPDATED : NRPCB_NEED_UPDATE); 119bbaa8b60SDan Kruchinin 120bbaa8b60SDan Kruchinin hostp->nh_rpcb_ustat = stat; 121bbaa8b60SDan Kruchinin cv_broadcast(&hostp->nh_rpcb_cv); 122bbaa8b60SDan Kruchinin } 123bbaa8b60SDan Kruchinin 124bbaa8b60SDan Kruchinin /* 125bbaa8b60SDan Kruchinin * Refresh RPC handle taken from host handles cache. 126bbaa8b60SDan Kruchinin * This function is called when an RPC handle is either 127bbaa8b60SDan Kruchinin * uninitialized or was initialized using a binding that's 128bbaa8b60SDan Kruchinin * no longer current. 129bbaa8b60SDan Kruchinin */ 130bbaa8b60SDan Kruchinin static int 131bbaa8b60SDan Kruchinin refresh_nlm_rpc(struct nlm_host *hostp, nlm_rpc_t *rpcp) 132bbaa8b60SDan Kruchinin { 133bbaa8b60SDan Kruchinin int ret; 134bbaa8b60SDan Kruchinin 135bbaa8b60SDan Kruchinin if (rpcp->nr_handle == NULL) { 136bbaa8b60SDan Kruchinin bool_t clset = TRUE; 137bbaa8b60SDan Kruchinin 138bbaa8b60SDan Kruchinin ret = clnt_tli_kcreate(&hostp->nh_knc, &hostp->nh_addr, 139bbaa8b60SDan Kruchinin NLM_PROG, rpcp->nr_vers, 0, NLM_RPC_RETRIES, 140bbaa8b60SDan Kruchinin CRED(), &rpcp->nr_handle); 141bbaa8b60SDan Kruchinin 142bbaa8b60SDan Kruchinin /* 143bbaa8b60SDan Kruchinin * Set the client's CLSET_NODELAYONERR option to true. The 144bbaa8b60SDan Kruchinin * RPC clnt_call interface creates an artificial delay for 145bbaa8b60SDan Kruchinin * certain call errors in order to prevent RPC consumers 146bbaa8b60SDan Kruchinin * from getting into tight retry loops. Since this function is 147bbaa8b60SDan Kruchinin * called by the NLM service routines we would like to avoid 148bbaa8b60SDan Kruchinin * this artificial delay when possible. We do not retry if the 149bbaa8b60SDan Kruchinin * NULL request fails so it is safe for us to turn this option 150bbaa8b60SDan Kruchinin * on. 151bbaa8b60SDan Kruchinin */ 152bbaa8b60SDan Kruchinin if (clnt_control(rpcp->nr_handle, CLSET_NODELAYONERR, 153*fc2b8335SDan McDonald (char *)&clset) == FALSE) { 154bbaa8b60SDan Kruchinin NLM_ERR("Unable to set CLSET_NODELAYONERR\n"); 155bbaa8b60SDan Kruchinin } 156bbaa8b60SDan Kruchinin } else { 157bbaa8b60SDan Kruchinin ret = clnt_tli_kinit(rpcp->nr_handle, &hostp->nh_knc, 158bbaa8b60SDan Kruchinin &hostp->nh_addr, 0, NLM_RPC_RETRIES, CRED()); 159bbaa8b60SDan Kruchinin if (ret == 0) { 160bbaa8b60SDan Kruchinin enum clnt_stat stat; 161bbaa8b60SDan Kruchinin 162bbaa8b60SDan Kruchinin /* 163bbaa8b60SDan Kruchinin * Check whether host's RPC binding is still 164bbaa8b60SDan Kruchinin * fresh, i.e. if remote program is still sits 165bbaa8b60SDan Kruchinin * on the same port we assume. Call NULL proc 166bbaa8b60SDan Kruchinin * to do it. 167bbaa8b60SDan Kruchinin * 168bbaa8b60SDan Kruchinin * Note: Even though we set no delay on error on the 169bbaa8b60SDan Kruchinin * client handle the call to nlm_null_rpc can still 170bbaa8b60SDan Kruchinin * delay for 10 seconds before returning an error. For 171bbaa8b60SDan Kruchinin * example the no delay on error option is not honored 172bbaa8b60SDan Kruchinin * for RPC_XPRTFAILED errors (see clnt_cots_kcallit). 173bbaa8b60SDan Kruchinin */ 174bbaa8b60SDan Kruchinin stat = nlm_null_rpc(rpcp->nr_handle, rpcp->nr_vers); 175bbaa8b60SDan Kruchinin if (NLM_STALE_CLNT(stat)) { 176bbaa8b60SDan Kruchinin ret = ESTALE; 177bbaa8b60SDan Kruchinin } 178bbaa8b60SDan Kruchinin } 179bbaa8b60SDan Kruchinin } 180bbaa8b60SDan Kruchinin 181bbaa8b60SDan Kruchinin return (ret); 182bbaa8b60SDan Kruchinin } 183bbaa8b60SDan Kruchinin 184bbaa8b60SDan Kruchinin /* 185bbaa8b60SDan Kruchinin * Get RPC handle that can be used to talk to the NLM 186bbaa8b60SDan Kruchinin * of given version running on given host. 187bbaa8b60SDan Kruchinin * Saves obtained RPC handle to rpcpp argument. 188bbaa8b60SDan Kruchinin * 189bbaa8b60SDan Kruchinin * If error occures, return nonzero error code. 190bbaa8b60SDan Kruchinin */ 191bbaa8b60SDan Kruchinin int 192bbaa8b60SDan Kruchinin nlm_host_get_rpc(struct nlm_host *hostp, int vers, nlm_rpc_t **rpcpp) 193bbaa8b60SDan Kruchinin { 194bbaa8b60SDan Kruchinin nlm_rpc_t *rpcp = NULL; 195bbaa8b60SDan Kruchinin int rc; 196bbaa8b60SDan Kruchinin 197bbaa8b60SDan Kruchinin mutex_enter(&hostp->nh_lock); 198bbaa8b60SDan Kruchinin 199bbaa8b60SDan Kruchinin /* 200bbaa8b60SDan Kruchinin * If this handle is either uninitialized, or was 201bbaa8b60SDan Kruchinin * initialized using binding that's now stale 202bbaa8b60SDan Kruchinin * do the init or re-init. 203bbaa8b60SDan Kruchinin * See comments to enum nlm_rpcb_state for more 204bbaa8b60SDan Kruchinin * details. 205bbaa8b60SDan Kruchinin */ 206bbaa8b60SDan Kruchinin again: 207bbaa8b60SDan Kruchinin while (hostp->nh_rpcb_state != NRPCB_UPDATED) { 208bbaa8b60SDan Kruchinin if (hostp->nh_rpcb_state == NRPCB_UPDATE_INPROGRESS) { 209bbaa8b60SDan Kruchinin rc = cv_wait_sig(&hostp->nh_rpcb_cv, &hostp->nh_lock); 210bbaa8b60SDan Kruchinin if (rc == 0) { 211bbaa8b60SDan Kruchinin mutex_exit(&hostp->nh_lock); 212bbaa8b60SDan Kruchinin return (EINTR); 213bbaa8b60SDan Kruchinin } 214bbaa8b60SDan Kruchinin } 215bbaa8b60SDan Kruchinin 216bbaa8b60SDan Kruchinin /* 217bbaa8b60SDan Kruchinin * Check if RPC binding was marked for update. 218bbaa8b60SDan Kruchinin * If so, start RPC binding update operation. 219bbaa8b60SDan Kruchinin * NOTE: the operation can be executed by only 220bbaa8b60SDan Kruchinin * one thread at time. 221bbaa8b60SDan Kruchinin */ 222bbaa8b60SDan Kruchinin if (hostp->nh_rpcb_state == NRPCB_NEED_UPDATE) 223bbaa8b60SDan Kruchinin update_host_rpcbinding(hostp, vers); 224bbaa8b60SDan Kruchinin 225bbaa8b60SDan Kruchinin /* 226bbaa8b60SDan Kruchinin * Check if RPC error occured during RPC binding 227bbaa8b60SDan Kruchinin * update operation. If so, report a correspoding 228bbaa8b60SDan Kruchinin * error. 229bbaa8b60SDan Kruchinin */ 230bbaa8b60SDan Kruchinin if (hostp->nh_rpcb_ustat != RPC_SUCCESS) { 231bbaa8b60SDan Kruchinin mutex_exit(&hostp->nh_lock); 232bbaa8b60SDan Kruchinin return (ENOENT); 233bbaa8b60SDan Kruchinin } 234bbaa8b60SDan Kruchinin } 235bbaa8b60SDan Kruchinin 236bbaa8b60SDan Kruchinin rpcp = get_nlm_rpc_fromcache(hostp, vers); 237bbaa8b60SDan Kruchinin mutex_exit(&hostp->nh_lock); 238bbaa8b60SDan Kruchinin if (rpcp == NULL) { 239bbaa8b60SDan Kruchinin /* 240bbaa8b60SDan Kruchinin * There weren't any RPC handles in a host 241bbaa8b60SDan Kruchinin * cache. No luck, just create a new one. 242bbaa8b60SDan Kruchinin */ 243bbaa8b60SDan Kruchinin rpcp = kmem_cache_alloc(nlm_rpch_cache, KM_SLEEP); 244bbaa8b60SDan Kruchinin rpcp->nr_vers = vers; 245bbaa8b60SDan Kruchinin } 246bbaa8b60SDan Kruchinin 247bbaa8b60SDan Kruchinin /* 248bbaa8b60SDan Kruchinin * Refresh RPC binding 249bbaa8b60SDan Kruchinin */ 250bbaa8b60SDan Kruchinin rc = refresh_nlm_rpc(hostp, rpcp); 251bbaa8b60SDan Kruchinin if (rc != 0) { 252bbaa8b60SDan Kruchinin if (rc == ESTALE) { 253bbaa8b60SDan Kruchinin /* 254bbaa8b60SDan Kruchinin * Host's RPC binding is stale, we have 255bbaa8b60SDan Kruchinin * to update it. Put the RPC handle back 256bbaa8b60SDan Kruchinin * to the cache and mark the host as 257bbaa8b60SDan Kruchinin * "need update". 258bbaa8b60SDan Kruchinin */ 259bbaa8b60SDan Kruchinin mutex_enter(&hostp->nh_lock); 260bbaa8b60SDan Kruchinin hostp->nh_rpcb_state = NRPCB_NEED_UPDATE; 261bbaa8b60SDan Kruchinin nlm_host_rele_rpc_locked(hostp, rpcp); 262bbaa8b60SDan Kruchinin goto again; 263bbaa8b60SDan Kruchinin } 264bbaa8b60SDan Kruchinin 265bbaa8b60SDan Kruchinin destroy_rpch(rpcp); 266bbaa8b60SDan Kruchinin return (rc); 267bbaa8b60SDan Kruchinin } 268bbaa8b60SDan Kruchinin 269bbaa8b60SDan Kruchinin DTRACE_PROBE2(end, struct nlm_host *, hostp, 270bbaa8b60SDan Kruchinin nlm_rpc_t *, rpcp); 271bbaa8b60SDan Kruchinin 272bbaa8b60SDan Kruchinin *rpcpp = rpcp; 273bbaa8b60SDan Kruchinin return (0); 274bbaa8b60SDan Kruchinin } 275bbaa8b60SDan Kruchinin 276bbaa8b60SDan Kruchinin void 277bbaa8b60SDan Kruchinin nlm_host_rele_rpc(struct nlm_host *hostp, nlm_rpc_t *rpcp) 278bbaa8b60SDan Kruchinin { 279bbaa8b60SDan Kruchinin mutex_enter(&hostp->nh_lock); 280bbaa8b60SDan Kruchinin nlm_host_rele_rpc_locked(hostp, rpcp); 281bbaa8b60SDan Kruchinin mutex_exit(&hostp->nh_lock); 282bbaa8b60SDan Kruchinin } 283bbaa8b60SDan Kruchinin 284bbaa8b60SDan Kruchinin static void 285bbaa8b60SDan Kruchinin nlm_host_rele_rpc_locked(struct nlm_host *hostp, nlm_rpc_t *rpcp) 286bbaa8b60SDan Kruchinin { 287bbaa8b60SDan Kruchinin ASSERT(mutex_owned(&hostp->nh_lock)); 288bbaa8b60SDan Kruchinin TAILQ_INSERT_HEAD(&hostp->nh_rpchc, rpcp, nr_link); 289bbaa8b60SDan Kruchinin } 290bbaa8b60SDan Kruchinin 291bbaa8b60SDan Kruchinin /* 292bbaa8b60SDan Kruchinin * The function invalidates host's RPC binding by marking it 293bbaa8b60SDan Kruchinin * as not fresh. In this case another time thread tries to 294bbaa8b60SDan Kruchinin * get RPC handle from host's handles cache, host's RPC binding 295bbaa8b60SDan Kruchinin * will be updated. 296bbaa8b60SDan Kruchinin * 297bbaa8b60SDan Kruchinin * The function should be executed when RPC call invoked via 298bbaa8b60SDan Kruchinin * handle taken from RPC cache returns RPC_PROCUNAVAIL. 299bbaa8b60SDan Kruchinin */ 300bbaa8b60SDan Kruchinin void 301bbaa8b60SDan Kruchinin nlm_host_invalidate_binding(struct nlm_host *hostp) 302bbaa8b60SDan Kruchinin { 303bbaa8b60SDan Kruchinin mutex_enter(&hostp->nh_lock); 304bbaa8b60SDan Kruchinin hostp->nh_rpcb_state = NRPCB_NEED_UPDATE; 305bbaa8b60SDan Kruchinin mutex_exit(&hostp->nh_lock); 306bbaa8b60SDan Kruchinin } 307bbaa8b60SDan Kruchinin 308bbaa8b60SDan Kruchinin void 309bbaa8b60SDan Kruchinin nlm_rpc_init(void) 310bbaa8b60SDan Kruchinin { 311bbaa8b60SDan Kruchinin nlm_rpch_cache = kmem_cache_create("nlm_rpch_cache", 312bbaa8b60SDan Kruchinin sizeof (nlm_rpc_t), 0, nlm_rpch_ctor, nlm_rpch_dtor, 313bbaa8b60SDan Kruchinin NULL, NULL, NULL, 0); 314bbaa8b60SDan Kruchinin } 315bbaa8b60SDan Kruchinin 316bbaa8b60SDan Kruchinin void 317bbaa8b60SDan Kruchinin nlm_rpc_cache_destroy(struct nlm_host *hostp) 318bbaa8b60SDan Kruchinin { 319bbaa8b60SDan Kruchinin nlm_rpc_t *rpcp; 320bbaa8b60SDan Kruchinin 321bbaa8b60SDan Kruchinin /* 322bbaa8b60SDan Kruchinin * There's no need to lock host's mutex here, 323bbaa8b60SDan Kruchinin * nlm_rpc_cache_destroy() should be called from 324bbaa8b60SDan Kruchinin * only one place: nlm_host_destroy, when all 325bbaa8b60SDan Kruchinin * resources host owns are already cleaned up. 326bbaa8b60SDan Kruchinin * So there shouldn't be any raises. 327bbaa8b60SDan Kruchinin */ 328bbaa8b60SDan Kruchinin while ((rpcp = TAILQ_FIRST(&hostp->nh_rpchc)) != NULL) { 329bbaa8b60SDan Kruchinin TAILQ_REMOVE(&hostp->nh_rpchc, rpcp, nr_link); 330bbaa8b60SDan Kruchinin destroy_rpch(rpcp); 331bbaa8b60SDan Kruchinin } 332bbaa8b60SDan Kruchinin } 333bbaa8b60SDan Kruchinin 334bbaa8b60SDan Kruchinin /* ARGSUSED */ 335bbaa8b60SDan Kruchinin static int 336bbaa8b60SDan Kruchinin nlm_rpch_ctor(void *datap, void *cdrarg, int kmflags) 337bbaa8b60SDan Kruchinin { 338bbaa8b60SDan Kruchinin nlm_rpc_t *rpcp = (nlm_rpc_t *)datap; 339bbaa8b60SDan Kruchinin 340bbaa8b60SDan Kruchinin bzero(rpcp, sizeof (*rpcp)); 341bbaa8b60SDan Kruchinin return (0); 342bbaa8b60SDan Kruchinin } 343bbaa8b60SDan Kruchinin 344bbaa8b60SDan Kruchinin /* ARGSUSED */ 345bbaa8b60SDan Kruchinin static void 346bbaa8b60SDan Kruchinin nlm_rpch_dtor(void *datap, void *cdrarg) 347bbaa8b60SDan Kruchinin { 348bbaa8b60SDan Kruchinin nlm_rpc_t *rpcp = (nlm_rpc_t *)datap; 349bbaa8b60SDan Kruchinin ASSERT(rpcp->nr_handle == NULL); 350bbaa8b60SDan Kruchinin } 351bbaa8b60SDan Kruchinin 352bbaa8b60SDan Kruchinin static void 353bbaa8b60SDan Kruchinin destroy_rpch(nlm_rpc_t *rpcp) 354bbaa8b60SDan Kruchinin { 355bbaa8b60SDan Kruchinin if (rpcp->nr_handle != NULL) { 356bbaa8b60SDan Kruchinin AUTH_DESTROY(rpcp->nr_handle->cl_auth); 357bbaa8b60SDan Kruchinin CLNT_DESTROY(rpcp->nr_handle); 358bbaa8b60SDan Kruchinin rpcp->nr_handle = NULL; 359bbaa8b60SDan Kruchinin } 360bbaa8b60SDan Kruchinin 361bbaa8b60SDan Kruchinin kmem_cache_free(nlm_rpch_cache, rpcp); 362bbaa8b60SDan Kruchinin } 363