git: 4cbe4c48a7e5 - main - VFS: add VOP_GETLOWVNODE()

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 28 Nov 2023 17:33:22 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=4cbe4c48a7e574ec1bb919351d7a57d252b00b62

commit 4cbe4c48a7e574ec1bb919351d7a57d252b00b62
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-11-18 08:55:48 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-11-28 17:32:53 +0000

    VFS: add VOP_GETLOWVNODE()
    
    It is similar to VOP_GETWRITEMOUNT(), and for given vnode vp should
    return the lower vnode which would actually handle write to vp.
    Flags allow to specify FREAD or FWRITE for benefit of possible unionfs
    implementation.
    
    Reviewed by:    markj, Olivier Certner <olce.freebsd@certner.fr>
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D42603
---
 sys/fs/nullfs/null_vnops.c | 18 ++++++++++++++++++
 sys/kern/vfs_default.c     | 10 ++++++++++
 sys/kern/vnode_if.src      |  7 +++++++
 3 files changed, 35 insertions(+)

diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index 7607b44e36c3..c05e3394a9a6 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -1127,6 +1127,23 @@ null_vput_pair(struct vop_vput_pair_args *ap)
 	return (res);
 }
 
+static int
+null_getlowvnode(struct vop_getlowvnode_args *ap)
+{
+	struct vnode *vp, *vpl;
+
+	vp = ap->a_vp;
+	if (vn_lock(vp, LK_SHARED) != 0)
+		return (EBADF);
+
+	vpl = NULLVPTOLOWERVP(vp);
+	vhold(vpl);
+	VOP_UNLOCK(vp);
+	VOP_GETLOWVNODE(vpl, ap->a_vplp, ap->a_flags);
+	vdrop(vpl);
+	return (0);
+}
+
 /*
  * Global vfs data structures
  */
@@ -1139,6 +1156,7 @@ struct vop_vector null_vnodeops = {
 	.vop_bmap =		VOP_EOPNOTSUPP,
 	.vop_stat =		null_stat,
 	.vop_getattr =		null_getattr,
+	.vop_getlowvnode =	null_getlowvnode,
 	.vop_getwritemount =	null_getwritemount,
 	.vop_inactive =		null_inactive,
 	.vop_need_inactive =	null_need_inactive,
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index a342cbb80c9c..67c7ace5f72f 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -82,6 +82,7 @@ static int vop_stdgetpages_async(struct vop_getpages_async_args *ap);
 static int vop_stdread_pgcache(struct vop_read_pgcache_args *ap);
 static int vop_stdstat(struct vop_stat_args *ap);
 static int vop_stdvput_pair(struct vop_vput_pair_args *ap);
+static int vop_stdgetlowvnode(struct vop_getlowvnode_args *ap);
 
 /*
  * This vnode table stores what we want to do if the filesystem doesn't
@@ -112,6 +113,7 @@ struct vop_vector default_vnodeops = {
 	.vop_fsync =		VOP_NULL,
 	.vop_stat =		vop_stdstat,
 	.vop_fdatasync =	vop_stdfdatasync,
+	.vop_getlowvnode = 	vop_stdgetlowvnode,
 	.vop_getpages =		vop_stdgetpages,
 	.vop_getpages_async =	vop_stdgetpages_async,
 	.vop_getwritemount = 	vop_stdgetwritemount,
@@ -1607,3 +1609,11 @@ vop_stdvput_pair(struct vop_vput_pair_args *ap)
 		vput(vp);
 	return (0);
 }
+
+static int
+vop_stdgetlowvnode(struct vop_getlowvnode_args *ap)
+{
+	vref(ap->a_vp);
+	*ap->a_vplp = ap->a_vp;
+	return (0);
+}
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index c4051fdfe327..a2b6a7c8ff9f 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -468,6 +468,13 @@ vop_getwritemount {
 	OUT struct mount **mpp;
 };
 
+%% getwritevnode vp	= = =
+
+vop_getlowvnode {
+	IN struct vnode *vp;
+	OUT struct vnode **vplp;
+	IN int flags;
+};
 
 %% print	vp	- - -