diff options
-rw-r--r-- | fs/dcache.c | 20 | ||||
-rw-r--r-- | include/linux/dcache.h | 1 |
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 | */ |
309 | static void dentry_lru_add(struct dentry *dentry) | 309 | static 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) | |||
320 | static void __dentry_lru_del(struct dentry *dentry) | 321 | static 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 | */ |
510 | void dput(struct dentry *dentry) | 512 | void dput(struct dentry *dentry) |
511 | { | 513 | { |
512 | if (!dentry) | 514 | if (unlikely(!dentry)) |
513 | return; | 515 | return; |
514 | 516 | ||
515 | repeat: | 517 | repeat: |
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 | ||
213 | extern seqlock_t rename_lock; | 214 | extern seqlock_t rename_lock; |