mirror of
https://git.openafs.org/openafs.git
synced 2025-01-22 08:50:17 +00:00
rework-linux-newvcache-clean-up-dentries-20020123
previous pass wasn't SMP-happy. rework closer to original code.
This commit is contained in:
parent
0c239bbb3a
commit
e91fca84fd
@ -525,97 +525,6 @@ afs_RemoveVCB(afid)
|
||||
} /*afs_RemoveVCB*/
|
||||
|
||||
|
||||
#if defined(AFS_LINUX22_ENV)
|
||||
/* afs_TryFlushDcacheChildren -- Shakes loose vcache references held by
|
||||
* children of the dentry
|
||||
* LOCKS -- Called with afs_xvcache write locked. Drops and reaquires
|
||||
* AFS_GLOCK, so it can call dput, which may call iput, but
|
||||
* keeps afs_xvcache exclusively.
|
||||
*
|
||||
* Tree traversal algorithm from fs/dcache.c: select_parent()
|
||||
*/
|
||||
static void afs_TryFlushDcacheChildren(struct dentry *parent)
|
||||
{
|
||||
struct dentry *this_parent = parent;
|
||||
struct list_head *next;
|
||||
|
||||
repeat:
|
||||
next = this_parent->d_subdirs.next;
|
||||
resume:
|
||||
while (next != &this_parent->d_subdirs) {
|
||||
struct list_head *tmp = next;
|
||||
struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
|
||||
|
||||
next = tmp->next;
|
||||
if (!DCOUNT(dentry) && !dentry->d_inode) {
|
||||
DGET(dentry);
|
||||
DUNLOCK();
|
||||
AFS_GUNLOCK();
|
||||
d_drop(dentry);
|
||||
dput(dentry);
|
||||
AFS_GLOCK();
|
||||
DLOCK();
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
/*
|
||||
* Descend a level if the d_subdirs list is non-empty.
|
||||
*/
|
||||
if (!list_empty(&dentry->d_subdirs)) {
|
||||
this_parent = dentry;
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* All done at this level ... ascend and resume the search.
|
||||
*/
|
||||
if (this_parent != parent) {
|
||||
next = this_parent->d_child.next;
|
||||
this_parent = this_parent->d_parent;
|
||||
goto resume;
|
||||
}
|
||||
}
|
||||
|
||||
/* afs_TryFlushDcache -- Shakes loose vcache references held by the Linux
|
||||
* dcache.
|
||||
*
|
||||
* LOCKS -- Called with afs_xvcache write locked. Drops and reaquires
|
||||
* AFS_GLOCK, so it can call dput, which may call iput, but
|
||||
* keeps afs_xvcache exclusively.
|
||||
*/
|
||||
static void afs_TryFlushDcache(struct vcache *vcp)
|
||||
{
|
||||
struct inode *ip = (struct inode *) vcp;
|
||||
|
||||
DLOCK();
|
||||
retry:
|
||||
if (!list_empty(&ip->i_dentry)) {
|
||||
struct list_head *cur, *head = &ip->i_dentry;
|
||||
cur = head;
|
||||
while ((cur = cur->next) != head) {
|
||||
struct dentry *dentry = list_entry(cur, struct dentry, d_alias);
|
||||
|
||||
if (DCOUNT(dentry)) {
|
||||
afs_TryFlushDcacheChildren(dentry);
|
||||
}
|
||||
|
||||
if (!DCOUNT(dentry)) {
|
||||
DGET(dentry);
|
||||
DUNLOCK();
|
||||
AFS_GUNLOCK();
|
||||
d_drop(dentry);
|
||||
dput(dentry);
|
||||
AFS_GLOCK();
|
||||
DLOCK();
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
DUNLOCK();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* afs_NewVCache
|
||||
*
|
||||
@ -650,6 +559,63 @@ struct vcache *afs_NewVCache(struct VenusFid *afid, struct server *serverp,
|
||||
int code, fv_slept;
|
||||
|
||||
AFS_STATCNT(afs_NewVCache);
|
||||
#ifdef AFS_LINUX22_ENV
|
||||
if (!freeVCList) {
|
||||
/* Free some if possible. */
|
||||
struct afs_q *tq, *uq;
|
||||
int i; char *panicstr;
|
||||
int vmax = 2 * afs_cacheStats;
|
||||
int vn = VCACHE_FREE;
|
||||
|
||||
i = 0;
|
||||
for(tq = VLRU.prev; tq != &VLRU && vn > 0; tq = uq) {
|
||||
tvc = QTOV(tq);
|
||||
uq = QPrev(tq);
|
||||
if (tvc->states & CVFlushed)
|
||||
refpanic ("CVFlushed on VLRU");
|
||||
else if (i++ > vmax)
|
||||
refpanic ("Exceeded pool of AFS vnodes(VLRU cycle?)");
|
||||
else if (QNext(uq) != tq)
|
||||
refpanic ("VLRU inconsistent");
|
||||
|
||||
if (tvc == afs_globalVp)
|
||||
continue;
|
||||
|
||||
if ( VREFCOUNT(tvc) && tvc->opens == 0 ) {
|
||||
struct inode *ip = (struct inode*)tvc;
|
||||
if (list_empty(&ip->i_dentry)) {
|
||||
vn --;
|
||||
}
|
||||
else {
|
||||
struct list_head *cur;
|
||||
struct list_head *head = &ip->i_dentry;
|
||||
int all = 1;
|
||||
restart:
|
||||
DLOCK();
|
||||
cur = head;
|
||||
while ((cur = cur->next) != head) {
|
||||
struct dentry *dentry = list_entry(cur, struct dentry, d_alias);
|
||||
if (!DCOUNT(dentry)) {
|
||||
AFS_GUNLOCK();
|
||||
DGET(dentry);
|
||||
DUNLOCK();
|
||||
d_drop(dentry);
|
||||
dput(dentry);
|
||||
AFS_GLOCK();
|
||||
goto restart;
|
||||
}
|
||||
else {
|
||||
all = 0;
|
||||
}
|
||||
}
|
||||
DUNLOCK();
|
||||
if (all) vn --;
|
||||
}
|
||||
}
|
||||
if (tq == uq) break;
|
||||
}
|
||||
}
|
||||
#endif /* AFS_LINUX22_ENV */
|
||||
#ifdef AFS_OSF_ENV
|
||||
#ifdef AFS_OSF30_ENV
|
||||
if (afs_vcount >= afs_maxvcount)
|
||||
@ -740,10 +706,6 @@ struct vcache *afs_NewVCache(struct VenusFid *afid, struct server *serverp,
|
||||
continue; /* start over - may have raced. */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(AFS_LINUX22_ENV)
|
||||
if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0)
|
||||
afs_TryFlushDcache(tvc);
|
||||
#endif
|
||||
if (VREFCOUNT(tvc) == 0 && tvc->opens == 0
|
||||
&& (tvc->states & CUnlinkedDel) == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user