- Use vrefcnt() where it is safe to do so instead of doing direct and

unlocked accesses to v_usecount.
 - Lock access to the buf lists in the various sync routines.  interlock
   locking could be avoided almost entirely in leaf filesystems if the
   fsync function had a generic helper.
This commit is contained in:
Jeff Roberson 2002-09-25 02:32:42 +00:00
parent c944ebed73
commit 4d93c0be1f
18 changed files with 71 additions and 60 deletions

View File

@ -528,7 +528,7 @@ fifo_close(ap)
if (fip->fi_writers == 0)
socantrcvmore(fip->fi_readsock);
}
if (vp->v_usecount > 1)
if (vrefcnt(vp) > 1)
return (0);
error1 = soclose(fip->fi_readsock);
error2 = soclose(fip->fi_writesock);

View File

@ -95,11 +95,15 @@ hpfs_fsync(ap)
* Flush all dirty buffers associated with a vnode.
*/
loop:
VI_LOCK(vp);
s = splbio();
for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
nbp = TAILQ_NEXT(bp, b_vnbufs);
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
VI_UNLOCK(vp);
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
VI_LOCK(vp);
continue;
}
if ((bp->b_flags & B_DELWRI) == 0)
panic("hpfs_fsync: not dirty");
bremfree(bp);
@ -107,19 +111,18 @@ hpfs_fsync(ap)
(void) bwrite(bp);
goto loop;
}
VI_LOCK(vp);
while (vp->v_numoutput) {
vp->v_iflag |= VI_BWAIT;
msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp), PRIBIO + 1,
"hpfsn", 0);
}
VI_UNLOCK(vp);
#ifdef DIAGNOSTIC
if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
vprint("hpfs_fsync: dirty", vp);
goto loop;
}
#endif
VI_UNLOCK(vp);
splx(s);
/*
@ -604,7 +607,7 @@ hpfs_inactive(ap)
return (error);
}
if (prtactive && vp->v_usecount != 0)
if (prtactive && vrefcnt(vp) != 0)
vprint("hpfs_inactive: pushing active", vp);
if (hp->h_flag & H_INVAL) {

View File

@ -653,7 +653,7 @@ msdosfs_reclaim(ap)
dep, dep->de_Name, dep->de_refcnt);
#endif
if (prtactive && vp->v_usecount != 0)
if (prtactive && vrefcnt(vp) != 0)
vprint("msdosfs_reclaim(): pushing active", vp);
/*
* Remove the denode from its hash chain.
@ -693,7 +693,7 @@ msdosfs_inactive(ap)
printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
#endif
if (prtactive && vp->v_usecount != 0)
if (prtactive && vrefcnt(vp) != 0)
vprint("msdosfs_inactive(): pushing active", vp);
/*
@ -725,8 +725,8 @@ msdosfs_inactive(ap)
* so that it can be reused immediately.
*/
#ifdef MSDOSFS_DEBUG
printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount,
dep->de_Name[0]);
printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n",
vrefcnt(vp), dep->de_Name[0]);
#endif
if (dep->de_Name[0] == SLOT_DELETED)
vrecycle(vp, NULL, td);

View File

@ -635,6 +635,7 @@ msdosfs_unmount(mp, mntflags, td)
{
struct vnode *vp = pmp->pm_devvp;
VI_LOCK(vp);
printf("msdosfs_umount(): just before calling VOP_CLOSE()\n");
printf("iflag %08lx, usecount %d, writecount %d, holdcnt %ld\n",
vp->vi_flag, vp->v_usecount, vp->v_writecount,
@ -652,6 +653,7 @@ msdosfs_unmount(mp, mntflags, td)
vp->v_socket, vp->v_tag,
((u_int *)vp->v_data)[0],
((u_int *)vp->v_data)[1]);
VI_UNLOCK(vp);
}
#endif
error = VOP_CLOSE(pmp->pm_devvp,
@ -747,13 +749,13 @@ msdosfs_sync(mp, waitfor, cred, td)
nvp = TAILQ_NEXT(vp, v_nmntvnodes);
mtx_unlock(&mntvnode_mtx);
mtx_lock(&vp->v_interlock);
VI_LOCK(vp);
dep = VTODE(vp);
if (vp->v_type == VNON ||
((dep->de_flag &
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0 &&
(TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY))) {
mtx_unlock(&vp->v_interlock);
VI_UNLOCK(vp);
mtx_lock(&mntvnode_mtx);
continue;
}

View File

@ -218,12 +218,12 @@ msdosfs_close(ap)
struct denode *dep = VTODE(vp);
struct timespec ts;
mtx_lock(&vp->v_interlock);
VI_LOCK(vp);
if (vp->v_usecount > 1) {
getnanotime(&ts);
DETIMES(dep, &ts, &ts, &ts);
}
mtx_unlock(&vp->v_interlock);
VI_UNLOCK(vp);
return 0;
}
@ -818,13 +818,15 @@ msdosfs_fsync(ap)
VI_LOCK(vp);
for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
nbp = TAILQ_NEXT(bp, b_vnbufs);
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
VI_UNLOCK(vp);
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
VI_LOCK(vp);
continue;
}
if ((bp->b_flags & B_DELWRI) == 0)
panic("msdosfs_fsync: not dirty");
bremfree(bp);
splx(s);
VI_UNLOCK(vp);
/* XXX Could do bawrite */
(void) bwrite(bp);
goto loop;
@ -834,13 +836,13 @@ msdosfs_fsync(ap)
(void) msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp),
PRIBIO + 1, "msdosfsn", 0);
}
VI_UNLOCK(vp);
#ifdef DIAGNOSTIC
if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
vprint("msdosfs_fsync: dirty", vp);
goto loop;
}
#endif
VI_UNLOCK(vp);
splx(s);
return (deupdat(VTODE(vp), ap->a_waitfor == MNT_WAIT));
}

View File

@ -488,7 +488,7 @@ ntfs_unmount(
/* Check if only system vnodes are rest */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if((ntmp->ntm_sysvn[i]) &&
(ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY);
(vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY);
/* Dereference all system vnodes */
for(i=0;i<NTFS_SYSNODESNUM;i++)

View File

@ -196,7 +196,7 @@ ntfs_inactive(ap)
dprintf(("ntfs_inactive: vnode: %p, ntnode: %d\n", vp, ip->i_number));
if (ntfs_prtactive && vp->v_usecount != 0)
if (ntfs_prtactive && vrefcnt(vp) != 0)
vprint("ntfs_inactive: pushing active", vp);
VOP_UNLOCK(vp, 0, ap->a_td);
@ -223,7 +223,7 @@ ntfs_reclaim(ap)
dprintf(("ntfs_reclaim: vnode: %p, ntnode: %d\n", vp, ip->i_number));
if (ntfs_prtactive && vp->v_usecount != 0)
if (ntfs_prtactive && vrefcnt(vp) != 0)
vprint("ntfs_reclaim: pushing active", vp);
if ((error = ntfs_ntget(ip)) != 0)

View File

@ -321,7 +321,7 @@ null_checkvp(vp, fil, lno)
while (null_checkvp_barrier) /*WAIT*/ ;
panic("null_checkvp");
}
if (a->null_lowervp->v_usecount < 1) {
if (vrefcnt(a->null_lowervp) < 1) {
int i; u_long *p;
printf("vp = %p, unref'ed lowervp\n", (void *)vp);
for (p = (u_long *) a, i = 0; i < 8; i++)
@ -333,8 +333,8 @@ null_checkvp(vp, fil, lno)
};
#ifdef notyet
printf("null %x/%d -> %x/%d [%s, %d]\n",
NULLTOV(a), NULLTOV(a)->v_usecount,
a->null_lowervp, a->null_lowervp->v_usecount,
NULLTOV(a), vrefcnt(NULLTOV(a)),
a->null_lowervp, vrefcnt(a->null_lowervp),
fil, lno);
#endif
return a->null_lowervp;

View File

@ -103,8 +103,8 @@ nwfs_sysctl_vnprint(SYSCTL_HANDLER_ARGS) {
LIST_FOREACH(np, nhpp, n_hash) {
vp = NWTOV(np);
vprint(NULL, vp);
printf("%s:%d:%d:%d:%d\n",np->n_name,vp->v_usecount,vp->v_holdcnt,
np->n_fid.f_id, np->n_fid.f_parent);
printf("%s:%d:%d:%d:%d\n",np->n_name,vrefcnt(vp),
vp->v_holdcnt,np->n_fid.f_id, np->n_fid.f_parent);
}
}
return 0;
@ -256,7 +256,7 @@ nwfs_reclaim(ap)
struct nwmount *nmp = VTONWFS(vp);
struct thread *td = ap->a_td;
NCPVNDEBUG("%s,%d\n", np->n_name, vp->v_usecount);
NCPVNDEBUG("%s,%d\n", np->n_name, vrefcnt(vp));
if (np->n_flag & NREFPARENT) {
np->n_flag &= ~NREFPARENT;
if (nwfs_lookupnp(nmp, np->n_parent, td, &dnp) == 0) {
@ -293,7 +293,7 @@ nwfs_inactive(ap)
struct nwnode *np = VTONW(vp);
int error;
NCPVNDEBUG("%s: %d\n", VTONW(vp)->n_name, vp->v_usecount);
NCPVNDEBUG("%s: %d\n", VTONW(vp)->n_name, vrefcnt(vp));
if (np->opened) {
error = nwfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, td, cred);

View File

@ -221,7 +221,7 @@ static int nwfs_mount(struct mount *mp, char *path, caddr_t data,
* Lose the lock but keep the ref.
*/
VOP_UNLOCK(vp, 0, curthread);
NCPVODEBUG("rootvp.vrefcnt=%d\n",vp->v_usecount);
NCPVODEBUG("rootvp.vrefcnt=%d\n",vrefcnt(vp));
return error;
bad:
if (nmp)
@ -490,10 +490,10 @@ nwfs_sync(mp, waitfor, cred, td)
goto loop;
nvp = TAILQ_NEXT(vp, v_nmntvnodes);
mtx_unlock(&mntvnode_mtx);
mtx_lock(&vp->v_interlock);
VI_LOCK(vp);
if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
waitfor == MNT_LAZY) {
mtx_unlock(&vp->v_interlock);
VI_UNLOCK(vp);
mtx_lock(&mntvnode_mtx);
continue;
}

View File

@ -490,7 +490,7 @@ nwfs_remove(ap)
struct nwmount *nmp = VTONWFS(vp);
int error;
if (vp->v_type == VDIR || np->opened || vp->v_usecount != 1)
if (vp->v_type == VDIR || np->opened || vrefcnt(vp) != 1)
return EPERM;
cache_purge(vp);
error = ncp_DeleteNSEntry(nmp, VTONW(dvp)->n_fid.f_id,
@ -533,7 +533,7 @@ nwfs_rename(ap)
goto out;
}
if (tvp && tvp->v_usecount > 1) {
if (tvp && vrefcnt(tvp) > 1) {
error = EBUSY;
goto out;
}

View File

@ -135,7 +135,7 @@ pfs_close(struct vop_close_args *va)
* Do nothing unless this is the last close and the node has a
* last-close handler.
*/
if (vn->v_usecount > 1 || pn->pn_close == NULL)
if (vrefcnt(vn) > 1 || pn->pn_close == NULL)
PFS_RETURN (0);
if (pvd->pvd_pid != NO_PID)

View File

@ -298,7 +298,7 @@ smbfs_reclaim(ap)
struct smbnode *np = VTOSMB(vp);
struct smbmount *smp = VTOSMBFS(vp);
SMBVDEBUG("%s,%d\n", np->n_name, vp->v_usecount);
SMBVDEBUG("%s,%d\n", np->n_name, vrefcnt(vp));
smbfs_hash_lock(smp, td);
@ -344,7 +344,7 @@ smbfs_inactive(ap)
struct smb_cred scred;
int error;
SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vp->v_usecount);
SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vrefcnt(vp));
if (np->n_opencount) {
error = smbfs_vinvalbuf(vp, V_SAVE, cred, td, 1);
smb_makescred(&scred, td, cred);

View File

@ -209,7 +209,7 @@ smbfs_mount(struct mount *mp, char *path, caddr_t data,
if (error)
goto bad;
VOP_UNLOCK(vp, 0, td);
SMBVDEBUG("root.v_usecount = %d\n", vp->v_usecount);
SMBVDEBUG("root.v_usecount = %d\n", vrefcnt(vp));
#ifdef DIAGNOSTICS
SMBERROR("mp=%p\n", mp);
@ -426,14 +426,17 @@ smbfs_sync(mp, waitfor, cred, td)
*/
if (vp->v_mount != mp)
goto loop;
VI_LOCK(vp);
#ifndef FB_RELENG3
if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
#else
if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
#endif
waitfor == MNT_LAZY)
waitfor == MNT_LAZY) {
VI_UNLOCK(vp);
continue;
if (vget(vp, LK_EXCLUSIVE, td))
}
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td))
goto loop;
error = VOP_FSYNC(vp, cred, waitfor, td);
if (error)

View File

@ -579,7 +579,7 @@ smbfs_remove(ap)
struct smb_cred scred;
int error;
if (vp->v_type == VDIR || np->n_opencount || vp->v_usecount != 1)
if (vp->v_type == VDIR || np->n_opencount || vrefcnt(vp) != 1)
return EPERM;
smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_delete(np, &scred);
@ -618,7 +618,7 @@ smbfs_rename(ap)
goto out;
}
if (tvp && tvp->v_usecount > 1) {
if (tvp && vrefcnt(tvp) > 1) {
error = EBUSY;
goto out;
}
@ -1183,6 +1183,7 @@ smbfs_lookup(ap)
int vpid;
vp = *vpp;
mp_fixme("Unlocked v_id access.");
vpid = vp->v_id;
if (dvp == vp) { /* lookup on current */
vref(vp);

View File

@ -328,7 +328,7 @@ umap_checkvp(vp, fil, lno)
while (umap_checkvp_barrier) /*WAIT*/ ;
panic("umap_checkvp");
}
if (a->umap_lowervp->v_usecount < 1) {
if (vrefcnt(a->umap_lowervp) < 1) {
int i; u_long *p;
printf("vp = %p, unref'ed lowervp\n", (void *)vp);
for (p = (u_long *) a, i = 0; i < 8; i++)

View File

@ -486,16 +486,16 @@ union_allocvp(vpp, mp, dvp, upperdvp, cnp, uppervp, lowervp, docache)
*/
UDEBUG(("Modify existing un %p vn %p upper %p(refs %d) -> %p(refs %d)\n",
un, un->un_vnode, un->un_uppervp,
(un->un_uppervp ? un->un_uppervp->v_usecount : -99),
(un->un_uppervp ? vrefcnt(un->un_uppervp) : -99),
uppervp,
(uppervp ? uppervp->v_usecount : -99)
(uppervp ? vrefcnt(uppervp) : -99)
));
if (uppervp != un->un_uppervp) {
KASSERT(uppervp == NULL || uppervp->v_usecount > 0, ("union_allocvp: too few refs %d (at least 1 required) on uppervp", uppervp->v_usecount));
KASSERT(uppervp == NULL || vrefcnt(uppervp) > 0, ("union_allocvp: too few refs %d (at least 1 required) on uppervp", vrefcnt(uppervp)));
union_newupper(un, uppervp);
} else if (uppervp) {
KASSERT(uppervp->v_usecount > 1, ("union_allocvp: too few refs %d (at least 2 required) on uppervp", uppervp->v_usecount));
KASSERT(vrefcnt(uppervp) > 1, ("union_allocvp: too few refs %d (at least 2 required) on uppervp", vrefcnt(uppervp)));
vrele(uppervp);
}
@ -776,7 +776,7 @@ union_copyup(un, docopy, cred, td)
lvp = un->un_lowervp;
KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
KASSERT(vrefcnt(uvp) > 0, ("copy: uvp refcount 0: %d", vrefcnt(uvp)));
if (docopy) {
/*
* XX - should not ignore errors
@ -798,9 +798,9 @@ union_copyup(un, docopy, cred, td)
VOP_UNLOCK(uvp, 0, td);
vn_finished_write(mp);
union_newupper(un, uvp);
KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
KASSERT(vrefcnt(uvp) > 0, ("copy: uvp refcount 0: %d", vrefcnt(uvp)));
union_vn_close(uvp, FWRITE, cred, td);
KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
KASSERT(vrefcnt(uvp) > 0, ("copy: uvp refcount 0: %d", vrefcnt(uvp)));
/*
* Subsequent IOs will go to the top layer, so
* call close on the lower vnode and open on the
@ -1279,10 +1279,10 @@ union_dircache(vp, td)
goto out;
/*vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, td);*/
UDEBUG(("ALLOCVP-3 %p ref %d\n", *vpp, (*vpp ? (*vpp)->v_usecount : -99)));
UDEBUG(("ALLOCVP-3 %p ref %d\n", *vpp, (*vpp ? vrefcnt(*vpp) : -99)));
VREF(*vpp);
error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, NULL, *vpp, NULLVP, 0);
UDEBUG(("ALLOCVP-3B %p ref %d\n", nvp, (*vpp ? (*vpp)->v_usecount : -99)));
UDEBUG(("ALLOCVP-3B %p ref %d\n", nvp, (*vpp ? vrefcnt(*vpp) : -99)));
if (error)
goto out;

View File

@ -117,7 +117,7 @@ union_lock_upper(struct union_node *un, struct thread *td)
VREF(uppervp);
vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
}
KASSERT((uppervp == NULL || uppervp->v_usecount > 0), ("uppervp usecount is 0"));
KASSERT((uppervp == NULL || vrefcnt(uppervp) > 0), ("uppervp usecount is 0"));
return(uppervp);
}
@ -361,10 +361,10 @@ union_lookup(ap)
"uerror %d upperdvp %p %d/%d, uppervp %p ref=%d/lck=%d\n",
uerror,
upperdvp,
upperdvp->v_usecount,
vrefcnt(upperdvp),
VOP_ISLOCKED(upperdvp, NULL),
uppervp,
(uppervp ? uppervp->v_usecount : -99),
(uppervp ? vrefcnt(uppervp) : -99),
(uppervp ? VOP_ISLOCKED(uppervp, NULL) : -99)
));
@ -542,7 +542,7 @@ union_lookup(ap)
error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
uppervp, lowervp, 1);
UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? ((*ap->a_vpp)->v_usecount) : -99));
UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? vrefcnt(*ap->a_vpp) : -99));
uppervp = NULL;
upperdvp = NULL;
@ -582,7 +582,7 @@ union_lookup(ap)
cnp->cn_flags &= ~LOCKPARENT;
UDEBUG(("Out %d vpp %p/%d lower %p upper %p\n", error, *ap->a_vpp,
((*ap->a_vpp) ? (*ap->a_vpp)->v_usecount : -99),
((*ap->a_vpp) ? vrefcnt(*ap->a_vpp) : -99),
lowervp, uppervp));
/*
@ -649,10 +649,10 @@ union_create(ap)
if (error == 0) {
mp = ap->a_dvp->v_mount;
VOP_UNLOCK(vp, 0, td);
UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vp->v_usecount));
UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vrefcnt(vp)));
error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
cnp, vp, NULLVP, 1);
UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_usecount));
UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vrefcnt(vp)));
}
union_unlock_upper(dvp, td);
}
@ -1491,10 +1491,10 @@ union_mkdir(ap)
if (error == 0) {
VOP_UNLOCK(vp, 0, td);
UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vp->v_usecount));
UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vrefcnt(vp)));
error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount,
ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1);
UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_usecount));
UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vrefcnt(vp)));
}
}
return (error);
@ -1723,7 +1723,7 @@ union_lock(ap)
*/
if (un->un_uppervp != NULLVP &&
(flags & LK_TYPE_MASK) == LK_EXCLUSIVE) {
if ((un->un_flags & UN_ULOCK) == 0 && vp->v_usecount) {
if ((un->un_flags & UN_ULOCK) == 0 && vrefcnt(vp)) {
error = vn_lock(un->un_uppervp, flags, td);
if (error) {
struct vop_unlock_args uap = { 0 };
@ -1760,7 +1760,7 @@ union_unlock(ap)
int error;
#if 0
KASSERT((un->un_uppervp == NULL || un->un_uppervp->v_usecount > 0), ("uppervp usecount is 0"));
KASSERT((un->un_uppervp == NULL || vrefcnt(un->un_uppervp) > 0), ("uppervp usecount is 0"));
#endif
error = vop_stdunlock(ap);