On Sat, Sep 24, 2016 at 04:35:39PM -0700, Philip Guenther wrote:
> On Sat, 24 Sep 2016, Sebastien Marie wrote:
> ...
> > The following diff adds a `va_nlink' member in `struct kinfo_file'. The
> > information become available though sysctl(3) via KERN_FILE interface,
> > as some others members of `struct vattr'.
> 
> The idea seems sound, but the placement of the member in the structure is 
> a problem:
> 
> > --- sys/sys/sysctl.h        21 Sep 2016 14:06:50 -0000      1.166
> > +++ sys/sys/sysctl.h        24 Sep 2016 11:26:25 -0000
> > @@ -697,6 +697,7 @@ struct kinfo_file {
> >     uint64_t        va_size;        /* UINT64_T: file size in bytes */
> >     uint32_t        va_mode;        /* MODE_T: file access mode and type */
> >     uint32_t        va_fsid;        /* DEV_T: filesystem device */
> > +   uint32_t        va_nlink;       /* NLINK_T: number of references to 
> > file */
> >     char            f_mntonname[KI_MNAMELEN];
> 
> That changes the layout of the structure, changing the ABI.  If instead 
> the new member is placed at the end of structure then there's no ABI 
> break, as the API permits additions to the end of structure.
> 
> Also, libkvm/kvm_file2.c should be updated to match the change to 
> kern_sysctl.c, so that the information is returned when debugging kernel 
> crash dumps.

I updated my diff:
  - adding the new member at end of kinfo_file : no more ABI change.
  - updating libkvm to match the change

One remark about libkvm changes: msdos and ntfs doesn't track va_nlink
in kernel (always set it to 1). So I keep the same behaviour in libkvm.
Maybe it could be revised later (and update kernel and libkvm to track
at least unlinking).

For the other part (adding mmap references to files to KERN_FILE API), I
need more time to understand the internals and make a diff.

> > Formally, for the final purpose, the information could be only partial: 
> > a library dynamically linked isn't referenced via KERN_FILE interface (I 
> > am unsure about the availability of the information). But as proper 
> > packages will have their signature changed by any library crank, a 
> > package update will make old program to be remplaced by a new one.
> 
> Yeah, mmap's hold references to files, but the KERN_FILE API doesn't see 
> them.  To get that you would need to walk the maps in the uvmspace and 
> pick out the non-anonymous mappings, skipping the base executable (which 
> _is_ already returned by KERN_FILE).  Doing that without races in the 
> kernel would be tricky, as copyout() can sleep if there's a page fault.  
> Could you deadlock the kernel by asking for information about your own 
> mappings, with sysctl() writing to a mapping which would need to be 
> faulted in?
> 
> Perhaps better to not hold a lock over copyout() but instead just track 
> the vaddr range that was being reported, and then restart the tree walk 
> from there.  That guarantees progress with no locks held.
> 

-- 
Sebastien Marie


Index: lib/libkvm/kvm_cd9660.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_cd9660.c,v
retrieving revision 1.6
diff -u -p -r1.6 kvm_cd9660.c
--- lib/libkvm/kvm_cd9660.c     16 Dec 2014 03:21:10 -0000      1.6
+++ lib/libkvm/kvm_cd9660.c     25 Sep 2016 15:50:08 -0000
@@ -50,6 +50,7 @@ _kvm_stat_cd9660(kvm_t *kd, struct kinfo
        kf->va_mode = inode.inode.iso_mode;
        kf->va_size = inode.i_size;
        kf->va_rdev = inode.i_dev;
+       kf->va_nlink = inode.inode.iso_links;
 
        return (0);
 }
Index: lib/libkvm/kvm_file2.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_file2.c,v
retrieving revision 1.49
diff -u -p -r1.49 kvm_file2.c
--- lib/libkvm/kvm_file2.c      4 May 2016 01:28:42 -0000       1.49
+++ lib/libkvm/kvm_file2.c      25 Sep 2016 15:50:08 -0000
@@ -798,6 +798,7 @@ ufs_filestat(kvm_t *kd, struct kinfo_fil
        kf->va_mode = inode.i_ffs1_mode;
        kf->va_size = inode.i_ffs1_size;
        kf->va_rdev = inode.i_ffs1_rdev;
+       kf->va_nlink = inode.i_ffs1_nlink;
 
        return (0);
 }
@@ -826,6 +827,7 @@ ext2fs_filestat(kvm_t *kd, struct kinfo_
        kf->va_mode = inode.i_e2fs_mode;
        kf->va_size = inode.i_e2fs_size;
        kf->va_rdev = 0;        /* XXX */
+       kf->va_nlink = inode.i_e2fs_nlink;
 
        return (0);
 }
@@ -851,6 +853,7 @@ msdos_filestat(kvm_t *kd, struct kinfo_f
        kf->va_mode = (mp.pm_mask & 0777) | _kvm_getftype(vp->v_type);
        kf->va_size = de.de_FileSize;
        kf->va_rdev = 0;  /* msdosfs doesn't support device files */
+       kf->va_nlink = 1;
 
        return (0);
 }
@@ -870,6 +873,7 @@ nfs_filestat(kvm_t *kd, struct kinfo_fil
        kf->va_size = nfsnode.n_size;
        kf->va_rdev = nfsnode.n_vattr.va_rdev;
        kf->va_mode = (mode_t)nfsnode.n_vattr.va_mode | 
_kvm_getftype(vp->v_type);
+       kf->va_nlink = nfsnode.n_vattr.va_nlink;
 
        return (0);
 }
Index: lib/libkvm/kvm_ntfs.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_ntfs.c,v
retrieving revision 1.4
diff -u -p -r1.4 kvm_ntfs.c
--- lib/libkvm/kvm_ntfs.c       16 Nov 2013 00:37:11 -0000      1.4
+++ lib/libkvm/kvm_ntfs.c       25 Sep 2016 15:50:08 -0000
@@ -78,6 +78,7 @@ _kvm_stat_ntfs(kvm_t *kd, struct kinfo_f
        kf->va_mode = (mode_t)ntm.ntm_mode | _kvm_getftype(vp->v_type);
        kf->va_size = fn.f_size;
        kf->va_rdev = 0;  /* XXX */
+       kf->va_nlink = 1;
 
        return (0);
 }
Index: lib/libkvm/kvm_udf.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_udf.c,v
retrieving revision 1.9
diff -u -p -r1.9 kvm_udf.c
--- lib/libkvm/kvm_udf.c        16 Dec 2014 03:21:10 -0000      1.9
+++ lib/libkvm/kvm_udf.c        25 Sep 2016 15:50:08 -0000
@@ -95,6 +95,7 @@ _kvm_stat_udf(kvm_t *kd, struct kinfo_fi
        kf->va_fileid = (long)up.u_ino;
        kf->va_mode = udf_permtomode(&up); /* XXX */
        kf->va_rdev = 0;
+       kf->va_nlink = letoh16(fentry.link_cnt);
        if (vp->v_type & VDIR) {
                /*
                 * Directories that are recorded within their ICB will show
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.311
diff -u -p -r1.311 kern_sysctl.c
--- sys/kern/kern_sysctl.c      21 Sep 2016 14:06:50 -0000      1.311
+++ sys/kern/kern_sysctl.c      25 Sep 2016 15:50:09 -0000
@@ -1057,6 +1057,7 @@ fill_file(struct kinfo_file *kf, struct 
                        kf->va_size = va.va_size;
                        kf->va_rdev = va.va_rdev;
                        kf->va_fsid = va.va_fsid & 0xffffffff;
+                       kf->va_nlink = va.va_nlink;
                }
                break;
 
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvs/src/sys/sys/sysctl.h,v
retrieving revision 1.166
diff -u -p -r1.166 sysctl.h
--- sys/sys/sysctl.h    21 Sep 2016 14:06:50 -0000      1.166
+++ sys/sys/sysctl.h    25 Sep 2016 15:50:09 -0000
@@ -748,6 +748,8 @@ struct kinfo_file {
        uint64_t        t_rcv_wnd;      /* ULONG: tcp receive window */
        uint64_t        t_snd_wnd;      /* ULONG: tcp send window */
        uint64_t        t_snd_cwnd;     /* ULONG: congestion-controlled win */
+
+       uint32_t        va_nlink;       /* NLINK_T: number of references to 
file */
 };
 
 /*
Index: usr.bin/fstat/fstat.1
===================================================================
RCS file: /cvs/src/usr.bin/fstat/fstat.1,v
retrieving revision 1.52
diff -u -p -r1.52 fstat.1
--- usr.bin/fstat/fstat.1       25 Apr 2016 19:18:41 -0000      1.52
+++ usr.bin/fstat/fstat.1       25 Sep 2016 15:50:10 -0000
@@ -146,6 +146,9 @@ flag is specified, this header is presen
 major/minor number of the device that this file resides in.
 .It Li INUM
 The inode number of the file.
+It will be followed by an asterisk
+.Pq Ql *
+if the inode is unlinked from disk.
 .It Li MODE
 The mode of the file.
 If the
Index: usr.bin/fstat/fstat.c
===================================================================
RCS file: /cvs/src/usr.bin/fstat/fstat.c,v
retrieving revision 1.88
diff -u -p -r1.88 fstat.c
--- usr.bin/fstat/fstat.c       4 May 2016 19:48:08 -0000       1.88
+++ usr.bin/fstat/fstat.c       25 Sep 2016 15:50:10 -0000
@@ -441,7 +441,9 @@ vtrans(struct kinfo_file *kf)
                (void)snprintf(mode, sizeof(mode), "%o", kf->va_mode);
        else
                strmode(kf->va_mode, mode);
-       printf(" %8llu %11s", kf->va_fileid, mode);
+       printf(" %8llu%s %11s", kf->va_fileid,
+           kf->va_nlink == 0 ? "*" : " ",
+           mode);
        rw[0] = '\0';
        if (kf->f_flag & FREAD)
                strlcat(rw, "r", sizeof rw);

Reply via email to