4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Main routines for cachefs daemon.
33 #include <stdio_ext.h>
38 #include <rpc/pmap_clnt.h> /* for pmap_unset */
39 #include <string.h> /* strcmp */
41 #include <unistd.h> /* setsid */
42 #include <sys/types.h>
45 #include <netconfig.h>
49 #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 #define RPCGEN_ACTION(X) X
66 #include "cachefsd_tbl.i"
69 #define SIG_PF void(*)(int)
72 typedef bool_t (* LOCAL
)(void *, void *, struct svc_req
*);
74 /* global definitions */
75 cfsd_all_object_t
*all_object_p
= NULL
;
77 /* forward references */
78 void msgout(char *msgp
);
79 void cachefsdprog_1(struct svc_req
*rqstp
, register SVCXPRT
*transp
);
80 void sigusr1_handler(int, siginfo_t
*, void *);
81 static int void_close(void *, int);
84 * -----------------------------------------------------------------
88 * main routine for the chart daemon.
93 * Returns 0 for a normal exit, !0 if an error occurred.
99 main(int argc
, char **argv
)
103 char mname
[FMNAMESZ
+ 1];
106 char *opt_root
= NULL
;
111 struct sigaction nact
;
114 struct netconfig
*nconf
= NULL
;
116 cfsd_fscache_object_t
*fscache_object_p
;
118 /* selectable maximum RPC request record size */
119 int maxrecsz
= RPC_MAXDATASIZE
;
122 dbug_process("cfsadmin");
124 (void) setlocale(LC_ALL
, "");
125 #if !defined(TEXT_DOMAIN)
126 #define TEXT_DOMAIN "SYS_TEST"
128 (void) textdomain(TEXT_DOMAIN
);
132 fprintf(stderr
, gettext("%s: must be run by root\n"), argv
[0]);
137 /* Increase number of file descriptors to maximum allowable */
138 xx
= getrlimit(RLIMIT_NOFILE
, &rl
);
141 "getrlimit/RLIMIT_NOFILE failed %d", errno
));
145 rl
.rlim_cur
= rl
.rlim_max
;
146 xx
= setrlimit(RLIMIT_NOFILE
, &rl
);
149 "setrlimit/RLIMIT_NOFILE failed %d", errno
));
153 (void) enable_extended_FILE_stdio(-1, -1);
155 while ((c
= getopt(argc
, argv
, "fmr:#:")) != EOF
) {
163 * XXX don't use this until race between mount
164 * and umount is fixed.
173 case '#': /* dbug args */
174 msgp
= dbug_push(optarg
);
176 printf("dbug_push failed \"%s\"\n", msgp
);
184 printf(gettext("illegal switch\n"));
190 /* XXX need some way to prevent multiple daemons from running */
192 dbug_print(("info", "cachefsd started..."));
195 dbug_print(("info", "MT_AUTO mode set"));
196 mode
= RPC_SVC_MT_AUTO
;
197 if (!rpc_control(RPC_SVC_MTMODE_SET
, &mode
)) {
198 msgout(gettext("unable to set automatic MT mode."));
205 * Enable non-blocking mode and maximum record size checks for
206 * connection oriented transports.
208 if (!rpc_control(RPC_SVC_CONNMAXREC_SET
, &maxrecsz
)) {
209 msgout(gettext("unable to set max RPC record size"));
213 nact
.sa_handler
= SIG_IGN
;
214 nact
.sa_sigaction
= NULL
;
215 sigemptyset(&nact
.sa_mask
);
217 xx
= sigaction(SIGPIPE
, &nact
, NULL
);
219 dbug_print(("error", "sigaction/SIGPIPE failed %d", errno
));
222 /* catch sigusr1 signals, used to wake up threads */
223 nact
.sa_handler
= NULL
;
224 nact
.sa_sigaction
= sigusr1_handler
;
225 sigemptyset(&nact
.sa_mask
);
226 nact
.sa_flags
= SA_SIGINFO
;
227 xx
= sigaction(SIGUSR1
, &nact
, NULL
);
229 dbug_print(("error", "sigaction failed %d", errno
));
232 /* do not set up rpc services if just taking care of root */
234 dbug_print(("info", "handling just root"));
236 /* make the fscache object */
238 cfsd_fscache_create("rootcache", opt_root
, 1);
240 /* init the fscache object with mount information */
241 fscache_lock(fscache_object_p
);
242 fscache_object_p
->i_refcnt
++;
243 fscache_setup(fscache_object_p
);
244 fscache_object_p
->i_mounted
= 1;
245 fscache_unlock(fscache_object_p
);
247 if (fscache_object_p
->i_disconnectable
&&
248 fscache_object_p
->i_mounted
) {
251 perror(gettext("cannot fork"));
252 cfsd_fscache_destroy(fscache_object_p
);
257 cfsd_fscache_destroy(fscache_object_p
);
261 (void) fdwalk(void_close
, &ofd
);
262 xx
= open("/dev/sysmsg", O_RDWR
);
267 fscache_process(fscache_object_p
);
269 /* not disconnectable */
270 cfsd_fscache_destroy(fscache_object_p
);
274 cfsd_fscache_destroy(fscache_object_p
);
279 /* if a inetd started us */
280 else if (!ioctl(0, I_LOOK
, mname
) &&
281 ((strcmp(mname
, "sockmod") == 0) ||
282 (strcmp(mname
, "timod") == 0))) {
283 dbug_print(("info", "started by inetd"));
285 if (freopen("/dev/null", "w", stderr
) == NULL
)
288 /* started from inetd */
289 if ((netid
= getenv("NLSPROVIDER")) == NULL
)
291 if ((nconf
= getnetconfigent(netid
)) == NULL
)
292 msgout(gettext("cannot get transport info"));
294 if (strcmp(mname
, "sockmod") == 0) {
295 if (ioctl(0, I_POP
, 0) || ioctl(0, I_PUSH
, "timod")) {
297 gettext("could not get the right module"));
302 if ((transp
= svc_tli_create(0, nconf
, NULL
, 0, 0)) == NULL
) {
303 msgout(gettext("cannot create server handle"));
308 freenetconfigent(nconf
);
309 xx
= svc_reg(transp
, CACHEFSDPROG
, CACHEFSDVERS
,
313 "unable to reg (CACHEFSDPROG, CACHEFSDVERS)."));
319 /* else if started by hand */
321 /* if we should fork */
323 dbug_print(("info", "forking"));
326 perror(gettext("cannot fork"));
334 (void) fdwalk(void_close
, &ofd
);
335 xx
= open("/dev/sysmsg", 2);
341 /* connect to *ANY* local loopback transport provider */
342 xx
= svc_create(cachefsdprog_1
, CACHEFSDPROG
, CACHEFSDVERS
,
345 msgout(gettext("unable to create (CACHEFSDPROG, "
346 "CACHEFSDVERS) for netpath."));
352 /* find existing caches and mounted file systems */
353 all_object_p
= cfsd_all_create();
354 subr_cache_setup(all_object_p
);
356 /* process requests */
359 msgout(gettext("svc_run returned"));
360 cfsd_all_destroy(all_object_p
);
366 * Callback function for fdwalk() to close all files.
369 void_close(void *ofdp
, int fd
)
371 if (fd
!= *(int *)ofdp
) {
374 "cannot close fd %d, %d", fd
, errno
));
380 * -----------------------------------------------------------------
384 * Outputs an error message to stderr.
395 dbug_enter("msgout");
398 (void) fprintf(stderr
, "%s\n", msgp
);
399 dbug_leave("msgout");
404 * -----------------------------------------------------------------
417 cachefsdprog_1(struct svc_req
*rqstp
, register SVCXPRT
*transp
)
420 struct rpcgen_table
*rtp
;
421 void *argumentp
= NULL
;
422 void *resultp
= NULL
;
426 dbug_enter("cachefsdprog_1");
429 dbug_precond(transp
);
431 /* make sure a valid command number */
432 index
= rqstp
->rq_proc
;
433 if ((index
< 0) || (cachefsdprog_1_nproc
<= index
)) {
434 msgout(gettext("bad message"));
435 svcerr_noproc(transp
);
436 dbug_leave("cachefsdprog_1");
440 /* get command information */
441 rtp
= &cachefsdprog_1_table
[index
];
443 /* get memory for the arguments */
444 if (rtp
->len_arg
!= 0)
445 argumentp
= (void *)cfsd_calloc(rtp
->len_arg
);
447 /* get memory for the results */
448 if (rtp
->len_res
!= 0)
449 resultp
= (void *)cfsd_calloc(rtp
->len_res
);
451 /* get the arguments */
452 if (rtp
->xdr_arg
&& argumentp
) {
453 if (!svc_getargs(transp
, rtp
->xdr_arg
, (caddr_t
)argumentp
)) {
454 svcerr_decode(transp
);
455 cfsd_free(argumentp
);
457 dbug_leave("cachefsdprog_1");
462 /* call the routine to process the command */
463 local
= (LOCAL
)rtp
->proc
;
464 xx
= (*local
)(argumentp
, resultp
, rqstp
);
466 /* if the command could not be processed */
468 svcerr_systemerr(transp
);
471 /* else send the results back to the caller */
473 xx
= svc_sendreply(transp
, rtp
->xdr_res
, (caddr_t
)resultp
);
475 svcerr_systemerr(transp
);
477 /* free the results */
478 xx
= cachefsdprog_1_freeresult(transp
, rtp
->xdr_res
,
481 msgout(gettext("unable to free results"));
484 /* free the passed in arguments */
485 if (!svc_freeargs(transp
, rtp
->xdr_arg
, (caddr_t
)argumentp
)) {
486 msgout(gettext("unable to free arguments"));
491 cfsd_free(argumentp
);
494 dbug_leave("cachefsdprog_1");
501 * Catches sigusr1 signal so threads wake up.
507 sigusr1_handler(int sig
, siginfo_t
*sp
, void *vp
)