diff options
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index a7c67cee5d83..d68631f18df1 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -68,15 +68,19 @@ struct dentry_stat_t dentry_stat = { | |||
68 | .age_limit = 45, | 68 | .age_limit = 45, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static void d_callback(struct rcu_head *head) | 71 | static void __d_free(struct dentry *dentry) |
72 | { | 72 | { |
73 | struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu); | ||
74 | |||
75 | if (dname_external(dentry)) | 73 | if (dname_external(dentry)) |
76 | kfree(dentry->d_name.name); | 74 | kfree(dentry->d_name.name); |
77 | kmem_cache_free(dentry_cache, dentry); | 75 | kmem_cache_free(dentry_cache, dentry); |
78 | } | 76 | } |
79 | 77 | ||
78 | static void d_callback(struct rcu_head *head) | ||
79 | { | ||
80 | struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu); | ||
81 | __d_free(dentry); | ||
82 | } | ||
83 | |||
80 | /* | 84 | /* |
81 | * no dcache_lock, please. The caller must decrement dentry_stat.nr_dentry | 85 | * no dcache_lock, please. The caller must decrement dentry_stat.nr_dentry |
82 | * inside dcache_lock. | 86 | * inside dcache_lock. |
@@ -85,7 +89,11 @@ static void d_free(struct dentry *dentry) | |||
85 | { | 89 | { |
86 | if (dentry->d_op && dentry->d_op->d_release) | 90 | if (dentry->d_op && dentry->d_op->d_release) |
87 | dentry->d_op->d_release(dentry); | 91 | dentry->d_op->d_release(dentry); |
88 | call_rcu(&dentry->d_u.d_rcu, d_callback); | 92 | /* if dentry was never inserted into hash, immediate free is OK */ |
93 | if (dentry->d_hash.pprev == NULL) | ||
94 | __d_free(dentry); | ||
95 | else | ||
96 | call_rcu(&dentry->d_u.d_rcu, d_callback); | ||
89 | } | 97 | } |
90 | 98 | ||
91 | /* | 99 | /* |