X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fstatd%2Fstatd.c;h=8337b64b993918fb8704daeb49cae711447779d3;hp=62009111edd5a0a594c823c3dc62972fa58f2193;hb=dda3455d8b96a7b078bc00c113e1af15ed421d5b;hpb=f113db5225e2954a53fd7eecccfc08326904909f diff --git a/utils/statd/statd.c b/utils/statd/statd.c index 6200911..8337b64 100644 --- a/utils/statd/statd.c +++ b/utils/statd/statd.c @@ -70,11 +70,13 @@ static struct option longopts[] = { "state-directory-path", 1, 0, 'P' }, { "notify-mode", 0, 0, 'N' }, { "ha-callout", 1, 0, 'H' }, + { "no-notify", 0, 0, 'L' }, { NULL, 0, 0, 0 } }; extern void sm_prog_1 (struct svc_req *, register SVCXPRT *); extern int statd_get_socket(void); +static void load_state_number(void); #ifdef SIMULATIONS extern void simulator (int, char **); @@ -158,6 +160,7 @@ usage() fprintf(stderr," -n, --name Specify a local hostname.\n"); fprintf(stderr," -P State directory path.\n"); fprintf(stderr," -N Run in notify only mode.\n"); + fprintf(stderr," -L, --no-notify Do not perform any notification.\n"); fprintf(stderr," -H Specify a high-availability callout program.\n"); } @@ -228,12 +231,10 @@ static void run_sm_notify(int outport) av[ac++] = op; } if (run_mode & STATIC_HOSTNAME) { - av[ac++] = "-N"; + av[ac++] = "-v"; av[ac++] = MY_NAME; } av[ac] = NULL; - fprintf(stderr, "%s: -N deprecated, consider using /usr/sbin/sm-notify directly\n", - name_p); execv(av[0], av); fprintf(stderr, "%s: failed to run %s\n", name_p, av[0]); exit(2); @@ -274,7 +275,7 @@ int main (int argc, char **argv) MY_NAME = NULL; /* Process command line switches */ - while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:", longopts, NULL)) != EOF) { + while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:L", longopts, NULL)) != EOF) { switch (arg) { case 'V': /* Version */ case 'v': @@ -286,6 +287,9 @@ int main (int argc, char **argv) case 'N': run_mode |= MODE_NOTIFY_ONLY; break; + case 'L': /* Listen only */ + run_mode |= MODE_NO_NOTIFY; + break; case 'd': /* No daemon only - log to stderr */ run_mode |= MODE_LOG_STDERR; break; @@ -363,8 +367,11 @@ int main (int argc, char **argv) exit(-1); } - if (run_mode & MODE_NOTIFY_ONLY) + if (run_mode & MODE_NOTIFY_ONLY) { + fprintf(stderr, "%s: -N deprecated, consider using /usr/sbin/sm-notify directly\n", + name_p); run_sm_notify(out_port); + } if (!(run_mode & MODE_NODAEMON)) { @@ -458,32 +465,42 @@ int main (int argc, char **argv) create_pidfile(); atexit(truncate_pidfile); - switch (pid = fork()) { - case 0: - run_sm_notify(out_port); - break; - case -1: - break; - default: - waitpid(pid, NULL, 0); - } + if (! (run_mode & MODE_NO_NOTIFY)) + switch (pid = fork()) { + case 0: + run_sm_notify(out_port); + break; + case -1: + break; + default: + waitpid(pid, NULL, 0); + } - drop_privs(); + /* Make sure we have a privilege port for calling into the kernel */ + statd_get_socket(); - for (;;) { - pmap_unset (SM_PROG, SM_VERS); + /* If sm-notify didn't take all the state files, load + * state information into our notify-list so we can + * pass on any SM_NOTIFY that arrives + */ + load_state(); + load_state_number(); + pmap_unset (SM_PROG, SM_VERS); - /* If we got this far, we have successfully started, so notify parent */ - if (pipefds[1] > 0) { - status = 0; - write(pipefds[1], &status, 1); - close(pipefds[1]); - pipefds[1] = -1; - } + /* this registers both UDP and TCP services */ + rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port); - /* this registers both UDP and TCP services */ - rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port); + /* If we got this far, we have successfully started, so notify parent */ + if (pipefds[1] > 0) { + status = 0; + write(pipefds[1], &status, 1); + close(pipefds[1]); + pipefds[1] = -1; + } + + drop_privs(); + for (;;) { /* * Handle incoming requests: SM_NOTIFY socket requests, as * well as callbacks from lockd. @@ -496,15 +513,37 @@ int main (int argc, char **argv) * responding to SM_SIMU_CRASH is an important use cases to * get perfect. */ - switch (pid = fork()) { - case 0: - run_sm_notify(out_port); - break; - case -1: - break; - default: - waitpid(pid, NULL, 0); - } + if (! (run_mode & MODE_NO_NOTIFY)) + switch (pid = fork()) { + case 0: + run_sm_notify(out_port); + break; + case -1: + break; + default: + waitpid(pid, NULL, 0); + } + } return 0; } + +static void +load_state_number(void) +{ + int fd; + + if ((fd = open(SM_STAT_PATH, O_RDONLY)) == -1) + return; + + read(fd, &MY_STATE, sizeof(MY_STATE)); + close(fd); + fd = open("/proc/sys/fs/nfs/nsm_local_state",O_WRONLY); + if (fd >= 0) { + char buf[20]; + snprintf(buf, sizeof(buf), "%d", MY_STATE); + write(fd, buf, strlen(buf)); + close(fd); + } + +}