aboutsummaryrefslogtreecommitdiff
path: root/sys/fs
diff options
context:
space:
mode:
authorJason A. Harmening <jah@FreeBSD.org>2025-11-28 07:36:24 +0000
committerJason A. Harmening <jah@FreeBSD.org>2025-12-12 06:32:05 +0000
commit5c025978fc3649730329994eecc56ada119e6717 (patch)
treee32890c5c339dbb3a66d4f69960e4fd0002e2d91 /sys/fs
parent38d60d453caad0f7377946d69d05d9421323f23f (diff)
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/unionfs/union_vnops.c45
1 files changed, 45 insertions, 0 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
@@ -2106,6 +2106,49 @@ unionfs_getwritemount(struct vop_getwritemount_args *ap)
}
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)
{
ap->a_vp->v_object = NULL;
@@ -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);