[Bug 264723] the KERN_LOCKF sysctl returns kl_file_fsid that doesn't match st_dev from stat()

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 17 Jun 2022 01:35:54 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=264723

            Bug ID: 264723
           Summary: the KERN_LOCKF sysctl returns kl_file_fsid that
                    doesn't match st_dev from stat()
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: damjan.jov@gmail.com

The new KERN_LOCKF sysctl (great work btw) returns struct kinfo_lockf, whose
kl_file_fsid matches neither the st_dev from stat(), nor the kf_file_fsid from
kinfo_getfiles() (even though stat() and kinfo_getfiles() match each other).
For example compare the FSID in "procstat advlock" for a locked file, with the
st_dev in "stat -s" output on it.

vop_stdstat() derives st_dev like this:
---snip---
        if (vap->va_fsid != VNOVAL)
                sb->st_dev = vap->va_fsid;
        else
                sb->st_dev = vp->v_mount->mnt_stat.f_fsid.val[0];
---snip---


vn_fill_kinfo_vnode() derives kf_file_fsid the same way:
---snip---
        if (va.va_fsid != VNOVAL)
                kif->kf_un.kf_file.kf_file_fsid = va.va_fsid;
        else
                kif->kf_un.kf_file.kf_file_fsid =
                    vp->v_mount->mnt_stat.f_fsid.val[0];
---snip---


But vfs_report_lockf() uses the entire mnt_stat.f_fsid, not just array element
0, and never uses va.va_fsid:
---snip---
       fsidx = mp->mnt_stat.f_fsid;
       ...
                               memcpy(&klf->kl.kl_file_fsid, &fsidx,
                                   sizeof(fsidx));
---snip---


vfs_report_lockf() does call VOP_STAT(), which is (usually?) the vop_stdstat()
function above, so it should be able to just copy its correctly populated
st_dev to kl_file_fsid. When I do that, as in the following patch, it seems to
work, the FSID in "procstat advlock" matches the st_dev in "stat -s":


---snip---
diff --git a/sys/kern/kern_lockf.c b/sys/kern/kern_lockf.c
index cad208197e7..98e29b2c929 100644
--- a/sys/kern/kern_lockf.c
+++ b/sys/kern/kern_lockf.c
@@ -2479,7 +2479,6 @@ vfs_report_lockf(struct mount *mp, struct sbuf *sb)
        struct ucred *ucred;
        char *fullpath, *freepath;
        struct stat stt;
-       fsid_t fsidx;
        STAILQ_HEAD(, kinfo_lockf_linked) locks;
        int error, gerror;

@@ -2522,7 +2521,6 @@ vfs_report_lockf(struct mount *mp, struct sbuf *sb)

        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;
@@ -2532,8 +2530,7 @@ vfs_report_lockf(struct mount *mp, struct sbuf *sb)
                                error = VOP_STAT(vp, &stt, ucred, NOCRED);
                        VOP_UNLOCK(vp);
                        if (error == 0) {
-                               memcpy(&klf->kl.kl_file_fsid, &fsidx,
-                                   sizeof(fsidx));
+                               klf->kl.kl_file_fsid = stt.st_dev;
                                klf->kl.kl_file_rdev = stt.st_rdev;
                                klf->kl.kl_file_fileid = stt.st_ino;
                                freepath = NULL;
---snip---

-- 
You are receiving this mail because:
You are the assignee for the bug.