All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.de>
To: Steve Dickson <steved@redhat.com>
Cc: linux-nfs@vger.kernel.org,
	Trond Myklebust <trond.myklebust@hammerspace.com>
Subject: [PATCH 4/6] Move fork_workers() and wait_for_workers() in cache.c
Date: Mon, 23 Oct 2023 12:58:34 +1100	[thread overview]
Message-ID: <20231023021052.5258-5-neilb@suse.de> (raw)
In-Reply-To: <20231023021052.5258-1-neilb@suse.de>

Both mountd and exported have fork_workers() and wait_for_workers()
which are nearly identical.
Move this code into cache.c (adding a cache_ prefix to the function
names) and leave the minor differences in the two callers.

Also remove duplicate declarations from mountd.h.

Signed-off-by: NeilBrown <neilb@suse.de>
---
 support/export/cache.c  | 75 ++++++++++++++++++++++++++++++++-
 support/export/export.h |  2 +
 utils/exportd/exportd.c | 90 ++++++----------------------------------
 utils/mountd/mountd.c   | 91 ++++++-----------------------------------
 utils/mountd/mountd.h   |  9 ----
 5 files changed, 99 insertions(+), 168 deletions(-)

diff --git a/support/export/cache.c b/support/export/cache.c
index 5307f6c8d872..1874156af5e5 100644
--- a/support/export/cache.c
+++ b/support/export/cache.c
@@ -1,10 +1,9 @@
-
 /*
  * Handle communication with knfsd internal cache
  *
  * We open /proc/net/rpc/{auth.unix.ip,nfsd.export,nfsd.fh}/channel
  * and listen for requests (using my_svc_run)
- * 
+ *
  */
 
 #ifdef HAVE_CONFIG_H
@@ -16,6 +15,7 @@
 #include <sys/select.h>
 #include <sys/stat.h>
 #include <sys/vfs.h>
+#include <sys/wait.h>
 #include <time.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -1775,3 +1775,74 @@ cache_get_filehandle(nfs_export *exp, int len, char *p)
 	fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE);
 	return &fh;
 }
+
+/* Wait for all worker child processes to exit and reap them */
+void
+cache_wait_for_workers(char *prog)
+{
+	int status;
+	pid_t pid;
+
+	for (;;) {
+
+		pid = waitpid(0, &status, 0);
+
+		if (pid < 0) {
+			if (errno == ECHILD)
+				return; /* no more children */
+			xlog(L_FATAL, "%s: can't wait: %s\n", prog,
+					strerror(errno));
+		}
+
+		/* Note: because we SIG_IGN'd SIGCHLD earlier, this
+		 * does not happen on 2.6 kernels, and waitpid() blocks
+		 * until all the children are dead then returns with
+		 * -ECHILD.  But, we don't need to do anything on the
+		 * death of individual workers, so we don't care. */
+		xlog(L_NOTICE, "%s: reaped child %d, status %d\n",
+		     prog, (int)pid, status);
+	}
+}
+
+/* Fork num_threads worker children and wait for them */
+int
+cache_fork_workers(char *prog, int num_threads)
+{
+	int i;
+	pid_t pid;
+
+	if (num_threads <= 1)
+		return 1;
+
+	xlog(L_NOTICE, "%s: starting %d threads\n", prog, num_threads);
+
+	for (i = 0 ; i < num_threads ; i++) {
+		pid = fork();
+		if (pid < 0) {
+			xlog(L_FATAL, "%s: cannot fork: %s\n", prog,
+					strerror(errno));
+		}
+		if (pid == 0) {
+			/* worker child */
+
+			/* Re-enable the default action on SIGTERM et al
+			 * so that workers die naturally when sent them.
+			 * Only the parent unregisters with pmap and
+			 * hence needs to do special SIGTERM handling. */
+			struct sigaction sa;
+			sa.sa_handler = SIG_DFL;
+			sa.sa_flags = 0;
+			sigemptyset(&sa.sa_mask);
+			sigaction(SIGHUP, &sa, NULL);
+			sigaction(SIGINT, &sa, NULL);
+			sigaction(SIGTERM, &sa, NULL);
+
+			/* fall into my_svc_run in caller */
+			return 1;
+		}
+	}
+
+	/* in parent */
+	cache_wait_for_workers(prog);
+	return 0;
+}
diff --git a/support/export/export.h b/support/export/export.h
index 8d5a0d3004ef..ce561f9fbd3e 100644
--- a/support/export/export.h
+++ b/support/export/export.h
@@ -29,6 +29,8 @@ int		v4clients_process(fd_set *fdset);
 struct nfs_fh_len *
 		cache_get_filehandle(nfs_export *exp, int len, char *p);
 int		cache_export(nfs_export *exp, char *path);
+int		cache_fork_workers(char *prog, int num_threads);
+void		cache_wait_for_workers(char *prog);
 
 bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai);
 bool namelist_client_matches(nfs_export *exp, char *dom);
diff --git a/utils/exportd/exportd.c b/utils/exportd/exportd.c
index 6f866445efc2..d07a885c6763 100644
--- a/utils/exportd/exportd.c
+++ b/utils/exportd/exportd.c
@@ -16,7 +16,6 @@
 #include <string.h>
 #include <getopt.h>
 #include <errno.h>
-#include <wait.h>
 
 #include "nfslib.h"
 #include "conffile.h"
@@ -54,90 +53,19 @@ static char shortopts[] = "d:fghs:t:liT:";
  */
 inline static void set_signals(void);
 
-/* Wait for all worker child processes to exit and reap them */
-static void
-wait_for_workers (void)
-{
-	int status;
-	pid_t pid;
-
-	for (;;) {
-
-		pid = waitpid(0, &status, 0);
-
-		if (pid < 0) {
-			if (errno == ECHILD)
-				return; /* no more children */
-			xlog(L_FATAL, "mountd: can't wait: %s\n",
-					strerror(errno));
-		}
-
-		/* Note: because we SIG_IGN'd SIGCHLD earlier, this
-		 * does not happen on 2.6 kernels, and waitpid() blocks
-		 * until all the children are dead then returns with
-		 * -ECHILD.  But, we don't need to do anything on the
-		 * death of individual workers, so we don't care. */
-		xlog(L_NOTICE, "mountd: reaped child %d, status %d\n",
-				(int)pid, status);
-	}
-}
-
 inline void
 cleanup_lockfiles (void)
 {
 	unlink(etab.lockfn);
 }
 
-/* Fork num_threads worker children and wait for them */
 static void
-fork_workers(void)
-{
-	int i;
-	pid_t pid;
-
-	xlog(L_NOTICE, "mountd: starting %d threads\n", num_threads);
-
-	for (i = 0 ; i < num_threads ; i++) {
-		pid = fork();
-		if (pid < 0) {
-			xlog(L_FATAL, "mountd: cannot fork: %s\n",
-					strerror(errno));
-		}
-		if (pid == 0) {
-			/* worker child */
-
-			/* Re-enable the default action on SIGTERM et al
-			 * so that workers die naturally when sent them.
-			 * Only the parent unregisters with pmap and
-			 * hence needs to do special SIGTERM handling. */
-			struct sigaction sa;
-			sa.sa_handler = SIG_DFL;
-			sa.sa_flags = 0;
-			sigemptyset(&sa.sa_mask);
-			sigaction(SIGHUP, &sa, NULL);
-			sigaction(SIGINT, &sa, NULL);
-			sigaction(SIGTERM, &sa, NULL);
-
-			/* fall into my_svc_run in caller */
-			return;
-		}
-	}
-
-	/* in parent */
-	wait_for_workers();
-	cleanup_lockfiles();
-	free_state_path_names(&etab);
-	xlog(L_NOTICE, "exportd: no more workers, exiting\n");
-	exit(0);
-}
-
-static void 
 killer (int sig)
 {
 	if (num_threads > 1) {
 		/* play Kronos and eat our children */
 		kill(0, SIGTERM);
-		wait_for_workers();
+		cache_wait_for_workers("exportd");
 	}
 	cleanup_lockfiles();
 	free_state_path_names(&etab);
@@ -145,6 +73,7 @@ killer (int sig)
 
 	exit(0);
 }
+
 static void
 sig_hup (int UNUSED(sig))
 {
@@ -152,8 +81,9 @@ sig_hup (int UNUSED(sig))
 	xlog (L_NOTICE, "Received SIGHUP... Ignoring.\n");
 	return;
 }
-inline static void 
-set_signals(void) 
+
+inline static void
+set_signals(void)
 {
 	struct sigaction sa;
 
@@ -295,9 +225,13 @@ main(int argc, char **argv)
 	 */
 	cache_open();
 
-	if (num_threads > 1)
-		fork_workers();
-
+	if (cache_fork_workers(progname, num_threads) == 0) {
+		/* We forked, waited, and now need to clean up */
+		cleanup_lockfiles();
+		free_state_path_names(&etab);
+		xlog(L_NOTICE, "%s: no more workers, exiting\n", progname);
+		exit(0);
+	}
 
 	v4clients_init();
 
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
index f9c62cded66c..dbd5546df61c 100644
--- a/utils/mountd/mountd.c
+++ b/utils/mountd/mountd.c
@@ -21,7 +21,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/resource.h>
-#include <sys/wait.h>
 
 #include "conffile.h"
 #include "xmalloc.h"
@@ -119,90 +118,17 @@ cleanup_lockfiles (void)
 	unlink(rmtab.lockfn);
 }
 
-/* Wait for all worker child processes to exit and reap them */
-static void
-wait_for_workers (void)
-{
-	int status;
-	pid_t pid;
-
-	for (;;) {
-
-		pid = waitpid(0, &status, 0);
-
-		if (pid < 0) {
-			if (errno == ECHILD)
-				return; /* no more children */
-			xlog(L_FATAL, "mountd: can't wait: %s\n",
-					strerror(errno));
-		}
-
-		/* Note: because we SIG_IGN'd SIGCHLD earlier, this
-		 * does not happen on 2.6 kernels, and waitpid() blocks
-		 * until all the children are dead then returns with
-		 * -ECHILD.  But, we don't need to do anything on the
-		 * death of individual workers, so we don't care. */
-		xlog(L_NOTICE, "mountd: reaped child %d, status %d\n",
-				(int)pid, status);
-	}
-}
-
-/* Fork num_threads worker children and wait for them */
-static void
-fork_workers(void)
-{
-	int i;
-	pid_t pid;
-
-	xlog(L_NOTICE, "mountd: starting %d threads\n", num_threads);
-
-	for (i = 0 ; i < num_threads ; i++) {
-		pid = fork();
-		if (pid < 0) {
-			xlog(L_FATAL, "mountd: cannot fork: %s\n",
-					strerror(errno));
-		}
-		if (pid == 0) {
-			/* worker child */
-
-			/* Re-enable the default action on SIGTERM et al
-			 * so that workers die naturally when sent them.
-			 * Only the parent unregisters with pmap and
-			 * hence needs to do special SIGTERM handling. */
-			struct sigaction sa;
-			sa.sa_handler = SIG_DFL;
-			sa.sa_flags = 0;
-			sigemptyset(&sa.sa_mask);
-			sigaction(SIGHUP, &sa, NULL);
-			sigaction(SIGINT, &sa, NULL);
-			sigaction(SIGTERM, &sa, NULL);
-
-			/* fall into my_svc_run in caller */
-			return;
-		}
-	}
-
-	/* in parent */
-	wait_for_workers();
-	unregister_services();
-	cleanup_lockfiles();
-	free_state_path_names(&etab);
-	free_state_path_names(&rmtab);
-	xlog(L_NOTICE, "mountd: no more workers, exiting\n");
-	exit(0);
-}
-
 /*
  * Signal handler.
  */
-static void 
+static void
 killer (int sig)
 {
 	unregister_services();
 	if (num_threads > 1) {
 		/* play Kronos and eat our children */
 		kill(0, SIGTERM);
-		wait_for_workers();
+		cache_wait_for_workers("mountd");
 	}
 	cleanup_lockfiles();
 	free_state_path_names(&etab);
@@ -220,7 +146,7 @@ sig_hup (int UNUSED(sig))
 }
 
 bool_t
-mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp), 
+mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp),
 	void *UNUSED(resp))
 {
 	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
@@ -922,8 +848,15 @@ main(int argc, char **argv)
 	 */
 	cache_open();
 
-	if (num_threads > 1)
-		fork_workers();
+	if (cache_fork_workers("mountd", num_threads) == 0) {
+		/* We forked, waited, and now need to clean up */
+		unregister_services();
+		cleanup_lockfiles();
+		free_state_path_names(&etab);
+		free_state_path_names(&rmtab);
+		xlog(L_NOTICE, "mountd: no more workers, exiting\n");
+		exit(0);
+	}
 
 	nfsd_path_init();
 	v4clients_init();
diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h
index d30775313f66..bd5c9576d8ad 100644
--- a/utils/mountd/mountd.h
+++ b/utils/mountd/mountd.h
@@ -51,13 +51,4 @@ void		mountlist_del(char *host, const char *path);
 void		mountlist_del_all(const struct sockaddr *sap);
 mountlist	mountlist_list(void);
 
-void		cache_open(void);
-struct nfs_fh_len *
-		cache_get_filehandle(nfs_export *exp, int len, char *p);
-int		cache_export(nfs_export *exp, char *path);
-
-bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai);
-bool namelist_client_matches(nfs_export *exp, char *dom);
-bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai);
-
 #endif /* MOUNTD_H */
-- 
2.42.0


  parent reply	other threads:[~2023-10-23  2:12 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-23  1:58 [PATCH 0/6 nfs-utils v2] fixes for error handling in nfsd_fh NeilBrown
2023-10-23  1:58 ` [PATCH 1/6] export: fix handling of error from match_fsid() NeilBrown
2023-10-23  1:58 ` [PATCH 2/6] export: add EACCES to the list of known path_lookup_error() errors NeilBrown
2023-10-23  1:58 ` [PATCH 3/6] export: move cache_open() before workers are forked NeilBrown
2023-10-23  1:58 ` NeilBrown [this message]
2023-10-23  1:58 ` [PATCH 5/6] Share process_loop code between mountd and exportd NeilBrown
2023-10-23  1:58 ` [PATCH 6/6] cache: periodically retry requests that couldn't be answered NeilBrown
2023-10-25 17:37 ` [PATCH 0/6 nfs-utils v2] fixes for error handling in nfsd_fh 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=20231023021052.5258-5-neilb@suse.de \
    --to=neilb@suse.de \
    --cc=linux-nfs@vger.kernel.org \
    --cc=steved@redhat.com \
    --cc=trond.myklebust@hammerspace.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.