git: f2c9d038bdee - main - FFS: implement special VOP_VPUT_PAIR().
Konstantin Belousov
kib at FreeBSD.org
Fri Feb 12 01:07:23 UTC 2021
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=f2c9d038bdee547be07c8b0404547617b71f2232
commit f2c9d038bdee547be07c8b0404547617b71f2232
Author: Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-01-27 18:09:53 +0000
Commit: Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-02-12 01:02:21 +0000
FFS: implement special VOP_VPUT_PAIR().
It cleans IN_NEEDSYNC flag on dvp before returning, by applying
ffs_syncvnode() until success or an error different from ERELOOKUP.
IN_NEEDSYNC cleanup is required to avoid creating holes in the directories
when extended into indirect block.
Reviewed by: chs, mckusick
Tested by: pho
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
---
sys/ufs/ffs/ffs_vnops.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index be2653e32adc..623b13790ce0 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -130,6 +130,7 @@ static vop_listextattr_t ffs_listextattr;
static vop_openextattr_t ffs_openextattr;
static vop_setextattr_t ffs_setextattr;
static vop_vptofh_t ffs_vptofh;
+static vop_vput_pair_t ffs_vput_pair;
/* Global vfs data structures for ufs. */
struct vop_vector ffs_vnodeops1 = {
@@ -146,6 +147,7 @@ struct vop_vector ffs_vnodeops1 = {
.vop_reallocblks = ffs_reallocblks,
.vop_write = ffs_write,
.vop_vptofh = ffs_vptofh,
+ .vop_vput_pair = ffs_vput_pair,
};
VFS_VOP_VECTOR_REGISTER(ffs_vnodeops1);
@@ -182,6 +184,7 @@ struct vop_vector ffs_vnodeops2 = {
.vop_openextattr = ffs_openextattr,
.vop_setextattr = ffs_setextattr,
.vop_vptofh = ffs_vptofh,
+ .vop_vput_pair = ffs_vput_pair,
};
VFS_VOP_VECTOR_REGISTER(ffs_vnodeops2);
@@ -1917,3 +1920,55 @@ ffs_getpages_async(struct vop_getpages_async_args *ap)
return (error);
}
+
+static int
+ffs_vput_pair(struct vop_vput_pair_args *ap)
+{
+ struct vnode *dvp, *vp, **vpp;
+ struct inode *dp;
+ int error, vp_locked;
+
+ dvp = ap->a_dvp;
+ dp = VTOI(dvp);
+ vpp = ap->a_vpp;
+ vp = vpp != NULL ? *vpp : NULL;
+
+ if ((dp->i_flag & IN_NEEDSYNC) == 0) {
+ vput(dvp);
+ if (vp != NULL && ap->a_unlock_vp)
+ vput(vp);
+ return (0);
+ }
+
+ if (vp != NULL) {
+ if (ap->a_unlock_vp) {
+ vput(vp);
+ } else {
+ MPASS(vp->v_type != VNON);
+ vp_locked = VOP_ISLOCKED(vp);
+ VOP_UNLOCK(vp);
+ }
+ }
+
+ do {
+ error = ffs_syncvnode(dvp, MNT_WAIT, 0);
+ } while (error == ERELOOKUP);
+ vput(dvp);
+
+ if (vp == NULL || ap->a_unlock_vp)
+ return (0);
+
+ /*
+ * It is possible that vp is reclaimed at this point. Only
+ * routines that call us with a_unlock_vp == false can find
+ * that their vp has been reclaimed. There are three areas
+ * that are affected:
+ * 1) vn_open_cred() - later VOPs could fail, but
+ * dead_open() returns 0 to simulate successful open.
+ * 2) ffs_snapshot() - creation of snapshot fails with EBADF.
+ * 3) NFS server (several places) - code is prepared to detect
+ * and respond to dead vnodes by returning ESTALE.
+ */
+ VOP_LOCK(vp, vp_locked | LK_RETRY);
+ return (0);
+}
More information about the dev-commits-src-all
mailing list