@@ -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;
+}
@@ -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);
@@ -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();
@@ -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();
@@ -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 */
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(-)