Prevent sm-notify from being run multiple times per reboot.
authorNeil Brown <neilb@suse.de>
Mon, 19 Mar 2007 22:50:33 +0000 (09:50 +1100)
committerNeil Brown <neilb@suse.de>
Mon, 19 Mar 2007 22:50:33 +0000 (09:50 +1100)
As "mount.nfs" can start statd, and as statd can start sm-notify,
the risk of sm-notify being run multiple times increases.
As this is not normally appropriate, sm-notify now creates a
file in /var/run which will stop future instances from being
run (though ofcourse this behaviour can be controlled by a
new command line option).

utils/statd/sm-notify.8
utils/statd/sm-notify.c

index 314e2c4..a1c10c3 100644 (file)
@@ -6,7 +6,7 @@
 .SH NAME
 sm-notify \- Send out NSM reboot notifications
 .SH SYNOPSIS
-.BI "/sbin/sm-notify [-d] [-q] [-m " time "] [-p " port "] [-P " path "] [-v " my_name " ]
+.BI "/sbin/sm-notify [-dfq] [-m " time "] [-p " port "] [-P " path "] [-v " my_name " ]
 .SH DESCRIPTION
 File locking over NFS (v2 and v3) requires a facility to notify peers in
 case of a reboot, so that clients can reclaim locks after
@@ -101,8 +101,31 @@ and the file
 .B state
 must exist in that directory with the standard names.
 .TP
+.B -f
+If the state path has not been reset with
+.BR -P ,
+.B sm-notify
+will normally create a file in
+.B /var/run
+to indicate that it has been
+run.  If this file is found when
+.B sm-notify
+starts, it will not run again (as it is normally only needed once per
+reboot).
+If
+.B -f
+(for
+.BR force )
+is given,
+.B sm-notify
+will run even if the file in
+.B /var/run
+is present.
+.TP
 .B -n
-Do not update the NSM state. This is for testing only.
+Do not update the NSM state. This is for testing only.  Setting this
+flag implies
+.BR -f .
 .TP
 .B -d
 Enables debugging.
@@ -117,6 +140,8 @@ list of hosts from
 .BR /var/lib/nfs/sm/*
 .br
 .BR /var/lib/nfs/sm.bak/*
+.br
+.BR /var/run/sm-notify.pid
 .SH SEE ALSO
 .BR rpc.nfsd(8),
 .BR portmap(8)
index aa2c7d1..0090137 100644 (file)
@@ -80,6 +80,7 @@ static int            addr_get_port(nsm_address *);
 static void            addr_set_port(nsm_address *, int);
 static int             host_lookup(int, const char *, nsm_address *);
 void                   nsm_log(int fac, const char *fmt, ...);
+static int             record_pid();
 
 static struct nsm_host *       hosts = NULL;
 
@@ -87,9 +88,13 @@ int
 main(int argc, char **argv)
 {
        int     c;
+       int     force = 0;
 
-       while ((c = getopt(argc, argv, "dm:np:v:qP:")) != -1) {
+       while ((c = getopt(argc, argv, "dm:np:v:qP:f")) != -1) {
                switch (c) {
+               case 'f':
+                       force = 1;
+                       break;
                case 'd':
                        opt_debug++;
                        break;
@@ -131,10 +136,18 @@ main(int argc, char **argv)
        }
 
        if (optind < argc) {
-usage:         fprintf(stderr, "sm-notify [-d]\n");
+usage:         fprintf(stderr,
+                       "Usage: sm-notify [-dfq] [-m max-retry-minutes] [-p srcport]\n"
+                       "            [-P /path/to/state/directory] [-N my_host_name\n");
                return 1;
        }
 
+       if (strcmp(_SM_BASE_PATH, BASEDIR) == 0) {
+               if (record_pid() == 0 && force == 0 && opt_update_state == 0)
+                       /* already run, don't try again */
+                       exit(0);
+       }
+
        if (opt_srcaddr) {
                strncpy(nsm_hostname, opt_srcaddr, sizeof(nsm_hostname)-1);
        } else
@@ -678,3 +691,23 @@ nsm_log(int fac, const char *fmt, ...)
        }
        va_end(ap);
 }
+
+/*
+ * Record pid in /var/run/sm-notify.pid
+ * This file should remain until a reboot, even if the
+ * program exits.
+ * If file already exists, fail.
+ */
+static int record_pid()
+{
+       char pid[20];
+       int fd;
+
+       snprintf(pid, 20, "%d\n", getpid());
+       fd = open("/var/run/sm-notify.pid", O_CREAT|O_EXCL|O_WRONLY, 0600);
+       if (!fd)
+               return 0;
+       write(fd, pid, strlen(pid));
+       close(fd);
+       return 1;
+}