svn commit: r351584 - in head/sys: fs/nullfs fs/unionfs kern sys
Mateusz Guzik
mjguzik at gmail.com
Wed Aug 28 20:35:59 UTC 2019
On 8/28/19, Mateusz Guzik <mjg at freebsd.org> wrote:
> Author: mjg
> Date: Wed Aug 28 20:34:24 2019
> New Revision: 351584
> URL: https://svnweb.freebsd.org/changeset/base/351584
>
> Log:
> vfs: add VOP_NEED_INACTIVE
>
> vnode usecount drops to 0 all the time (e.g. for directories during path
> lookup).
> When that happens the kernel would always lock the exclusive lock for the
> vnode
> in order to call vinactive(). This blocks other threads who want to use
> the vnode
> for looukp.
>
> vinactive is very rarely needed and can be tested for without the vnode
> lock held.
>
> This patch gives filesytems an opportunity to do it, sample total wait
> time for
> tmpfs over 500 minutes of poudriere -j 104:
>
> before: 557563641706 (lockmgr:tmpfs)
> after: 46309603301 (lockmgr:tmpfs)
>
> Sponsored by: The FreeBSD Foundation
> Differential Revision: https://reviews.freebsd.org/D21371
>
Reviewed by: kib
Tested by: pho
> Modified:
> head/sys/fs/nullfs/null_vnops.c
> head/sys/fs/unionfs/union_vnops.c
> head/sys/kern/vfs_default.c
> head/sys/kern/vfs_subr.c
> head/sys/kern/vnode_if.src
> head/sys/sys/vnode.h
>
> Modified: head/sys/fs/nullfs/null_vnops.c
> ==============================================================================
> --- head/sys/fs/nullfs/null_vnops.c Wed Aug 28 20:23:49 2019 (r351583)
> +++ head/sys/fs/nullfs/null_vnops.c Wed Aug 28 20:34:24 2019 (r351584)
> @@ -907,6 +907,7 @@ struct vop_vector null_vnodeops = {
> .vop_getattr = null_getattr,
> .vop_getwritemount = null_getwritemount,
> .vop_inactive = null_inactive,
> + .vop_need_inactive = vop_stdneed_inactive,
> .vop_islocked = vop_stdislocked,
> .vop_lock1 = null_lock,
> .vop_lookup = null_lookup,
>
> Modified: head/sys/fs/unionfs/union_vnops.c
> ==============================================================================
> --- head/sys/fs/unionfs/union_vnops.c Wed Aug 28 20:23:49 2019 (r351583)
> +++ head/sys/fs/unionfs/union_vnops.c Wed Aug 28 20:34:24 2019 (r351584)
> @@ -2523,6 +2523,7 @@ struct vop_vector unionfs_vnodeops = {
> .vop_getextattr = unionfs_getextattr,
> .vop_getwritemount = unionfs_getwritemount,
> .vop_inactive = unionfs_inactive,
> + .vop_need_inactive = vop_stdneed_inactive,
> .vop_islocked = unionfs_islocked,
> .vop_ioctl = unionfs_ioctl,
> .vop_link = unionfs_link,
>
> Modified: head/sys/kern/vfs_default.c
> ==============================================================================
> --- head/sys/kern/vfs_default.c Wed Aug 28 20:23:49 2019 (r351583)
> +++ head/sys/kern/vfs_default.c Wed Aug 28 20:34:24 2019 (r351584)
> @@ -120,6 +120,7 @@ struct vop_vector default_vnodeops = {
> .vop_getpages_async = vop_stdgetpages_async,
> .vop_getwritemount = vop_stdgetwritemount,
> .vop_inactive = VOP_NULL,
> + .vop_need_inactive = vop_stdneed_inactive,
> .vop_ioctl = vop_stdioctl,
> .vop_kqfilter = vop_stdkqfilter,
> .vop_islocked = vop_stdislocked,
> @@ -1155,6 +1156,13 @@ vop_stdadd_writecount(struct vop_add_writecount_args
> *
> }
> VI_UNLOCK(vp);
> return (error);
> +}
> +
> +int
> +vop_stdneed_inactive(struct vop_need_inactive_args *ap)
> +{
> +
> + return (1);
> }
>
> static int
>
> Modified: head/sys/kern/vfs_subr.c
> ==============================================================================
> --- head/sys/kern/vfs_subr.c Wed Aug 28 20:23:49 2019 (r351583)
> +++ head/sys/kern/vfs_subr.c Wed Aug 28 20:34:24 2019 (r351584)
> @@ -2891,6 +2891,21 @@ vputx(struct vnode *vp, int func)
> CTR2(KTR_VFS, "%s: return vnode %p to the freelist", __func__, vp);
>
> /*
> + * Check if the fs wants to perform inactive processing. Note we
> + * may be only holding the interlock, in which case it is possible
> + * someone else called vgone on the vnode and ->v_data is now NULL.
> + * Since vgone performs inactive on its own there is nothing to do
> + * here but to drop our hold count.
> + */
> + if (__predict_false(vp->v_iflag & VI_DOOMED) ||
> + VOP_NEED_INACTIVE(vp) == 0) {
> + if (func == VPUTX_VPUT)
> + VOP_UNLOCK(vp, 0);
> + vdropl(vp);
> + return;
> + }
> +
> + /*
> * We must call VOP_INACTIVE with the node locked. Mark
> * as VI_DOINGINACT to avoid recursion.
> */
> @@ -4353,6 +4368,7 @@ static struct vop_vector sync_vnodeops = {
> .vop_close = sync_close, /* close */
> .vop_fsync = sync_fsync, /* fsync */
> .vop_inactive = sync_inactive, /* inactive */
> + .vop_need_inactive = vop_stdneed_inactive, /* need_inactive */
> .vop_reclaim = sync_reclaim, /* reclaim */
> .vop_lock1 = vop_stdlock, /* lock */
> .vop_unlock = vop_stdunlock, /* unlock */
> @@ -4514,6 +4530,20 @@ sync_reclaim(struct vop_reclaim_args *ap)
> return (0);
> }
>
> +int
> +vn_need_pageq_flush(struct vnode *vp)
> +{
> + struct vm_object *obj;
> + int need;
> +
> + MPASS(mtx_owned(VI_MTX(vp)));
> + need = 0;
> + if ((obj = vp->v_object) != NULL && (vp->v_vflag & VV_NOSYNC) == 0 &&
> + (obj->flags & OBJ_MIGHTBEDIRTY) != 0)
> + need = 1;
> + return (need);
> +}
> +
> /*
> * Check if vnode represents a disk device
> */
> @@ -4893,6 +4923,22 @@ vop_unlock_post(void *ap, int rc)
>
> if (a->a_flags & LK_INTERLOCK)
> ASSERT_VI_UNLOCKED(a->a_vp, "VOP_UNLOCK");
> +}
> +
> +void
> +vop_need_inactive_pre(void *ap)
> +{
> + struct vop_need_inactive_args *a = ap;
> +
> + ASSERT_VI_LOCKED(a->a_vp, "VOP_NEED_INACTIVE");
> +}
> +
> +void
> +vop_need_inactive_post(void *ap, int rc)
> +{
> + struct vop_need_inactive_args *a = ap;
> +
> + ASSERT_VI_LOCKED(a->a_vp, "VOP_NEED_INACTIVE");
> }
> #endif
>
>
> Modified: head/sys/kern/vnode_if.src
> ==============================================================================
> --- head/sys/kern/vnode_if.src Wed Aug 28 20:23:49 2019 (r351583)
> +++ head/sys/kern/vnode_if.src Wed Aug 28 20:34:24 2019 (r351584)
> @@ -358,6 +358,12 @@ vop_inactive {
> IN struct thread *td;
> };
>
> +%! need_inactive pre vop_need_inactive_pre
> +%! need_inactive post vop_need_inactive_post
> +
> +vop_need_inactive {
> + IN struct vnode *vp;
> +};
>
> %% reclaim vp E E E
> %! reclaim post vop_reclaim_post
>
> Modified: head/sys/sys/vnode.h
> ==============================================================================
> --- head/sys/sys/vnode.h Wed Aug 28 20:23:49 2019 (r351583)
> +++ head/sys/sys/vnode.h Wed Aug 28 20:34:24 2019 (r351584)
> @@ -682,6 +682,7 @@ int vn_generic_copy_file_range(struct vnode *invp, off
> struct vnode *outvp, off_t *outoffp, size_t *lenp,
> unsigned int flags, struct ucred *incred, struct ucred *outcred,
> struct thread *fsize_td);
> +int vn_need_pageq_flush(struct vnode *vp);
> int vn_isdisk(struct vnode *vp, int *errp);
> int _vn_lock(struct vnode *vp, int flags, char *file, int line);
> #define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__)
> @@ -753,6 +754,7 @@ int vop_stdfsync(struct vop_fsync_args *);
> int vop_stdgetwritemount(struct vop_getwritemount_args *);
> int vop_stdgetpages(struct vop_getpages_args *);
> int vop_stdinactive(struct vop_inactive_args *);
> +int vop_stdneed_inactive(struct vop_need_inactive_args *);
> int vop_stdislocked(struct vop_islocked_args *);
> int vop_stdkqfilter(struct vop_kqfilter_args *);
> int vop_stdlock(struct vop_lock1_args *);
> @@ -813,12 +815,16 @@ void vop_lock_pre(void *a);
> void vop_lock_post(void *a, int rc);
> void vop_unlock_pre(void *a);
> void vop_unlock_post(void *a, int rc);
> +void vop_need_inactive_pre(void *a);
> +void vop_need_inactive_post(void *a, int rc);
> #else
> #define vop_strategy_pre(x) do { } while (0)
> #define vop_lock_pre(x) do { } while (0)
> #define vop_lock_post(x, y) do { } while (0)
> #define vop_unlock_pre(x) do { } while (0)
> #define vop_unlock_post(x, y) do { } while (0)
> +#define vop_need_inactive_pre(x) do { } while (0)
> +#define vop_need_inactive_post(x, y) do { } while (0)
> #endif
>
> void vop_rename_fail(struct vop_rename_args *ap);
>
>
--
Mateusz Guzik <mjguzik gmail.com>
More information about the svn-src-head
mailing list