]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE12-linux-dcache-flushing-experimental-20020819
authorChas Williams <chas@cmf.nrl.navy.mil>
Fri, 15 Nov 2002 13:29:28 +0000 (13:29 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 15 Nov 2002 13:29:28 +0000 (13:29 +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 2b9658304e302de717dfc9ce082125138e002e57..24817af5aa6baddb8c71d3bedc275c68efc8e0c8 100644 (file)
@@ -131,6 +131,6 @@ error_table 2 ZCM
        ec      CM_TRACE_RESIDCMD, "ResidencyCmd tvc 0x%x command %d fid (%d:%d.%d.%d)"
        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"
 end
 
index 28857055c27696ed30cda263229394cbef777610..5fa9e89789574950438644a9a0cf934a4876ca28 100644 (file)
@@ -467,6 +467,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 */
+               DUNLOCK();
+               dput(dentry);
+               DLOCK();
+               if (!--found)
+                       break;
+       }
+}
+
 /* afs_TryFlushDcacheChildren -- Shakes loose vcache references held by
  *                               children of the dentry
  *
@@ -485,51 +547,43 @@ static void afs_TryFlushDcacheChildren(struct vcache *tvc)
     struct list_head *head = &ip->i_dentry;
     struct dentry *dentry;
     
+    AFS_GUNLOCK();
 restart:
+#ifndef old_vcache_scheme
     DLOCK();
     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) {
-                   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;
-           }
-       }
-#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 (!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:
+    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 (!DCOUNT(dentry)) {
            AFS_GUNLOCK();
@@ -542,7 +596,7 @@ restart:
        }
     }
     DUNLOCK();
-
+#endif
 }
 #endif /* AFS_LINUX22_ENV */