Date: Fri, 12 Dec 2025 06:32:55 +0000 From: Jason A. Harmening <jah@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 5c025978fc36 - main - unionfs: Implement VOP_GETLOWVNODE Message-ID: <693bb717.2542b.2fc8a436@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by jah: URL: https://cgit.FreeBSD.org/src/commit/?id=5c025978fc3649730329994eecc56ada119e6717 commit 5c025978fc3649730329994eecc56ada119e6717 Author: Jason A. Harmening <jah@FreeBSD.org> AuthorDate: 2025-11-28 07:36:24 +0000 Commit: Jason A. Harmening <jah@FreeBSD.org> CommitDate: 2025-12-12 06:32:05 +0000 unionfs: Implement VOP_GETLOWVNODE This function returns the vnode that will be used to resolve the access type specified in the 'flags' argument, and is useful for optimal behavior of vn_copy_file_range(). While most filesystems can simply use the default implementation which returns the passed- in vnode, unionfs (like nullfs) ideally should resolve the access request to whichever base layer vnode will be used for the I/O. For unionfs, write accesses must be resolved through the upper vnode, while read accesses will be resolved through the upper vnode if present or the lower vnode otherwise. Provide a simple unionfs_getlowvnode() implementation that reflects this policy. Reviewed by: kib, olce Tested by: pho MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D53988 --- sys/fs/unionfs/union_vnops.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ sys/kern/vfs_default.c | 3 +-- sys/sys/vnode.h | 1 + 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 66fee97a07d5..060863866fcf 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -2105,6 +2105,49 @@ unionfs_getwritemount(struct vop_getwritemount_args *ap) return (error); } +static int +unionfs_getlowvnode(struct vop_getlowvnode_args *ap) +{ + struct unionfs_node *unp; + struct vnode *vp, *basevp; + + vp = ap->a_vp; + VI_LOCK(vp); + unp = VTOUNIONFS(vp); + if (unp == NULL) { + VI_UNLOCK(vp); + return (EBADF); + } + + if (ap->a_flags & FWRITE) { + basevp = unp->un_uppervp; + /* + * If write access is being requested, we expect the unionfs + * vnode has already been opened for write access and thus any + * necessary copy-up has already been performed. Return an + * error if that expectation is not met and an upper vnode has + * not been instantiated. We could proactively do a copy-up + * here, but that would require additional locking as well as + * the addition of a 'cred' argument to VOP_GETLOWVNODE(). + */ + if (basevp == NULL) { + VI_UNLOCK(vp); + return (EACCES); + } + } else { + basevp = (unp->un_uppervp != NULL) ? + unp->un_uppervp : unp->un_lowervp; + } + + VNASSERT(basevp != NULL, vp, ("%s: no upper/lower vnode", __func__)); + + vholdnz(basevp); + VI_UNLOCK(vp); + VOP_GETLOWVNODE(basevp, ap->a_vplp, ap->a_flags); + vdrop(basevp); + return (0); +} + static int unionfs_inactive(struct vop_inactive_args *ap) { @@ -3000,6 +3043,7 @@ struct vop_vector unionfs_vnodeops = { .vop_getattr = unionfs_getattr, .vop_getextattr = unionfs_getextattr, .vop_getwritemount = unionfs_getwritemount, + .vop_getlowvnode = unionfs_getlowvnode, .vop_inactive = unionfs_inactive, .vop_need_inactive = vop_stdneed_inactive, .vop_islocked = vop_stdislocked, @@ -3039,5 +3083,6 @@ struct vop_vector unionfs_vnodeops = { .vop_unp_bind = unionfs_unp_bind, .vop_unp_connect = unionfs_unp_connect, .vop_unp_detach = unionfs_unp_detach, + .vop_copy_file_range = vop_stdcopy_file_range, }; VFS_VOP_VECTOR_REGISTER(unionfs_vnodeops); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 4eca09aef145..468d5d18b02b 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -77,7 +77,6 @@ static int dirent_exists(struct vnode *vp, const char *dirname, static int vop_stdis_text(struct vop_is_text_args *ap); static int vop_stdunset_text(struct vop_unset_text_args *ap); static int vop_stdadd_writecount(struct vop_add_writecount_args *ap); -static int vop_stdcopy_file_range(struct vop_copy_file_range_args *ap); static int vop_stdfdatasync(struct vop_fdatasync_args *ap); static int vop_stdgetpages_async(struct vop_getpages_async_args *ap); static int vop_stdread_pgcache(struct vop_read_pgcache_args *ap); @@ -1426,7 +1425,7 @@ vfs_stdnosync(struct mount *mp, int waitfor) return (0); } -static int +int vop_stdcopy_file_range(struct vop_copy_file_range_args *ap) { int error; diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 0bf438a1b821..1a267e0e272c 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -906,6 +906,7 @@ int vop_stdunp_bind(struct vop_unp_bind_args *ap); int vop_stdunp_connect(struct vop_unp_connect_args *ap); int vop_stdunp_detach(struct vop_unp_detach_args *ap); int vop_stdadd_writecount_nomsync(struct vop_add_writecount_args *ap); +int vop_stdcopy_file_range(struct vop_copy_file_range_args *ap); int vop_eopnotsupp(struct vop_generic_args *ap); int vop_ebadf(struct vop_generic_args *ap); int vop_einval(struct vop_generic_args *ap);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?693bb717.2542b.2fc8a436>
