git: a5229a255ea9 - main - Implement procstat(1) advlocks command

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 09 Apr 2022 21:48:26 UTC
The branch main has been updated by kib:

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

commit a5229a255ea9e67fe935da1f566be803c1e7f99f
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-04-02 14:13:17 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-04-09 21:47:50 +0000

    Implement procstat(1) advlocks command
    
    to display list of the advisory file locks in the system.
    
    Example output
    $ procstat advlock
    RW  TYPE   PID SYSID          FSID               RDEV   INO START LEN PATH
    RO FCNTL  5836     0  0x878700ff02 0xffffffffffffffff    57     0   0 /tmp/2
    RW FLOCK    -1     0  0x878700ff02 0xffffffffffffffff    13     0   0 /tmp/1
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D34834
---
 usr.bin/procstat/Makefile           |   1 +
 usr.bin/procstat/procstat.c         |   2 +
 usr.bin/procstat/procstat.h         |   1 +
 usr.bin/procstat/procstat_advlock.c | 102 ++++++++++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+)

diff --git a/usr.bin/procstat/Makefile b/usr.bin/procstat/Makefile
index 0b88f2f4634a..85bff9dae3e2 100644
--- a/usr.bin/procstat/Makefile
+++ b/usr.bin/procstat/Makefile
@@ -5,6 +5,7 @@
 PROG=	procstat
 MAN=	procstat.1
 SRCS=	procstat.c		\
+	procstat_advlock.c	\
 	procstat_args.c		\
 	procstat_auxv.c		\
 	procstat_basic.c	\
diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c
index 220f63f2703e..2388c035b431 100644
--- a/usr.bin/procstat/procstat.c
+++ b/usr.bin/procstat/procstat.c
@@ -87,6 +87,8 @@ static const struct procstat_cmd pacmd_table[] = {
 
 /* procstat parameters and arguments */
 static const struct procstat_cmd cmd_table[] = {
+	{ "advlock", "advisory_locks", NULL, &procstat_advlocks, &cmdopt_none,
+	    PS_CMP_PLURAL | PS_CMP_SUBSTR | PS_MODE_NO_KINFO_PROC },
 	{ "argument", "arguments", NULL, &procstat_args, &cmdopt_none,
 	    PS_CMP_PLURAL | PS_CMP_SUBSTR },
 	{ "auxv", "auxv", NULL, &procstat_auxv, &cmdopt_none, PS_CMP_NORMAL },
diff --git a/usr.bin/procstat/procstat.h b/usr.bin/procstat/procstat.h
index 5b54d4c4ff2f..d3bd12d42ffd 100644
--- a/usr.bin/procstat/procstat.h
+++ b/usr.bin/procstat/procstat.h
@@ -57,6 +57,7 @@ struct kinfo_proc;
 void	kinfo_proc_sort(struct kinfo_proc *kipp, int count);
 const char *	kinfo_proc_thread_name(const struct kinfo_proc *kipp);
 
+void	procstat_advlocks(struct procstat *prstat, struct kinfo_proc *kipp);
 void	procstat_args(struct procstat *prstat, struct kinfo_proc *kipp);
 void	procstat_auxv(struct procstat *prstat, struct kinfo_proc *kipp);
 void	procstat_basic(struct procstat *prstat, struct kinfo_proc *kipp);
diff --git a/usr.bin/procstat/procstat_advlock.c b/usr.bin/procstat/procstat_advlock.c
new file mode 100644
index 000000000000..e0b256a8023a
--- /dev/null
+++ b/usr.bin/procstat/procstat_advlock.c
@@ -0,0 +1,102 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2022 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <libprocstat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "procstat.h"
+
+void
+procstat_advlocks(struct procstat *prstat, struct kinfo_proc *kipp __unused)
+{
+	struct advlock_list *advl;
+	struct advlock *a;
+	static const char advisory_lock_item[] = "advisory_lock";
+
+	if ((procstat_opts & PS_OPT_NOHEADER) == 0)
+		xo_emit("{T:/%2s %5s %5s %5s %18s %18s %8s %9s %9s %s}\n",
+		    "RW", "TYPE", "PID", "SYSID", "FSID", "RDEV", "INO",
+		    "START", "LEN", "PATH");
+
+	xo_open_list(advisory_lock_item);
+	advl = procstat_getadvlock(prstat);
+	if (advl == NULL) {
+		xo_close_list(advisory_lock_item);
+		return;
+	}
+
+	STAILQ_FOREACH(a, advl, next) {
+		xo_open_instance(advisory_lock_item);
+		switch (a->rw) {
+		case PS_ADVLOCK_RO:
+			xo_emit("{:rw/%s} ", "RO");
+			break;
+		case PS_ADVLOCK_RW:
+			xo_emit("{:rw/%s} ", "RW");
+			break;
+		default:
+			xo_emit("{:rw/%s} ", "??");
+			break;
+		}
+		switch (a->type) {
+		case PS_ADVLOCK_TYPE_FLOCK:
+			xo_emit("{:type/%s} ", "FLOCK");
+			break;
+		case PS_ADVLOCK_TYPE_PID:
+			xo_emit("{:type/%s} ", "FCNTL");
+			break;
+		case PS_ADVLOCK_TYPE_REMOTE:
+			xo_emit("{:type/%s} ", "LOCKD");
+			break;
+		default:
+			xo_emit("{:type/%s} ", "?????");
+			break;
+		}
+		xo_emit("{:pid/%5d} ", a->pid);
+		xo_emit("{:sysid/%5d} ", a->sysid);
+		xo_emit("{:fsid/%18#jx} ", (uintmax_t)a->file_fsid);
+		xo_emit("{:rdev/%#18jx} ", (uintmax_t)a->file_rdev);
+		xo_emit("{:ino/%8ju} ", (uintmax_t)a->file_fileid);
+		xo_emit("{:start/%9ju} ", (uintmax_t)a->start);
+		xo_emit("{:len/%9ju} ", (uintmax_t)a->len);
+		xo_emit("{:path/%s}", a->path == NULL ? "" : a->path);
+		xo_emit("\n");
+		xo_close_instance(advisory_lock_item);
+	}
+	xo_close_list(advisory_lock_item);
+	procstat_freeadvlock(prstat, advl);
+}