This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / dcache.c
index 425c2e5..1ab2caf 100644 (file)
@@ -61,6 +61,9 @@ static unsigned int d_hash_shift;
 static struct hlist_head *dentry_hashtable;
 static LIST_HEAD(dentry_unused);
 
+static void prune_dcache(int count);
+
+
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {
        .age_limit = 45,
@@ -379,6 +382,8 @@ static void prune_dcache(int count)
                struct dentry *dentry;
                struct list_head *tmp;
 
+               cond_resched_lock(&dcache_lock);
+
                tmp = dentry_unused.prev;
                if (tmp == &dentry_unused)
                        break;
@@ -628,7 +633,7 @@ void shrink_dcache_anon(struct hlist_head *head)
                        struct dentry *this = hlist_entry(lp, struct dentry, d_hash);
                        if (!list_empty(&this->d_lru)) {
                                dentry_stat.nr_unused--;
-                               list_del_init(&this->d_lru);
+                               list_del(&this->d_lru);
                        }
 
                        /* 
@@ -683,6 +688,19 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
        struct dentry *dentry;
        char *dname;
 
+#define DENTRY_UNUSED_THRESHOLD 30000
+#define DENTRY_BATCH_COUNT 32
+       if (dentry_stat.nr_unused > DENTRY_UNUSED_THRESHOLD) {
+               int doit = 1;
+               spin_lock(&dcache_lock);
+               if (dentry_stat.nr_unused < DENTRY_UNUSED_THRESHOLD)
+                       doit = 0;
+               spin_unlock(&dcache_lock);
+               if (doit)
+                       prune_dcache(DENTRY_BATCH_COUNT);
+       }
+
        dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); 
        if (!dentry)
                return NULL;