Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / am-utils / dist / amd / nfs_start.c
blob593de63282a256b2149bd54d6ebb98e633ea2e21
1 /* $NetBSD$ */
3 /*
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.
8 * All rights reserved.
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
15 * are met:
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
39 * SUCH DAMAGE.
42 * File: am-utils/amd/nfs_start.c
46 #ifdef HAVE_CONFIG_H
47 # include <config.h>
48 #endif /* HAVE_CONFIG_H */
49 #include <am_defs.h>
50 #include <amd.h>
52 #ifndef SELECT_MAXWAIT
53 # define SELECT_MAXWAIT 16
54 #endif /* not SELECT_MAXWAIT */
56 SVCXPRT *nfsxprt = NULL;
57 u_short nfs_port = 0;
59 #ifndef HAVE_SIGACTION
60 # define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
61 #endif /* not HAVE_SIGACTION */
63 #ifdef DEBUG
65 * Check that we are not burning resources
67 static void
68 checkup(void)
70 static int max_fd = 0;
71 static char *max_mem = NULL;
72 int next_fd = dup(0);
73 caddr_t next_mem = sbrk(0);
75 close(next_fd);
77 if (max_fd < next_fd) {
78 dlog("%d new fds allocated; total is %d",
79 next_fd - max_fd, next_fd);
80 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 */
91 max_mem = next_mem;
95 #else /* not DEBUG */
96 #define checkup()
97 #endif /* not DEBUG */
100 static int
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 */
108 int sig;
109 int nsel;
111 if ((sig = setjmp(select_intr))) {
112 select_intr_valid = 0;
113 /* Got a signal */
114 switch (sig) {
115 case SIGINT:
116 case SIGTERM:
117 amd_state = Finishing;
118 reschedule_timeout_mp();
119 break;
121 nsel = -1;
122 errno = EINTR;
123 } else {
124 select_intr_valid = 1;
126 * Allow interrupts. If a signal
127 * occurs, then it will cause a longjmp
128 * up above.
130 #ifdef HAVE_SIGACTION
131 sigprocmask(SIG_SETMASK, &smask, NULL);
132 #else /* not HAVE_SIGACTION */
133 (void) sigsetmask(smask);
134 #endif /* not HAVE_SIGACTION */
137 * Wait for input
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)) {
153 mapc_reload();
154 do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
156 return nsel;
161 * Determine whether anything is left in
162 * the RPC input queue.
164 static int
165 rpc_pending_now(void)
167 struct timeval tvv;
168 int nsel;
169 fd_set readfds;
171 FD_ZERO(&readfds);
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);
176 if (nsel < 1)
177 return (0);
178 if (FD_ISSET(fwd_sock, &readfds))
179 return (1);
181 return (0);
185 static serv_state
186 run_rpc(void)
188 #ifdef HAVE_SIGACTION
189 sigset_t smask;
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);
197 amd_state = Run;
200 * Keep on trucking while we are in Run mode. This state
201 * is switched to Quit after all the file systems have
202 * been unmounted.
204 while ((int) amd_state <= (int) Finishing) {
205 struct timeval tvv;
206 int nsel;
207 time_t now;
208 fd_set readfds;
210 #ifdef HAVE_SVC_GETREQSET
211 memmove(&readfds, &svc_fdset, sizeof(svc_fdset));
212 #else /* not HAVE_SVC_GETREQSET */
213 FD_ZERO(&readfds);
214 # ifdef HAVE_FD_SET_FDS_BITS
215 readfds.fds_bits[0] = svc_fds;
216 # else /* not HAVE_FD_SET_FDS_BITS */
217 readfds = svc_fds;
218 # endif /* not HAVE_FD_SET_FDS_BITS */
219 #endif /* not HAVE_SVC_GETREQSET */
220 FD_SET(fwd_sock, &readfds);
222 checkup();
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)
232 umount_exported();
233 tvv.tv_sec = softclock();
234 } else {
235 tvv.tv_sec = next_softclock - now;
237 tvv.tv_usec = 0;
239 if (amd_state == Finishing && get_exported_ap(0) == NULL) {
240 flush_mntfs();
241 amd_state = Quit;
242 break;
245 #ifdef HAVE_FS_AUTOFS
246 autofs_add_fdset(&readfds);
247 #endif /* HAVE_FS_AUTOFS */
249 if (tvv.tv_sec <= 0)
250 tvv.tv_sec = SELECT_MAXWAIT;
251 if (tvv.tv_sec) {
252 dlog("Select waits for %ds", (int) tvv.tv_sec);
253 } else {
254 dlog("Select waits for Godot");
257 nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv);
259 switch (nsel) {
260 case -1:
261 if (errno == EINTR) {
262 dlog("select interrupted");
263 continue;
265 plog(XLOG_ERROR, "select: %m");
266 break;
268 case 0:
269 break;
271 default:
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);
278 --nsel;
279 do {
280 fwd_reply();
281 } while (rpc_pending_now() > 0);
284 #ifdef HAVE_FS_AUTOFS
285 if (nsel)
286 nsel = autofs_handle_fdset(&readfds, nsel);
287 #endif /* HAVE_FS_AUTOFS */
289 if (nsel) {
291 * Anything left must be a normal
292 * RPC request.
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 */
300 svc_getreq(readfds);
301 # endif /* not HAVE_FD_SET_FDS_BITS */
302 #endif /* not HAVE_SVC_GETREQSET */
304 break;
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)
315 amd_state = Done;
317 return amd_state;
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;
330 int nmount, ret;
331 int soNFS;
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
339 * to reserve them.
341 if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
342 restart_automounter_nodes();
345 * Start RPC forwarding
347 if (fwd_init() != 0)
348 return 3;
351 * Construct the root automount node
353 make_root_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)
361 restart();
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().
368 if (nfs_port == 0) {
369 ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
370 if (ret != 0)
371 return ret;
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,
379 &udp_amqp,
380 &udp_amqncp,
381 &tcp_soAMQ,
382 &tcp_amqp,
383 &tcp_amqncp,
384 gopt.preferred_amq_port);
385 if (ret != 0)
386 return ret;
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 */
396 if (ret != 0) {
397 plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
398 amd_use_autofs = 0;
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
411 if (ppid)
412 kill(ppid, SIGQUIT);
414 if (nmount == 0) {
415 plog(XLOG_FATAL, "No work to do - quitting");
416 amd_state = Done;
417 return 0;
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);
430 if (!tcp_ok)
431 plog(XLOG_FATAL,
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);
437 if (!udp_ok)
438 plog(XLOG_FATAL,
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) {
444 amd_state = Done;
445 return 3;
450 * Start timeout_mp rolling
452 reschedule_timeout_mp();
455 * Start the server
457 if (run_rpc() != Done) {
458 plog(XLOG_FATAL, "run_rpc failed");
459 amd_state = Done;
461 return 0;