diff options
authorKonstantin Belousov <kib@FreeBSD.org>2021-01-28 22:30:53 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-02-12 01:02:20 +0000
commit49c117c193768b10f5fb1c5e4d6b88300cfbcdd6 (patch)
parentee965dfa64929227ced8adb68900c35f877480e7 (diff)
Add VOP_VPUT_PAIR() with trivial default implementation.
The VOP is intended to be used in situations where VFS has two referenced locked vnodes, typically a directory vnode dvp and a vnode vp that is linked from the directory, and at least dvp is vput(9)ed. The child vnode can be also vput-ed, but optionally left referenced and locked. There, at least UFS may need to do some actions with dvp which cannot be done while vp is also locked, so its lock might be dropped temporary. For instance, in some cases UFS needs to sync dvp to avoid filesystem state that is currently not handled by either kernel nor fsck. Having such VOP provides the neccessary context for filesystem which can do correct locking and handle potential reclamation of vp after relock. Trivial implementation does vput(dvp) and optionally vput(vp). Reviewed by: chs, mckusick Tested by: pho MFC after: 2 weeks Sponsored by: The FreeBSD Foundation
2 files changed, 24 insertions, 0 deletions
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index 4b96d9522ce3..382fbb2d9ace 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -92,6 +92,7 @@ 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);
static int vop_stdstat(struct vop_stat_args *ap);
+static int vop_stdvput_pair(struct vop_vput_pair_args *ap);
* This vnode table stores what we want to do if the filesystem doesn't
@@ -151,6 +152,7 @@ struct vop_vector default_vnodeops = {
.vop_unset_text = vop_stdunset_text,
.vop_add_writecount = vop_stdadd_writecount,
.vop_copy_file_range = vop_stdcopy_file_range,
+ .vop_vput_pair = vop_stdvput_pair,
@@ -1592,3 +1594,16 @@ vop_stdread_pgcache(struct vop_read_pgcache_args *ap __unused)
+static int
+vop_stdvput_pair(struct vop_vput_pair_args *ap)
+ struct vnode *dvp, *vp, **vpp;
+ dvp = ap->a_dvp;
+ vpp = ap->a_vpp;
+ vput(dvp);
+ if (vpp != NULL && ap->a_unlock_vp && (vp = *vpp) != NULL)
+ vput(vp);
+ return (0);
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index 5d15d4a0c863..b506237f385d 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -792,6 +792,15 @@ vop_copy_file_range {
+%% vput_pair dvp E - -
+vop_vput_pair {
+ IN struct vnode *dvp;
+ INOUT struct vnode **vpp;
+ IN bool unlock_vp;
# The VOPs below are spares at the end of the table to allow new VOPs to be
# added in stable branches without breaking the KBI. New VOPs in HEAD should
# be added above these spares. When merging a new VOP to a stable branch,