Merge to Fedora Core 2 kernel-2.6.8-1.521
[linux-2.6.git] / fs / dcache.c
index 1ab2caf..e779a1c 100644 (file)
@@ -86,6 +86,10 @@ static void d_free(struct dentry *dentry)
 {
        if (dentry->d_op && dentry->d_op->d_release)
                dentry->d_op->d_release(dentry);
+       if (dentry->d_extra_attributes) {
+               kfree(dentry->d_extra_attributes);
+               dentry->d_extra_attributes = NULL;
+       }
        call_rcu(&dentry->d_rcu, d_callback);
 }
 
@@ -633,7 +637,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(&this->d_lru);
+                               list_del_init(&this->d_lru);
                        }
 
                        /* 
@@ -729,6 +733,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
        dentry->d_sb = NULL;
        dentry->d_op = NULL;
        dentry->d_fsdata = NULL;
+       dentry->d_extra_attributes = NULL;
        dentry->d_mounted = 0;
        dentry->d_cookie = NULL;
        dentry->d_bucket = NULL;
@@ -1251,6 +1256,16 @@ already_unhashed:
        /* Unhash the target: dput() will then get rid of it */
        __d_drop(target);
 
+       /* flush any possible attributes */
+       if (dentry->d_extra_attributes) {
+               kfree(dentry->d_extra_attributes);
+               dentry->d_extra_attributes = NULL;
+       }
+       if (target->d_extra_attributes) {
+               kfree(target->d_extra_attributes);
+               target->d_extra_attributes = NULL;
+       }
+
        list_del(&dentry->d_child);
        list_del(&target->d_child);
 
@@ -1295,7 +1310,7 @@ already_unhashed:
  *
  * "buflen" should be positive. Caller holds the dcache_lock.
  */
-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
+char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
                        struct dentry *root, struct vfsmount *rootmnt,
                        char *buffer, int buflen)
 {
@@ -1363,6 +1378,8 @@ Elong:
        return ERR_PTR(-ENAMETOOLONG);
 }
 
+EXPORT_SYMBOL_GPL(__d_path);
+
 /* write full pathname into buffer and return start of pathname */
 char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
                                char *buf, int buflen)
@@ -1598,6 +1615,23 @@ static void __init dcache_init_early(void)
                INIT_HLIST_HEAD(&dentry_hashtable[loop]);
 }
 
+void flush_dentry_attributes (void)
+{
+       struct hlist_node *tmp;
+       struct dentry *dentry;
+       int i;
+
+       spin_lock(&dcache_lock);
+       for (i = 0; i <= d_hash_mask; i++)
+               hlist_for_each_entry(dentry, tmp, dentry_hashtable+i, d_hash) {
+                       kfree(dentry->d_extra_attributes);
+                       dentry->d_extra_attributes = NULL;
+               }
+       spin_unlock(&dcache_lock);
+}
+
+EXPORT_SYMBOL_GPL(flush_dentry_attributes);
+
 static void __init dcache_init(unsigned long mempages)
 {
        /*