git: e858a8053d47 - stable/13 - Add sysctl KERN_LOCKF
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 16 Apr 2022 02:18:43 UTC
The branch stable/13 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=e858a8053d4749096feecd1ea129811816825a46
commit e858a8053d4749096feecd1ea129811816825a46
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-04-01 23:23:06 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-04-16 02:18:18 +0000
Add sysctl KERN_LOCKF
(cherry picked from commit eca39864f702e577eba3bc7e9992d1e5e56eba58)
---
sys/kern/kern_lockf.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++
sys/kern/vfs_init.c | 15 +++++-
sys/sys/mount.h | 6 ++-
sys/sys/sysctl.h | 1 +
4 files changed, 158 insertions(+), 2 deletions(-)
diff --git a/sys/kern/kern_lockf.c b/sys/kern/kern_lockf.c
index 2455c84ad65c..f1a432e66bd8 100644
--- a/sys/kern/kern_lockf.c
+++ b/sys/kern/kern_lockf.c
@@ -68,14 +68,18 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/hash.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/stat.h>
#include <sys/sx.h>
#include <sys/unistd.h>
+#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/fcntl.h>
@@ -2459,6 +2463,140 @@ graph_init(struct owner_graph *g)
return (g);
}
+struct kinfo_lockf_linked {
+ struct kinfo_lockf kl;
+ struct vnode *vp;
+ STAILQ_ENTRY(kinfo_lockf_linked) link;
+};
+
+int
+vfs_report_lockf(struct mount *mp, struct sbuf *sb)
+{
+ struct lockf *ls;
+ struct lockf_entry *lf;
+ struct kinfo_lockf_linked *klf;
+ struct vnode *vp;
+ struct ucred *ucred;
+ char *fullpath, *freepath;
+ struct stat stt;
+ fsid_t fsidx;
+ STAILQ_HEAD(, kinfo_lockf_linked) locks;
+ int error, gerror;
+
+ STAILQ_INIT(&locks);
+ sx_slock(&lf_lock_states_lock);
+ LIST_FOREACH(ls, &lf_lock_states, ls_link) {
+ sx_slock(&ls->ls_lock);
+ LIST_FOREACH(lf, &ls->ls_active, lf_link) {
+ vp = lf->lf_vnode;
+ if (VN_IS_DOOMED(vp) || vp->v_mount != mp)
+ continue;
+ vhold(vp);
+ klf = malloc(sizeof(struct kinfo_lockf_linked),
+ M_LOCKF, M_WAITOK | M_ZERO);
+ klf->vp = vp;
+ klf->kl.kl_structsize = sizeof(struct kinfo_lockf);
+ klf->kl.kl_start = lf->lf_start;
+ klf->kl.kl_len = lf->lf_end == OFF_MAX ? 0 :
+ lf->lf_end - lf->lf_start + 1;
+ klf->kl.kl_rw = lf->lf_type == F_RDLCK ?
+ KLOCKF_RW_READ : KLOCKF_RW_WRITE;
+ if (lf->lf_owner->lo_sysid != 0) {
+ klf->kl.kl_pid = lf->lf_owner->lo_pid;
+ klf->kl.kl_sysid = lf->lf_owner->lo_sysid;
+ klf->kl.kl_type = KLOCKF_TYPE_REMOTE;
+ } else if (lf->lf_owner->lo_pid == -1) {
+ klf->kl.kl_pid = -1;
+ klf->kl.kl_sysid = 0;
+ klf->kl.kl_type = KLOCKF_TYPE_FLOCK;
+ } else {
+ klf->kl.kl_pid = lf->lf_owner->lo_pid;
+ klf->kl.kl_sysid = 0;
+ klf->kl.kl_type = KLOCKF_TYPE_PID;
+ }
+ STAILQ_INSERT_TAIL(&locks, klf, link);
+ }
+ sx_sunlock(&ls->ls_lock);
+ }
+ sx_sunlock(&lf_lock_states_lock);
+
+ gerror = 0;
+ ucred = curthread->td_ucred;
+ fsidx = mp->mnt_stat.f_fsid;
+ while ((klf = STAILQ_FIRST(&locks)) != NULL) {
+ STAILQ_REMOVE_HEAD(&locks, link);
+ vp = klf->vp;
+ if (gerror == 0 && vn_lock(vp, LK_SHARED) == 0) {
+ error = prison_canseemount(ucred, vp->v_mount);
+ if (error == 0)
+ error = VOP_STAT(vp, &stt, ucred, NOCRED,
+ curthread);
+ VOP_UNLOCK(vp);
+ if (error == 0) {
+ memcpy(&klf->kl.kl_file_fsid, &fsidx,
+ sizeof(fsidx));
+ klf->kl.kl_file_rdev = stt.st_rdev;
+ klf->kl.kl_file_fileid = stt.st_ino;
+ freepath = NULL;
+ fullpath = "-";
+ error = vn_fullpath(vp, &fullpath, &freepath);
+ if (error == 0)
+ strlcpy(klf->kl.kl_path, fullpath,
+ sizeof(klf->kl.kl_path));
+ free(freepath, M_TEMP);
+ if (sbuf_bcat(sb, &klf->kl,
+ klf->kl.kl_structsize) != 0) {
+ gerror = sbuf_error(sb);
+ }
+ }
+ }
+ vdrop(vp);
+ free(klf, M_LOCKF);
+ }
+
+ return (gerror);
+}
+
+static int
+sysctl_kern_lockf_run(struct sbuf *sb)
+{
+ struct mount *mp;
+ int error;
+
+ error = 0;
+ mtx_lock(&mountlist_mtx);
+ TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+ error = vfs_busy(mp, MBF_MNTLSTLOCK);
+ if (error != 0)
+ continue;
+ error = mp->mnt_op->vfs_report_lockf(mp, sb);
+ mtx_lock(&mountlist_mtx);
+ vfs_unbusy(mp);
+ if (error != 0)
+ break;
+ }
+ mtx_unlock(&mountlist_mtx);
+ return (error);
+}
+
+static int
+sysctl_kern_lockf(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf sb;
+ int error, error2;
+
+ sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_lockf) * 5, req);
+ sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
+ error = sysctl_kern_lockf_run(&sb);
+ error2 = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+ return (error != 0 ? error : error2);
+}
+SYSCTL_PROC(_kern, KERN_LOCKF, lockf,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ 0, 0, sysctl_kern_lockf, "S,lockf",
+ "Advisory locks table");
+
#ifdef LOCKF_DEBUG
/*
* Print description of a lock owner
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index e22a9561305d..a8f5eb63396a 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -350,6 +350,17 @@ vfs_purge_sigdefer(struct mount *mp)
sigallowstop(prev_stops);
}
+static int
+vfs_report_lockf_sigdefer(struct mount *mp, struct sbuf *sb)
+{
+ int prev_stops, rc;
+
+ prev_stops = sigdeferstop(SIGDEFERSTOP_SILENT);
+ rc = (*mp->mnt_vfc->vfc_vfsops_sd->vfs_report_lockf)(mp, sb);
+ sigallowstop(prev_stops);
+ return (rc);
+}
+
static struct vfsops vfsops_sigdefer = {
.vfs_mount = vfs_mount_sigdefer,
.vfs_unmount = vfs_unmount_sigdefer,
@@ -367,7 +378,7 @@ static struct vfsops vfsops_sigdefer = {
.vfs_reclaim_lowervp = vfs_reclaim_lowervp_sigdefer,
.vfs_unlink_lowervp = vfs_unlink_lowervp_sigdefer,
.vfs_purge = vfs_purge_sigdefer,
-
+ .vfs_report_lockf = vfs_report_lockf_sigdefer,
};
/* Register a new filesystem type in the global table */
@@ -481,6 +492,8 @@ vfs_register(struct vfsconf *vfc)
vfsops->vfs_extattrctl = vfs_stdextattrctl;
if (vfsops->vfs_sysctl == NULL)
vfsops->vfs_sysctl = vfs_stdsysctl;
+ if (vfsops->vfs_report_lockf == NULL)
+ vfsops->vfs_report_lockf = vfs_report_lockf;
if ((vfc->vfc_flags & VFCF_SBDRY) != 0) {
vfc->vfc_vfsops_sd = vfc->vfc_vfsops;
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 93193eb3e28c..0e7ecd646964 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -775,6 +775,8 @@ typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op,
typedef void vfs_susp_clean_t(struct mount *mp);
typedef void vfs_notify_lowervp_t(struct mount *mp, struct vnode *lowervp);
typedef void vfs_purge_t(struct mount *mp);
+struct sbuf;
+typedef int vfs_report_lockf_t(struct mount *mp, struct sbuf *sb);
struct vfsops {
vfs_mount_t *vfs_mount;
@@ -796,7 +798,8 @@ struct vfsops {
vfs_notify_lowervp_t *vfs_reclaim_lowervp;
vfs_notify_lowervp_t *vfs_unlink_lowervp;
vfs_purge_t *vfs_purge;
- vfs_mount_t *vfs_spare[6]; /* spares for ABI compat */
+ vfs_report_lockf_t *vfs_report_lockf;
+ vfs_mount_t *vfs_spare[5]; /* spares for ABI compat */
};
vfs_statfs_t __vfs_statfs;
@@ -1005,6 +1008,7 @@ int vfs_suser(struct mount *, struct thread *);
void vfs_unbusy(struct mount *);
void vfs_unmountall(void);
int vfs_remount_ro(struct mount *mp);
+int vfs_report_lockf(struct mount *mp, struct sbuf *sb);
extern TAILQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */
extern struct mtx_padalign mountlist_mtx;
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 9e9bd723f4bd..8f7741eb0b4c 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -982,6 +982,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
#define KERN_HOSTUUID 36 /* string: host UUID identifier */
#define KERN_ARND 37 /* int: from arc4rand() */
#define KERN_MAXPHYS 38 /* int: MAXPHYS value */
+#define KERN_LOCKF 39 /* struct: lockf reports */
/*
* KERN_PROC subtypes
*/