From 4dcdf3987c1cc95d0d344468e8aa15452254691c Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 18 May 2021 12:47:21 +0200 Subject: [PATCH] vfs: replace the MNTK_TEXT_REFS flag with VIRF_TEXT_REF This allows to stop maintaing the VI_TEXT_REF flag and consequently opens up fully lockless v_writecount adjustment. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D33127 --- sys/fs/tmpfs/tmpfs_subr.c | 2 +- sys/fs/tmpfs/tmpfs_vfsops.c | 2 +- sys/kern/vfs_default.c | 20 +++++++++----------- sys/kern/vfs_subr.c | 8 ++++---- sys/sys/mount.h | 2 +- sys/sys/vnode.h | 3 ++- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 9810c1776314..41d9b6d5dcca 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -967,7 +967,7 @@ tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, int lkflag, vp->v_object = object; object->un_pager.swp.swp_tmpfs = vp; vm_object_set_flag(object, OBJ_TMPFS); - vn_irflag_set_locked(vp, VIRF_PGREAD); + vn_irflag_set_locked(vp, VIRF_PGREAD | VIRF_TEXT_REF); VI_UNLOCK(vp); VM_OBJECT_WUNLOCK(object); break; diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c index b8ecedbb0348..7bd44decd830 100644 --- a/sys/fs/tmpfs/tmpfs_vfsops.c +++ b/sys/fs/tmpfs/tmpfs_vfsops.c @@ -469,7 +469,7 @@ tmpfs_mount(struct mount *mp) MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED | - MNTK_TEXT_REFS | MNTK_NOMSYNC; + MNTK_NOMSYNC; if (!nonc && (mp->mnt_flag & MNT_UNION) == 0) mp->mnt_kern_flag |= MNTK_FPLOOKUP; MNT_IUNLOCK(mp); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 50829ad3044e..1f5869bd8cf3 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -1300,7 +1300,6 @@ int vop_stdset_text(struct vop_set_text_args *ap) { struct vnode *vp; - struct mount *mp; int error, n; vp = ap->a_vp; @@ -1326,12 +1325,10 @@ vop_stdset_text(struct vop_set_text_args *ap) * If requested by fs, keep a use reference to the * vnode until the last text reference is released. */ - mp = vp->v_mount; - if (mp != NULL && (mp->mnt_kern_flag & MNTK_TEXT_REFS) != 0 && - vp->v_writecount == 0) { - VNPASS((vp->v_iflag & VI_TEXT_REF) == 0, vp); - vp->v_iflag |= VI_TEXT_REF; - vrefl(vp); + if ((vn_irflag_read(vp) & VIRF_TEXT_REF) != 0) { + if (vp->v_writecount == 0) { + vrefl(vp); + } } atomic_subtract_int(&vp->v_writecount, 1); @@ -1366,11 +1363,12 @@ vop_stdunset_text(struct vop_unset_text_args *ap) last = false; VI_LOCK(vp); if (vp->v_writecount < 0) { - if ((vp->v_iflag & VI_TEXT_REF) != 0 && - vp->v_writecount == -1) { - last = true; - vp->v_iflag &= ~VI_TEXT_REF; + if ((vn_irflag_read(vp) & VIRF_TEXT_REF) != 0) { + if (vp->v_writecount == -1) { + last = true; + } } + atomic_add_int(&vp->v_writecount, 1); error = 0; } else { diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 65a9ebf304fe..06ca5dc7d93a 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -4122,7 +4122,9 @@ vn_printf(struct vnode *vp, const char *fmt, ...) strlcat(buf, "|VIRF_PGREAD", sizeof(buf)); if (irflag & VIRF_MOUNTPOINT) strlcat(buf, "|VIRF_MOUNTPOINT", sizeof(buf)); - flags = irflag & ~(VIRF_DOOMED | VIRF_PGREAD | VIRF_MOUNTPOINT); + if (irflag & VIRF_TEXT_REF) + strlcat(buf, "|VIRF_TEXT_REF", sizeof(buf)); + flags = irflag & ~(VIRF_DOOMED | VIRF_PGREAD | VIRF_MOUNTPOINT | VIRF_TEXT_REF); if (flags != 0) { snprintf(buf2, sizeof(buf2), "|VIRF(0x%lx)", flags); strlcat(buf, buf2, sizeof(buf)); @@ -4163,8 +4165,6 @@ vn_printf(struct vnode *vp, const char *fmt, ...) snprintf(buf2, sizeof(buf2), "|VV(0x%lx)", flags); strlcat(buf, buf2, sizeof(buf)); } - if (vp->v_iflag & VI_TEXT_REF) - strlcat(buf, "|VI_TEXT_REF", sizeof(buf)); if (vp->v_iflag & VI_MOUNT) strlcat(buf, "|VI_MOUNT", sizeof(buf)); if (vp->v_iflag & VI_DOINGINACT) @@ -4175,7 +4175,7 @@ vn_printf(struct vnode *vp, const char *fmt, ...) strlcat(buf, "|VI_DEFINACT", sizeof(buf)); if (vp->v_iflag & VI_FOPENING) strlcat(buf, "|VI_FOPENING", sizeof(buf)); - flags = vp->v_iflag & ~(VI_TEXT_REF | VI_MOUNT | VI_DOINGINACT | + flags = vp->v_iflag & ~(VI_MOUNT | VI_DOINGINACT | VI_OWEINACT | VI_DEFINACT | VI_FOPENING); if (flags != 0) { snprintf(buf2, sizeof(buf2), "|VI(0x%lx)", flags); diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 1863a36738d1..d47d67f1156b 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -489,7 +489,7 @@ struct mntoptnames { #define MNTK_LOOKUP_EXCL_DOTDOT 0x00000800 #define MNTK_UNMAPPED_BUFS 0x00002000 #define MNTK_USES_BCACHE 0x00004000 /* FS uses the buffer cache. */ -#define MNTK_TEXT_REFS 0x00008000 /* Keep use ref for text */ +#define MNTK_UNUSED0 0x00008000 /* unused */ #define MNTK_VMSETSIZE_BUG 0x00010000 #define MNTK_UNIONFS 0x00020000 /* A hack for F_ISUNIONSTACK */ #define MNTK_FPLOOKUP 0x00040000 /* fast path lookup is supported */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index c84d015b011c..53b0a45064b9 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -251,8 +251,9 @@ struct xvnode { #define VIRF_PGREAD 0x0002 /* Direct reads from the page cache are permitted, never cleared once set */ #define VIRF_MOUNTPOINT 0x0004 /* This vnode is mounted on */ +#define VIRF_TEXT_REF 0x0008 /* Executable mappings ref the vnode */ -#define VI_TEXT_REF 0x0001 /* Text ref grabbed use ref */ +#define VI_UNUSED0 0x0001 /* unused */ #define VI_MOUNT 0x0002 /* Mount in progress */ #define VI_DOINGINACT 0x0004 /* VOP_INACTIVE is in progress */ #define VI_OWEINACT 0x0008 /* Need to call inactive */