FFS: implement special VOP_VPUT_PAIR().

(cherry picked from commit f2c9d038bd)
This commit is contained in:
Konstantin Belousov 2021-01-27 20:09:53 +02:00
parent d96c8375a6
commit 1de6eb52fd

View file

@ -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);
}