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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox