From: Derrick Brashear Date: Tue, 2 Apr 2002 03:13:26 +0000 (+0000) Subject: STABLE12-linux-dcache-create-negative-dentries-22-needs-while-still-avoiding-vlru... X-Git-Tag: openafs-stable-1_2_4~75 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=159e76add3366a2ab95b391fa0768b639bcccfa1;p=packages%2Fo%2Fopenafs.git STABLE12-linux-dcache-create-negative-dentries-22-needs-while-still-avoiding-vlru-cycle-20020328 based on patch by Srikanth Vishwanathan and modifications based on suggestions from Ted Anderson applicable to this part of the code. the original theory we operated under, namely that negative dentries could be banished entirely, causes file creation to stop working under linux 2.2 kernels. reverting that change means we have to deal with these negative dentries, and Srikanth's original suggested patch does so. (cherry picked from commit 4beb9adb661bade7caff8adf40ecb3882ae7deac) --- diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 82a9c28b5..e89bd61cc 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -466,6 +466,59 @@ static afs_int32 afs_QueueVCB(struct vcache *avc) return 0; } +#ifdef 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: + DLOCK(); + 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); + AFS_GUNLOCK(); + 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; + } + } + 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 */ /* * afs_RemoveVCB @@ -595,6 +648,10 @@ struct vcache *afs_NewVCache(struct VenusFid *afid, struct server *serverp, 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);