Both vn_close() and VFS_PROLOGUE() evaluate vp->v_mount twice, without

holding the vnode lock; vp->v_mount is checked first for NULL
equiality, and then dereferenced if not NULL.  If vnode is reclaimed
meantime, second dereference would still give NULL.  Change
VFS_PROLOGUE() to evaluate the mp once, convert MNTK_SHARED_WRITES and
MNTK_EXTENDED_SHARED tests into inline functions.

Reviewed by:	alc
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2013-11-09 20:30:13 +00:00
parent 335521936f
commit 6272798a3f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=257898
3 changed files with 21 additions and 13 deletions

View file

@ -424,13 +424,8 @@ needs_exclusive_leaf(struct mount *mp, int flags)
* extended shared operations, then use a shared lock for the
* leaf node, otherwise use an exclusive lock.
*/
if (flags & ISOPEN) {
if (mp != NULL &&
(mp->mnt_kern_flag & MNTK_EXTENDED_SHARED))
return (0);
else
return (1);
}
if ((flags & ISOPEN) != 0)
return (!MNT_EXTENDED_SHARED(mp));
/*
* Lookup requests outside of open() that specify LOCKSHARED

View file

@ -360,8 +360,8 @@ vn_close(vp, flags, file_cred, td)
struct mount *mp;
int error, lock_flags;
if (vp->v_type != VFIFO && !(flags & FWRITE) && vp->v_mount != NULL &&
vp->v_mount->mnt_kern_flag & MNTK_EXTENDED_SHARED)
if (vp->v_type != VFIFO && (flags & FWRITE) == 0 &&
MNT_EXTENDED_SHARED(vp->v_mount))
lock_flags = LK_SHARED;
else
lock_flags = LK_EXCLUSIVE;

View file

@ -362,8 +362,19 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
#define MNTK_LOOKUP_SHARED 0x40000000 /* FS supports shared lock lookups */
#define MNTK_NOKNOTE 0x80000000 /* Don't send KNOTEs from VOP hooks */
#define MNT_SHARED_WRITES(mp) (((mp) != NULL) && \
((mp)->mnt_kern_flag & MNTK_SHARED_WRITES))
static inline int
MNT_SHARED_WRITES(struct mount *mp)
{
return (mp != NULL && (mp->mnt_kern_flag & MNTK_SHARED_WRITES) != 0);
}
static inline int
MNT_EXTENDED_SHARED(struct mount *mp)
{
return (mp != NULL && (mp->mnt_kern_flag & MNTK_EXTENDED_SHARED) != 0);
}
/*
* Sysctl CTL_VFS definitions.
@ -636,10 +647,12 @@ struct vfsops {
vfs_statfs_t __vfs_statfs;
#define VFS_PROLOGUE(MP) do { \
struct mount *mp__; \
int _enable_stops; \
\
_enable_stops = ((MP) != NULL && \
((MP)->mnt_vfc->vfc_flags & VFCF_SBDRY) && sigdeferstop())
mp__ = (MP); \
_enable_stops = (mp__ != NULL && \
(mp__->mnt_vfc->vfc_flags & VFCF_SBDRY) && sigdeferstop())
#define VFS_EPILOGUE(MP) \
if (_enable_stops) \