All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chuck Lever <chuck.lever@oracle.com>
To: steved@redhat.com
Cc: chris.mason@oracle.com, linux-nfs@vger.kernel.org
Subject: [PATCH 2/3] statd: Use the new nsm_ file.c calls in sm_notify
Date: Fri, 08 Jan 2010 13:13:41 -0500	[thread overview]
Message-ID: <20100108181341.452.24112.stgit@localhost.localdomain> (raw)
In-Reply-To: <20100108180144.452.14970.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

Replace open-coded accesses to on-disk NSM data with calls to the new
libnsm.a API.

One major change is that sync(2) is no longer called when the NSM
state number is updated at boot time.  Otherwise sm-notify should
behave much the same as it did before.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---

 utils/statd/sm-notify.c |  288 ++++++++++-------------------------------------
 1 files changed, 63 insertions(+), 225 deletions(-)

diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
index 0dba891..581234e 100644
--- a/utils/statd/sm-notify.c
+++ b/utils/statd/sm-notify.c
@@ -8,6 +8,7 @@
 #include <config.h>
 #endif
 
+#include <err.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -29,25 +30,9 @@
 #include <grp.h>
 
 #include "xlog.h"
+#include "nsm.h"
 #include "nfsrpc.h"
 
-#ifndef BASEDIR
-# ifdef NFS_STATEDIR
-#  define BASEDIR		NFS_STATEDIR
-# else
-#  define BASEDIR		"/var/lib/nfs"
-# endif
-#endif
-
-#define DEFAULT_SM_STATE_PATH	BASEDIR "/state"
-#define	DEFAULT_SM_DIR_PATH	BASEDIR "/sm"
-#define	DEFAULT_SM_BAK_PATH	DEFAULT_SM_DIR_PATH ".bak"
-
-char *_SM_BASE_PATH = BASEDIR;
-char *_SM_STATE_PATH = DEFAULT_SM_STATE_PATH;
-char *_SM_DIR_PATH = DEFAULT_SM_DIR_PATH;
-char *_SM_BAK_PATH = DEFAULT_SM_BAK_PATH;
-
 #define NSM_PROG	100024
 #define NSM_PROGRAM	100024
 #define NSM_VERSION	1
@@ -59,7 +44,6 @@ char *_SM_BAK_PATH = DEFAULT_SM_BAK_PATH;
 struct nsm_host {
 	struct nsm_host *	next;
 	char *			name;
-	char *			path;
 	struct sockaddr_storage	addr;
 	struct addrinfo		*ai;
 	time_t			last_used;
@@ -70,24 +54,19 @@ struct nsm_host {
 };
 
 static char		nsm_hostname[256];
-static uint32_t		nsm_state;
+static int		nsm_state;
 static int		opt_debug = 0;
-static int		opt_update_state = 1;
+static _Bool		opt_update_state = true;
 static unsigned int	opt_max_retry = 15 * 60;
 static char *		opt_srcaddr = 0;
 static uint16_t		opt_srcport = 0;
 
-static unsigned int	nsm_get_state(int);
 static void		notify(void);
 static int		notify_host(int, struct nsm_host *);
 static void		recv_reply(int);
-static void		backup_hosts(const char *, const char *);
-static void		get_hosts(const char *);
 static void		insert_host(struct nsm_host *);
 static struct nsm_host *find_host(uint32_t);
 static int		record_pid(void);
-static void		drop_privs(void);
-static void		set_kernel_nsm_state(int state);
 
 static struct nsm_host *	hosts = NULL;
 
@@ -111,10 +90,39 @@ static struct addrinfo *smn_lookup(const char *name)
 	return ai;
 }
 
+__attribute_malloc__
+static struct nsm_host *
+smn_alloc_host(const char *hostname, const time_t timestamp)
+{
+	struct nsm_host	*host;
+
+	host = calloc(1, sizeof(*host));
+	if (host == NULL)
+		goto out_nomem;
+
+	host->name = strdup(hostname);
+	if (host->name == NULL) {
+		free(host);
+		goto out_nomem;
+	}
+
+	host->last_used = timestamp;
+	host->timeout = NSM_TIMEOUT;
+	host->retries = 100;		/* force address retry */
+
+	return host;
+
+out_nomem:
+	xlog_warn("Unable to allocate memory");
+	return NULL;
+}
+
 static void smn_forget_host(struct nsm_host *host)
 {
-	unlink(host->path);
-	free(host->path);
+	xlog(D_CALL, "Removing %s from notify list", host->name);
+
+	nsm_delete_notified_host(host->name);
+
 	free(host->name);
 	if (host->ai)
 		freeaddrinfo(host->ai);
@@ -122,6 +130,23 @@ static void smn_forget_host(struct nsm_host *host)
 	free(host);
 }
 
+static unsigned int
+smn_get_host(const char *hostname,
+		__attribute__ ((unused)) const struct sockaddr *sap,
+		__attribute__ ((unused)) const struct mon *m,
+		const time_t timestamp)
+{
+	struct nsm_host	*host;
+
+	host = smn_alloc_host(hostname, timestamp);
+	if (host == NULL)
+		return 0;
+
+	insert_host(host);
+	xlog(D_GENERAL, "Added host %s to notify list", hostname);
+	return 1;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -147,7 +172,7 @@ main(int argc, char **argv)
 			opt_max_retry = atoi(optarg) * 60;
 			break;
 		case 'n':
-			opt_update_state = 0;
+			opt_update_state = false;
 			break;
 		case 'p':
 			opt_srcport = atoi(optarg);
@@ -156,20 +181,8 @@ main(int argc, char **argv)
 			opt_srcaddr = optarg;
 			break;
 		case 'P':
-			_SM_BASE_PATH = strdup(optarg);
-			_SM_STATE_PATH = malloc(strlen(optarg)+1+sizeof("state"));
-			_SM_DIR_PATH = malloc(strlen(optarg)+1+sizeof("sm"));
-			_SM_BAK_PATH = malloc(strlen(optarg)+1+sizeof("sm.bak"));
-			if (_SM_BASE_PATH == NULL ||
-			    _SM_STATE_PATH == NULL ||
-			    _SM_DIR_PATH == NULL ||
-			    _SM_BAK_PATH == NULL) {
-				fprintf(stderr, "unable to allocate memory");
+			if (!nsm_setup_pathnames(argv[0], optarg))
 				exit(1);
-			}
-			strcat(strcpy(_SM_STATE_PATH, _SM_BASE_PATH), "/state");
-			strcat(strcpy(_SM_DIR_PATH, _SM_BASE_PATH), "/sm");
-			strcat(strcpy(_SM_BAK_PATH, _SM_BASE_PATH), "/sm.bak");
 			break;
 
 		default:
@@ -195,8 +208,8 @@ usage:		fprintf(stderr,
 	xlog_open(progname);
 	xlog(L_NOTICE, "Version " VERSION " starting");
 
-	if (strcmp(_SM_BASE_PATH, BASEDIR) == 0) {
-		if (record_pid() == 0 && force == 0 && opt_update_state == 1) {
+	if (nsm_is_default_parentdir()) {
+		if (record_pid() == 0 && force == 0 && opt_update_state) {
 			/* already run, don't try again */
 			xlog(L_NOTICE, "Already notifying clients; Exiting!");
 			exit(0);
@@ -211,18 +224,16 @@ usage:		fprintf(stderr,
 		exit(1);
 	}
 
-	backup_hosts(_SM_DIR_PATH, _SM_BAK_PATH);
-	get_hosts(_SM_BAK_PATH);
-
-	/* If there are not hosts to notify, just exit */
-	if (!hosts) {
+	(void)nsm_retire_monitored_hosts();
+	if (nsm_load_notify_list(smn_get_host) == 0) {
 		xlog(D_GENERAL, "No hosts to notify; exiting");
 		return 0;
 	}
 
-	/* 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 (nsm_state == 0)
+		exit(1);
+	nsm_update_kernel_state(nsm_state);
 
 	if (!opt_debug) {
 		xlog(L_NOTICE, "Backgrounding to notify hosts...\n");
@@ -316,7 +327,8 @@ notify(void)
 	if (opt_max_retry)
 		failtime = time(NULL) + opt_max_retry;
 
-	drop_privs();
+	if (!nsm_drop_privileges(-1))
+		exit(1);
 
 	while (hosts) {
 		struct pollfd	pfd;
@@ -554,82 +566,6 @@ fail:	/* Re-insert the host */
 }
 
 /*
- * Back up all hosts from the sm directory to sm.bak
- */
-static void
-backup_hosts(const char *dirname, const char *bakname)
-{
-	struct dirent	*de;
-	DIR		*dir;
-
-	if (!(dir = opendir(dirname))) {
-		xlog_warn("Failed to open %s: %m", dirname);
-		return;
-	}
-
-	while ((de = readdir(dir)) != NULL) {
-		char	src[1024], dst[1024];
-
-		if (de->d_name[0] == '.')
-			continue;
-
-		snprintf(src, sizeof(src), "%s/%s", dirname, de->d_name);
-		snprintf(dst, sizeof(dst), "%s/%s", bakname, de->d_name);
-		if (rename(src, dst) < 0)
-			xlog_warn("Failed to rename %s -> %s: %m", src, dst);
-	}
-	closedir(dir);
-}
-
-/*
- * Get all entries from sm.bak and convert them to host entries
- */
-static void
-get_hosts(const char *dirname)
-{
-	struct nsm_host	*host;
-	struct dirent	*de;
-	DIR		*dir;
-
-	if (!(dir = opendir(dirname))) {
-		xlog_warn("Failed to open %s: %m", dirname);
-		return;
-	}
-
-	host = NULL;
-	while ((de = readdir(dir)) != NULL) {
-		struct stat	stb;
-		char		path[1024];
-
-		if (de->d_name[0] == '.')
-			continue;
-		if (host == NULL)
-			host = calloc(1, sizeof(*host));
-		if (host == NULL) {
-			xlog_warn("Unable to allocate memory");
-			return;
-		}
-
-		snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name);
-		if (stat(path, &stb) < 0)
-			continue;
-
-		host->last_used = stb.st_mtime;
-		host->timeout = NSM_TIMEOUT;
-		host->path = strdup(path);
-		host->name = strdup(de->d_name);
-		host->retries = 100; /* force address retry */
-
-		insert_host(host);
-		host = NULL;
-	}
-	closedir(dir);
-
-	if (host)
-		free(host);
-}
-
-/*
  * Insert host into sorted list
  */
 static void
@@ -676,60 +612,6 @@ find_host(uint32_t xid)
 	return NULL;
 }
 
-
-/*
- * Retrieve the current NSM state
- */
-static unsigned int
-nsm_get_state(int update)
-{
-	char		newfile[PATH_MAX];
-	int		fd, state;
-
-	if ((fd = open(_SM_STATE_PATH, O_RDONLY)) < 0) {
-		xlog_warn("%s: %m", _SM_STATE_PATH);
-		xlog_warn("Creating %s, set initial state 1",
-			_SM_STATE_PATH);
-		state = 1;
-		update = 1;
-	} else {
-		if (read(fd, &state, sizeof(state)) != sizeof(state)) {
-			xlog_warn("%s: bad file size, setting state = 1",
-				_SM_STATE_PATH);
-			state = 1;
-			update = 1;
-		} else {
-			if (!(state & 1))
-				state += 1;
-		}
-		close(fd);
-	}
-
-	if (update) {
-		state += 2;
-		snprintf(newfile, sizeof(newfile),
-				"%s.new", _SM_STATE_PATH);
-		if ((fd = open(newfile, O_CREAT|O_WRONLY, 0644)) < 0) {
-			xlog(L_ERROR, "Cannot create %s: %m", newfile);
-			exit(1);
-		}
-		if (write(fd, &state, sizeof(state)) != sizeof(state)) {
-			xlog(L_ERROR,
-				"Failed to write state to %s", newfile);
-			exit(1);
-		}
-		close(fd);
-		if (rename(newfile, _SM_STATE_PATH) < 0) {
-			xlog(L_ERROR,
-				"Cannot create %s: %m", _SM_STATE_PATH);
-			exit(1);
-		}
-		sync();
-	}
-
-	return state;
-}
-
 /*
  * Record pid in /var/run/sm-notify.pid
  * This file should remain until a reboot, even if the
@@ -756,47 +638,3 @@ static int record_pid(void)
 	(void)close(fd);
 	return 1;
 }
-
-/* Drop privileges to match owner of state-directory
- * (in case a reply triggers some unknown bug).
- */
-static void drop_privs(void)
-{
-	struct stat st;
-
-	if (stat(_SM_DIR_PATH, &st) == -1 &&
-	    stat(_SM_BASE_PATH, &st) == -1) {
-		st.st_uid = 0;
-		st.st_gid = 0;
-	}
-
-	if (st.st_uid == 0) {
-		xlog_warn("Running as 'root'.  "
-			"chown %s to choose different user", _SM_DIR_PATH);
-		return;
-	}
-
-	setgroups(0, NULL);
-	if (setgid(st.st_gid) == -1
-	    || setuid(st.st_uid) == -1) {
-		xlog(L_ERROR, "Fail to drop privileges");
-		exit(1);
-	}
-}
-
-static void set_kernel_nsm_state(int state)
-{
-	int fd;
-	const char *file = "/proc/sys/fs/nfs/nsm_local_state";
-
-	fd = open(file ,O_WRONLY);
-	if (fd >= 0) {
-		char buf[20];
-		snprintf(buf, sizeof(buf), "%d", state);
-		if (write(fd, buf, strlen(buf)) != strlen(buf)) {
-			xlog_warn("Writing to '%s' failed: errno %d (%m)",
-				file, errno);
-		}
-		close(fd);
-	}
-}


  parent reply	other threads:[~2010-01-08 18:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-08 18:13 [PATCH 0/3] Create shared API to access on-disk NSM data Chuck Lever
     [not found] ` <20100108180144.452.14970.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2010-01-08 18:13   ` [PATCH 1/3] libnsm.a: Introduce common routines to handle persistent storage Chuck Lever
2010-01-08 18:13   ` Chuck Lever [this message]
2010-01-08 18:13   ` [PATCH 3/3] statd: Use the new nsm_ file.c calls in rpc.statd Chuck Lever
2010-01-12 12:25   ` [PATCH 0/3] Create shared API to access on-disk NSM data Steve Dickson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100108181341.452.24112.stgit@localhost.localdomain \
    --to=chuck.lever@oracle.com \
    --cc=chris.mason@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=steved@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.