diff options
author | Christoph Hellwig <hch@lst.de> | 2011-03-15 16:51:24 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-16 09:56:03 -0400 |
commit | bab1d9444d9a147f1dc3478dd06c16f490227f3e (patch) | |
tree | e5dd5220c976f604163c0b96945af3ee0be1fe24 | |
parent | 5229645bdc35f1cc43eb8b25b6993c8fa58b4b43 (diff) |
prune back iprune_sem
iprune_sem is continously giving us lockdep warnings because we do take it in
read mode in the reclaim path, but we're also doing non-NOFS allocations under
it taken in write mode.
Taking a bit deeper look at it I think it's fixable quite trivially:
- for invalidate_inodes we do not need iprune_sem at all. We have an active
reference on the superblock, so the filesystem is not going away until it
has finished.
- for evict_inodes we do need it, to make sure prune_icache has done it's
work before we tear down the superblock. But there is no reason to
hold it over the actual reclaim operation - it's enough to cycle through
it after the actual reclaim to make sure we wait for any pending
prune_icache to complete. We just have to remove the WARN_ON for
otherwise busy inodes as they can actually happen now.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/inode.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/fs/inode.c b/fs/inode.c index 0647d80accf6..9910c039f026 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -84,16 +84,13 @@ static struct hlist_head *inode_hashtable __read_mostly; | |||
84 | DEFINE_SPINLOCK(inode_lock); | 84 | DEFINE_SPINLOCK(inode_lock); |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * iprune_sem provides exclusion between the kswapd or try_to_free_pages | 87 | * iprune_sem provides exclusion between the icache shrinking and the |
88 | * icache shrinking path, and the umount path. Without this exclusion, | 88 | * umount path. |
89 | * by the time prune_icache calls iput for the inode whose pages it has | ||
90 | * been invalidating, or by the time it calls clear_inode & destroy_inode | ||
91 | * from its final dispose_list, the struct super_block they refer to | ||
92 | * (for inode->i_sb->s_op) may already have been freed and reused. | ||
93 | * | 89 | * |
94 | * We make this an rwsem because the fastpath is icache shrinking. In | 90 | * We don't actually need it to protect anything in the umount path, |
95 | * some cases a filesystem may be doing a significant amount of work in | 91 | * but only need to cycle through it to make sure any inode that |
96 | * its inode reclaim code, so this should improve parallelism. | 92 | * prune_icache took off the LRU list has been fully torn down by the |
93 | * time we are past evict_inodes. | ||
97 | */ | 94 | */ |
98 | static DECLARE_RWSEM(iprune_sem); | 95 | static DECLARE_RWSEM(iprune_sem); |
99 | 96 | ||
@@ -516,17 +513,12 @@ void evict_inodes(struct super_block *sb) | |||
516 | struct inode *inode, *next; | 513 | struct inode *inode, *next; |
517 | LIST_HEAD(dispose); | 514 | LIST_HEAD(dispose); |
518 | 515 | ||
519 | down_write(&iprune_sem); | ||
520 | |||
521 | spin_lock(&inode_lock); | 516 | spin_lock(&inode_lock); |
522 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | 517 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { |
523 | if (atomic_read(&inode->i_count)) | 518 | if (atomic_read(&inode->i_count)) |
524 | continue; | 519 | continue; |
525 | 520 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) | |
526 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { | ||
527 | WARN_ON(1); | ||
528 | continue; | 521 | continue; |
529 | } | ||
530 | 522 | ||
531 | inode->i_state |= I_FREEING; | 523 | inode->i_state |= I_FREEING; |
532 | 524 | ||
@@ -542,6 +534,13 @@ void evict_inodes(struct super_block *sb) | |||
542 | spin_unlock(&inode_lock); | 534 | spin_unlock(&inode_lock); |
543 | 535 | ||
544 | dispose_list(&dispose); | 536 | dispose_list(&dispose); |
537 | |||
538 | /* | ||
539 | * Cycle through iprune_sem to make sure any inode that prune_icache | ||
540 | * moved off the list before we took the lock has been fully torn | ||
541 | * down. | ||
542 | */ | ||
543 | down_write(&iprune_sem); | ||
545 | up_write(&iprune_sem); | 544 | up_write(&iprune_sem); |
546 | } | 545 | } |
547 | 546 | ||
@@ -561,8 +560,6 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) | |||
561 | struct inode *inode, *next; | 560 | struct inode *inode, *next; |
562 | LIST_HEAD(dispose); | 561 | LIST_HEAD(dispose); |
563 | 562 | ||
564 | down_write(&iprune_sem); | ||
565 | |||
566 | spin_lock(&inode_lock); | 563 | spin_lock(&inode_lock); |
567 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | 564 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { |
568 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) | 565 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) |
@@ -590,7 +587,6 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) | |||
590 | spin_unlock(&inode_lock); | 587 | spin_unlock(&inode_lock); |
591 | 588 | ||
592 | dispose_list(&dispose); | 589 | dispose_list(&dispose); |
593 | up_write(&iprune_sem); | ||
594 | 590 | ||
595 | return busy; | 591 | return busy; |
596 | } | 592 | } |