git: 42905aa17b7e - main - nfsd, rpcbind: add -P option to support pidfile path
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 09 Jun 2025 15:41:11 UTC
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);
}