From: Neil Brown Date: Mon, 19 Mar 2007 23:09:50 +0000 (+1100) Subject: Remove notify functionality from statd in favour of sm-notify X-Git-Tag: nfs-utils-1-1-0-rc1~35 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=f113db52;p=nfs-utils.git Remove notify functionality from statd in favour of sm-notify statd now execs sm-notify to notify peers and only listens to monitor requests and remote notifications itself. --- diff --git a/utils/statd/Makefile.am b/utils/statd/Makefile.am index 093659a..efe9356 100644 --- a/utils/statd/Makefile.am +++ b/utils/statd/Makefile.am @@ -14,8 +14,8 @@ GENFILES = $(GENFILES_CLNT) $(GENFILES_SVC) $(GENFILES_XDR) $(GENFILES_H) RPCPREFIX = rpc. KPREFIX = @kprefix@ sbin_PROGRAMS = statd sm-notify -statd_SOURCES = callback.c notlist.c log.c misc.c monitor.c notify.c \ - simu.c stat.c statd.c state.c svc_run.c rmtcall.c \ +statd_SOURCES = callback.c notlist.c log.c misc.c monitor.c \ + simu.c stat.c statd.c svc_run.c rmtcall.c \ sm_inter_clnt.c sm_inter_svc.c sm_inter_xdr.c log.h \ notlist.h statd.h system.h version.h sm_inter.h sm_notify_SOURCES = sm-notify.c diff --git a/utils/statd/callback.c b/utils/statd/callback.c index 8a85ce9..bb8bf52 100644 --- a/utils/statd/callback.c +++ b/utils/statd/callback.c @@ -49,7 +49,6 @@ sm_notify_1_svc(struct stat_chge *argp, struct svc_req *rqstp) if (NL_STATE(lp) != argp->state) { NL_STATE(lp) = argp->state; call = nlist_clone(lp); - NL_TYPE(call) = NOTIFY_CALLBACK; nlist_insert(¬ify, call); } lp = NL_NEXT(lp); diff --git a/utils/statd/notify.c b/utils/statd/notify.c deleted file mode 100644 index d7aa1dd..0000000 --- a/utils/statd/notify.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff - * Modified by Olaf Kirch, Oct. 1996. - * Modified by H.J. Lu, 1998. - * - * NSM for Linux. - */ - -/* - * NSM notify list handling. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "misc.h" -#include "statd.h" -#include "notlist.h" - -/* - * Initial (startup) notify list. - */ -notify_list *inl = NULL; - - -/* - * Get list of hosts from stable storage, build list of hosts to - * contact. These hosts are added to the global RPC notify list - * which is processed as soon as statd enters svc_run. - */ -void -notify_hosts(void) -{ - DIR *nld; - struct dirent *de; - notify_list *call; - - if (!(nld = opendir(SM_BAK_DIR))) { - perror("opendir"); - exit(errno); - } - - while ((de = readdir(nld))) { - if (de->d_name[0] == '.') - continue; - - /* The following can happen for loopback NFS mounts - * (e.g. with cfsd) */ - if (matchhostname(de->d_name, MY_NAME) - || matchhostname(de->d_name, "localhost")) { - char *fname; - fname=xmalloc(strlen(SM_BAK_DIR)+sizeof(de->d_name)+2); - dprintf(N_DEBUG, "We're on our own notify list?!?"); - sprintf(fname, "%s/%s", SM_BAK_DIR, de->d_name); - if (unlink(fname)) - note(N_ERROR, "unlink(%s): %s", - fname, strerror(errno)); - free(fname); - continue; - } - - call = nlist_new(MY_NAME, de->d_name, -1); - NL_TYPE(call) = NOTIFY_REBOOT; - nlist_insert(¬ify, call); - } - - if (closedir(nld) == -1) { - perror("closedir"); - exit(1); - } -} diff --git a/utils/statd/notlist.h b/utils/statd/notlist.h index 911c092..12962af 100644 --- a/utils/statd/notlist.h +++ b/utils/statd/notlist.h @@ -20,14 +20,10 @@ struct notify_list { struct notify_list *prev; /* Linked list backward pointer. */ u_int32_t xid; /* XID of MS_NOTIFY RPC call */ time_t when; /* notify: timeout for re-xmit */ - int type; /* type of notify (REBOOT/CALLBACK) */ }; typedef struct notify_list notify_list; -#define NOTIFY_REBOOT 0 /* notify remote of our reboot */ -#define NOTIFY_CALLBACK 1 /* notify client of remote reboot */ - /* * Global Variables */ @@ -67,4 +63,3 @@ extern notify_list * nlist_gethost(notify_list *, char *, int); #define NL_MY_PROG(L) (NL_MY_ID((L)).my_prog) #define NL_MY_VERS(L) (NL_MY_ID((L)).my_vers) #define NL_WHEN(L) ((L)->when) -#define NL_TYPE(L) ((L)->type) diff --git a/utils/statd/rmtcall.c b/utils/statd/rmtcall.c index 35cbccb..362e1f6 100644 --- a/utils/statd/rmtcall.c +++ b/utils/statd/rmtcall.c @@ -59,7 +59,7 @@ static int sockfd = -1; /* notify socket */ * Initialize callback socket */ int -statd_get_socket(int port) +statd_get_socket(void) { struct sockaddr_in sin; @@ -76,77 +76,14 @@ statd_get_socket(int port) memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; - /* - * If a local hostname is given (-n option to statd), bind to the address - * specified. This is required to support clients that ignore the mon_name in - * the statd protocol but use the source address from the request packet. - */ - if (MY_NAME) { - struct hostent *hp = gethostbyname(MY_NAME); - if (hp) - sin.sin_addr = *(struct in_addr *) hp->h_addr; - } - if (port != 0) { - sin.sin_port = htons(port); - if (bind(sockfd, &sin, sizeof(sin)) == 0) - goto out_success; - note(N_CRIT, "statd: failed to bind to outgoing port, %d\n" - " falling back on randomly chosen port\n", port); - } + if (bindresvport(sockfd, &sin) < 0) { dprintf(N_WARNING, "process_hosts: can't bind to reserved port\n"); } -out_success: return sockfd; } -#ifdef HAVE_IFADDRS_H -/* - * Using the NL_ADDR(lp), reset (if needed) the hostname - * that will be put in the SM_NOTIFY to the hostname - * that is associated with the network interface - * that was monitored - */ -static void -reset_my_name(notify_list *lp) -{ - struct ifaddrs *ifa = NULL, *ifap; - struct in_addr netaddr, tmp; - struct sockaddr_in *sin, *nsin; - struct hostent *hp; - - netaddr.s_addr = inet_netof(NL_ADDR(lp)); - if (getifaddrs(&ifa) >= 0) { - for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { - if (!(ifap->ifa_flags & IFF_UP)) - continue; - - note(N_DEBUG, "ifa_name %s\n", ifap->ifa_name); - if (ifap->ifa_addr == NULL) - continue; - if (ifap->ifa_addr->sa_family != AF_INET) - continue; - - sin = (struct sockaddr_in *)ifap->ifa_addr; - nsin = (struct sockaddr_in *)ifap->ifa_netmask; - tmp.s_addr = sin->sin_addr.s_addr & nsin->sin_addr.s_addr; - if (memcmp(&tmp.s_addr, &netaddr.s_addr, sizeof(netaddr.s_addr))) - continue; - hp = gethostbyaddr((char *)&sin->sin_addr, - sizeof(sin->sin_addr), AF_INET); - if (hp == NULL) - continue; - if (strcmp(NL_MY_NAME(lp), hp->h_name)) { - free(NL_MY_NAME(lp)); - NL_MY_NAME(lp)= strdup(hp->h_name); - note(N_DEBUG, "NL_MY_NAME %s\n", NL_MY_NAME(lp)); - } - } - } - return; -} -#endif /* HAVE_IFADDRS_H */ /* * Try to resolve host name for notify/callback request * @@ -159,10 +96,7 @@ try_to_resolve(notify_list *lp) { char *hname; - if (NL_TYPE(lp) == NOTIFY_REBOOT) - hname = NL_MON_NAME(lp); - else - hname = NL_MY_NAME(lp); + hname = NL_MY_NAME(lp); if (!inet_aton(hname, &(NL_ADDR(lp)))) { note(N_ERROR, "%s is not an dotted-quad address", hname); NL_TIMES(lp) = 0; @@ -182,10 +116,7 @@ try_to_resolve(notify_list *lp) struct hostent *hp; char *hname; - if (NL_TYPE(lp) == NOTIFY_REBOOT) - hname = NL_MON_NAME(lp); - else - hname = NL_MY_NAME(lp); + hname = NL_MY_NAME(lp); dprintf(N_DEBUG, "Trying to resolve %s.", hname); if (!(hp = gethostbyname(hname))) { @@ -356,7 +287,6 @@ process_entry(int sockfd, notify_list *lp) { struct sockaddr_in sin; struct status new_status; - stat_chge new_stat; xdrproc_t func; void *objp; u_int32_t proc, vers, prog; @@ -375,49 +305,19 @@ process_entry(int sockfd, notify_list *lp) sin.sin_port = lp->port; /* LH - moved address into switch */ - switch (NL_TYPE(lp)) { - case NOTIFY_REBOOT: - prog = SM_PROG; - vers = SM_VERS; - proc = SM_NOTIFY; - - /* Use source address for notify replies */ - sin.sin_addr = lp->addr; - /* - * Unless a static hostname has been defined - * set the NL_MY_NAME(lp) hostname to the - * one associated with the network interface - */ -#ifdef HAVE_IFADDRS_H - if (!(run_mode & STATIC_HOSTNAME)) - reset_my_name(lp); -#endif /* HAVE_IFADDRS_H */ - func = (xdrproc_t) xdr_stat_chge; - new_stat.state = MY_STATE; - new_stat.mon_name = NL_MY_NAME(lp); + prog = NL_MY_PROG(lp); + vers = NL_MY_VERS(lp); + proc = NL_MY_PROC(lp); - objp = &new_stat; - break; - case NOTIFY_CALLBACK: - prog = NL_MY_PROG(lp); - vers = NL_MY_VERS(lp); - proc = NL_MY_PROC(lp); - - /* __FORCE__ loopback for callbacks to lockd ... */ - /* Just in case we somehow ignored it thus far */ - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - func = (xdrproc_t) xdr_status; - objp = &new_status; - new_status.mon_name = NL_MON_NAME(lp); - new_status.state = NL_STATE(lp); - memcpy(new_status.priv, NL_PRIV(lp), SM_PRIV_SIZE); - break; - default: - note(N_ERROR, "notify_host: unknown notify type %d", - NL_TYPE(lp)); - return 0; - } + /* __FORCE__ loopback for callbacks to lockd ... */ + /* Just in case we somehow ignored it thus far */ + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + func = (xdrproc_t) xdr_status; + objp = &new_status; + new_status.mon_name = NL_MON_NAME(lp); + new_status.state = NL_STATE(lp); + memcpy(new_status.priv, NL_PRIV(lp), SM_PRIV_SIZE); lp->xid = xmit_call(sockfd, &sin, prog, vers, proc, func, objp); if (!lp->xid) { @@ -455,12 +355,7 @@ process_reply(FD_SET_TYPE *rfds) return 1; } note(N_WARNING, "recv_rply: [%s] service %d not registered", - inet_ntoa(lp->addr), - NL_TYPE(lp) == NOTIFY_REBOOT? SM_PROG : NL_MY_PROG(lp)); - } else if (NL_TYPE(lp) == NOTIFY_REBOOT) { - dprintf(N_DEBUG, "Notification of %s succeeded.", - NL_MON_NAME(lp)); - xunlink(SM_BAK_DIR, NL_MON_NAME(lp), 0); + inet_ntoa(lp->addr), NL_MY_PROG(lp)); } else { dprintf(N_DEBUG, "Callback to %s (for %d) succeeded.", NL_MY_NAME(lp), NL_MON_NAME(lp)); @@ -481,7 +376,7 @@ process_notify_list(void) time_t now; int fd; - if ((fd = statd_get_socket(0)) < 0) + if ((fd = statd_get_socket()) < 0) return 0; while ((entry = notify) != NULL && NL_WHEN(entry) < time(&now)) { @@ -489,21 +384,13 @@ process_notify_list(void) NL_WHEN(entry) = time(NULL) + NOTIFY_TIMEOUT; nlist_remove(¬ify, entry); nlist_insert_timer(¬ify, entry); - } else if (NL_TYPE(entry) == NOTIFY_CALLBACK) { + } else { note(N_ERROR, "Can't callback %s (%d,%d), giving up.", NL_MY_NAME(entry), NL_MY_PROG(entry), NL_MY_VERS(entry)); nlist_free(¬ify, entry); - } else { - note(N_ERROR, - "Can't notify %s, giving up.", - NL_MON_NAME(entry)); - /* PRC: do the HA callout */ - ha_callout("del-client", NL_MON_NAME(entry), NL_MY_NAME(entry), -1); - xunlink(SM_BAK_DIR, NL_MON_NAME(entry), 0); - nlist_free(¬ify, entry); } } diff --git a/utils/statd/statd.c b/utils/statd/statd.c index c92e12f..6200911 100644 --- a/utils/statd/statd.c +++ b/utils/statd/statd.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "statd.h" #include "version.h" @@ -44,7 +45,6 @@ char * SM_STAT_PATH = DEFAULT_SM_STAT_PATH; /* ----- end of state directory path stuff ------- */ -short int restart = 0; int run_mode = 0; /* foreground logging mode */ /* LH - I had these local to main, but it seemed silly to have @@ -74,7 +74,7 @@ static struct option longopts[] = }; extern void sm_prog_1 (struct svc_req *, register SVCXPRT *); -extern int statd_get_socket(int port); +extern int statd_get_socket(void); #ifdef SIMULATIONS extern void simulator (int, char **); @@ -107,8 +107,7 @@ static void killer (int sig) { note (N_FATAL, "Caught signal %d, un-registering and exiting.", sig); - if (!(run_mode & MODE_NOTIFY_ONLY)) - pmap_unset (SM_PROG, SM_VERS); + pmap_unset (SM_PROG, SM_VERS); exit (0); } @@ -116,9 +115,10 @@ killer (int sig) static void sigusr (int sig) { + extern void my_svc_exit (void); dprintf (N_DEBUG, "Caught signal %d, re-notifying (state %d).", sig, MY_STATE); - re_notify = 1; + my_svc_exit(); } /* @@ -138,16 +138,7 @@ static void log_modes(void) if (run_mode & MODE_LOG_STDERR) strcat(buf,"Log-STDERR "); - if (run_mode & MODE_NOTIFY_ONLY) - { - strcat(buf,"Notify-Only "); - } note(N_WARNING,buf); - /* future: IP aliasing - if (run_mode & MODE_NOTIFY_ONLY) - { - dprintf(N_DEBUG,"Notify IP: %s",svr_addr); - } */ } /* @@ -223,6 +214,31 @@ static void drop_privs(void) } } +static void run_sm_notify(int outport) +{ + char op[20]; + char *av[6]; + int ac = 0; + + av[ac++] = "/usr/sbin/sm-notify"; + if (run_mode & MODE_NODAEMON) + av[ac++] = "-d"; + if (outport) { + sprintf(op, "-p%d", outport); + av[ac++] = op; + } + if (run_mode & STATIC_HOSTNAME) { + av[ac++] = "-N"; + 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); + +} /* * Entry routine/main loop. */ @@ -347,6 +363,10 @@ int main (int argc, char **argv) exit(-1); } + if (run_mode & MODE_NOTIFY_ONLY) + run_sm_notify(out_port); + + if (!(run_mode & MODE_NODAEMON)) { run_mode &= ~MODE_LOG_STDERR; /* Never log to console in daemon mode. */ @@ -435,24 +455,23 @@ int main (int argc, char **argv) */ signal(SIGPIPE, SIG_IGN); - /* initialize out_port */ - statd_get_socket(out_port); - create_pidfile(); atexit(truncate_pidfile); + + switch (pid = fork()) { + case 0: + run_sm_notify(out_port); + break; + case -1: + break; + default: + waitpid(pid, NULL, 0); + } + drop_privs(); for (;;) { - if (!(run_mode & MODE_NOTIFY_ONLY)) { - /* Do not do pmap_unset() when running in notify mode. - * We may clear the portmapper record for a statd not - * running in notify mode disabling it. - * Juan C. Gomez j_carlos_gomez@yahoo.com - */ - pmap_unset (SM_PROG, SM_VERS); - } - change_state (); - shuffle_dirs (); /* Move directory names around */ + pmap_unset (SM_PROG, SM_VERS); /* If we got this far, we have successfully started, so notify parent */ if (pipefds[1] > 0) { @@ -462,13 +481,8 @@ int main (int argc, char **argv) pipefds[1] = -1; } - notify_hosts (); /* Send out notify requests */ - ++restart; - /* this registers both UDP and TCP services */ - if (!(run_mode & MODE_NOTIFY_ONLY)) { - rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port); - } + rpc_init("statd", SM_PROG, SM_VERS, sm_prog_1, port); /* * Handle incoming requests: SM_NOTIFY socket requests, as @@ -476,8 +490,21 @@ int main (int argc, char **argv) */ my_svc_run(); /* I rolled my own, Olaf made it better... */ - if ((run_mode & MODE_NOTIFY_ONLY)) - break; + /* Only get here when simulating a crash so we should probably + * start sm-notify running again. As we have already dropped + * privileges, this might not work, but I don't think + * 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); + } } return 0; } diff --git a/utils/statd/statd.h b/utils/statd/statd.h index ace2ce5..13c80da 100644 --- a/utils/statd/statd.h +++ b/utils/statd/statd.h @@ -90,4 +90,3 @@ extern int run_mode; extern char *name_p; /* program basename */ extern const char *version_p; /* program version */ -extern int re_notify; /* time to re-read notify list */ diff --git a/utils/statd/state.c b/utils/statd/state.c deleted file mode 100644 index f46dae5..0000000 --- a/utils/statd/state.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 1995-1997, 1999 Jeffrey A. Uphoff - * Modified by Olaf Kirch, 1996. - * Modified by H.J. Lu, 1998. - * - * NSM for Linux. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include "statd.h" - - -/* - * Most NSM's keep the status number in an ASCII file. I'm keeping it - * as an int (4-byte binary) for now... - */ -void -change_state (void) -{ - int fd, size; - - if ((fd = open (SM_STAT_PATH, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) == -1) - die ("open (%s): %s", SM_STAT_PATH, strerror (errno)); - - if ((size = read (fd, &MY_STATE, sizeof MY_STATE)) == -1) - die ("read (%s): %s", SM_STAT_PATH, strerror (errno)); - - if (size != 0 && size != sizeof MY_STATE) { - note (N_ERROR, "Error in status file format...correcting."); - - if (close (fd) == -1) - die ("close (%s): %s", SM_STAT_PATH, strerror (errno)); - - if ((fd = creat (SM_STAT_PATH, S_IRUSR | S_IWUSR)) == -1) - die ("creat (%s): %s", SM_STAT_PATH, strerror (errno)); - } - note (N_DEBUG, "New state: %u", (++MY_STATE % 2) ? MY_STATE : ++MY_STATE); - - if (lseek (fd, 0, SEEK_SET) == -1) - die ("lseek (%s): %s", SM_STAT_PATH, strerror (errno)); - - if (write (fd, &MY_STATE, sizeof MY_STATE) != sizeof MY_STATE) - die ("write (%s): %s", SM_STAT_PATH, strerror (errno)); - - if (fsync (fd) == -1) - note (N_ERROR, "fsync (%s): %s", SM_STAT_PATH, strerror (errno)); - - if (close (fd) == -1) - note (N_ERROR, "close (%s): %s", SM_STAT_PATH, strerror (errno)); - - if (MY_NAME == NULL) { - char fullhost[SM_MAXSTRLEN + 1]; - struct hostent *hostinfo; - - if (gethostname (fullhost, SM_MAXSTRLEN) == -1) - die ("gethostname: %s", strerror (errno)); - - if ((hostinfo = gethostbyname (fullhost)) == NULL) - note (N_ERROR, "gethostbyname error for %s", fullhost); - else { - strncpy (fullhost, hostinfo->h_name, sizeof (fullhost) - 1); - fullhost[sizeof (fullhost) - 1] = '\0'; - } - - MY_NAME = xstrdup (fullhost); - } -} - - -/* - * Fairly traditional use of two directories for this. - */ -void -shuffle_dirs (void) -{ - DIR *nld; - struct dirent *de; - struct stat st; - char *src, *dst; - int len1, len2, len; - - if (stat (SM_DIR, &st) == -1 && errno != ENOENT) - die ("stat (%s): %s", SM_DIR, strerror (errno)); - - if (!S_ISDIR (st.st_mode)) - if (mkdir (SM_DIR, S_IRWXU) == -1) - die ("mkdir (%s): %s", SM_DIR, strerror (errno)); - - memset (&st, 0, sizeof st); - - if (stat (SM_BAK_DIR, &st) == -1 && errno != ENOENT) - die ("stat (%s): %s", SM_BAK_DIR, strerror (errno)); - - if (!S_ISDIR (st.st_mode)) - if (mkdir (SM_BAK_DIR, S_IRWXU) == -1) - die ("mkdir (%s): %s", SM_BAK_DIR, strerror (errno)); - - if (!(nld = opendir (SM_DIR))) - die ("opendir (%s): %s", SM_DIR, strerror (errno)); - - len1=strlen(SM_DIR); - len2=strlen(SM_BAK_DIR); - while ((de = readdir (nld))) { - if (de->d_name[0] == '.') - continue; - len=strlen(de->d_name); - src=xmalloc(len1+len+2); - dst=xmalloc(len2+len+2); - sprintf (src, "%s/%s", SM_DIR, de->d_name); - sprintf (dst, "%s/%s", SM_BAK_DIR, de->d_name); - if (rename (src, dst) == -1) - die ("rename (%s to %s): %s", SM_DIR, SM_BAK_DIR, strerror (errno)); - free(src); - free(dst); - } - if (closedir (nld) == -1) - note (N_ERROR, "closedir (%s): %s", SM_DIR, strerror (errno)); -} diff --git a/utils/statd/svc_run.c b/utils/statd/svc_run.c index 67bb05c..a33da0d 100644 --- a/utils/statd/svc_run.c +++ b/utils/statd/svc_run.c @@ -64,7 +64,6 @@ static int svc_stop = 0; * requests are put. */ notify_list * notify = NULL; -int re_notify = 0; /* * Jump-off function. @@ -91,13 +90,6 @@ my_svc_run(void) for (;;) { if (svc_stop) return; - if (re_notify) { - change_state(); - dprintf(N_DEBUG, "Notifying...(new state %d)", - MY_STATE); - notify_hosts(); - re_notify = 0; - } /* Ah, there are some notifications to be processed */ while (notify && NL_WHEN(notify) <= time(&now)) { @@ -114,9 +106,7 @@ my_svc_run(void) tv.tv_sec); selret = select(FD_SETSIZE, &readfds, (void *) 0, (void *) 0, &tv); - } else if (run_mode & MODE_NOTIFY_ONLY) - return; - else { + } else { dprintf(N_DEBUG, "Waiting for client connections."); selret = select(FD_SETSIZE, &readfds, (void *) 0, (void *) 0, (struct timeval *) 0);