From: Derrick Brashear Date: Thu, 28 Mar 2002 20:43:03 +0000 (+0000) Subject: linux-dcache-create-negative-dentries-22-needs-while-still-avoiding-vlru-cycle-20020328 X-Git-Tag: openafs-devel_1_3_3~168 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=4beb9adb661bade7caff8adf40ecb3882ae7deac;hp=1ad668aee2c995e44974f89728b1d5e13470aec1 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. --- diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index e4ac272..13e91ab 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -462,6 +462,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 @@ -591,6 +644,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);