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 *
get_nlm_rpc_fromcache(struct nlm_host * hostp,int vers)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
update_host_rpcbinding(struct nlm_host * hostp,int vers)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
refresh_nlm_rpc(struct nlm_host * hostp,nlm_rpc_t * rpcp)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*87b81b14SDan 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
nlm_host_get_rpc(struct nlm_host * hostp,int vers,nlm_rpc_t ** rpcpp)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
nlm_host_rele_rpc(struct nlm_host * hostp,nlm_rpc_t * rpcp)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
nlm_host_rele_rpc_locked(struct nlm_host * hostp,nlm_rpc_t * rpcp)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
nlm_host_invalidate_binding(struct nlm_host * hostp)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
nlm_rpc_init(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
nlm_rpc_cache_destroy(struct nlm_host * hostp)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
nlm_rpch_ctor(void * datap,void * cdrarg,int kmflags)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
nlm_rpch_dtor(void * datap,void * cdrarg)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
destroy_rpch(nlm_rpc_t * rpcp)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