From ed5a1ec3ca173154f324c7dcbe8db65499f9919b Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Sat, 6 Apr 2002 05:57:23 +0000 Subject: [PATCH] STABLE12-linux-newvcache-more-simplification-20020405 based on suggestion from vsrikanth@in.ibm.com eliminate extra for loop, flatten function to drop dentries, fix locking error i introduced (cherry picked from commit 7747fce7e77e45ebb22728498052e96f527d2de0) --- src/afs/afs_vcache.c | 146 +++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 89 deletions(-) diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index e89bd61cc..ecfdb8c61 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -476,47 +476,71 @@ static afs_int32 afs_QueueVCB(struct vcache *avc) * * Tree traversal algorithm from fs/dcache.c: select_parent() */ -static void afs_TryFlushDcacheChildren(struct dentry *parent) +static void afs_TryFlushDcacheChildren(struct vcache *tvc) { - struct dentry *this_parent = parent; + struct inode *ip = AFSTOI(tvc); + struct dentry *this_parent; struct list_head *next; - - repeat: - next = this_parent->d_subdirs.next; - resume: + struct list_head *cur; + struct list_head *head = &ip->i_dentry; + struct dentry *dentry; + +restart: DLOCK(); - while (next != &this_parent->d_subdirs) { - struct list_head *tmp = next; - struct dentry *dentry = list_entry(tmp, struct dentry, d_child); + cur = head; + while ((cur = cur->next) != head) { + dentry = list_entry(cur, struct dentry, d_alias); + if (DCOUNT(dentry)) { + this_parent = dentry; + repeat: + next = this_parent->d_subdirs.next; + resume: + while (next != &this_parent->d_subdirs) { + struct list_head *tmp = next; + struct dentry *dchld = list_entry(tmp, struct dentry, d_child); + + next = tmp->next; + if (!DCOUNT(dchld) && !dchld->d_inode) { + DGET(dchld); + AFS_GUNLOCK(); + DUNLOCK(); + d_drop(dchld); + dput(dchld); + AFS_GLOCK(); + DLOCK(); + goto repeat; + } + /* + * Descend a level if the d_subdirs list is non-empty. + */ + if (!list_empty(&dchld->d_subdirs)) { + this_parent = dchld; + goto repeat; + } + } + + /* + * All done at this level ... ascend and resume the search. + */ + if (this_parent != dentry) { + next = this_parent->d_child.next; + this_parent = this_parent->d_parent; + goto resume; + } + } - next = tmp->next; - if (!DCOUNT(dentry) && !dentry->d_inode) { - DGET(dentry); + if (!DCOUNT(dentry)) { AFS_GUNLOCK(); + DGET(dentry); DUNLOCK(); d_drop(dentry); dput(dentry); AFS_GLOCK(); - goto repeat; - } - /* - * Descend a level if the d_subdirs list is non-empty. - */ - if (!list_empty(&dentry->d_subdirs)) { - this_parent = dentry; - goto repeat; + goto restart; } } DUNLOCK(); - /* - * 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; - } } #endif /* AFS_LINUX22_ENV */ @@ -612,67 +636,6 @@ 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_TryFlushDcacheChildren(dentry); - } - - 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) @@ -764,6 +727,11 @@ struct vcache *afs_NewVCache(struct VenusFid *afid, struct server *serverp, } } #endif +#if defined(AFS_LINUX22_ENV) + if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0) + afs_TryFlushDcacheChildren(tvc); +#endif + if (VREFCOUNT(tvc) == 0 && tvc->opens == 0 && (tvc->states & CUnlinkedDel) == 0) { code = afs_FlushVCache(tvc, &fv_slept); -- 2.39.5