Author: rmacklem
Date: Sun Jun 28 04:08:42 2020
New Revision: 362717
URL: https://svnweb.freebsd.org/changeset/base/362717

Log:
  MFC: r361854
  Fix mountd so that it will not lose SIGHUPs that indicate "reload exports".
  
  Without this patch, if a SIGHUP is handled while the process is executing
  get_exportlist(), that SIGHUP is essentially ignored because the got_sighup
  variable is reset to 0 after get_exportlist().
  This results in the exports file(s) not being reloaded until another SIGHUP
  signal is sent to mountd.
  This patch fixes this by resetting got_sighup to zero before the
  get_exportlist() call while SIGHUP is blocked.
  It also defines a delay time of 250msec before doing another exports reload
  if there are RPC request(s) to process. This prevents repeated exports reloads
  from delaying handling of RPC requests significantly.
  
  PR:           246597

Modified:
  stable/11/usr.sbin/mountd/mountd.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.sbin/mountd/mountd.c
==============================================================================
--- stable/11/usr.sbin/mountd/mountd.c  Sun Jun 28 03:28:28 2020        
(r362716)
+++ stable/11/usr.sbin/mountd/mountd.c  Sun Jun 28 04:08:42 2020        
(r362717)
@@ -182,6 +182,12 @@ struct fhreturn {
 
 #define        GETPORT_MAXTRY  20      /* Max tries to get a port # */
 
+/*
+ * How long to delay a reload of exports when there are RPC request(s)
+ * to process, in usec.  Must be less than 1second.
+ */
+#define        RELOADDELAY     250000
+
 /* Global defs */
 static char    *add_expdir(struct dirlist **, char *, int);
 static void    add_dlist(struct dirlist **, struct dirlist *,
@@ -408,6 +414,10 @@ main(int argc, char **argv)
        int maxrec = RPC_MAXDATASIZE;
        int attempt_cnt, port_len, port_pos, ret;
        char **port_list;
+       uint64_t curtime, nexttime;
+       struct timeval tv;
+       struct timespec tp;
+       sigset_t sighup_mask;
 
        /* Check that another mountd isn't already running. */
        pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
@@ -663,19 +673,49 @@ main(int argc, char **argv)
        }
 
        /* Expand svc_run() here so that we can call get_exportlist(). */
+       curtime = nexttime = 0;
+       sigemptyset(&sighup_mask);
+       sigaddset(&sighup_mask, SIGHUP);
        for (;;) {
-               if (got_sighup) {
-                       get_exportlist(1);
+               clock_gettime(CLOCK_MONOTONIC, &tp);
+               curtime = tp.tv_sec;
+               curtime = curtime * 1000000 + tp.tv_nsec / 1000;
+               sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
+               if (got_sighup && curtime >= nexttime) {
                        got_sighup = 0;
-               }
+                       sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
+                       get_exportlist(1);
+                       clock_gettime(CLOCK_MONOTONIC, &tp);
+                       nexttime = tp.tv_sec;
+                       nexttime = nexttime * 1000000 + tp.tv_nsec / 1000 +
+                           RELOADDELAY;
+               } else
+                       sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
+
+               /*
+                * If a reload is pending, poll for received request(s),
+                * otherwise set a RELOADDELAY timeout, since a SIGHUP
+                * could be processed between the got_sighup test and
+                * the select() system call.
+                */
+               tv.tv_sec = 0;
+               if (got_sighup)
+                       tv.tv_usec = 0;
+               else
+                       tv.tv_usec = RELOADDELAY;
                readfds = svc_fdset;
-               switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) {
+               switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tv)) {
                case -1:
-                       if (errno == EINTR)
-                                continue;
+                       if (errno == EINTR) {
+                               /* Allow a reload now. */
+                               nexttime = 0;
+                               continue;
+                       }
                        syslog(LOG_ERR, "mountd died: select: %m");
                        exit(1);
                case 0:
+                       /* Allow a reload now. */
+                       nexttime = 0;
                        continue;
                default:
                        svc_getreqset(&readfds);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to