diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c --- a/sbin/mount/mount.c +++ b/sbin/mount/mount.c @@ -692,6 +692,13 @@ xo_emit("{D:, }{Lw:fsid}{:fsid}", fsidbuf); free(fsidbuf); } + if (sfp->f_nvnodelistsize != 0 || sfp->f_avnodecount != 0) { + xo_open_container("vnodes"); + xo_emit("{D:, }{Lwc:vnodes}{Lw:count}{w:count/%ju}{Lw:active}{:active/%ju}", + (uintmax_t)sfp->f_nvnodelistsize, + (uintmax_t)sfp->f_avnodecount); + xo_close_container("vnodes"); + } } xo_emit("{D:)}\n"); } diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -2610,6 +2610,8 @@ int __vfs_statfs(struct mount *mp, struct statfs *sbp) { + struct vnode *vp; + uint32_t count; /* * Filesystems only fill in part of the structure for updates, we @@ -2624,6 +2626,16 @@ sbp->f_version = STATFS_VERSION; sbp->f_namemax = NAME_MAX; sbp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + sbp->f_nvnodelistsize = mp->mnt_nvnodelistsize; + + count = 0; + MNT_ILOCK(mp); + TAILQ_FOREACH(vp, &mp->mnt_nvnodelist, v_nmntvnodes) { + if (vrefcnt(vp) > 0) /* racy but does not matter */ + count++; + } + MNT_IUNLOCK(mp); + sbp->f_avnodecount = count; return (mp->mnt_op->vfs_statfs(mp, sbp)); } diff --git a/sys/sys/mount.h b/sys/sys/mount.h --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -91,7 +91,9 @@ uint64_t f_asyncwrites; /* count of async writes since mount */ uint64_t f_syncreads; /* count of sync reads since mount */ uint64_t f_asyncreads; /* count of async reads since mount */ - uint64_t f_spare[10]; /* unused spare */ + uint32_t f_nvnodelistsize; /* # of vnodes */ + uint32_t f_avnodecount; /* # of active vnodes */ + uint64_t f_spare[9]; /* unused spare */ uint32_t f_namemax; /* maximum filename length */ uid_t f_owner; /* user that mounted the filesystem */ fsid_t f_fsid; /* filesystem id */