git: a01ca46b9b86 - main - unionfs: use VV_ROOT to check for root vnode in unionfs_lock()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 30 Jan 2022 04:28:26 UTC
The branch main has been updated by jah: URL: https://cgit.FreeBSD.org/src/commit/?id=a01ca46b9b86608bfa080a4d86d586beb9e756c9 commit a01ca46b9b86608bfa080a4d86d586beb9e756c9 Author: Jason A. Harmening <jah@FreeBSD.org> AuthorDate: 2022-01-17 01:03:54 +0000 Commit: Jason A. Harmening <jah@FreeBSD.org> CommitDate: 2022-01-30 04:38:44 +0000 unionfs: use VV_ROOT to check for root vnode in unionfs_lock() This avoids a potentially wild reference to the mount object. Additionally, simplify some of the checks around VV_ROOT in unionfs_nodeget(). Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D33914 --- sys/fs/unionfs/union_subr.c | 19 +++++++++++-------- sys/fs/unionfs/union_vfsops.c | 5 +++++ sys/fs/unionfs/union_vnops.c | 11 ++--------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index e051d42c07cc..2b5754a560c7 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -334,12 +334,6 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp, } } - if ((uppervp == NULLVP || ump->um_uppervp != uppervp) || - (lowervp == NULLVP || ump->um_lowervp != lowervp)) { - /* dvp will be NULLVP only in case of root vnode. */ - if (dvp == NULLVP) - return (EINVAL); - } unp = malloc(sizeof(struct unionfs_node), M_UNIONFSNODE, M_WAITOK | M_ZERO); @@ -381,9 +375,18 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp, vp->v_type = vt; vp->v_data = unp; - if ((uppervp != NULLVP && ump->um_uppervp == uppervp) && - (lowervp != NULLVP && ump->um_lowervp == lowervp)) + /* + * TODO: This is an imperfect check, as there's no guarantee that + * the underlying filesystems will always return vnode pointers + * for the root inodes that match our cached values. To reduce + * the likelihood of failure, for example in the case where either + * vnode has been forcibly doomed, we check both pointers and set + * VV_ROOT if either matches. + */ + if (ump->um_uppervp == uppervp || ump->um_lowervp == lowervp) vp->v_vflag |= VV_ROOT; + KASSERT(dvp != NULL || (vp->v_vflag & VV_ROOT) != 0, + ("%s: NULL dvp for non-root vp %p", __func__, vp)); vn_lock_pair(lowervp, false, uppervp, false); error = insmntque1(vp, mp, NULL, NULL); diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index ea49d1e189da..dd6e7084ebc1 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -241,6 +241,8 @@ unionfs_domount(struct mount *mp) /* get root vnodes */ lowerrootvp = mp->mnt_vnodecovered; upperrootvp = ndp->ni_vp; + KASSERT(lowerrootvp != NULL, ("%s: NULL lower root vp", __func__)); + KASSERT(upperrootvp != NULL, ("%s: NULL upper root vp", __func__)); /* create unionfs_mount */ ump = malloc(sizeof(struct unionfs_mount), M_UNIONFSMNT, @@ -289,6 +291,9 @@ unionfs_domount(struct mount *mp) mp->mnt_data = NULL; return (error); } + KASSERT(ump->um_rootvp != NULL, ("rootvp cannot be NULL")); + KASSERT((ump->um_rootvp->v_vflag & VV_ROOT) != 0, + ("%s: rootvp without VV_ROOT", __func__)); lowermp = vfs_register_upper_from_vp(ump->um_lowervp, mp, &ump->um_lower_link); diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 19779112941e..c9d8aac12362 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -1908,8 +1908,6 @@ unionfs_revlock(struct vnode *vp, int flags) static int unionfs_lock(struct vop_lock1_args *ap) { - struct mount *mp; - struct unionfs_mount *ump; struct unionfs_node *unp; struct vnode *vp; struct vnode *uvp; @@ -1944,13 +1942,8 @@ unionfs_lock(struct vop_lock1_args *ap) if ((flags & LK_INTERLOCK) == 0) VI_LOCK(vp); - mp = vp->v_mount; - if (mp == NULL) - goto unionfs_lock_null_vnode; - - ump = MOUNTTOUNIONFSMOUNT(mp); unp = VTOUNIONFS(vp); - if (ump == NULL || unp == NULL) + if (unp == NULL) goto unionfs_lock_null_vnode; lvp = unp->un_lowervp; uvp = unp->un_uppervp; @@ -1967,7 +1960,7 @@ unionfs_lock(struct vop_lock1_args *ap) * (ex. vfs_domount: mounted vnode is already locked.) */ if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE && - vp == ump->um_rootvp) + (vp->v_vflag & VV_ROOT) != 0) flags |= LK_CANRECURSE; if (lvp != NULLVP) {