4 * Copyright (c) 1997-2009 Erez Zadok
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 The Regents of the University of California.
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgment:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * File: am-utils/amd/nfs_start.c
48 #endif /* HAVE_CONFIG_H */
52 #ifndef SELECT_MAXWAIT
53 # define SELECT_MAXWAIT 16
54 #endif /* not SELECT_MAXWAIT */
56 SVCXPRT
*nfsxprt
= NULL
;
59 #ifndef HAVE_SIGACTION
60 # define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
61 #endif /* not HAVE_SIGACTION */
65 * Check that we are not burning resources
70 static int max_fd
= 0;
71 static char *max_mem
= NULL
;
73 caddr_t next_mem
= sbrk(0);
77 if (max_fd
< next_fd
) {
78 dlog("%d new fds allocated; total is %d",
79 next_fd
- max_fd
, next_fd
);
82 if (max_mem
< next_mem
) {
83 #ifdef HAVE_GETPAGESIZE
84 dlog("%#lx bytes of memory allocated; total is %#lx (%ld pages)",
85 (long) (next_mem
- max_mem
), (unsigned long) next_mem
,
86 ((long) next_mem
+ getpagesize() - 1) / (long) getpagesize());
87 #else /* not HAVE_GETPAGESIZE */
88 dlog("%#lx bytes of memory allocated; total is %#lx",
89 (long) (next_mem
- max_mem
), (unsigned long) next_mem
);
90 #endif /* not HAVE_GETPAGESIZE */
97 #endif /* not DEBUG */
101 #ifdef HAVE_SIGACTION
102 do_select(sigset_t smask
, int fds
, fd_set
*fdp
, struct timeval
*tvp
)
103 #else /* not HAVE_SIGACTION */
104 do_select(int smask
, int fds
, fd_set
*fdp
, struct timeval
*tvp
)
105 #endif /* not HAVE_SIGACTION */
111 if ((sig
= setjmp(select_intr
))) {
112 select_intr_valid
= 0;
117 amd_state
= Finishing
;
118 reschedule_timeout_mp();
124 select_intr_valid
= 1;
126 * Allow interrupts. If a signal
127 * occurs, then it will cause a longjmp
130 #ifdef HAVE_SIGACTION
131 sigprocmask(SIG_SETMASK
, &smask
, NULL
);
132 #else /* not HAVE_SIGACTION */
133 (void) sigsetmask(smask
);
134 #endif /* not HAVE_SIGACTION */
139 nsel
= select(fds
, fdp
, (fd_set
*) NULL
, (fd_set
*) NULL
,
140 tvp
->tv_sec
? tvp
: (struct timeval
*) NULL
);
143 #ifdef HAVE_SIGACTION
144 sigprocmask(SIG_BLOCK
, &masked_sigs
, NULL
);
145 #else /* not HAVE_SIGACTION */
146 (void) sigblock(MASKED_SIGS
);
147 #endif /* not HAVE_SIGACTION */
150 * Perhaps reload the cache?
152 if (do_mapc_reload
< clocktime(NULL
)) {
154 do_mapc_reload
= clocktime(NULL
) + gopt
.map_reload_interval
;
161 * Determine whether anything is left in
162 * the RPC input queue.
165 rpc_pending_now(void)
172 FD_SET(fwd_sock
, &readfds
);
174 tvv
.tv_sec
= tvv
.tv_usec
= 0;
175 nsel
= select(FD_SETSIZE
, &readfds
, (fd_set
*) NULL
, (fd_set
*) NULL
, &tvv
);
178 if (FD_ISSET(fwd_sock
, &readfds
))
188 #ifdef HAVE_SIGACTION
190 sigprocmask(SIG_BLOCK
, &masked_sigs
, &smask
);
191 #else /* not HAVE_SIGACTION */
192 int smask
= sigblock(MASKED_SIGS
);
193 #endif /* not HAVE_SIGACTION */
195 next_softclock
= clocktime(NULL
);
200 * Keep on trucking while we are in Run mode. This state
201 * is switched to Quit after all the file systems have
204 while ((int) amd_state
<= (int) Finishing
) {
210 #ifdef HAVE_SVC_GETREQSET
211 memmove(&readfds
, &svc_fdset
, sizeof(svc_fdset
));
212 #else /* not HAVE_SVC_GETREQSET */
214 # ifdef HAVE_FD_SET_FDS_BITS
215 readfds
.fds_bits
[0] = svc_fds
;
216 # else /* not HAVE_FD_SET_FDS_BITS */
218 # endif /* not HAVE_FD_SET_FDS_BITS */
219 #endif /* not HAVE_SVC_GETREQSET */
220 FD_SET(fwd_sock
, &readfds
);
225 * If the full timeout code is not called,
226 * then recompute the time delta manually.
228 now
= clocktime(NULL
);
230 if (next_softclock
<= now
) {
231 if (amd_state
== Finishing
)
233 tvv
.tv_sec
= softclock();
235 tvv
.tv_sec
= next_softclock
- now
;
239 if (amd_state
== Finishing
&& get_exported_ap(0) == NULL
) {
245 #ifdef HAVE_FS_AUTOFS
246 autofs_add_fdset(&readfds
);
247 #endif /* HAVE_FS_AUTOFS */
250 tvv
.tv_sec
= SELECT_MAXWAIT
;
252 dlog("Select waits for %ds", (int) tvv
.tv_sec
);
254 dlog("Select waits for Godot");
257 nsel
= do_select(smask
, FD_SETSIZE
, &readfds
, &tvv
);
261 if (errno
== EINTR
) {
262 dlog("select interrupted");
265 plog(XLOG_ERROR
, "select: %m");
273 * Read all pending NFS responses at once to avoid having responses
274 * queue up as a consequence of retransmissions.
276 if (FD_ISSET(fwd_sock
, &readfds
)) {
277 FD_CLR(fwd_sock
, &readfds
);
281 } while (rpc_pending_now() > 0);
284 #ifdef HAVE_FS_AUTOFS
286 nsel
= autofs_handle_fdset(&readfds
, nsel
);
287 #endif /* HAVE_FS_AUTOFS */
291 * Anything left must be a normal
294 #ifdef HAVE_SVC_GETREQSET
295 svc_getreqset(&readfds
);
296 #else /* not HAVE_SVC_GETREQSET */
297 # ifdef HAVE_FD_SET_FDS_BITS
298 svc_getreq(readfds
.fds_bits
[0]);
299 # else /* not HAVE_FD_SET_FDS_BITS */
301 # endif /* not HAVE_FD_SET_FDS_BITS */
302 #endif /* not HAVE_SVC_GETREQSET */
308 #ifdef HAVE_SIGACTION
309 sigprocmask(SIG_SETMASK
, &smask
, NULL
);
310 #else /* not HAVE_SIGACTION */
311 (void) sigsetmask(smask
);
312 #endif /* not HAVE_SIGACTION */
314 if (amd_state
== Quit
)
322 mount_automounter(int ppid
)
325 * Old code replaced by rpc-trash patch.
326 * Erez Zadok <ezk@cs.columbia.edu>
327 int so = socket(AF_INET, SOCK_DGRAM, 0);
329 SVCXPRT
*udp_amqp
= NULL
, *tcp_amqp
= NULL
;
332 int udp_soAMQ
, tcp_soAMQ
;
333 struct netconfig
*udp_amqncp
, *tcp_amqncp
;
336 * This must be done first, because it attempts to bind
337 * to various UDP ports and we don't want anything else
338 * potentially taking over those ports before we get a chance
341 if (gopt
.flags
& CFM_RESTART_EXISTING_MOUNTS
)
342 restart_automounter_nodes();
345 * Start RPC forwarding
351 * Construct the root automount node
356 * Pick up the pieces from a previous run
357 * This is likely to (indirectly) need the rpc_fwd package
358 * so it *must* come after the call to fwd_init().
360 if (gopt
.flags
& CFM_RESTART_EXISTING_MOUNTS
)
364 * Create the nfs service for amd
365 * If nfs_port is already initialized, it means we
366 * already created the service during restart_automounter_nodes().
369 ret
= create_nfs_service(&soNFS
, &nfs_port
, &nfsxprt
, nfs_program_2
);
373 xsnprintf(pid_fsname
, sizeof(pid_fsname
), "%s:(pid%ld,port%u)",
374 am_get_hostname(), (long) am_mypid
, nfs_port
);
376 /* security: if user sets -D noamq, don't even create listening socket */
377 if (amuDebug(D_AMQ
)) {
378 ret
= create_amq_service(&udp_soAMQ
,
384 gopt
.preferred_amq_port
);
389 #ifdef HAVE_FS_AUTOFS
390 if (amd_use_autofs
) {
392 * Create the autofs service for amd.
394 ret
= create_autofs_service();
395 /* if autofs service fails it is OK if using a test amd */
397 plog(XLOG_WARNING
, "autofs service registration failed, turning off autofs support");
401 #endif /* HAVE_FS_AUTOFS */
404 * Mount the top-level auto-mountpoints
406 nmount
= mount_exported();
409 * Now safe to tell parent that we are up and running
415 plog(XLOG_FATAL
, "No work to do - quitting");
420 if (amuDebug(D_AMQ
)) {
422 * Complete registration of amq (first TCP service then UDP)
424 int tcp_ok
= 0, udp_ok
= 0;
426 unregister_amq(); /* unregister leftover Amd, if any, just in case */
428 tcp_ok
= amu_svc_register(tcp_amqp
, get_amd_program_number(), AMQ_VERSION
,
429 amq_program_1
, IPPROTO_TCP
, tcp_amqncp
);
432 "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)",
433 get_amd_program_number());
435 udp_ok
= amu_svc_register(udp_amqp
, get_amd_program_number(), AMQ_VERSION
,
436 amq_program_1
, IPPROTO_UDP
, udp_amqncp
);
439 "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)",
440 get_amd_program_number());
442 /* return error only if both failed */
443 if (!tcp_ok
&& !udp_ok
) {
450 * Start timeout_mp rolling
452 reschedule_timeout_mp();
457 if (run_rpc() != Done
) {
458 plog(XLOG_FATAL
, "run_rpc failed");