aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dcache.c20
-rw-r--r--include/linux/dcache.h1
2 files changed, 11 insertions, 10 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 761e31bacbc2..bf3c4f9569eb 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -308,8 +308,9 @@ static void dentry_unlink_inode(struct dentry * dentry)
308 */ 308 */
309static void dentry_lru_add(struct dentry *dentry) 309static void dentry_lru_add(struct dentry *dentry)
310{ 310{
311 if (list_empty(&dentry->d_lru)) { 311 if (unlikely(!(dentry->d_flags & DCACHE_LRU_LIST))) {
312 spin_lock(&dcache_lru_lock); 312 spin_lock(&dcache_lru_lock);
313 dentry->d_flags |= DCACHE_LRU_LIST;
313 list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); 314 list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
314 dentry->d_sb->s_nr_dentry_unused++; 315 dentry->d_sb->s_nr_dentry_unused++;
315 dentry_stat.nr_unused++; 316 dentry_stat.nr_unused++;
@@ -320,7 +321,7 @@ static void dentry_lru_add(struct dentry *dentry)
320static void __dentry_lru_del(struct dentry *dentry) 321static void __dentry_lru_del(struct dentry *dentry)
321{ 322{
322 list_del_init(&dentry->d_lru); 323 list_del_init(&dentry->d_lru);
323 dentry->d_flags &= ~DCACHE_SHRINK_LIST; 324 dentry->d_flags &= ~(DCACHE_SHRINK_LIST | DCACHE_LRU_LIST);
324 dentry->d_sb->s_nr_dentry_unused--; 325 dentry->d_sb->s_nr_dentry_unused--;
325 dentry_stat.nr_unused--; 326 dentry_stat.nr_unused--;
326} 327}
@@ -341,6 +342,7 @@ static void dentry_lru_move_list(struct dentry *dentry, struct list_head *list)
341{ 342{
342 spin_lock(&dcache_lru_lock); 343 spin_lock(&dcache_lru_lock);
343 if (list_empty(&dentry->d_lru)) { 344 if (list_empty(&dentry->d_lru)) {
345 dentry->d_flags |= DCACHE_LRU_LIST;
344 list_add_tail(&dentry->d_lru, list); 346 list_add_tail(&dentry->d_lru, list);
345 dentry->d_sb->s_nr_dentry_unused++; 347 dentry->d_sb->s_nr_dentry_unused++;
346 dentry_stat.nr_unused++; 348 dentry_stat.nr_unused++;
@@ -509,24 +511,22 @@ relock:
509 */ 511 */
510void dput(struct dentry *dentry) 512void dput(struct dentry *dentry)
511{ 513{
512 if (!dentry) 514 if (unlikely(!dentry))
513 return; 515 return;
514 516
515repeat: 517repeat:
516 if (dentry->d_lockref.count == 1)
517 might_sleep();
518 if (lockref_put_or_lock(&dentry->d_lockref)) 518 if (lockref_put_or_lock(&dentry->d_lockref))
519 return; 519 return;
520 520
521 if (dentry->d_flags & DCACHE_OP_DELETE) { 521 /* Unreachable? Get rid of it */
522 if (unlikely(d_unhashed(dentry)))
523 goto kill_it;
524
525 if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) {
522 if (dentry->d_op->d_delete(dentry)) 526 if (dentry->d_op->d_delete(dentry))
523 goto kill_it; 527 goto kill_it;
524 } 528 }
525 529
526 /* Unreachable? Get rid of it */
527 if (d_unhashed(dentry))
528 goto kill_it;
529
530 dentry->d_flags |= DCACHE_REFERENCED; 530 dentry->d_flags |= DCACHE_REFERENCED;
531 dentry_lru_add(dentry); 531 dentry_lru_add(dentry);
532 532
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index fe50f3db3af9..feaa8d88eef7 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -208,6 +208,7 @@ struct dentry_operations {
208#define DCACHE_MANAGED_DENTRY \ 208#define DCACHE_MANAGED_DENTRY \
209 (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) 209 (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
210 210
211#define DCACHE_LRU_LIST 0x80000
211#define DCACHE_DENTRY_KILLED 0x100000 212#define DCACHE_DENTRY_KILLED 0x100000
212 213
213extern seqlock_t rename_lock; 214extern seqlock_t rename_lock;