git: b7d28c4e9073 - stable/13 - ffs_vput_pair(): try harder to recover from the vnode reclaim
Konstantin Belousov
kib at FreeBSD.org
Wed Feb 24 07:58:57 UTC 2021
The branch stable/13 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=b7d28c4e9073299c2a18c5c7d8013f5f55eb73ce
commit b7d28c4e9073299c2a18c5c7d8013f5f55eb73ce
Author: Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-01-27 18:10:51 +0000
Commit: Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-02-24 07:45:01 +0000
ffs_vput_pair(): try harder to recover from the vnode reclaim
(cherry picked from commit 30bfb2fa0fad8e5bbcce369df46dcaa2e08324f3)
---
sys/ufs/ffs/ffs_vnops.c | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 623b13790ce0..2ac67adad5f2 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1924,8 +1924,11 @@ ffs_getpages_async(struct vop_getpages_async_args *ap)
static int
ffs_vput_pair(struct vop_vput_pair_args *ap)
{
- struct vnode *dvp, *vp, **vpp;
- struct inode *dp;
+ struct mount *mp;
+ struct vnode *dvp, *vp, *vp1, **vpp;
+ struct inode *dp, *ip;
+ ino_t ip_ino;
+ u_int64_t ip_gen;
int error, vp_locked;
dvp = ap->a_dvp;
@@ -1940,12 +1943,17 @@ ffs_vput_pair(struct vop_vput_pair_args *ap)
return (0);
}
+ mp = NULL;
if (vp != NULL) {
if (ap->a_unlock_vp) {
vput(vp);
} else {
MPASS(vp->v_type != VNON);
vp_locked = VOP_ISLOCKED(vp);
+ ip = VTOI(vp);
+ ip_ino = ip->i_number;
+ ip_gen = ip->i_gen;
+ mp = vp->v_mount;
VOP_UNLOCK(vp);
}
}
@@ -1957,6 +1965,7 @@ ffs_vput_pair(struct vop_vput_pair_args *ap)
if (vp == NULL || ap->a_unlock_vp)
return (0);
+ MPASS(mp != NULL);
/*
* It is possible that vp is reclaimed at this point. Only
@@ -1970,5 +1979,29 @@ ffs_vput_pair(struct vop_vput_pair_args *ap)
* and respond to dead vnodes by returning ESTALE.
*/
VOP_LOCK(vp, vp_locked | LK_RETRY);
- return (0);
+ if (!VN_IS_DOOMED(vp))
+ return (0);
+
+ /*
+ * Try harder to recover from reclaimed vp if reclaim was not
+ * because underlying inode was cleared. We saved inode
+ * number and inode generation, so we can try to reinstantiate
+ * exactly same version of inode. If this fails, return
+ * original doomed vnode and let caller to handle
+ * consequences.
+ *
+ * Note that callers must keep write started around
+ * VOP_VPUT_PAIR() calls, so it is safe to use mp without
+ * busying it.
+ */
+ VOP_UNLOCK(vp);
+ error = ffs_inotovp(mp, ip_ino, ip_gen, LK_EXCLUSIVE, &vp1,
+ FFSV_REPLACE_DOOMED);
+ if (error != 0) {
+ VOP_LOCK(vp, vp_locked | LK_RETRY);
+ } else {
+ vrele(vp);
+ *vpp = vp1;
+ }
+ return (error);
}
More information about the dev-commits-src-all
mailing list