summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--utils/statd/monitor.c18
-rw-r--r--utils/statd/sm-notify.c21
-rw-r--r--utils/statd/stat.c15
-rw-r--r--utils/statd/statd.c23
4 files changed, 68 insertions, 9 deletions
diff --git a/utils/statd/monitor.c b/utils/statd/monitor.c
index b95b0ad..bbc1dec 100644
--- a/utils/statd/monitor.c
+++ b/utils/statd/monitor.c
@@ -166,9 +166,7 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
mon_name, my_name);
/* But we'll let you pass anyway. */
- result.res_stat = STAT_SUCC;
- result.state = MY_STATE;
- return (&result);
+ goto success;
}
clnt = NL_NEXT(clnt);
}
@@ -222,10 +220,20 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
ha_callout("add-client", mon_name, my_name, -1);
nlist_insert(&rtnl, clnt);
close(fd);
-
+ dprintf(N_DEBUG, "MONITORING %s for %s", mon_name, my_name);
+ success:
result.res_stat = STAT_SUCC;
+ /* SUN's sm_inter.x says this should be "state number of local site".
+ * X/Open says '"state" will be contain the state of the remote NSM.'
+ * href=http://www.opengroup.org/onlinepubs/9629799/SM_MON.htm
+ * Linux lockd currently (2.6.21 and prior) ignores whatever is
+ * returned, and given the above contraction, it probably always will..
+ * So we just return what we always returned. If possible, we
+ * have already told lockd about our state number via a sysctl.
+ * If lockd wants the remote state, it will need to
+ * use SM_STAT (and prayer).
+ */
result.state = MY_STATE;
- dprintf(N_DEBUG, "MONITORING %s for %s", mon_name, my_name);
return (&result);
failure:
diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
index a94876d..bb6c2ef 100644
--- a/utils/statd/sm-notify.c
+++ b/utils/statd/sm-notify.c
@@ -88,6 +88,7 @@ static struct addrinfo *host_lookup(int, const char *);
void nsm_log(int fac, const char *fmt, ...);
static int record_pid();
static void drop_privs(void);
+static void set_kernel_nsm_state(int state);
static struct nsm_host * hosts = NULL;
@@ -166,6 +167,10 @@ usage: fprintf(stderr,
backup_hosts(_SM_DIR_PATH, _SM_BAK_PATH);
get_hosts(_SM_BAK_PATH);
+ /* Get and update the NSM state. This will call sync() */
+ nsm_state = nsm_get_state(opt_update_state);
+ set_kernel_nsm_state(nsm_state);
+
if (!opt_debug) {
if (!opt_quiet)
printf("Backgrounding to notify hosts...\n");
@@ -184,9 +189,6 @@ usage: fprintf(stderr,
close(2);
}
- /* Get and update the NSM state. This will call sync() */
- nsm_state = nsm_get_state(opt_update_state);
-
notify();
if (hosts) {
@@ -758,3 +760,16 @@ static void drop_privs(void)
exit(1);
}
}
+
+static void set_kernel_nsm_state(int state)
+{
+ int fd;
+
+ fd = open("/proc/sys/fs/nfs/nsm_local_state",O_WRONLY);
+ if (fd >= 0) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%d", state);
+ write(fd, buf, strlen(buf));
+ close(fd);
+ }
+}
diff --git a/utils/statd/stat.c b/utils/statd/stat.c
index bcd3550..799239f 100644
--- a/utils/statd/stat.c
+++ b/utils/statd/stat.c
@@ -21,6 +21,21 @@
* status." My implementation is operative; it returns 'STAT_SUCC'
* whenever it can resolve the hostname that it's being asked to
* monitor, and returns 'STAT_FAIL' otherwise.
+ *
+ * sm_inter.x says the 'state' returned should be
+ * "state number of site sm_name". It is not clear how to get this.
+ * X/Open says:
+ * STAT_SUCC
+ * The NSM will monitor the given host. "sm_stat_res.state" contains
+ * the state of the NSM.
+ * Which implies that 'state' is the state number of the *local* NSM.
+ * href=http://www.opengroup.org/onlinepubs/9629799/SM_STAT.htm
+ *
+ * We return the *local* state as
+ * 1/ We have easy access to it.
+ * 2/ It might be useful to a remote client who needs it and has no
+ * other way to get it.
+ * 3/ That's what we always did in the past.
*/
struct sm_stat_res *
sm_stat_1_svc (struct sm_name *argp, struct svc_req *rqstp)
diff --git a/utils/statd/statd.c b/utils/statd/statd.c
index 091ced9..8337b64 100644
--- a/utils/statd/statd.c
+++ b/utils/statd/statd.c
@@ -76,6 +76,7 @@ static struct option longopts[] =
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 **);
@@ -483,7 +484,7 @@ int main (int argc, char **argv)
* pass on any SM_NOTIFY that arrives
*/
load_state();
-
+ load_state_number();
pmap_unset (SM_PROG, SM_VERS);
/* this registers both UDP and TCP services */
@@ -526,3 +527,23 @@ int main (int argc, char **argv)
}
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);
+ }
+
+}