svn commit: r361854 - head/usr.sbin/mountd
Rick Macklem
rmacklem at FreeBSD.org
Sat Jun 6 00:40:02 UTC 2020
Author: rmacklem
Date: Sat Jun 6 00:40:02 2020
New Revision: 361854
URL: https://svnweb.freebsd.org/changeset/base/361854
Log:
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
Reported by: patrykkotlowski at gmail.com
Tested by: patrykkotlowski at gmail.com
Reviewed by: markj
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D25127
Modified:
head/usr.sbin/mountd/mountd.c
Modified: head/usr.sbin/mountd/mountd.c
==============================================================================
--- head/usr.sbin/mountd/mountd.c Sat Jun 6 00:35:41 2020 (r361853)
+++ head/usr.sbin/mountd/mountd.c Sat Jun 6 00:40:02 2020 (r361854)
@@ -184,6 +184,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 *,
@@ -410,6 +416,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);
@@ -665,19 +675,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-all
mailing list