diff options
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/inode.c b/fs/inode.c index f09148e07198..78a17b8859e1 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -575,6 +575,7 @@ static void dispose_list(struct list_head *head) | |||
575 | list_del_init(&inode->i_lru); | 575 | list_del_init(&inode->i_lru); |
576 | 576 | ||
577 | evict(inode); | 577 | evict(inode); |
578 | cond_resched(); | ||
578 | } | 579 | } |
579 | } | 580 | } |
580 | 581 | ||
@@ -592,6 +593,7 @@ void evict_inodes(struct super_block *sb) | |||
592 | struct inode *inode, *next; | 593 | struct inode *inode, *next; |
593 | LIST_HEAD(dispose); | 594 | LIST_HEAD(dispose); |
594 | 595 | ||
596 | again: | ||
595 | spin_lock(&sb->s_inode_list_lock); | 597 | spin_lock(&sb->s_inode_list_lock); |
596 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | 598 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { |
597 | if (atomic_read(&inode->i_count)) | 599 | if (atomic_read(&inode->i_count)) |
@@ -607,6 +609,18 @@ void evict_inodes(struct super_block *sb) | |||
607 | inode_lru_list_del(inode); | 609 | inode_lru_list_del(inode); |
608 | spin_unlock(&inode->i_lock); | 610 | spin_unlock(&inode->i_lock); |
609 | list_add(&inode->i_lru, &dispose); | 611 | list_add(&inode->i_lru, &dispose); |
612 | |||
613 | /* | ||
614 | * We can have a ton of inodes to evict at unmount time given | ||
615 | * enough memory, check to see if we need to go to sleep for a | ||
616 | * bit so we don't livelock. | ||
617 | */ | ||
618 | if (need_resched()) { | ||
619 | spin_unlock(&sb->s_inode_list_lock); | ||
620 | cond_resched(); | ||
621 | dispose_list(&dispose); | ||
622 | goto again; | ||
623 | } | ||
610 | } | 624 | } |
611 | spin_unlock(&sb->s_inode_list_lock); | 625 | spin_unlock(&sb->s_inode_list_lock); |
612 | 626 | ||