svn commit: r187887 - in stable/7/sys: . contrib/pf dev/ath/ath_hal
dev/cxgb fs/pseudofs
Konstantin Belousov
kib at FreeBSD.org
Thu Jan 29 03:03:58 PST 2009
Author: kib
Date: Thu Jan 29 11:03:57 2009
New Revision: 187887
URL: http://svn.freebsd.org/changeset/base/187887
Log:
MFC r186560:
After the pfs_vncache_mutex is dropped, another thread may attempt to
do pfs_vncache_alloc() for the same pfs_node and pid. In this case, we
could end up with two vnodes for the pair. Recheck the cache under the
locked pfs_vncache_mutex after all sleeping operations are done.
Do not call free() on the struct pfs_vdata after insmntque() failure,
because vp->v_data points to the structure, and pseudofs_reclaim()
frees it by the call to pfs_vncache_free().
MFC r186981 (by marcus):
vput the vnode.
Modified:
stable/7/sys/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/dev/ath/ath_hal/ (props changed)
stable/7/sys/dev/cxgb/ (props changed)
stable/7/sys/fs/pseudofs/pseudofs_vncache.c
Modified: stable/7/sys/fs/pseudofs/pseudofs_vncache.c
==============================================================================
--- stable/7/sys/fs/pseudofs/pseudofs_vncache.c Thu Jan 29 10:49:21 2009 (r187886)
+++ stable/7/sys/fs/pseudofs/pseudofs_vncache.c Thu Jan 29 11:03:57 2009 (r187887)
@@ -111,7 +111,7 @@ int
pfs_vncache_alloc(struct mount *mp, struct vnode **vpp,
struct pfs_node *pn, pid_t pid)
{
- struct pfs_vdata *pvd;
+ struct pfs_vdata *pvd, *pvd2;
struct vnode *vp;
int error;
@@ -146,19 +146,11 @@ retry:
}
}
mtx_unlock(&pfs_vncache_mutex);
- ++pfs_vncache_misses;
/* nope, get a new one */
MALLOC(pvd, struct pfs_vdata *, sizeof *pvd, M_PFSVNCACHE, M_WAITOK);
- mtx_lock(&pfs_vncache_mutex);
- if (++pfs_vncache_entries > pfs_vncache_maxentries)
- pfs_vncache_maxentries = pfs_vncache_entries;
- mtx_unlock(&pfs_vncache_mutex);
error = getnewvnode("pseudofs", mp, &pfs_vnodeops, vpp);
if (error) {
- mtx_lock(&pfs_vncache_mutex);
- --pfs_vncache_entries;
- mtx_unlock(&pfs_vncache_mutex);
FREE(pvd, M_PFSVNCACHE);
return (error);
}
@@ -200,14 +192,36 @@ retry:
vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread);
error = insmntque(*vpp, mp);
if (error != 0) {
- mtx_lock(&pfs_vncache_mutex);
- --pfs_vncache_entries;
- mtx_unlock(&pfs_vncache_mutex);
- FREE(pvd, M_PFSVNCACHE);
*vpp = NULLVP;
return (error);
}
+retry2:
mtx_lock(&pfs_vncache_mutex);
+ /*
+ * Other thread may race with us, creating the entry we are
+ * going to insert into the cache. Recheck after
+ * pfs_vncache_mutex is reacquired.
+ */
+ for (pvd2 = pfs_vncache; pvd2; pvd2 = pvd2->pvd_next) {
+ if (pvd2->pvd_pn == pn && pvd2->pvd_pid == pid &&
+ pvd2->pvd_vnode->v_mount == mp) {
+ vp = pvd2->pvd_vnode;
+ VI_LOCK(vp);
+ mtx_unlock(&pfs_vncache_mutex);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, curthread) == 0) {
+ ++pfs_vncache_hits;
+ vgone(*vpp);
+ vput(*vpp);
+ *vpp = vp;
+ cache_purge(vp);
+ return (0);
+ }
+ goto retry2;
+ }
+ }
+ ++pfs_vncache_misses;
+ if (++pfs_vncache_entries > pfs_vncache_maxentries)
+ pfs_vncache_maxentries = pfs_vncache_entries;
pvd->pvd_prev = NULL;
pvd->pvd_next = pfs_vncache;
if (pvd->pvd_next)
More information about the svn-src-all
mailing list