xref: /titanic_41/usr/src/cmd/fs.d/cachefs/cfsd/cfsd_svc.c (revision 70025d765b044c6d8594bb965a2247a61e991a99)
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 1994-2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * RPC service routines.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <rpc/rpc.h>
38 #include <rpc/pmap_clnt.h> /* for pmap_unset */
39 #include <string.h> /* strcmp */
40 #include <signal.h>
41 #include <unistd.h> /* setsid */
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <time.h>
45 #include <memory.h>
46 #include <stropts.h>
47 #include <netconfig.h>
48 #include <sys/resource.h> /* rlimit */
49 #include <thread.h>
50 #include <synch.h>
51 #include <mdbug/mdbug.h>
52 #include <common/cachefsd.h>
53 #include <sys/fs/cachefs_fs.h>
54 #include <sys/fs/cachefs_dlog.h>
55 #include <sys/fs/cachefs_ioctl.h>
56 #include "cfsd.h"
57 #include "cfsd_kmod.h"
58 #include "cfsd_maptbl.h"
59 #include "cfsd_logfile.h"
60 #include "cfsd_fscache.h"
61 #include "cfsd_cache.h"
62 #include "cfsd_all.h"
63 #include "cfsd_subr.h"
64 
65 /* declared in cfsd_main.c */
66 extern cfsd_all_object_t *all_object_p;
67 
68 /*
69  *			cachefsd_null_1_svc
70  *
71  * Description:
72  *	Routine to process NULLPROC command, see /usr/include/rpc/clnt.h.
73  * Arguments:
74  *	inp	should be NULL
75  *	outp	should be NULL
76  *	reqp	svc_req info
77  * Returns:
78  *	Always returns 1, e.g. returns success result.
79  * Preconditions:
80  *	precond(reqp)
81  */
82 bool_t
83 cachefsd_null_1_svc(void *inp, void *outp, struct svc_req *reqp)
84 {
85 	dbug_enter("cachefsd_null_1_svc");
86 	dbug_precond(reqp);
87 
88 	dbug_assert(inp == NULL);
89 	dbug_assert(outp == NULL);
90 
91 	dbug_leave("cachefsd_null_1_svc");
92 	return (1);
93 }
94 
95 /*
96  *			cachefsd_caches_1_svc
97  *
98  * Description:
99  *	Returns list of caches on the system.
100  * Arguments:
101  *	inp	should be NULL
102  *	outp	should point to return object
103  *	reqp	svc_req info
104  * Returns:
105  *	Returns 1 for success 0 if an error occurs.
106  * Preconditions:
107  *	precond(reqp)
108  */
109 bool_t
110 cachefsd_caches_1_svc(void *inp,
111 	cachefsd_caches_return *outp,
112 	struct svc_req *reqp)
113 {
114 	size_t cnt;
115 	size_t index;
116 	cfsd_cache_object_t *cache_object_p;
117 	cachefsd_caches_id *headp, *idp;
118 
119 	dbug_enter("cachefsd_caches_1_svc");
120 	dbug_precond(reqp);
121 
122 	dbug_assert(inp == NULL);
123 	dbug_assert(outp);
124 
125 	if (inp || (outp == NULL)) {
126 		dbug_leave("cachefsd_caches_1_svc");
127 		return (0);
128 	}
129 	all_lock(all_object_p);
130 	headp = NULL;
131 
132 	/* if there are any caches */
133 	cnt = all_object_p->i_cachecount;
134 	if (cnt) {
135 		/* allocate space for each cache information */
136 		headp = idp = cfsd_calloc(sizeof (cachefsd_caches_id) * cnt);
137 
138 		/* for each cache */
139 		for (index = 0; index < cnt; index++, idp++) {
140 			/* get the cache */
141 			cache_object_p = all_cachelist_at(all_object_p, index);
142 			dbug_assert(cache_object_p);
143 
144 			/* get the cache id and name */
145 			idp->cci_cacheid = cache_object_p->i_cacheid;
146 			idp->cci_name = subr_strdup(cache_object_p->i_cachedir);
147 		}
148 	}
149 
150 	/* fill in the return object */
151 	outp->ccr_modify = all_object_p->i_modify;
152 	outp->ccr_ids.ccr_ids_len = cnt;
153 	outp->ccr_ids.ccr_ids_val = headp;
154 
155 	all_unlock(all_object_p);
156 
157 	dbug_leave("cachefsd_caches_1_svc");
158 	return (1);
159 }
160 
161 /*
162  *			cachefsd_cache_status_1_svc
163  *
164  * Description:
165  *	Returns status about a particular cache.
166  * Arguments:
167  *	inp	should be ptr to cache id
168  *	outp	should be ptr to place to put cache status
169  *	reqp	svc_req info
170  * Returns:
171  *	Returns 1 for success 0 if an error occurs.
172  * Preconditions:
173  *	precond(reqp)
174  */
175 bool_t
176 cachefsd_cache_status_1_svc(int *inp, struct cachefsd_cache_status *outp,
177     struct svc_req *reqp)
178 {
179 	cfsd_fscache_object_t *fscache_object_p = NULL;
180 	size_t cnt, index;
181 	cfsd_cache_object_t *cache_object_p;
182 	cfsd_kmod_object_t *kmod_object_p;
183 	cachefsio_getstats_t gs;
184 	int xx;
185 
186 	dbug_enter("cachefsd_cache_status_1_svc");
187 	dbug_precond(reqp);
188 
189 	dbug_assert(inp);
190 	dbug_assert(outp);
191 
192 	if ((inp == NULL) || (outp == NULL)) {
193 		dbug_leave("cachefsd_cache_status_1_svc");
194 		return (0);
195 	}
196 	memset(outp, 0, sizeof (*outp));
197 
198 	/* find the requested cache */
199 	all_lock(all_object_p);
200 	cnt = all_object_p->i_cachecount;
201 	for (index = 0; index < cnt; index++) {
202 		/* get the cache */
203 		cache_object_p = all_cachelist_at(all_object_p, index);
204 		dbug_assert(cache_object_p);
205 
206 		/* if a match */
207 		if (cache_object_p->i_cacheid == *inp) {
208 			cache_lock(cache_object_p);
209 			cache_object_p->i_refcnt++;
210 			cache_unlock(cache_object_p);
211 			break;
212 		}
213 	}
214 	all_unlock(all_object_p);
215 
216 	/* if no match */
217 	if (index >= cnt) {
218 		dbug_leave("cachefsd_cache_status_1_svc");
219 		return (1);
220 	}
221 	/* find a mounted file system in the cache */
222 	cache_lock(cache_object_p);
223 	cnt = cache_object_p->i_fscachecount;
224 	for (index = 0; index < cnt; index++) {
225 		/* get the fscache */
226 		fscache_object_p = cache_fscachelist_at(cache_object_p, index);
227 		dbug_assert(fscache_object_p);
228 
229 		/* mounted */
230 		if (fscache_object_p->i_mounted) {
231 			fscache_lock(fscache_object_p);
232 			fscache_object_p->i_refcnt++;
233 			fscache_unlock(fscache_object_p);
234 			break;
235 		}
236 		fscache_object_p = NULL;
237 	}
238 	cache_unlock(cache_object_p);
239 
240 	outp->ccs_size = 0;
241 	outp->ccs_lrusize = 0;
242 	outp->ccs_packsize = 0;
243 	outp->ccs_freesize = 0;
244 	outp->ccs_lrutime = 0;
245 
246 	kmod_object_p = cfsd_kmod_create();
247 	if (fscache_object_p) {
248 		xx = kmod_setup(kmod_object_p, fscache_object_p->i_mntpt);
249 		if (xx != 0) {
250 			dbug_print(("err",
251 			    "setup of kmod interface failed %d", xx));
252 		} else if ((xx = kmod_getstats(kmod_object_p, &gs)) != 0) {
253 			dbug_print(("err", "getstat failed %d", xx));
254 		} else {
255 			outp->ccs_size = gs.gs_total;
256 			outp->ccs_lrusize = gs.gs_gc + gs.gs_active;
257 			outp->ccs_packsize = gs.gs_packed;
258 			outp->ccs_freesize = gs.gs_free;
259 			outp->ccs_lrutime = gs.gs_gctime;
260 
261 			fscache_lock(fscache_object_p);
262 			fscache_object_p->i_refcnt--;
263 			fscache_unlock(fscache_object_p);
264 		}
265 	}
266 	cfsd_kmod_destroy(kmod_object_p);
267 
268 	outp->ccs_id = cache_object_p->i_cacheid;
269 	outp->ccs_name = subr_strdup(cache_object_p->i_cachedir);
270 	outp->ccs_modify = cache_object_p->i_modify;
271 	cache_lock(cache_object_p);
272 	cache_object_p->i_refcnt--;
273 	cache_unlock(cache_object_p);
274 
275 	dbug_leave("cachefsd_cache_status_1_svc");
276 	return (1);
277 }
278 
279 /*
280  *			cachefsd_mounts_1_svc
281  *
282  * Description:
283  *	Returns the list of file systems that are in the cache.
284  * Arguments:
285  *	inp	should be ptr to cache id
286  *	outp	should be ptr to place to put mounts
287  *	reqp	svc_req info
288  * Returns:
289  *	Returns 1 for success 0 if an internal error occurs.
290  * Preconditions:
291  *	precond(reqp)
292  */
293 bool_t
294 cachefsd_mounts_1_svc(int *inp, struct cachefsd_mount_returns *outp,
295     struct svc_req *reqp)
296 {
297 	size_t cnt, index;
298 	cfsd_cache_object_t *cache_object_p;
299 	cfsd_fscache_object_t *fscache_object_p;
300 	struct cachefsd_mount *headp, *idp;
301 
302 	dbug_enter("cachefsd_mounts_1_svc");
303 	dbug_precond(reqp);
304 
305 	dbug_assert(inp);
306 	dbug_assert(outp);
307 	if ((inp == NULL) || (outp == NULL)) {
308 		dbug_leave("cachefsd_mounts_1_svc");
309 		return (0);
310 	}
311 	memset(outp, 0, sizeof (*outp));
312 
313 	/* find the requested cache */
314 	all_lock(all_object_p);
315 	cnt = all_object_p->i_cachecount;
316 	for (index = 0; index < cnt; index++) {
317 		/* get the cache */
318 		cache_object_p = all_cachelist_at(all_object_p, index);
319 		dbug_assert(cache_object_p);
320 
321 		/* if a match */
322 		if (cache_object_p->i_cacheid == *inp) {
323 			cache_lock(cache_object_p);
324 			cache_object_p->i_refcnt++;
325 			cache_unlock(cache_object_p);
326 			break;
327 		}
328 	}
329 	all_unlock(all_object_p);
330 
331 	/* if no match was found */
332 	if (index >= cnt) {
333 		outp->cmr_error = ENOENT;
334 		dbug_leave("cachefsd_mounts_1_svc");
335 		return (1);
336 	}
337 
338 	cache_lock(cache_object_p);
339 	headp = NULL;
340 
341 	/* if there are any fscaches */
342 	cnt = cache_object_p->i_fscachecount;
343 	if (cnt) {
344 		/* allocate space for each fscache information */
345 		headp = idp = cfsd_calloc(sizeof (cachefsd_mount) * cnt);
346 		/* for each fscache */
347 		for (index = 0; index < cnt; index++, idp++) {
348 			/* get the fscache */
349 			fscache_object_p =
350 			    cache_fscachelist_at(cache_object_p, index);
351 			dbug_assert(fscache_object_p);
352 
353 			/* get the fscache id and name */
354 			idp->cm_fsid = fscache_object_p->i_fscacheid;
355 			idp->cm_name = subr_strdup(fscache_object_p->i_name);
356 		}
357 	}
358 
359 	/* fill in the return object */
360 	outp->cmr_modify = cache_object_p->i_modify;
361 	outp->cmr_error = 0;
362 	outp->cmr_names.cmr_names_len = cnt;
363 	outp->cmr_names.cmr_names_val = headp;
364 
365 	cache_object_p->i_refcnt--;
366 	cache_unlock(cache_object_p);
367 
368 	dbug_leave("cachefsd_mounts_1_svc");
369 	return (1);
370 }
371 
372 /*
373  *			cachefsd_mount_stat_1_svc
374  *
375  * Description:
376  *	Returns status information about a single file system
377  *	in the cache.
378  * Arguments:
379  *	inp	should be which file system to get info for
380  *	outp	should be place to put mount info
381  *	reqp	svc_req info
382  * Returns:
383  *	Returns 1 for success 0 if an error occurs.
384  * Preconditions:
385  *	precond(reqp)
386  */
387 bool_t
388 cachefsd_mount_stat_1_svc(struct cachefsd_mount_stat_args *inp,
389     struct cachefsd_mount_stat *outp, struct svc_req *reqp)
390 {
391 	size_t cnt, index;
392 	cfsd_cache_object_t *cache_object_p;
393 	cfsd_fscache_object_t *fscache_object_p;
394 	char namebuf[MAXPATHLEN];
395 	struct stat sinfo;
396 
397 	dbug_enter("cachefsd_mount_stat_1_svc");
398 	dbug_precond(reqp);
399 
400 	dbug_assert(inp);
401 	dbug_assert(outp);
402 	if ((inp == NULL) || (outp == NULL)) {
403 		dbug_leave("cachefsd_mount_stat_1_svc");
404 		return (0);
405 	}
406 	memset(outp, 0, sizeof (*outp));
407 
408 	/* find the requested cache */
409 	all_lock(all_object_p);
410 	cnt = all_object_p->i_cachecount;
411 	for (index = 0; index < cnt; index++) {
412 		/* get the cache */
413 		cache_object_p = all_cachelist_at(all_object_p, index);
414 		dbug_assert(cache_object_p);
415 
416 		/* if a match */
417 		if (cache_object_p->i_cacheid == inp->cma_cacheid) {
418 			cache_lock(cache_object_p);
419 			cache_object_p->i_refcnt++;
420 			cache_unlock(cache_object_p);
421 			break;
422 		}
423 	}
424 	all_unlock(all_object_p);
425 
426 	/* if no match was found */
427 	if (index >= cnt) {
428 		dbug_leave("cachefsd_mount_stat_1_svc");
429 		return (1);
430 	}
431 
432 	/* find the requested fscache */
433 	cache_lock(cache_object_p);
434 	cnt = cache_object_p->i_fscachecount;
435 	for (index = 0; index < cnt; index++) {
436 		/* get the fscache */
437 		fscache_object_p = cache_fscachelist_at(cache_object_p, index);
438 		dbug_assert(fscache_object_p);
439 
440 		/* if a match */
441 		if (fscache_object_p->i_fscacheid == inp->cma_fsid) {
442 			fscache_lock(fscache_object_p);
443 			fscache_object_p->i_refcnt++;
444 			fscache_unlock(fscache_object_p);
445 			break;
446 		}
447 	}
448 	cache_unlock(cache_object_p);
449 
450 	/* if no match was found */
451 	if (index >= cnt) {
452 		cache_lock(cache_object_p);
453 		cache_object_p->i_refcnt--;
454 		cache_unlock(cache_object_p);
455 		dbug_leave("cachefsd_mount_stat_1_svc");
456 		return (1);
457 	}
458 
459 	fscache_lock(fscache_object_p);
460 
461 	/* see if there are changes to roll to the server */
462 	if ((fscache_object_p->i_connected == 0) &&
463 	    (fscache_object_p->i_changes == 0)) {
464 		snprintf(namebuf, sizeof (namebuf), "%s/%s/%s",
465 		    cache_object_p->i_cachedir, fscache_object_p->i_name,
466 		    CACHEFS_DLOG_FILE);
467 		if (stat(namebuf, &sinfo) == 0) {
468 			fscache_changes(fscache_object_p, 1);
469 		}
470 	}
471 
472 	/* fill in the return object */
473 	outp->cms_cacheid = cache_object_p->i_cacheid;
474 	outp->cms_fsid = fscache_object_p->i_fscacheid;
475 	outp->cms_name = subr_strdup(fscache_object_p->i_name);
476 	outp->cms_backfs = subr_strdup(fscache_object_p->i_backfs);
477 	outp->cms_mountpt = subr_strdup(fscache_object_p->i_mntpt);
478 	outp->cms_backfstype = subr_strdup(fscache_object_p->i_backfstype);
479 	outp->cms_writemode = NULL;
480 	outp->cms_options = subr_strdup(fscache_object_p->i_cfsopt);
481 	outp->cms_mounted = fscache_object_p->i_mounted;
482 	outp->cms_connected = fscache_object_p->i_connected;
483 	outp->cms_reconcile = fscache_object_p->i_reconcile;
484 	outp->cms_changes = fscache_object_p->i_changes;
485 	outp->cms_time_state = fscache_object_p->i_time_state;
486 	outp->cms_mnttime = fscache_object_p->i_time_mnt;
487 	outp->cms_modify = fscache_object_p->i_modify;
488 
489 	fscache_object_p->i_refcnt--;
490 	fscache_unlock(fscache_object_p);
491 
492 	cache_lock(cache_object_p);
493 	cache_object_p->i_refcnt--;
494 	cache_unlock(cache_object_p);
495 
496 	dbug_leave("cachefsd_mount_stat_1_svc");
497 	return (1);
498 }
499 
500 /*
501  *			cachefsd_fs_mounted_1_svc
502  *
503  * Description:
504  *	Sent by the mount command to indicate a new file system
505  *	has been mounted
506  * Arguments:
507  *	inp	ptr to mount information
508  *	outp	should be null
509  *	reqp	svc_req info
510  * Returns:
511  *	Returns 1 for success 0 if an internal error occurs.
512  * Preconditions:
513  *	precond(inp)
514  */
515 bool_t
516 cachefsd_fs_mounted_1_svc(struct cachefsd_fs_mounted *inp, void *outp,
517     struct svc_req *reqp)
518 {
519 	int error = 0;
520 
521 	dbug_enter("cachefsd_fs_mounted_1_svc");
522 	dbug_precond(reqp);
523 
524 	dbug_assert(inp);
525 	dbug_assert(outp == NULL);
526 	if ((inp == NULL) || outp) {
527 		dbug_leave("cachefsd_fs_mounted_1_svc");
528 		return (0);
529 	}
530 
531 	if (inp->mt_cachedir == NULL) {
532 		dbug_print(("error", "cachedir is null"));
533 		error = 1;
534 	}
535 	if (inp->mt_cacheid == NULL) {
536 		dbug_print(("error", "cacheid is null"));
537 		error = 1;
538 	}
539 
540 	if (error == 0) {
541 		dbug_print(("info", "Mounted in %s file system %s",
542 		    inp->mt_cachedir, inp->mt_cacheid));
543 		subr_add_mount(all_object_p, inp->mt_cachedir, inp->mt_cacheid);
544 	}
545 
546 	dbug_leave("cachefsd_fs_mounted_1_svc");
547 	return (1);
548 }
549 
550 /*
551  *			cachefsd_fs_unmounted_1_svc
552  *
553  * Description:
554  * Arguments:
555  *	inp
556  *	outp
557  *	reqp
558  * Returns:
559  *	Returns 1 for success 0 if an internal error occurs.
560  * Preconditions:
561  *	precond(inp)
562  *	precond(outp == NULL)
563  *	precond(reqp)
564  */
565 bool_t
566 cachefsd_fs_unmounted_1_svc(struct cachefsd_fs_unmounted *inp, int *outp,
567     struct svc_req *reqp)
568 {
569 	size_t cnt1, cnt2, index1, index2;
570 	cfsd_cache_object_t *cache_object_p;
571 	cfsd_fscache_object_t *fscache_object_p = NULL;
572 	int found = 0;
573 	int flag = 0;
574 
575 	dbug_enter("cachefsd_fs_unmounted_1_svc");
576 
577 	dbug_precond(inp);
578 	dbug_precond(outp);
579 	dbug_precond(reqp);
580 
581 	if ((inp == NULL) || (outp == NULL)) {
582 		dbug_leave("cachefsd_fs_unmounted_1_svc");
583 		return (0);
584 	}
585 	memset(outp, 0, sizeof (*outp));
586 
587 	if (inp->mntpt == NULL) {
588 		dbug_print(("error", "mntpt is null"));
589 		*outp = EIO;
590 		dbug_leave("cachefsd_fs_unmounted_1_svc");
591 		return (1);
592 	}
593 
594 	/* for each cache */
595 	all_lock(all_object_p);
596 	cnt1 = all_object_p->i_cachecount;
597 	for (index1 = 0; index1 < cnt1; index1++) {
598 		/* get the cache */
599 		cache_object_p = all_cachelist_at(all_object_p, index1);
600 		dbug_assert(cache_object_p);
601 
602 		/* for each file system in this cache */
603 		cache_lock(cache_object_p);
604 		cnt2 = cache_object_p->i_fscachecount;
605 		for (index2 = 0; index2 < cnt2; index2++) {
606 			/* get the fscache */
607 			fscache_object_p =
608 			    cache_fscachelist_at(cache_object_p, index2);
609 			dbug_assert(fscache_object_p);
610 
611 			/* skip if not mounted */
612 			if (fscache_object_p->i_mounted == 0)
613 				continue;
614 
615 			/* if a match */
616 			if (strcmp(fscache_object_p->i_mntpt,
617 				inp->mntpt) == 0) {
618 				fscache_lock(fscache_object_p);
619 				fscache_object_p->i_refcnt++;
620 				flag = inp->flag;
621 				fscache_unlock(fscache_object_p);
622 				found = 1;
623 				break;
624 			}
625 		}
626 		cache_unlock(cache_object_p);
627 		if (found)
628 			break;
629 		fscache_object_p = NULL;
630 	}
631 	all_unlock(all_object_p);
632 
633 	/* if no match */
634 	if (fscache_object_p == NULL) {
635 		*outp = EIO;
636 	} else {
637 		*outp = fscache_unmount(fscache_object_p, flag);
638 
639 		fscache_lock(fscache_object_p);
640 		fscache_object_p->i_refcnt--;
641 		fscache_unlock(fscache_object_p);
642 	}
643 	dbug_leave("cachefsd_fs_unmounted_1_svc");
644 	return (1);
645 }
646 
647 /*
648  *			cachefsd_disconnection_1_svc
649  *
650  * Description:
651  * Arguments:
652  *	inp
653  *	outp
654  *	reqp
655  * Returns:
656  *	Returns 1 for success 0 if an internal error occurs.
657  * Preconditions:
658  *	precond(inp)
659  *	precond(outp)
660  *	precond(reqp)
661  */
662 bool_t
663 cachefsd_disconnection_1_svc(struct cachefsd_disconnection_args *inp, int *outp,
664     struct svc_req *reqp)
665 {
666 	size_t cnt1, cnt2, index1, index2;
667 	cfsd_cache_object_t *cache_object_p;
668 	cfsd_fscache_object_t *fscache_object_p = NULL;
669 	int found = 0;
670 
671 	dbug_enter("cachefsd_disconnection_1_svc");
672 
673 	dbug_precond(inp);
674 	dbug_precond(outp);
675 	dbug_precond(reqp);
676 
677 	if ((inp == NULL) || (outp == NULL)) {
678 		dbug_leave("cachefsd_disconnection_1_svc");
679 		return (0);
680 	}
681 	memset(outp, 0, sizeof (*outp));
682 
683 	/* for each cache */
684 	all_lock(all_object_p);
685 	cnt1 = all_object_p->i_cachecount;
686 	for (index1 = 0; index1 < cnt1; index1++) {
687 		/* get the cache */
688 		cache_object_p = all_cachelist_at(all_object_p, index1);
689 		dbug_assert(cache_object_p);
690 
691 		/* for each file system in this cache */
692 		cache_lock(cache_object_p);
693 		cnt2 = cache_object_p->i_fscachecount;
694 		for (index2 = 0; index2 < cnt2; index2++) {
695 			/* get the fscache */
696 			fscache_object_p =
697 			    cache_fscachelist_at(cache_object_p, index2);
698 			dbug_assert(fscache_object_p);
699 
700 			/* if a match */
701 			if (strcmp(fscache_object_p->i_mntpt, inp->cda_mntpt)
702 			    == 0) {
703 				fscache_lock(fscache_object_p);
704 				fscache_object_p->i_refcnt++;
705 				fscache_unlock(fscache_object_p);
706 				found = 1;
707 				break;
708 			}
709 		}
710 		cache_unlock(cache_object_p);
711 		if (found)
712 			break;
713 		fscache_object_p = NULL;
714 	}
715 	all_unlock(all_object_p);
716 
717 	/* if no match */
718 	if (fscache_object_p == NULL) {
719 		*outp = 3;
720 	} else {
721 		*outp = fscache_simdisconnect(fscache_object_p,
722 		    inp->cda_disconnect);
723 
724 		fscache_lock(fscache_object_p);
725 		fscache_object_p->i_refcnt--;
726 		fscache_unlock(fscache_object_p);
727 	}
728 	dbug_leave("cachefsd_disconnection_1_svc");
729 	return (1);
730 }
731 
732 /*
733  *			cachefsdprog_1_freeresult
734  *
735  * Description:
736  * Arguments:
737  *	transp
738  *	xdr_result
739  *	resultp
740  * Returns:
741  *	Returns ...
742  * Preconditions:
743  *	precond(transp)
744  */
745 int
746 cachefsdprog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result,
747 	caddr_t resultp)
748 {
749 	dbug_enter("cachefsdprog_1_freeresult");
750 
751 	dbug_precond(transp);
752 
753 	(void) xdr_free(xdr_result, resultp);
754 	dbug_leave("cachefsdprog_1_freeresult");
755 	return (1);
756 }
757