autofs-5.1.8 - eliminate last remaining state_pipe usage

From: Ian Kent <raven@themaw.net>

Eliminate the last remaining usage autofs mount struct state_pipe that
is used when changing state to ST_SHUTDOWN at submount exit. Ths single
usage consumes a pipe file handle pair for every autofs file system
mount.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG           |    1 +
 daemon/automount.c  |   78 ++++++++++++++++++++-------------------------------
 daemon/direct.c     |    2 -
 daemon/indirect.c   |    7 -----
 daemon/master.c     |   21 ++------------
 daemon/state.c      |   16 +++-------
 include/automount.h |    1 -
 include/state.h     |    1 -
 8 files changed, 40 insertions(+), 87 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 087dff58..76dfb34a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -63,6 +63,7 @@
 - make amd mapent search function name clear.
 - rename statemachine() to signal_handler().
 - make signal handling consistent.
+- eliminate last remaining state_pipe usage.
 
 19/10/2021 autofs-5.1.8
 - add xdr_exports().
diff --git a/daemon/automount.c b/daemon/automount.c
index 624d3349..840c178a 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1078,58 +1078,51 @@ static int set_log_priority(const char *path, int priority)
 	return 0;
 }
 
+static void dummy(int sig)
+{
+}
+
 static int get_pkt(struct autofs_point *ap, union autofs_v5_packet_union *pkt)
 {
-	struct pollfd fds[3];
-	int pollfds = 3;
+	struct sigaction sa;
+	sigset_t signalset;
+	struct pollfd fds[2];
+	int pollfds = 2;
 	char buf[MAX_ERR_BUF];
 	size_t read;
 	char *estr;
 
 	fds[0].fd = ap->pipefd;
 	fds[0].events = POLLIN;
-	fds[1].fd = ap->state_pipe[0];
+	fds[1].fd = ap->logpri_fifo;
 	fds[1].events = POLLIN;
-	fds[2].fd = ap->logpri_fifo;
-	fds[2].events = POLLIN;
-	if (fds[2].fd  == -1)
+	if (fds[1].fd  == -1)
 		pollfds--;
 
-	for (;;) {
-		if (poll(fds, pollfds, -1) == -1) {
-			if (errno == EINTR)
-				continue;
-			estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			logerr("poll failed: %s", estr);
-			return -1;
-		}
-
-		if (fds[1].revents & POLLIN) {
-			enum states next_state;
-			size_t read_size = sizeof(next_state);
-			int state_pipe;
+	sa.sa_handler = dummy;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	if (sigaction(SIGCONT, &sa, NULL) == -1)
+		error(LOGOPT_ANY, "failed to set signal handler %d", errno);
 
-			next_state = ST_INVAL;
-
-			st_mutex_lock();
-
-			state_pipe = ap->state_pipe[0];
+	sigfillset(&signalset);
+	sigdelset(&signalset, SIGCONT);
 
-			read = fullread(state_pipe, &next_state, read_size);
-			if (read) {
-				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				error(ap->logopt,
-				      "read error on state pipe, "
-				      "read %lu, error %s",
-				      read, estr);
+	for (;;) {
+		errno = 0;
+		if (ppoll(fds, pollfds, NULL, &signalset) == -1) {
+			if (errno == EINTR) {
+				st_mutex_lock();
+				if (ap->state == ST_SHUTDOWN) {
+					st_mutex_unlock();
+					return -1;
+				}
 				st_mutex_unlock();
 				continue;
 			}
-
-			st_mutex_unlock();
-
-			if (next_state == ST_SHUTDOWN)
-				return -1;
+			estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			logerr("poll failed: %s", estr);
+			return -1;
 		}
 
 		if (fds[0].revents & POLLIN) {
@@ -1144,9 +1137,9 @@ static int get_pkt(struct autofs_point *ap, union autofs_v5_packet_union *pkt)
 			return read;
 		}
 
-		if (fds[2].fd != -1 && fds[2].revents & POLLIN) {
+		if (fds[1].fd != -1 && fds[1].revents & POLLIN) {
 			debug(ap->logopt, "message pending on control fifo.");
-			handle_fifo_message(ap, fds[2].fd);
+			handle_fifo_message(ap, fds[1].fd);
 		}
 	}
 }
@@ -1209,15 +1202,6 @@ static int autofs_init_ap(struct autofs_point *ap)
 	ap->pipefd = pipefd[0];
 	ap->kpipefd = pipefd[1];
 
-	/* Pipe state changes from signal handler to main loop */
-	if (open_pipe(ap->state_pipe) < 0) {
-		crit(ap->logopt,
-		     "failed create state pipe for autofs path %s", ap->path);
-		close(ap->pipefd);
-		close(ap->kpipefd);	/* Close kernel pipe end */
-		return -1;
-	}
-
 	if (create_logpri_fifo(ap) < 0) {
 		logmsg("could not create FIFO for path %s\n", ap->path);
 		logmsg("dynamic log level changes not available for %s", ap->path);
diff --git a/daemon/direct.c b/daemon/direct.c
index 316ffd78..2a199af4 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -263,8 +263,6 @@ done:
 	}
 	pthread_cleanup_pop(1);
 
-	close(ap->state_pipe[0]);
-	close(ap->state_pipe[1]);
 	if (ap->pipefd >= 0)
 		close(ap->pipefd);
 	if (ap->kpipefd >= 0) {
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 4534907d..47d866eb 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -152,8 +152,6 @@ out_rmdir:
 out_err:
 	if (options)
 		free(options);
-	close(ap->state_pipe[0]);
-	close(ap->state_pipe[1]);
 	close(ap->pipefd);
 	close(ap->kpipefd);
 
@@ -216,11 +214,6 @@ void close_mount_fds(struct autofs_point *ap)
 	if (ap->submount)
 		lookup_source_close_ioctlfd(ap->parent, ap->path);
 
-	close(ap->state_pipe[0]);
-	close(ap->state_pipe[1]);
-	ap->state_pipe[0] = -1;
-	ap->state_pipe[1] = -1;
-
 	if (ap->pipefd >= 0)
 		close(ap->pipefd);
 
diff --git a/daemon/master.c b/daemon/master.c
index cb4fcb7e..284c5596 100644
--- a/daemon/master.c
+++ b/daemon/master.c
@@ -113,8 +113,6 @@ int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
 
 	ap->state = ST_INIT;
 
-	ap->state_pipe[0] = -1;
-	ap->state_pipe[1] = -1;
 	ap->logpri_fifo = -1;
 
 	ap->path = strdup(entry->path);
@@ -1399,7 +1397,7 @@ static int master_do_mount(struct master_mapent *entry)
 		handle_mounts_startup_cond_destroy(&suc);
 		return 0;
 	}
-	entry->thid = thid;
+	entry->thid = ap->thid = thid;
 
 	handle_mounts_startup_cond_destroy(&suc);
 
@@ -1483,9 +1481,6 @@ int master_mount_mounts(struct master *master, time_t age)
 		struct master_mapent *this;
 		struct autofs_point *ap;
 		struct mapent *ne, *nested;
-		struct stat st;
-		int state_pipe, save_errno;
-		int ret;
 
 		this = list_entry(p, struct master_mapent, list);
 		p = p->next;
@@ -1541,19 +1536,9 @@ int master_mount_mounts(struct master *master, time_t age)
 		}
 		cache_unlock(nc);
 cont:
-		st_mutex_lock();
-
-		state_pipe = this->ap->state_pipe[1];
-
-		/* No pipe so mount is needed */
-		ret = fstat(state_pipe, &st);
-		save_errno = errno;
-
-		st_mutex_unlock();
-
-		if (!ret)
+		if (ap->thid && is_mounted(this->path, MNTS_AUTOFS))
 			check_update_map_sources(this, master->readall);
-		else if (ret == -1 && save_errno == EBADF) {
+		else {
 			if (!master_do_mount(this)) {
 				list_del_init(&this->list);
 				master_free_mapent_sources(ap->entry, 1);
diff --git a/daemon/state.c b/daemon/state.c
index 28ad68ca..9912ffec 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -52,16 +52,6 @@ void st_mutex_unlock(void)
 		fatal(status);
 }
 
-void nextstate(int statefd, enum states next)
-{
-	char buf[MAX_ERR_BUF];
-
-	if (write(statefd, &next, sizeof(next)) != sizeof(next)) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		logerr("write failed %s", estr);
-	}
-}
-
 /*
  * Handle expire thread cleanup and return the next state the system
  * should enter as a result.
@@ -631,12 +621,16 @@ static unsigned int st_force_shutdown(struct autofs_point *ap)
 
 static unsigned int st_shutdown(struct autofs_point *ap)
 {
+	int ret;
+
 	debug(ap->logopt, "state %d path %s", ap->state, ap->path);
 
 	assert(ap->state == ST_SHUTDOWN_PENDING || ap->state == ST_SHUTDOWN_FORCE);
 
 	ap->state = ST_SHUTDOWN;
-	nextstate(ap->state_pipe[1], ST_SHUTDOWN);
+	ret = pthread_kill(ap->thid, SIGCONT);
+	if (ret)
+		error(LOGOPT_ANY, "error %d sending shutdown signal", ret);
 
 	return 0;
 }
diff --git a/include/automount.h b/include/automount.h
index 9387ad1b..404777a2 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -570,7 +570,6 @@ struct autofs_point {
 	pthread_t exp_thread;		/* Thread that is expiring */
 	pthread_t readmap_thread;	/* Thread that is reading maps */
 	enum states state;		/* Current state */
-	int state_pipe[2];		/* State change router pipe */
 	struct autofs_point *parent;	/* Owner of mounts list for submount */
 	struct list_head mounts;	/* List of autofs mounts at current level */
 	unsigned int submount;		/* Is this a submount */
diff --git a/include/state.h b/include/state.h
index 98f27d3f..fbb21cac 100644
--- a/include/state.h
+++ b/include/state.h
@@ -86,7 +86,6 @@ void st_mutex_unlock(void);
 
 void expire_cleanup(void *);
 void expire_proc_cleanup(void *);
-void nextstate(int, enum states);
 
 int st_add_task(struct autofs_point *, enum states);
 int __st_add_task(struct autofs_point *, enum states);