aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/dcache.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index a7c67cee5d8..d68631f18df 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -68,15 +68,19 @@ struct dentry_stat_t dentry_stat = {
.age_limit = 45,
};
-static void d_callback(struct rcu_head *head)
+static void __d_free(struct dentry *dentry)
{
- struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu);
-
if (dname_external(dentry))
kfree(dentry->d_name.name);
kmem_cache_free(dentry_cache, dentry);
}
+static void d_callback(struct rcu_head *head)
+{
+ struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu);
+ __d_free(dentry);
+}
+
/*
* no dcache_lock, please. The caller must decrement dentry_stat.nr_dentry
* inside dcache_lock.
@@ -85,7 +89,11 @@ static void d_free(struct dentry *dentry)
{
if (dentry->d_op && dentry->d_op->d_release)
dentry->d_op->d_release(dentry);
- call_rcu(&dentry->d_u.d_rcu, d_callback);
+ /* if dentry was never inserted into hash, immediate free is OK */
+ if (dentry->d_hash.pprev == NULL)
+ __d_free(dentry);
+ else
+ call_rcu(&dentry->d_u.d_rcu, d_callback);
}
/*