Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Jun 2025 15:41:11 GMT
From:      Ka Ho Ng <khng@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 42905aa17b7e - main - nfsd, rpcbind: add -P option to support pidfile path
Message-ID:  <202506091541.559FfBcD084625@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by khng:

URL: https://cgit.FreeBSD.org/src/commit/?id=42905aa17b7e90a1f6881d84903e58330488f4ea

commit 42905aa17b7e90a1f6881d84903e58330488f4ea
Author:     Ka Ho Ng <khng@FreeBSD.org>
AuthorDate: 2025-06-09 03:30:46 +0000
Commit:     Ka Ho Ng <khng@FreeBSD.org>
CommitDate: 2025-06-09 15:24:07 +0000

    nfsd, rpcbind: add -P option to support pidfile path
    
    The -P option, when specified opens a pidfile to a given path.
    Both daemons also install a default pid file to the corresponding
    locations, that is, /var/run/nfsd.pid and /var/run/rpcbind.pid.
    
    Sponsored by:   Juniper Networks, Inc.
    MFC after:      7 days
    Reviewed by:    rmacklem
    Differential Revision:  https://reviews.freebsd.org/D50624
---
 usr.sbin/nfsd/Makefile           |  2 ++
 usr.sbin/nfsd/Makefile.depend    |  1 +
 usr.sbin/nfsd/nfsd.8             |  7 ++++++-
 usr.sbin/nfsd/nfsd.c             | 29 ++++++++++++++++++++++++---
 usr.sbin/rpcbind/Makefile        |  2 ++
 usr.sbin/rpcbind/Makefile.depend |  1 +
 usr.sbin/rpcbind/rpcbind.8       |  8 ++++++--
 usr.sbin/rpcbind/rpcbind.c       | 43 +++++++++++++++++++++++++++++++++++++---
 8 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/usr.sbin/nfsd/Makefile b/usr.sbin/nfsd/Makefile
index d7ca8c380c48..b6bd9a28e651 100644
--- a/usr.sbin/nfsd/Makefile
+++ b/usr.sbin/nfsd/Makefile
@@ -3,4 +3,6 @@ PACKAGE=	nfs
 PROG=	nfsd
 MAN=	nfsd.8 nfsv4.4 stablerestart.5 pnfs.4 pnfsserver.4
 
+LIBADD=	util
+
 .include <bsd.prog.mk>
diff --git a/usr.sbin/nfsd/Makefile.depend b/usr.sbin/nfsd/Makefile.depend
index 732a025c9552..7e5c47e39608 100644
--- a/usr.sbin/nfsd/Makefile.depend
+++ b/usr.sbin/nfsd/Makefile.depend
@@ -9,6 +9,7 @@ DIRDEPS = \
 	lib/${CSU_DIR} \
 	lib/libc \
 	lib/libcompiler_rt \
+	lib/libutil \
 
 
 .include <dirdeps.mk>
diff --git a/usr.sbin/nfsd/nfsd.8 b/usr.sbin/nfsd/nfsd.8
index 992228fba752..2e5724dbce33 100644
--- a/usr.sbin/nfsd/nfsd.8
+++ b/usr.sbin/nfsd/nfsd.8
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd February 21, 2025
+.Dd May 30, 2025
 .Dt NFSD 8
 .Os
 .Sh NAME
@@ -39,6 +39,7 @@ NFS server
 .Op Fl h Ar bindip
 .Op Fl p Ar pnfs_setup
 .Op Fl m Ar mirror_level
+.Op Fl P Ar pidfile
 .Op Fl V Ar virtual_hostname
 .Op Fl Fl maxthreads Ar max_threads
 .Op Fl Fl minthreads Ar min_threads
@@ -84,6 +85,10 @@ options to re-register NFS if the rpcbind server is restarted.
 Unregister the NFS service with
 .Xr rpcbind 8
 without creating any servers.
+.It Fl P Ar pidfile
+Specify alternative location of a file where main process PID will be stored.
+The default location is
+.Pa /var/run/nfsd.pid .
 .It Fl V Ar virtual_hostname
 Specifies a hostname to be used as a principal name, instead of
 the default hostname.
diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c
index f1f04af192da..94c30ae6dee1 100644
--- a/usr.sbin/nfsd/nfsd.c
+++ b/usr.sbin/nfsd/nfsd.c
@@ -58,6 +58,7 @@
 
 #include <err.h>
 #include <errno.h>
+#include <libutil.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -70,6 +71,7 @@
 static int	debug = 0;
 static int	nofork = 0;
 
+#define	DEFAULT_PIDFILE		"/var/run/nfsd.pid"
 #define	NFSD_STABLERESTART	"/var/db/nfs-stablerestart"
 #define	NFSD_STABLEBACKUP	"/var/db/nfs-stablerestart.bak"
 #define	MAXNFSDCNT	256
@@ -79,6 +81,7 @@ static int	nofork = 0;
 #define NFS_VER4	 4
 static pid_t children[MAXNFSDCNT]; /* PIDs of children */
 static pid_t masterpid;		   /* PID of master/parent */
+static struct pidfh *masterpidfh = NULL;	/* pidfh of master/parent */
 static int nfsdcnt;		/* number of children */
 static int nfsdcnt_set;
 static int minthreads;
@@ -161,7 +164,8 @@ main(int argc, char **argv)
 	size_t jailed_size, nfs_minvers_size;
 	const char *lopt;
 	char **bindhost = NULL;
-	pid_t pid;
+	const char *pidfile_path = DEFAULT_PIDFILE;
+	pid_t pid, otherpid;
 	struct nfsd_nfsd_args nfsdargs;
 	const char *vhostname = NULL;
 
@@ -171,14 +175,14 @@ main(int argc, char **argv)
 	nfsdcnt = DEFNFSDCNT;
 	unregister = reregister = tcpflag = maxsock = 0;
 	bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
-	getopt_shortopts = "ah:n:rdtuep:m:V:N";
+	getopt_shortopts = "ah:n:rdtuep:m:V:NP:";
 	getopt_usage =
 	    "usage:\n"
 	    "  nfsd [-ardtueN] [-h bindip]\n"
 	    "       [-n numservers] [--minthreads #] [--maxthreads #]\n"
 	    "       [-p/--pnfs dsserver0:/dsserver0-mounted-on-dir,...,"
 	    "dsserverN:/dsserverN-mounted-on-dir] [-m mirrorlevel]\n"
-	    "       [-V virtual_hostname]\n";
+	    "       [-P pidfile ] [-V virtual_hostname]\n";
 	while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts,
 		    &longindex)) != -1)
 		switch (ch) {
@@ -234,6 +238,9 @@ main(int argc, char **argv)
 		case 'N':
 			nofork = 1;
 			break;
+		case 'P':
+			pidfile_path = optarg;
+			break;
 		case 0:
 			lopt = longopts[longindex].name;
 			if (!strcmp(lopt, "minthreads")) {
@@ -415,6 +422,16 @@ main(int argc, char **argv)
 		}
 		exit (0);
 	}
+
+	if (pidfile_path != NULL) {
+		masterpidfh = pidfile_open(pidfile_path, 0600, &otherpid);
+		if (masterpidfh == NULL) {
+			if (errno == EEXIST)
+				errx(1, "daemon already running, pid: %jd.",
+				    (intmax_t)otherpid);
+			warn("cannot open pid file");
+		}
+	}
 	if (debug == 0 && nofork == 0) {
 		daemon(0, 0);
 		(void)signal(SIGHUP, SIG_IGN);
@@ -434,6 +451,9 @@ main(int argc, char **argv)
 
 	openlog("nfsd", LOG_PID | (debug ? LOG_PERROR : 0), LOG_DAEMON);
 
+	if (masterpidfh != NULL && pidfile_write(masterpidfh) != 0)
+		syslog(LOG_ERR, "pidfile_write(): %m");
+
 	/*
 	 * For V4, we open the stablerestart file and call nfssvc()
 	 * to get it loaded. This is done before the daemons do the
@@ -490,6 +510,7 @@ main(int argc, char **argv)
 		if (pid) {
 			children[0] = pid;
 		} else {
+			pidfile_close(masterpidfh);
 			(void)signal(SIGUSR1, child_cleanup);
 			setproctitle("server");
 			start_server(0, &nfsdargs, vhostname);
@@ -1008,6 +1029,8 @@ nfsd_exit(int status)
 {
 	killchildren();
 	unregistration();
+	if (masterpidfh != NULL)
+		pidfile_remove(masterpidfh);
 	exit(status);
 }
 
diff --git a/usr.sbin/rpcbind/Makefile b/usr.sbin/rpcbind/Makefile
index 1bb2d7584ed2..eadadc71310e 100644
--- a/usr.sbin/rpcbind/Makefile
+++ b/usr.sbin/rpcbind/Makefile
@@ -9,6 +9,8 @@ SRCS=	check_bound.c rpcb_stat.c rpcb_svc_4.c rpcbind.c pmap_svc.c \
 
 CFLAGS+= -DPORTMAP
 
+LIBADD=	util
+
 .if ${MK_INET6_SUPPORT} != "no"
 CFLAGS+= -DINET6
 .endif
diff --git a/usr.sbin/rpcbind/Makefile.depend b/usr.sbin/rpcbind/Makefile.depend
index 732a025c9552..7e5c47e39608 100644
--- a/usr.sbin/rpcbind/Makefile.depend
+++ b/usr.sbin/rpcbind/Makefile.depend
@@ -9,6 +9,7 @@ DIRDEPS = \
 	lib/${CSU_DIR} \
 	lib/libc \
 	lib/libcompiler_rt \
+	lib/libutil \
 
 
 .include <dirdeps.mk>
diff --git a/usr.sbin/rpcbind/rpcbind.8 b/usr.sbin/rpcbind/rpcbind.8
index 36c7a8da9984..0132c8f6a5d0 100644
--- a/usr.sbin/rpcbind/rpcbind.8
+++ b/usr.sbin/rpcbind/rpcbind.8
@@ -1,6 +1,6 @@
 .\" Copyright 1989 AT&T
 .\" Copyright 1991 Sun Microsystems, Inc.
-.Dd July 11, 2024
+.Dd May 30, 2025
 .Dt RPCBIND 8
 .Os
 .Sh NAME
@@ -8,7 +8,7 @@
 .Nd universal addresses to RPC program number mapper
 .Sh SYNOPSIS
 .Nm
-.Op Fl 6adIiLlNswW
+.Op Fl 6adIiLlNPswW
 .Op Fl h Ar bindip
 .Sh DESCRIPTION
 The
@@ -135,6 +135,10 @@ Run in foreground mode.
 In this mode,
 .Nm
 will not fork when it starts.
+.It Fl P
+Specify alternative location of a file where main process PID will be stored.
+The default location is
+.Pa /var/run/rpcbind.pid .
 .It Fl s
 Cause
 .Nm
diff --git a/usr.sbin/rpcbind/rpcbind.c b/usr.sbin/rpcbind/rpcbind.c
index 622e954f903b..d165bcd9fbfc 100644
--- a/usr.sbin/rpcbind/rpcbind.c
+++ b/usr.sbin/rpcbind/rpcbind.c
@@ -61,6 +61,7 @@
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <libutil.h>
 #include <netconfig.h>
 #include <netdb.h>
 #include <pwd.h>
@@ -86,6 +87,11 @@ int rpcbindlockfd;
 
 #define RPCBINDDLOCK "/var/run/rpcbind.lock"
 
+#define DEFAULT_PIDFILE "/var/run/rpcbind.pid"
+
+char *pidfile_path = DEFAULT_PIDFILE;
+struct pidfh *pidfh = NULL;
+
 static int runasdaemon = 0;
 int insecure = 0;
 int oldstyle_local = 0;
@@ -135,6 +141,7 @@ static struct t_bind netlink_taddr = {
 static int init_transport(struct netconfig *);
 static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *,
 			     struct netbuf *);
+static void cleanup_pidfile(void);
 static void terminate(int);
 static void parseargs(int, char *[]);
 static void update_bound_sa(void);
@@ -163,6 +170,13 @@ main(int argc, char *argv[])
 	if (flock(rpcbindlockfd, LOCK_EX|LOCK_NB) != 0 && errno == EWOULDBLOCK)
 		errx(1, "another rpcbind is already running. Aborting");
 
+	if (pidfile_path != NULL) {
+		pidfh = pidfile_open(pidfile_path, 0600, NULL);
+		if (pidfh == NULL)
+			warn("cannot open pid file");
+		atexit(cleanup_pidfile);
+	}
+
 	getrlimit(RLIMIT_NOFILE, &rl);
 	if (rl.rlim_cur < 128) {
 		if (rl.rlim_max <= 128)
@@ -248,6 +262,9 @@ main(int argc, char *argv[])
 			err(1, "fork failed");
 	}
 
+	if (pidfh != NULL && pidfile_write(pidfh) != 0)
+		syslog(LOG_ERR, "pidfile_write(): %m");
+
 	if (runasdaemon) {
 		struct passwd *p;
 
@@ -781,6 +798,16 @@ rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
 	list_rbl = rbl;
 }
 
+/*
+ * atexit callback for pidfh cleanup
+ */
+static void
+cleanup_pidfile(void)
+{
+	if (pidfh != NULL)
+		pidfile_remove(pidfh);
+}
+
 /*
  * Catch the signal and die
  */
@@ -792,8 +819,15 @@ terminate(int signum)
 
 	doterminate = signum;
 	wr = write(terminate_wfd, &c, 1);
-	if (wr < 1)
+	if (wr < 1) {
+		/*
+		 * The call to cleanup_pidfile should be async-signal safe.
+		 * pidfile_remove calls fstat and funlinkat system calls, and
+		 * we are exiting immediately.
+		 */
+		cleanup_pidfile();
 		_exit(2);
+	}
 }
 
 void
@@ -821,7 +855,7 @@ parseargs(int argc, char *argv[])
 #else
 #define WRAPOP	""
 #endif
-	while ((c = getopt(argc, argv, "6adh:IiLlNs" WRAPOP WSOP)) != -1) {
+	while ((c = getopt(argc, argv, "6adh:IiLlNP:s" WRAPOP WSOP)) != -1) {
 		switch (c) {
 		case '6':
 			ipv6_only = 1;
@@ -860,6 +894,9 @@ parseargs(int argc, char *argv[])
 		case 's':
 			runasdaemon = 1;
 			break;
+		case 'P':
+			pidfile_path = strdup(optarg);
+			break;
 #ifdef LIBWRAP
 		case 'W':
 			libwrap = 1;
@@ -872,7 +909,7 @@ parseargs(int argc, char *argv[])
 #endif
 		default:	/* error */
 			fprintf(stderr,
-			    "usage: rpcbind [-6adIiLls%s%s] [-h bindip]\n",
+			    "usage: rpcbind [-6adIiLlNPs%s%s] [-h bindip]\n",
 			    WRAPOP, WSOP);
 			exit (1);
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506091541.559FfBcD084625>