Re: git: 6468cd8e0ef9 - main - mount: add vnode usage per file system with mount -v

From: Mateusz Guzik <mjguzik_at_gmail.com>
Date: Mon, 13 Jun 2022 16:43:31 UTC
On 6/13/22, Doug Ambrisko <ambrisko@freebsd.org> wrote:
> The branch main has been updated by ambrisko:
>
> URL:
> https://cgit.FreeBSD.org/src/commit/?id=6468cd8e0ef9d1d3331e9de26cd2be59bc778494
>
> commit 6468cd8e0ef9d1d3331e9de26cd2be59bc778494
> Author:     Doug Ambrisko <ambrisko@FreeBSD.org>
> AuthorDate: 2022-06-13 14:56:38 +0000
> Commit:     Doug Ambrisko <ambrisko@FreeBSD.org>
> CommitDate: 2022-06-13 14:56:38 +0000
>
>     mount: add vnode usage per file system with mount -v
>
>     This avoids the need to drop into the ddb to figure out vnode
>     usage per file system.  It helps to see if they are or are not
>     being freed.  Suggestion to report active vnode count was from
>     kib@
>
>     Reviewed by:    kib
>     Differential Revision: https://reviews.freebsd.org/D35436
> ---
>  sbin/mount/mount.c   |  7 +++++++
>  sys/kern/vfs_mount.c | 12 ++++++++++++
>  sys/sys/mount.h      |  4 +++-
>  3 files changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c
> index 79d9d6cb0caf..bd3d0073c474 100644
> --- a/sbin/mount/mount.c
> +++ b/sbin/mount/mount.c
> @@ -692,6 +692,13 @@ prmount(struct statfs *sfp)
>  			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
> index 71a40fd97a9c..e3818b67e841 100644
> --- a/sys/kern/vfs_mount.c
> +++ b/sys/kern/vfs_mount.c
> @@ -2610,6 +2610,8 @@ vfs_copyopt(struct vfsoptlist *opts, const char *name,
> void *dest, int len)
>  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 @@ __vfs_statfs(struct mount *mp, struct statfs *sbp)
>  	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;
>

libc uses statfs for dir walk (see gen/fts.c), most notably find
immediately runs into it. As such the linear scan by default is a
non-starter.

I don't know if mount is the right place to dump this kind of info to
begin with, but even so, it should only happen with a dedicated flag.

As statfs does not take any flags on its own, there is no way to
prevent it from doing the above walk. Perhaps a dedicated sysctl which
takes mount point id could do the walk instead, when asked.

Short of making the walk optional I'm afraid this will have to be reverted.

>  	return (mp->mnt_op->vfs_statfs(mp, sbp));
>  }
> diff --git a/sys/sys/mount.h b/sys/sys/mount.h
> index 3383bfe8f431..edac64171f9a 100644
> --- a/sys/sys/mount.h
> +++ b/sys/sys/mount.h
> @@ -91,7 +91,9 @@ struct statfs {
>  	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 */
>


-- 
Mateusz Guzik <mjguzik gmail.com>