Date: Sat, 16 Apr 2022 02:18:43 GMT From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: e858a8053d47 - stable/13 - Add sysctl KERN_LOCKF Message-ID: <202204160218.23G2IhPb025427@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202204160218.23G2IhPb025427>