linux-revised-dentry-invalidation-20050121
authorChas Williams <chas@cmf.nrl.navy.mil>
Fri, 21 Jan 2005 19:13:33 +0000 (19:13 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 21 Jan 2005 19:13:33 +0000 (19:13 +0000)
FIXES 17337

"the latest 2.6 version of "tryflushdcachechildren" is probably
good enough for 2.2/2.4 as well. further, we can just call
d_invalidate() to make things less complicated. unification
is good.

its seen limited testing here under 2.4/2.6."

src/afs/afs.h
src/afs/afs_vcache.c

index c3f3bd6..16d29cb 100644 (file)
@@ -562,19 +562,13 @@ struct SimpleLocks {
 #define VREFCOUNT_SET(v, c)    atomic_set(&((vnode_t *) v)->v_count, c)
 #define VREFCOUNT_DEC(v)       atomic_dec(&((vnode_t *) v)->v_count)
 #define VREFCOUNT_INC(v)       atomic_inc(&((vnode_t *) v)->v_count)
-#define DLOCK()      spin_lock(&dcache_lock)
-#define DUNLOCK()    spin_unlock(&dcache_lock)
-#define DGET(d)      dget_locked(d)
-#define DCOUNT(d)    atomic_read(&(d)->d_count)
 #else
 #define VREFCOUNT(v)           ((v)->vrefCount)
 #define VREFCOUNT_SET(v, c)    (v)->vrefCount = c;
 #define VREFCOUNT_DEC(v)       (v)->vrefCount--;
 #define VREFCOUNT_INC(v)       (v)->vrefCount++;
-#define DLOCK()
-#define DUNLOCK()
-#define DGET(d)      dget(d)
-#define DCOUNT(d)    ((d)->d_count)
+#define d_unhash(d) list_empty(&(d)->d_hash)
+#define dget_locked(d) dget(d)
 #endif
 
 #define        AFS_MAXDV   0x7fffffff  /* largest dataversion number */
index c314b09..efc7503 100644 (file)
@@ -557,148 +557,6 @@ afs_RemoveVCB(struct VenusFid *afid)
     MReleaseWriteLock(&afs_xvcb);
 }
 
-#if defined(AFS_LINUX22_ENV) && !defined(AFS_LINUX26_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 (!DCOUNT(dentry)) {
-           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;
-#ifdef AFS_LINUX24_ENV
-       list_del_init(tmp);
-#else
-       list_del(tmp);
-       INIT_LIST_HEAD(tmp);
-#endif /* AFS_LINUX24_ENV */
-       dentry = list_entry(tmp, struct dentry, d_lru);
-
-#ifdef AFS_LINUX24_ENV
-       /* Unused dentry with a count? */
-       if (DCOUNT(dentry))
-           BUG();
-#endif
-       DGET(dentry);
-#ifdef AFS_LINUX24_ENV
-       list_del_init(&dentry->d_hash); /* d_drop */
-#else
-       list_del(&dentry->d_hash);
-       INIT_LIST_HEAD(&dentry->d_hash);
-#endif /* AFS_LINUX24_ENV */
-       DUNLOCK();
-       dput(dentry);
-       DLOCK();
-       if (!--found)
-           break;
-    }
-}
-
-/* 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 vcache *tvc)
-{
-    struct inode *ip = AFSTOI(tvc);
-    struct dentry *this_parent;
-    struct list_head *next;
-    struct list_head *cur;
-    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);
-
-       if (!list_empty(&dentry->d_hash) && !list_empty(&dentry->d_subdirs))
-           __shrink_dcache_parent(dentry);
-
-       if (!DCOUNT(dentry)) {
-           DGET(dentry);
-#ifdef AFS_LINUX24_ENV
-           list_del_init(&dentry->d_hash);     /* d_drop */
-#else
-           list_del(&dentry->d_hash);
-           INIT_LIST_HEAD(&dentry->d_hash);
-#endif /* AFS_LINUX24_ENV */
-           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);
-
-       if (!DCOUNT(dentry)) {
-           AFS_GUNLOCK();
-           DGET(dentry);
-           DUNLOCK();
-           d_drop(dentry);
-           dput(dentry);
-           AFS_GLOCK();
-           goto restart;
-       }
-    }
-    DUNLOCK();
-#endif
-}
-#endif /* AFS_LINUX22_ENV && !AFS_LINUX26_ENV */
-
 /*
  * afs_NewVCache
  *
@@ -834,14 +692,15 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp)
            }
 #elif defined(AFS_LINUX22_ENV)
            if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0) {
-#if defined(AFS_LINUX26_ENV)
                 struct dentry *dentry;
                 struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
                 AFS_FAST_HOLD(tvc);
                 AFS_GUNLOCK();
 
 restart:
+#if defined(AFS_LINUX24_ENV)
                 spin_lock(&dcache_lock);
+#endif
                 cur = head;
                 while ((cur = cur->next) != head) {
                     dentry = list_entry(cur, struct dentry, d_alias);
@@ -851,37 +710,23 @@ restart:
 
                    dget_locked(dentry);
 
-                   if (!list_empty(&dentry->d_subdirs)) {
-                        DUNLOCK();
-                       shrink_dcache_parent(dentry);
-                        DLOCK();
-                    }
-
-                   spin_lock(&dentry->d_lock);
-                   if (atomic_read(&dentry->d_count) > 1) {
-                       if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
-                           spin_unlock(&dentry->d_lock);
-                           spin_unlock(&dcache_lock);
-                           dput(dentry);
-                           goto inuse;
-                       }
-                   }
-
-                   __d_drop(dentry);
-                   spin_unlock(&dentry->d_lock);
+#if defined(AFS_LINUX24_ENV)
                    spin_unlock(&dcache_lock);
+#endif
+                   if (d_invalidate(dentry) == -EBUSY) {
+                       dput(dentry);
+                       /* perhaps lock and try to continue? (use cur as head?) */
+                       goto inuse;
+                   }
                    dput(dentry);
                    goto restart;
-
-                }
-                DUNLOCK();
-inuse:
-
-                AFS_GLOCK();
-                AFS_FAST_RELE(tvc);
-#else
-               afs_TryFlushDcacheChildren(tvc);
+               }                   
+#if defined(AFS_LINUX24_ENV)
+               spin_unlock(&dcache_lock);
 #endif
+           inuse:
+               AFS_GLOCK();
+               AFS_FAST_RELE(tvc);
            }
 #endif