diff options
-rw-r--r-- | fs/dcache.c | 335 | ||||
-rw-r--r-- | fs/super.c | 1 | ||||
-rw-r--r-- | include/linux/fs.h | 4 |
3 files changed, 185 insertions, 155 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 6068c25b393c..3818d6ab76ca 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -61,7 +61,6 @@ static struct kmem_cache *dentry_cache __read_mostly; | |||
61 | static unsigned int d_hash_mask __read_mostly; | 61 | static unsigned int d_hash_mask __read_mostly; |
62 | static unsigned int d_hash_shift __read_mostly; | 62 | static unsigned int d_hash_shift __read_mostly; |
63 | static struct hlist_head *dentry_hashtable __read_mostly; | 63 | static struct hlist_head *dentry_hashtable __read_mostly; |
64 | static LIST_HEAD(dentry_unused); | ||
65 | 64 | ||
66 | /* Statistics gathering. */ | 65 | /* Statistics gathering. */ |
67 | struct dentry_stat_t dentry_stat = { | 66 | struct dentry_stat_t dentry_stat = { |
@@ -96,14 +95,6 @@ static void d_free(struct dentry *dentry) | |||
96 | call_rcu(&dentry->d_u.d_rcu, d_callback); | 95 | call_rcu(&dentry->d_u.d_rcu, d_callback); |
97 | } | 96 | } |
98 | 97 | ||
99 | static void dentry_lru_remove(struct dentry *dentry) | ||
100 | { | ||
101 | if (!list_empty(&dentry->d_lru)) { | ||
102 | list_del_init(&dentry->d_lru); | ||
103 | dentry_stat.nr_unused--; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /* | 98 | /* |
108 | * Release the dentry's inode, using the filesystem | 99 | * Release the dentry's inode, using the filesystem |
109 | * d_iput() operation if defined. | 100 | * d_iput() operation if defined. |
@@ -130,6 +121,41 @@ static void dentry_iput(struct dentry * dentry) | |||
130 | } | 121 | } |
131 | } | 122 | } |
132 | 123 | ||
124 | /* | ||
125 | * dentry_lru_(add|add_tail|del|del_init) must be called with dcache_lock held. | ||
126 | */ | ||
127 | static void dentry_lru_add(struct dentry *dentry) | ||
128 | { | ||
129 | list_add(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); | ||
130 | dentry->d_sb->s_nr_dentry_unused++; | ||
131 | dentry_stat.nr_unused++; | ||
132 | } | ||
133 | |||
134 | static void dentry_lru_add_tail(struct dentry *dentry) | ||
135 | { | ||
136 | list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru); | ||
137 | dentry->d_sb->s_nr_dentry_unused++; | ||
138 | dentry_stat.nr_unused++; | ||
139 | } | ||
140 | |||
141 | static void dentry_lru_del(struct dentry *dentry) | ||
142 | { | ||
143 | if (!list_empty(&dentry->d_lru)) { | ||
144 | list_del(&dentry->d_lru); | ||
145 | dentry->d_sb->s_nr_dentry_unused--; | ||
146 | dentry_stat.nr_unused--; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static void dentry_lru_del_init(struct dentry *dentry) | ||
151 | { | ||
152 | if (likely(!list_empty(&dentry->d_lru))) { | ||
153 | list_del_init(&dentry->d_lru); | ||
154 | dentry->d_sb->s_nr_dentry_unused--; | ||
155 | dentry_stat.nr_unused--; | ||
156 | } | ||
157 | } | ||
158 | |||
133 | /** | 159 | /** |
134 | * d_kill - kill dentry and return parent | 160 | * d_kill - kill dentry and return parent |
135 | * @dentry: dentry to kill | 161 | * @dentry: dentry to kill |
@@ -212,8 +238,7 @@ repeat: | |||
212 | goto kill_it; | 238 | goto kill_it; |
213 | if (list_empty(&dentry->d_lru)) { | 239 | if (list_empty(&dentry->d_lru)) { |
214 | dentry->d_flags |= DCACHE_REFERENCED; | 240 | dentry->d_flags |= DCACHE_REFERENCED; |
215 | list_add(&dentry->d_lru, &dentry_unused); | 241 | dentry_lru_add(dentry); |
216 | dentry_stat.nr_unused++; | ||
217 | } | 242 | } |
218 | spin_unlock(&dentry->d_lock); | 243 | spin_unlock(&dentry->d_lock); |
219 | spin_unlock(&dcache_lock); | 244 | spin_unlock(&dcache_lock); |
@@ -222,7 +247,8 @@ repeat: | |||
222 | unhash_it: | 247 | unhash_it: |
223 | __d_drop(dentry); | 248 | __d_drop(dentry); |
224 | kill_it: | 249 | kill_it: |
225 | dentry_lru_remove(dentry); | 250 | /* if dentry was on the d_lru list delete it from there */ |
251 | dentry_lru_del(dentry); | ||
226 | dentry = d_kill(dentry); | 252 | dentry = d_kill(dentry); |
227 | if (dentry) | 253 | if (dentry) |
228 | goto repeat; | 254 | goto repeat; |
@@ -290,7 +316,7 @@ int d_invalidate(struct dentry * dentry) | |||
290 | static inline struct dentry * __dget_locked(struct dentry *dentry) | 316 | static inline struct dentry * __dget_locked(struct dentry *dentry) |
291 | { | 317 | { |
292 | atomic_inc(&dentry->d_count); | 318 | atomic_inc(&dentry->d_count); |
293 | dentry_lru_remove(dentry); | 319 | dentry_lru_del_init(dentry); |
294 | return dentry; | 320 | return dentry; |
295 | } | 321 | } |
296 | 322 | ||
@@ -406,133 +432,167 @@ static void prune_one_dentry(struct dentry * dentry) | |||
406 | 432 | ||
407 | if (dentry->d_op && dentry->d_op->d_delete) | 433 | if (dentry->d_op && dentry->d_op->d_delete) |
408 | dentry->d_op->d_delete(dentry); | 434 | dentry->d_op->d_delete(dentry); |
409 | dentry_lru_remove(dentry); | 435 | dentry_lru_del_init(dentry); |
410 | __d_drop(dentry); | 436 | __d_drop(dentry); |
411 | dentry = d_kill(dentry); | 437 | dentry = d_kill(dentry); |
412 | spin_lock(&dcache_lock); | 438 | spin_lock(&dcache_lock); |
413 | } | 439 | } |
414 | } | 440 | } |
415 | 441 | ||
416 | /** | 442 | /* |
417 | * prune_dcache - shrink the dcache | 443 | * Shrink the dentry LRU on a given superblock. |
418 | * @count: number of entries to try and free | 444 | * @sb : superblock to shrink dentry LRU. |
419 | * @sb: if given, ignore dentries for other superblocks | 445 | * @count: If count is NULL, we prune all dentries on superblock. |
420 | * which are being unmounted. | 446 | * @flags: If flags is non-zero, we need to do special processing based on |
421 | * | 447 | * which flags are set. This means we don't need to maintain multiple |
422 | * Shrink the dcache. This is done when we need | 448 | * similar copies of this loop. |
423 | * more memory, or simply when we need to unmount | ||
424 | * something (at which point we need to unuse | ||
425 | * all dentries). | ||
426 | * | ||
427 | * This function may fail to free any resources if | ||
428 | * all the dentries are in use. | ||
429 | */ | 449 | */ |
430 | 450 | static void __shrink_dcache_sb(struct super_block *sb, int *count, int flags) | |
431 | static void prune_dcache(int count, struct super_block *sb) | ||
432 | { | 451 | { |
433 | spin_lock(&dcache_lock); | 452 | LIST_HEAD(referenced); |
434 | for (; count ; count--) { | 453 | LIST_HEAD(tmp); |
435 | struct dentry *dentry; | 454 | struct dentry *dentry; |
436 | struct list_head *tmp; | 455 | int cnt = 0; |
437 | struct rw_semaphore *s_umount; | ||
438 | |||
439 | cond_resched_lock(&dcache_lock); | ||
440 | 456 | ||
441 | tmp = dentry_unused.prev; | 457 | BUG_ON(!sb); |
442 | if (sb) { | 458 | BUG_ON((flags & DCACHE_REFERENCED) && count == NULL); |
443 | /* Try to find a dentry for this sb, but don't try | 459 | spin_lock(&dcache_lock); |
444 | * too hard, if they aren't near the tail they will | 460 | if (count != NULL) |
445 | * be moved down again soon | 461 | /* called from prune_dcache() and shrink_dcache_parent() */ |
462 | cnt = *count; | ||
463 | restart: | ||
464 | if (count == NULL) | ||
465 | list_splice_init(&sb->s_dentry_lru, &tmp); | ||
466 | else { | ||
467 | while (!list_empty(&sb->s_dentry_lru)) { | ||
468 | dentry = list_entry(sb->s_dentry_lru.prev, | ||
469 | struct dentry, d_lru); | ||
470 | BUG_ON(dentry->d_sb != sb); | ||
471 | |||
472 | spin_lock(&dentry->d_lock); | ||
473 | /* | ||
474 | * If we are honouring the DCACHE_REFERENCED flag and | ||
475 | * the dentry has this flag set, don't free it. Clear | ||
476 | * the flag and put it back on the LRU. | ||
446 | */ | 477 | */ |
447 | int skip = count; | 478 | if ((flags & DCACHE_REFERENCED) |
448 | while (skip && tmp != &dentry_unused && | 479 | && (dentry->d_flags & DCACHE_REFERENCED)) { |
449 | list_entry(tmp, struct dentry, d_lru)->d_sb != sb) { | 480 | dentry->d_flags &= ~DCACHE_REFERENCED; |
450 | skip--; | 481 | list_move_tail(&dentry->d_lru, &referenced); |
451 | tmp = tmp->prev; | 482 | spin_unlock(&dentry->d_lock); |
483 | } else { | ||
484 | list_move_tail(&dentry->d_lru, &tmp); | ||
485 | spin_unlock(&dentry->d_lock); | ||
486 | cnt--; | ||
487 | if (!cnt) | ||
488 | break; | ||
452 | } | 489 | } |
453 | } | 490 | } |
454 | if (tmp == &dentry_unused) | 491 | } |
455 | break; | 492 | while (!list_empty(&tmp)) { |
456 | list_del_init(tmp); | 493 | dentry = list_entry(tmp.prev, struct dentry, d_lru); |
457 | prefetch(dentry_unused.prev); | 494 | dentry_lru_del_init(dentry); |
458 | dentry_stat.nr_unused--; | 495 | spin_lock(&dentry->d_lock); |
459 | dentry = list_entry(tmp, struct dentry, d_lru); | ||
460 | |||
461 | spin_lock(&dentry->d_lock); | ||
462 | /* | 496 | /* |
463 | * We found an inuse dentry which was not removed from | 497 | * We found an inuse dentry which was not removed from |
464 | * dentry_unused because of laziness during lookup. Do not free | 498 | * the LRU because of laziness during lookup. Do not free |
465 | * it - just keep it off the dentry_unused list. | 499 | * it - just keep it off the LRU list. |
466 | */ | 500 | */ |
467 | if (atomic_read(&dentry->d_count)) { | 501 | if (atomic_read(&dentry->d_count)) { |
468 | spin_unlock(&dentry->d_lock); | 502 | spin_unlock(&dentry->d_lock); |
469 | continue; | 503 | continue; |
470 | } | 504 | } |
471 | /* If the dentry was recently referenced, don't free it. */ | 505 | prune_one_dentry(dentry); |
472 | if (dentry->d_flags & DCACHE_REFERENCED) { | 506 | /* dentry->d_lock was dropped in prune_one_dentry() */ |
473 | dentry->d_flags &= ~DCACHE_REFERENCED; | 507 | cond_resched_lock(&dcache_lock); |
474 | list_add(&dentry->d_lru, &dentry_unused); | 508 | } |
475 | dentry_stat.nr_unused++; | 509 | if (count == NULL && !list_empty(&sb->s_dentry_lru)) |
476 | spin_unlock(&dentry->d_lock); | 510 | goto restart; |
511 | if (count != NULL) | ||
512 | *count = cnt; | ||
513 | if (!list_empty(&referenced)) | ||
514 | list_splice(&referenced, &sb->s_dentry_lru); | ||
515 | spin_unlock(&dcache_lock); | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * prune_dcache - shrink the dcache | ||
520 | * @count: number of entries to try to free | ||
521 | * | ||
522 | * Shrink the dcache. This is done when we need more memory, or simply when we | ||
523 | * need to unmount something (at which point we need to unuse all dentries). | ||
524 | * | ||
525 | * This function may fail to free any resources if all the dentries are in use. | ||
526 | */ | ||
527 | static void prune_dcache(int count) | ||
528 | { | ||
529 | struct super_block *sb; | ||
530 | int w_count; | ||
531 | int unused = dentry_stat.nr_unused; | ||
532 | int prune_ratio; | ||
533 | int pruned; | ||
534 | |||
535 | if (unused == 0 || count == 0) | ||
536 | return; | ||
537 | spin_lock(&dcache_lock); | ||
538 | restart: | ||
539 | if (count >= unused) | ||
540 | prune_ratio = 1; | ||
541 | else | ||
542 | prune_ratio = unused / count; | ||
543 | spin_lock(&sb_lock); | ||
544 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
545 | if (sb->s_nr_dentry_unused == 0) | ||
477 | continue; | 546 | continue; |
478 | } | 547 | sb->s_count++; |
479 | /* | 548 | /* Now, we reclaim unused dentrins with fairness. |
480 | * If the dentry is not DCACHED_REFERENCED, it is time | 549 | * We reclaim them same percentage from each superblock. |
481 | * to remove it from the dcache, provided the super block is | 550 | * We calculate number of dentries to scan on this sb |
482 | * NULL (which means we are trying to reclaim memory) | 551 | * as follows, but the implementation is arranged to avoid |
483 | * or this dentry belongs to the same super block that | 552 | * overflows: |
484 | * we want to shrink. | 553 | * number of dentries to scan on this sb = |
485 | */ | 554 | * count * (number of dentries on this sb / |
486 | /* | 555 | * number of dentries in the machine) |
487 | * If this dentry is for "my" filesystem, then I can prune it | ||
488 | * without taking the s_umount lock (I already hold it). | ||
489 | */ | 556 | */ |
490 | if (sb && dentry->d_sb == sb) { | 557 | spin_unlock(&sb_lock); |
491 | prune_one_dentry(dentry); | 558 | if (prune_ratio != 1) |
492 | continue; | 559 | w_count = (sb->s_nr_dentry_unused / prune_ratio) + 1; |
493 | } | 560 | else |
561 | w_count = sb->s_nr_dentry_unused; | ||
562 | pruned = w_count; | ||
494 | /* | 563 | /* |
495 | * ...otherwise we need to be sure this filesystem isn't being | 564 | * We need to be sure this filesystem isn't being unmounted, |
496 | * unmounted, otherwise we could race with | 565 | * otherwise we could race with generic_shutdown_super(), and |
497 | * generic_shutdown_super(), and end up holding a reference to | 566 | * end up holding a reference to an inode while the filesystem |
498 | * an inode while the filesystem is unmounted. | 567 | * is unmounted. So we try to get s_umount, and make sure |
499 | * So we try to get s_umount, and make sure s_root isn't NULL. | 568 | * s_root isn't NULL. |
500 | * (Take a local copy of s_umount to avoid a use-after-free of | ||
501 | * `dentry'). | ||
502 | */ | 569 | */ |
503 | s_umount = &dentry->d_sb->s_umount; | 570 | if (down_read_trylock(&sb->s_umount)) { |
504 | if (down_read_trylock(s_umount)) { | 571 | if ((sb->s_root != NULL) && |
505 | if (dentry->d_sb->s_root != NULL) { | 572 | (!list_empty(&sb->s_dentry_lru))) { |
506 | prune_one_dentry(dentry); | 573 | spin_unlock(&dcache_lock); |
507 | up_read(s_umount); | 574 | __shrink_dcache_sb(sb, &w_count, |
508 | continue; | 575 | DCACHE_REFERENCED); |
576 | pruned -= w_count; | ||
577 | spin_lock(&dcache_lock); | ||
509 | } | 578 | } |
510 | up_read(s_umount); | 579 | up_read(&sb->s_umount); |
511 | } | 580 | } |
512 | spin_unlock(&dentry->d_lock); | 581 | spin_lock(&sb_lock); |
582 | count -= pruned; | ||
513 | /* | 583 | /* |
514 | * Insert dentry at the head of the list as inserting at the | 584 | * restart only when sb is no longer on the list and |
515 | * tail leads to a cycle. | 585 | * we have more work to do. |
516 | */ | 586 | */ |
517 | list_add(&dentry->d_lru, &dentry_unused); | 587 | if (__put_super_and_need_restart(sb) && count > 0) { |
518 | dentry_stat.nr_unused++; | 588 | spin_unlock(&sb_lock); |
589 | goto restart; | ||
590 | } | ||
519 | } | 591 | } |
592 | spin_unlock(&sb_lock); | ||
520 | spin_unlock(&dcache_lock); | 593 | spin_unlock(&dcache_lock); |
521 | } | 594 | } |
522 | 595 | ||
523 | /* | ||
524 | * Shrink the dcache for the specified super block. | ||
525 | * This allows us to unmount a device without disturbing | ||
526 | * the dcache for the other devices. | ||
527 | * | ||
528 | * This implementation makes just two traversals of the | ||
529 | * unused list. On the first pass we move the selected | ||
530 | * dentries to the most recent end, and on the second | ||
531 | * pass we free them. The second pass must restart after | ||
532 | * each dput(), but since the target dentries are all at | ||
533 | * the end, it's really just a single traversal. | ||
534 | */ | ||
535 | |||
536 | /** | 596 | /** |
537 | * shrink_dcache_sb - shrink dcache for a superblock | 597 | * shrink_dcache_sb - shrink dcache for a superblock |
538 | * @sb: superblock | 598 | * @sb: superblock |
@@ -541,44 +601,9 @@ static void prune_dcache(int count, struct super_block *sb) | |||
541 | * is used to free the dcache before unmounting a file | 601 | * is used to free the dcache before unmounting a file |
542 | * system | 602 | * system |
543 | */ | 603 | */ |
544 | |||
545 | void shrink_dcache_sb(struct super_block * sb) | 604 | void shrink_dcache_sb(struct super_block * sb) |
546 | { | 605 | { |
547 | struct list_head *tmp, *next; | 606 | __shrink_dcache_sb(sb, NULL, 0); |
548 | struct dentry *dentry; | ||
549 | |||
550 | /* | ||
551 | * Pass one ... move the dentries for the specified | ||
552 | * superblock to the most recent end of the unused list. | ||
553 | */ | ||
554 | spin_lock(&dcache_lock); | ||
555 | list_for_each_prev_safe(tmp, next, &dentry_unused) { | ||
556 | dentry = list_entry(tmp, struct dentry, d_lru); | ||
557 | if (dentry->d_sb != sb) | ||
558 | continue; | ||
559 | list_move_tail(tmp, &dentry_unused); | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | * Pass two ... free the dentries for this superblock. | ||
564 | */ | ||
565 | repeat: | ||
566 | list_for_each_prev_safe(tmp, next, &dentry_unused) { | ||
567 | dentry = list_entry(tmp, struct dentry, d_lru); | ||
568 | if (dentry->d_sb != sb) | ||
569 | continue; | ||
570 | dentry_stat.nr_unused--; | ||
571 | list_del_init(tmp); | ||
572 | spin_lock(&dentry->d_lock); | ||
573 | if (atomic_read(&dentry->d_count)) { | ||
574 | spin_unlock(&dentry->d_lock); | ||
575 | continue; | ||
576 | } | ||
577 | prune_one_dentry(dentry); | ||
578 | cond_resched_lock(&dcache_lock); | ||
579 | goto repeat; | ||
580 | } | ||
581 | spin_unlock(&dcache_lock); | ||
582 | } | 607 | } |
583 | 608 | ||
584 | /* | 609 | /* |
@@ -595,7 +620,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
595 | 620 | ||
596 | /* detach this root from the system */ | 621 | /* detach this root from the system */ |
597 | spin_lock(&dcache_lock); | 622 | spin_lock(&dcache_lock); |
598 | dentry_lru_remove(dentry); | 623 | dentry_lru_del_init(dentry); |
599 | __d_drop(dentry); | 624 | __d_drop(dentry); |
600 | spin_unlock(&dcache_lock); | 625 | spin_unlock(&dcache_lock); |
601 | 626 | ||
@@ -609,7 +634,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
609 | spin_lock(&dcache_lock); | 634 | spin_lock(&dcache_lock); |
610 | list_for_each_entry(loop, &dentry->d_subdirs, | 635 | list_for_each_entry(loop, &dentry->d_subdirs, |
611 | d_u.d_child) { | 636 | d_u.d_child) { |
612 | dentry_lru_remove(loop); | 637 | dentry_lru_del_init(loop); |
613 | __d_drop(loop); | 638 | __d_drop(loop); |
614 | cond_resched_lock(&dcache_lock); | 639 | cond_resched_lock(&dcache_lock); |
615 | } | 640 | } |
@@ -791,14 +816,13 @@ resume: | |||
791 | struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); | 816 | struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); |
792 | next = tmp->next; | 817 | next = tmp->next; |
793 | 818 | ||
794 | dentry_lru_remove(dentry); | 819 | dentry_lru_del_init(dentry); |
795 | /* | 820 | /* |
796 | * move only zero ref count dentries to the end | 821 | * move only zero ref count dentries to the end |
797 | * of the unused list for prune_dcache | 822 | * of the unused list for prune_dcache |
798 | */ | 823 | */ |
799 | if (!atomic_read(&dentry->d_count)) { | 824 | if (!atomic_read(&dentry->d_count)) { |
800 | list_add_tail(&dentry->d_lru, &dentry_unused); | 825 | dentry_lru_add_tail(dentry); |
801 | dentry_stat.nr_unused++; | ||
802 | found++; | 826 | found++; |
803 | } | 827 | } |
804 | 828 | ||
@@ -840,10 +864,11 @@ out: | |||
840 | 864 | ||
841 | void shrink_dcache_parent(struct dentry * parent) | 865 | void shrink_dcache_parent(struct dentry * parent) |
842 | { | 866 | { |
867 | struct super_block *sb = parent->d_sb; | ||
843 | int found; | 868 | int found; |
844 | 869 | ||
845 | while ((found = select_parent(parent)) != 0) | 870 | while ((found = select_parent(parent)) != 0) |
846 | prune_dcache(found, parent->d_sb); | 871 | __shrink_dcache_sb(sb, &found, 0); |
847 | } | 872 | } |
848 | 873 | ||
849 | /* | 874 | /* |
@@ -863,7 +888,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask) | |||
863 | if (nr) { | 888 | if (nr) { |
864 | if (!(gfp_mask & __GFP_FS)) | 889 | if (!(gfp_mask & __GFP_FS)) |
865 | return -1; | 890 | return -1; |
866 | prune_dcache(nr, NULL); | 891 | prune_dcache(nr); |
867 | } | 892 | } |
868 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; | 893 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; |
869 | } | 894 | } |
@@ -1215,7 +1240,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
1215 | * rcu_read_lock() and rcu_read_unlock() are used to disable preemption while | 1240 | * rcu_read_lock() and rcu_read_unlock() are used to disable preemption while |
1216 | * lookup is going on. | 1241 | * lookup is going on. |
1217 | * | 1242 | * |
1218 | * dentry_unused list is not updated even if lookup finds the required dentry | 1243 | * The dentry unused LRU is not updated even if lookup finds the required dentry |
1219 | * in there. It is updated in places such as prune_dcache, shrink_dcache_sb, | 1244 | * in there. It is updated in places such as prune_dcache, shrink_dcache_sb, |
1220 | * select_parent and __dget_locked. This laziness saves lookup from dcache_lock | 1245 | * select_parent and __dget_locked. This laziness saves lookup from dcache_lock |
1221 | * acquisition. | 1246 | * acquisition. |
diff --git a/fs/super.c b/fs/super.c index 453877c5697b..e931ae9511fe 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -70,6 +70,7 @@ static struct super_block *alloc_super(struct file_system_type *type) | |||
70 | INIT_LIST_HEAD(&s->s_instances); | 70 | INIT_LIST_HEAD(&s->s_instances); |
71 | INIT_HLIST_HEAD(&s->s_anon); | 71 | INIT_HLIST_HEAD(&s->s_anon); |
72 | INIT_LIST_HEAD(&s->s_inodes); | 72 | INIT_LIST_HEAD(&s->s_inodes); |
73 | INIT_LIST_HEAD(&s->s_dentry_lru); | ||
73 | init_rwsem(&s->s_umount); | 74 | init_rwsem(&s->s_umount); |
74 | mutex_init(&s->s_lock); | 75 | mutex_init(&s->s_lock); |
75 | lockdep_set_class(&s->s_umount, &type->s_umount_key); | 76 | lockdep_set_class(&s->s_umount, &type->s_umount_key); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index ff54ae4933f3..e5e6a244096c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1025,6 +1025,7 @@ extern int send_sigurg(struct fown_struct *fown); | |||
1025 | extern struct list_head super_blocks; | 1025 | extern struct list_head super_blocks; |
1026 | extern spinlock_t sb_lock; | 1026 | extern spinlock_t sb_lock; |
1027 | 1027 | ||
1028 | #define sb_entry(list) list_entry((list), struct super_block, s_list) | ||
1028 | #define S_BIAS (1<<30) | 1029 | #define S_BIAS (1<<30) |
1029 | struct super_block { | 1030 | struct super_block { |
1030 | struct list_head s_list; /* Keep this first */ | 1031 | struct list_head s_list; /* Keep this first */ |
@@ -1058,6 +1059,9 @@ struct super_block { | |||
1058 | struct list_head s_more_io; /* parked for more writeback */ | 1059 | struct list_head s_more_io; /* parked for more writeback */ |
1059 | struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ | 1060 | struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ |
1060 | struct list_head s_files; | 1061 | struct list_head s_files; |
1062 | /* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */ | ||
1063 | struct list_head s_dentry_lru; /* unused dentry lru */ | ||
1064 | int s_nr_dentry_unused; /* # of dentry on lru */ | ||
1061 | 1065 | ||
1062 | struct block_device *s_bdev; | 1066 | struct block_device *s_bdev; |
1063 | struct mtd_info *s_mtd; | 1067 | struct mtd_info *s_mtd; |