xref: /titanic_41/usr/src/uts/common/klm/nlm_rpc_handle.c (revision 87b81b143fe0922503cebced570aa8e9fdbeaebd)
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