The branch stable/13 has been updated by kib:

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

commit e858a8053d4749096feecd1ea129811816825a46
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2022-04-01 23:23:06 +0000
Commit:     Konstantin Belousov <k...@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
  */

Reply via email to