Try to decrease the number of bugs in unionfs after the VV_TEXT flag removal.

- Provide unionfs_add_writecount() which passes the writecount to the
  lower or upper vnode as appropriate.
- In unionfs VOP_RECLAIM() implementation, annulate unionfs
  writecounts from upper or lower vnode.  It is not clear that it is
  always correct to remove the all references from either lower or
  upper vnode, but we currently do not track which vnode get how many
  refs anyway.

Reported and tested by:	t_uemura@macome.co.jp
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Konstantin Belousov 2019-08-01 14:40:37 +00:00
parent 8e28ac6b96
commit 30d49d536b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=350504
2 changed files with 35 additions and 0 deletions

View File

@ -349,6 +349,13 @@ unionfs_noderem(struct vnode *vp, struct thread *td)
vp->v_vnlock = &(vp->v_lock);
vp->v_data = NULL;
vp->v_object = NULL;
if (vp->v_writecount > 0) {
if (uvp != NULL)
VOP_ADD_WRITECOUNT(uvp, -vp->v_writecount);
else if (lvp != NULL)
VOP_ADD_WRITECOUNT(lvp, -vp->v_writecount);
} else if (vp->v_writecount < 0)
vp->v_writecount = 0;
VI_UNLOCK(vp);
if (lvp != NULLVP)

View File

@ -2511,6 +2511,33 @@ unionfs_vptofh(struct vop_vptofh_args *ap)
return (EOPNOTSUPP);
}
static int
unionfs_add_writecount(struct vop_add_writecount_args *ap)
{
struct vnode *tvp, *vp;
struct unionfs_node *unp;
int error;
vp = ap->a_vp;
unp = VTOUNIONFS(vp);
tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp;
VI_LOCK(vp);
/* text refs are bypassed to lowervp */
VNASSERT(vp->v_writecount >= 0, vp, ("wrong null writecount"));
VNASSERT(vp->v_writecount + ap->a_inc >= 0, vp,
("wrong writecount inc %d", ap->a_inc));
if (tvp != NULL)
error = VOP_ADD_WRITECOUNT(tvp, ap->a_inc);
else if (vp->v_writecount < 0)
error = ETXTBSY;
else
error = 0;
if (error == 0)
vp->v_writecount += ap->a_inc;
VI_UNLOCK(vp);
return (error);
}
struct vop_vector unionfs_vnodeops = {
.vop_default = &default_vnodeops,
@ -2559,4 +2586,5 @@ struct vop_vector unionfs_vnodeops = {
.vop_whiteout = unionfs_whiteout,
.vop_write = unionfs_write,
.vop_vptofh = unionfs_vptofh,
.vop_add_writecount = unionfs_add_writecount,
};