home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume21 / amd / part06 / nfs_start.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-10  |  7.3 KB  |  379 lines

  1. /*
  2.  * $Id: nfs_start.c,v 5.1.1.2 90/01/11 17:13:06 jsp Exp Locker: jsp $
  3.  *
  4.  * Copyright (c) 1990 Jan-Simon Pendry
  5.  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  6.  * Copyright (c) 1990 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * This code is derived from software contributed to Berkeley by
  10.  * Jan-Simon Pendry at Imperial College, London.
  11.  *
  12.  * Redistribution and use in source and binary forms are permitted
  13.  * provided that the above copyright notice and this paragraph are
  14.  * duplicated in all such forms and that any documentation,
  15.  * advertising materials, and other materials related to such
  16.  * distribution and use acknowledge that the software was developed
  17.  * by Imperial College of Science, Technology and Medicine, London, UK.
  18.  * The names of the College and University may not be used to endorse
  19.  * or promote products derived from this software without specific
  20.  * prior written permission.
  21.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  22.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  23.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  24.  *
  25.  *    %W% (Berkeley) %G%
  26.  */
  27.  
  28. #include "am.h"
  29. #include "amq.h"
  30. #include <sys/signal.h>
  31. #include <setjmp.h>
  32. extern jmp_buf select_intr;
  33. extern int select_intr_valid;
  34.  
  35. #ifdef HAS_TFS
  36. /*
  37.  * Use replacement for RPC/UDP transport
  38.  * so that we do NFS gatewaying.
  39.  */
  40. #define    svcudp_create svcudp2_create
  41. extern SVCXPRT *svcudp2_create P((int));
  42. #endif
  43.  
  44. extern void nfs_program_2();
  45. extern void amq_program_1();
  46.  
  47. unsigned short nfs_port;
  48. SVCXPRT *nfsxprt;
  49.  
  50. extern int fwd_sock;
  51.  
  52. #ifndef NFDS
  53. static int nfds = -1;
  54. #ifdef FD_SET
  55. #define    NFDS (nfds < 0 ? nfds = getdtablesize() : nfds)
  56. #else
  57. #define NFDS (sizeof(int) * 8)
  58. #endif
  59. #endif
  60.  
  61. #define    MASKED_SIGS    (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
  62.  
  63. #ifdef DEBUG
  64. /*
  65.  * Check that we are not burning resources
  66.  */
  67. static void checkup(P_void)
  68. {
  69.  
  70. static int max_fd = 0;
  71. static char *max_mem = 0;
  72.  
  73.     int next_fd = dup(0);
  74.     extern caddr_t sbrk P((int));
  75.     caddr_t next_mem = sbrk(0);
  76.     close(next_fd);
  77.  
  78.     /*if (max_fd < 0) {
  79.         max_fd = next_fd;
  80.     } else*/ if (max_fd < next_fd) {
  81.         dlog("%d new fds allocated; total is %d",
  82.             next_fd - max_fd, next_fd);
  83.         max_fd = next_fd;
  84.     }
  85.  
  86.     /*if (max_mem == 0) {
  87.         max_mem = next_mem;
  88.     } else*/ if (max_mem < next_mem) {
  89.         dlog("%#x bytes of memory allocated; total is %#x (%d pages)",
  90.             next_mem - max_mem,
  91.             next_mem,
  92.             ((int)next_mem+getpagesize()-1)/getpagesize());
  93.         max_mem = next_mem;
  94.     }
  95. }
  96. #endif
  97.  
  98. static int do_select(smask, fds, fdp, tvp)
  99. int smask;
  100. int fds;
  101. int *fdp;
  102. struct timeval *tvp;
  103. {
  104.     int sig;
  105.     int nsel;
  106.     if (sig = setjmp(select_intr)) {
  107.         select_intr_valid = 0;
  108.         /* Got a signal */
  109.         switch (sig) {
  110.         case SIGINT:
  111.         case SIGTERM:
  112.             amd_state = Finishing;
  113.             reschedule_timeout_mp();
  114.             break;
  115.         }
  116.         nsel = -1;
  117.         errno = EINTR;
  118.     } else {
  119.         select_intr_valid = 1;
  120.         /*
  121.          * Invalidate the current clock value
  122.          */
  123.         clock_valid = 0;
  124.         /*
  125.          * Allow interrupts.  If a signal
  126.          * occurs, then it will cause a longjmp
  127.          * up above.
  128.          */
  129.         (void) sigsetmask(smask);
  130.         /*
  131.          * Wait for input
  132.          */
  133.         nsel = select(fds, fdp, (int *) 0, (int *) 0,
  134.                 tvp->tv_sec ? tvp : (struct timeval *) 0);
  135.  
  136.     }
  137.  
  138.     (void) sigblock(MASKED_SIGS);
  139.  
  140.     /*
  141.      * Perhaps reload the cache?
  142.      */
  143.     if (do_mapc_reload < clocktime()) {
  144.         mapc_reload();
  145.         do_mapc_reload = clocktime() + ONE_HOUR;
  146.     }
  147.     return nsel;
  148. }
  149.  
  150. static serv_state run_rpc(P_void)
  151. {
  152.     int dtbsz = NFDS;
  153.     int smask = sigblock(MASKED_SIGS);
  154.  
  155.     next_softclock = clocktime();
  156.  
  157.     amd_state = Run;
  158.  
  159.     /*
  160.      * Keep on trucking while we are in Run mode.  This state
  161.      * is switched to Quit after all the file systems have
  162.      * been unmounted.
  163.      */
  164.     while ((int)amd_state <= (int)Finishing) {
  165.         struct timeval tvv;
  166.         int nsel;
  167.         time_t now;
  168. #ifdef RPC_4
  169.         fd_set readfds;
  170.         readfds = svc_fdset;
  171.         FD_SET(fwd_sock, &readfds);
  172. #else
  173. #ifdef FD_SET
  174.         fd_set readfds;
  175.         FD_ZERO(&readfds);
  176.         readfds.fds_bits[0] = svc_fds;
  177.         FD_SET(fwd_sock, &readfds);
  178. #else
  179.         int readfds = svc_fds | (1 << fwd_sock);
  180. #endif /* FD_SET */
  181. #endif /* RPC_4 */
  182.  
  183. #ifdef DEBUG
  184.         checkup();
  185. #endif
  186.  
  187.         /*
  188.          * If the full timeout code is not called,
  189.          * then recompute the time delta manually.
  190.          */
  191.         now = clocktime();
  192.  
  193.         if (next_softclock <= now) {
  194.             if (amd_state == Finishing)
  195.                 umount_exported();
  196.             tvv.tv_sec = softclock();
  197.         } else {
  198.             tvv.tv_sec = next_softclock - now;
  199.         }
  200.         tvv.tv_usec = 0;
  201.  
  202.         if (amd_state == Finishing && last_used_map < 0) {
  203.             flush_mntfs();
  204.             amd_state = Quit;
  205.             break;
  206.         }
  207.  
  208. #ifdef DEBUG
  209.         if (tvv.tv_sec)
  210.             dlog("Select waits for %ds", tvv.tv_sec);
  211.         else
  212.             dlog("Select waits for Godot");
  213. #endif
  214.  
  215.         nsel = do_select(smask, dtbsz, &readfds, &tvv);
  216.  
  217.  
  218.         switch (nsel) {
  219.         case -1:
  220.             if (errno == EINTR) {
  221. #ifdef DEBUG
  222.                 dlog("select interrupted");
  223. #endif
  224.                 continue;
  225.             }
  226.             perror("select");
  227.             break;
  228.  
  229.         case 0:
  230. #ifdef DEBUG
  231.             /*dlog("select returned 0");*/
  232. #endif
  233.             break;
  234.  
  235.         default:
  236. #ifdef FD_SET
  237.             if (FD_ISSET(fwd_sock, &readfds)) {
  238.                 FD_CLR(fwd_sock, &readfds);
  239.                 fwd_reply();
  240.                 --nsel;
  241.             }
  242. #else
  243.             if (readfds & (1 << fwd_sock)) {
  244.                 readfds &= ~(1 << fwd_sock);
  245.                 fwd_reply();
  246.                 --nsel;
  247.             }
  248. #endif
  249.  
  250.             if (nsel) {
  251.                 /*
  252.                  * Anything left must be a normal
  253.                  * RPC request.
  254.                  */
  255. #ifdef RPC_4
  256.                 svc_getreqset(&readfds);
  257. #else
  258. #ifdef FD_SET
  259.                 svc_getreq(readfds.fds_bits[0]);
  260. #else
  261.                 svc_getreq(readfds);
  262. #endif
  263. #endif
  264.             }
  265.             break;
  266.         }
  267.     }
  268.  
  269.     (void) sigsetmask(smask);
  270.  
  271.     if (amd_state == Quit)
  272.         amd_state = Done;
  273.  
  274.     return amd_state;
  275. }
  276.  
  277. static int bindnfs_port(so)
  278. int so;
  279. {
  280.     unsigned short port;
  281.     int error = bind_resv_port(so, &port);
  282.     if (error == 0)
  283.         nfs_port = port;
  284.     return error;
  285. }
  286.  
  287. void unregister_amq(P_void)
  288. {
  289. #ifdef DEBUG
  290.     Debug(D_AMQ)
  291. #endif
  292.     (void) pmap_unset(AMQ_PROGRAM, AMQ_VERSION);
  293. }
  294.  
  295. int mount_automounter(ppid)
  296. int ppid;
  297. {
  298.     int so = socket(AF_INET, SOCK_DGRAM, 0);
  299.     SVCXPRT *amqp;
  300.     int nmount;
  301.  
  302.     unregister_amq();
  303.  
  304.     if (so < 0 || bindnfs_port(so) < 0) {
  305.         perror("Can't create privileged nfs port");
  306.         return 1;
  307.     }
  308.  
  309.     if ((nfsxprt = svcudp_create(so)) == NULL || 
  310.             (amqp = svcudp_create(so)) == NULL) {
  311.         plog(XLOG_FATAL, "cannot create rpc/udp service");
  312.         return 2;
  313.     }
  314.  
  315.     if (!svc_register(nfsxprt, NFS_PROGRAM, NFS_VERSION, nfs_program_2, 0)) {
  316.         plog(XLOG_FATAL, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
  317.         return 3;
  318.     }
  319.  
  320. #ifdef DEBUG
  321.     Debug(D_AMQ)
  322. #endif
  323.     if (!svc_register(amqp, AMQ_PROGRAM, AMQ_VERSION, amq_program_1, IPPROTO_UDP)) {
  324.         plog(XLOG_FATAL, "unable to register (AMQ_PROGRAM, AMQ_VERSION, udp)");
  325.         return 3;
  326.     }
  327.  
  328.     /*
  329.      * Start RPC forwarding
  330.      */
  331.     if (fwd_init() != 0)
  332.         return 3;
  333.  
  334.     /*
  335.      * Construct the root automount node
  336.      */
  337.     make_root_node();
  338.  
  339.     /*
  340.      * Pick up the pieces from a previous run
  341.      * This is likely to (indirectly) need the rpc_fwd package
  342.      * so it *must* come after the call to fwd_init().
  343.      */
  344.     if (restart_existing_mounts)
  345.         restart();
  346.  
  347.     /*
  348.      * Mount the top-level auto-mountpoints
  349.      */
  350.     nmount = mount_exported();
  351.  
  352.     /*
  353.      * Now safe to tell parent that we are up and running
  354.      */
  355.     if (ppid)
  356.         kill(ppid, SIGQUIT);
  357.  
  358.     if (nmount == 0) {
  359.         plog(XLOG_FATAL, "No work to do - quitting");
  360.         amd_state = Done;
  361.         return 0;
  362.     }
  363.  
  364.     /*
  365.      * Start timeout_mp rolling
  366.      */
  367.     reschedule_timeout_mp();
  368.  
  369.     /*
  370.      * Start the server
  371.      */
  372.     if (run_rpc() != Done) {
  373.         plog(XLOG_FATAL, "run_rpc failed");
  374.         amd_state = Done;
  375.     }
  376.  
  377.     return 0;
  378. }
  379.