svn commit: r362717 - stable/11/usr.sbin/mountd

Rick Macklem rmacklem at FreeBSD.org
Sun Jun 28 04:08:43 UTC 2020


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);


More information about the svn-src-stable mailing list