]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
linux-dcache-flushing-experimental-20020819
authorChas Williams <chas@cmf.nrl.navy.mil>
Mon, 19 Aug 2002 23:06:02 +0000 (23:06 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 19 Aug 2002 23:06:02 +0000 (23:06 +0000)
shadow@dementia.org at least partly to blame.

hold the dcache lock only briefly; instead put dcache entries to be junked
onto a free list, by unhashing them, then grab the dcache lock, junk them,
and release it.

src/afs/afs_trace.et
src/afs/afs_vcache.c

index 934cca1729e8360e6295fb41bd70c91147e26c73..727ec0af55f9e24ccb34c92a40a5560bf2dc21fa 100644 (file)
@@ -159,7 +159,7 @@ error_table 2 ZCM
        ec      CM_TRACE_WAKE, "Wakeup: evp 0x%x, evp->seq 0x%x"
        ec      CM_TRACE_DENTRYDELETE, "d_delete inode 0x%x d_name %s/%s"
        ec      CM_TRACE_DENTRYIPUT, "d_iput inode 0x%x d_name %s/%s"
-       ec      CM_TRACE_TRYFLUSHDCACHECHILDREN, "TryFlushDcacheChildren ip 0x%x"
+       ec      CM_TRACE_TRYFLUSHDCACHECHILDREN, "TryFlushDcacheChildren ip 0x%x name %s parent %s"
        ec      CM_TRACE_DCACHEWAKE, "%s line %d: waking up waiters for 0x%x flags 0x%x"
 end
 
index 78999c526dcfad8091725ef18deabba6e0b8ffbc..1721f4c8e43fda99c1cbfb1f62bd8702d917266c 100644 (file)
@@ -463,6 +463,68 @@ static afs_int32 afs_QueueVCB(struct vcache *avc)
 }
 
 #ifdef AFS_LINUX22_ENV
+
+static void __shrink_dcache_parent(struct dentry * parent)
+{
+       struct dentry *this_parent = parent;
+       struct list_head *next;
+       int found = 0;
+       LIST_HEAD(afs_dentry_unused);
+
+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 (!atomic_read(&dentry->d_count)) {
+                       list_del(&dentry->d_lru);
+                       list_add(&dentry->d_lru, afs_dentry_unused.prev);
+                       found++;
+               }
+               /*
+                * 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;
+       }
+
+       for (;;) {
+               struct dentry *dentry;
+               struct list_head *tmp;
+
+               tmp = afs_dentry_unused.prev;
+
+               if (tmp == &afs_dentry_unused)
+                       break;
+               list_del_init(tmp);
+               dentry = list_entry(tmp, struct dentry, d_lru);
+
+               /* Unused dentry with a count? */
+               if (atomic_read(&dentry->d_count))
+                       BUG();
+
+               DGET(dentry);
+               list_del_init(&dentry->d_hash);         /* d_drop */
+               spin_unlock(&dcache_lock);
+               dput(dentry);
+               DLOCK();
+               if (!--found)
+                       break;
+       }
+}
+
 /* afs_TryFlushDcacheChildren -- Shakes loose vcache references held by
  *                               children of the dentry
  *
@@ -481,13 +543,31 @@ static void afs_TryFlushDcacheChildren(struct vcache *tvc)
     struct list_head *head = &ip->i_dentry;
     struct dentry *dentry;
     
-    afs_Trace1(afs_iclSetp, CM_TRACE_TRYFLUSHDCACHECHILDREN,
-              ICL_TYPE_POINTER, ip);
-#if 0
-    VN_HOLD(tvc);
     AFS_GUNLOCK();
-    d_prune_aliases(ip);
-    VN_RELE(tvc);
+restart:
+#ifndef old_vcache_scheme
+    DLOCK();
+    cur = head;
+    while ((cur = cur->next) != head) {
+       dentry = list_entry(cur, struct dentry, d_alias);
+       
+        afs_Trace3(afs_iclSetp, CM_TRACE_TRYFLUSHDCACHECHILDREN,
+                  ICL_TYPE_POINTER, ip,
+                  ICL_TYPE_STRING, dentry->d_parent->d_name.name,
+                  ICL_TYPE_STRING, dentry->d_name.name);
+
+        if (!list_empty(&dentry->d_hash) && !list_empty(&dentry->d_subdirs))
+           __shrink_dcache_parent(dentry);
+
+        if (!atomic_read(&dentry->d_count)) {
+           DGET(dentry);
+           list_del_init(&dentry->d_hash);     /* d_drop */
+           DUNLOCK();
+           dput(dentry);
+           goto restart;
+        }
+    }
+    DUNLOCK();
     AFS_GLOCK();
 #else
 restart:
@@ -495,46 +575,11 @@ restart:
     cur = head;
     while ((cur = cur->next) != head) {
        dentry = list_entry(cur, struct dentry, d_alias);
-#ifdef notdef
-       if (DCOUNT(dentry)) {
-           this_parent = dentry;
-       repeat:
-           next = this_parent->d_subdirs.next;
-       resume:
-           while (next && 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) {
-                   AFS_GUNLOCK();
-                   DGET(dchld);
-                   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;
-           }
-       }
-#endif
+
+        afs_Trace3(afs_iclSetp, CM_TRACE_TRYFLUSHDCACHECHILDREN,
+                  ICL_TYPE_POINTER, ip,
+                  ICL_TYPE_STRING, dentry->d_parent->d_name.name,
+                  ICL_TYPE_STRING, dentry->d_name.name);
 
        if (!DCOUNT(dentry)) {
            AFS_GUNLOCK();