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@gmail.com Tested by: patrykkotlowski@gmail.com Reviewed by: markj MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D25127
This commit is contained in:
parent
24ed6f550a
commit
7674d489fc
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user