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
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.
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]
23 * Copyright 1994-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * RPC service routines.
38 #include <rpc/pmap_clnt.h> /* for pmap_unset */
39 #include <string.h> /* strcmp */
41 #include <unistd.h> /* setsid */
42 #include <sys/types.h>
47 #include <netconfig.h>
48 #include <sys/resource.h> /* rlimit */
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>
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"
63 #include "cfsd_subr.h"
65 /* declared in cfsd_main.c */
66 extern cfsd_all_object_t
*all_object_p
;
72 * Routine to process NULLPROC command, see /usr/include/rpc/clnt.h.
78 * Always returns 1, e.g. returns success result.
83 cachefsd_null_1_svc(void *inp
, void *outp
, struct svc_req
*reqp
)
85 dbug_enter("cachefsd_null_1_svc");
88 dbug_assert(inp
== NULL
);
89 dbug_assert(outp
== NULL
);
91 dbug_leave("cachefsd_null_1_svc");
96 * cachefsd_caches_1_svc
99 * Returns list of caches on the system.
102 * outp should point to return object
105 * Returns 1 for success 0 if an error occurs.
110 cachefsd_caches_1_svc(void *inp
,
111 cachefsd_caches_return
*outp
,
112 struct svc_req
*reqp
)
116 cfsd_cache_object_t
*cache_object_p
;
117 cachefsd_caches_id
*headp
, *idp
;
119 dbug_enter("cachefsd_caches_1_svc");
122 dbug_assert(inp
== NULL
);
125 if (inp
|| (outp
== NULL
)) {
126 dbug_leave("cachefsd_caches_1_svc");
129 all_lock(all_object_p
);
132 /* if there are any caches */
133 cnt
= all_object_p
->i_cachecount
;
135 /* allocate space for each cache information */
136 headp
= idp
= cfsd_calloc(sizeof (cachefsd_caches_id
) * cnt
);
139 for (index
= 0; index
< cnt
; index
++, idp
++) {
141 cache_object_p
= all_cachelist_at(all_object_p
, index
);
142 dbug_assert(cache_object_p
);
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
);
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
;
155 all_unlock(all_object_p
);
157 dbug_leave("cachefsd_caches_1_svc");
162 * cachefsd_cache_status_1_svc
165 * Returns status about a particular cache.
167 * inp should be ptr to cache id
168 * outp should be ptr to place to put cache status
171 * Returns 1 for success 0 if an error occurs.
176 cachefsd_cache_status_1_svc(int *inp
, struct cachefsd_cache_status
*outp
,
177 struct svc_req
*reqp
)
179 cfsd_fscache_object_t
*fscache_object_p
= NULL
;
181 cfsd_cache_object_t
*cache_object_p
;
182 cfsd_kmod_object_t
*kmod_object_p
;
183 cachefsio_getstats_t gs
;
186 dbug_enter("cachefsd_cache_status_1_svc");
192 if ((inp
== NULL
) || (outp
== NULL
)) {
193 dbug_leave("cachefsd_cache_status_1_svc");
196 memset(outp
, 0, sizeof (*outp
));
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
++) {
203 cache_object_p
= all_cachelist_at(all_object_p
, index
);
204 dbug_assert(cache_object_p
);
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
);
214 all_unlock(all_object_p
);
218 dbug_leave("cachefsd_cache_status_1_svc");
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
);
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
);
236 fscache_object_p
= NULL
;
238 cache_unlock(cache_object_p
);
241 outp
->ccs_lrusize
= 0;
242 outp
->ccs_packsize
= 0;
243 outp
->ccs_freesize
= 0;
244 outp
->ccs_lrutime
= 0;
246 kmod_object_p
= cfsd_kmod_create();
247 if (fscache_object_p
) {
248 xx
= kmod_setup(kmod_object_p
, fscache_object_p
->i_mntpt
);
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
));
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
;
261 fscache_lock(fscache_object_p
);
262 fscache_object_p
->i_refcnt
--;
263 fscache_unlock(fscache_object_p
);
266 cfsd_kmod_destroy(kmod_object_p
);
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
);
275 dbug_leave("cachefsd_cache_status_1_svc");
280 * cachefsd_mounts_1_svc
283 * Returns the list of file systems that are in the cache.
285 * inp should be ptr to cache id
286 * outp should be ptr to place to put mounts
289 * Returns 1 for success 0 if an internal error occurs.
294 cachefsd_mounts_1_svc(int *inp
, struct cachefsd_mount_returns
*outp
,
295 struct svc_req
*reqp
)
298 cfsd_cache_object_t
*cache_object_p
;
299 cfsd_fscache_object_t
*fscache_object_p
;
300 struct cachefsd_mount
*headp
, *idp
;
302 dbug_enter("cachefsd_mounts_1_svc");
307 if ((inp
== NULL
) || (outp
== NULL
)) {
308 dbug_leave("cachefsd_mounts_1_svc");
311 memset(outp
, 0, sizeof (*outp
));
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
++) {
318 cache_object_p
= all_cachelist_at(all_object_p
, index
);
319 dbug_assert(cache_object_p
);
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
);
329 all_unlock(all_object_p
);
331 /* if no match was found */
333 outp
->cmr_error
= ENOENT
;
334 dbug_leave("cachefsd_mounts_1_svc");
338 cache_lock(cache_object_p
);
341 /* if there are any fscaches */
342 cnt
= cache_object_p
->i_fscachecount
;
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 */
350 cache_fscachelist_at(cache_object_p
, index
);
351 dbug_assert(fscache_object_p
);
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
);
359 /* fill in the return object */
360 outp
->cmr_modify
= cache_object_p
->i_modify
;
362 outp
->cmr_names
.cmr_names_len
= cnt
;
363 outp
->cmr_names
.cmr_names_val
= headp
;
365 cache_object_p
->i_refcnt
--;
366 cache_unlock(cache_object_p
);
368 dbug_leave("cachefsd_mounts_1_svc");
373 * cachefsd_mount_stat_1_svc
376 * Returns status information about a single file system
379 * inp should be which file system to get info for
380 * outp should be place to put mount info
383 * Returns 1 for success 0 if an error occurs.
388 cachefsd_mount_stat_1_svc(struct cachefsd_mount_stat_args
*inp
,
389 struct cachefsd_mount_stat
*outp
, struct svc_req
*reqp
)
392 cfsd_cache_object_t
*cache_object_p
;
393 cfsd_fscache_object_t
*fscache_object_p
;
394 char namebuf
[MAXPATHLEN
];
397 dbug_enter("cachefsd_mount_stat_1_svc");
402 if ((inp
== NULL
) || (outp
== NULL
)) {
403 dbug_leave("cachefsd_mount_stat_1_svc");
406 memset(outp
, 0, sizeof (*outp
));
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
++) {
413 cache_object_p
= all_cachelist_at(all_object_p
, index
);
414 dbug_assert(cache_object_p
);
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
);
424 all_unlock(all_object_p
);
426 /* if no match was found */
428 dbug_leave("cachefsd_mount_stat_1_svc");
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
);
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
);
448 cache_unlock(cache_object_p
);
450 /* if no match was found */
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");
459 fscache_lock(fscache_object_p
);
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
,
467 if (stat(namebuf
, &sinfo
) == 0) {
468 fscache_changes(fscache_object_p
, 1);
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
;
489 fscache_object_p
->i_refcnt
--;
490 fscache_unlock(fscache_object_p
);
492 cache_lock(cache_object_p
);
493 cache_object_p
->i_refcnt
--;
494 cache_unlock(cache_object_p
);
496 dbug_leave("cachefsd_mount_stat_1_svc");
501 * cachefsd_fs_mounted_1_svc
504 * Sent by the mount command to indicate a new file system
507 * inp ptr to mount information
508 * outp should be null
511 * Returns 1 for success 0 if an internal error occurs.
516 cachefsd_fs_mounted_1_svc(struct cachefsd_fs_mounted
*inp
, void *outp
,
517 struct svc_req
*reqp
)
521 dbug_enter("cachefsd_fs_mounted_1_svc");
525 dbug_assert(outp
== NULL
);
526 if ((inp
== NULL
) || outp
) {
527 dbug_leave("cachefsd_fs_mounted_1_svc");
531 if (inp
->mt_cachedir
== NULL
) {
532 dbug_print(("error", "cachedir is null"));
535 if (inp
->mt_cacheid
== NULL
) {
536 dbug_print(("error", "cacheid is null"));
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
);
546 dbug_leave("cachefsd_fs_mounted_1_svc");
551 * cachefsd_fs_unmounted_1_svc
559 * Returns 1 for success 0 if an internal error occurs.
562 * precond(outp == NULL)
566 cachefsd_fs_unmounted_1_svc(struct cachefsd_fs_unmounted
*inp
, int *outp
,
567 struct svc_req
*reqp
)
569 size_t cnt1
, cnt2
, index1
, index2
;
570 cfsd_cache_object_t
*cache_object_p
;
571 cfsd_fscache_object_t
*fscache_object_p
= NULL
;
575 dbug_enter("cachefsd_fs_unmounted_1_svc");
581 if ((inp
== NULL
) || (outp
== NULL
)) {
582 dbug_leave("cachefsd_fs_unmounted_1_svc");
585 memset(outp
, 0, sizeof (*outp
));
587 if (inp
->mntpt
== NULL
) {
588 dbug_print(("error", "mntpt is null"));
590 dbug_leave("cachefsd_fs_unmounted_1_svc");
595 all_lock(all_object_p
);
596 cnt1
= all_object_p
->i_cachecount
;
597 for (index1
= 0; index1
< cnt1
; index1
++) {
599 cache_object_p
= all_cachelist_at(all_object_p
, index1
);
600 dbug_assert(cache_object_p
);
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 */
608 cache_fscachelist_at(cache_object_p
, index2
);
609 dbug_assert(fscache_object_p
);
611 /* skip if not mounted */
612 if (fscache_object_p
->i_mounted
== 0)
616 if (strcmp(fscache_object_p
->i_mntpt
,
618 fscache_lock(fscache_object_p
);
619 fscache_object_p
->i_refcnt
++;
621 fscache_unlock(fscache_object_p
);
626 cache_unlock(cache_object_p
);
629 fscache_object_p
= NULL
;
631 all_unlock(all_object_p
);
634 if (fscache_object_p
== NULL
) {
637 *outp
= fscache_unmount(fscache_object_p
, flag
);
639 fscache_lock(fscache_object_p
);
640 fscache_object_p
->i_refcnt
--;
641 fscache_unlock(fscache_object_p
);
643 dbug_leave("cachefsd_fs_unmounted_1_svc");
648 * cachefsd_disconnection_1_svc
656 * Returns 1 for success 0 if an internal error occurs.
663 cachefsd_disconnection_1_svc(struct cachefsd_disconnection_args
*inp
, int *outp
,
664 struct svc_req
*reqp
)
666 size_t cnt1
, cnt2
, index1
, index2
;
667 cfsd_cache_object_t
*cache_object_p
;
668 cfsd_fscache_object_t
*fscache_object_p
= NULL
;
671 dbug_enter("cachefsd_disconnection_1_svc");
677 if ((inp
== NULL
) || (outp
== NULL
)) {
678 dbug_leave("cachefsd_disconnection_1_svc");
681 memset(outp
, 0, sizeof (*outp
));
684 all_lock(all_object_p
);
685 cnt1
= all_object_p
->i_cachecount
;
686 for (index1
= 0; index1
< cnt1
; index1
++) {
688 cache_object_p
= all_cachelist_at(all_object_p
, index1
);
689 dbug_assert(cache_object_p
);
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 */
697 cache_fscachelist_at(cache_object_p
, index2
);
698 dbug_assert(fscache_object_p
);
701 if (strcmp(fscache_object_p
->i_mntpt
, inp
->cda_mntpt
)
703 fscache_lock(fscache_object_p
);
704 fscache_object_p
->i_refcnt
++;
705 fscache_unlock(fscache_object_p
);
710 cache_unlock(cache_object_p
);
713 fscache_object_p
= NULL
;
715 all_unlock(all_object_p
);
718 if (fscache_object_p
== NULL
) {
721 *outp
= fscache_simdisconnect(fscache_object_p
,
722 inp
->cda_disconnect
);
724 fscache_lock(fscache_object_p
);
725 fscache_object_p
->i_refcnt
--;
726 fscache_unlock(fscache_object_p
);
728 dbug_leave("cachefsd_disconnection_1_svc");
733 * cachefsdprog_1_freeresult
746 cachefsdprog_1_freeresult(SVCXPRT
*transp
, xdrproc_t xdr_result
,
749 dbug_enter("cachefsdprog_1_freeresult");
751 dbug_precond(transp
);
753 (void) xdr_free(xdr_result
, resultp
);
754 dbug_leave("cachefsdprog_1_freeresult");