diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-25 20:49:35 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-10-25 21:27:18 -0400 |
| commit | 63997e98a3be68d7cec806d22bf9b02b2e1daabb (patch) | |
| tree | acd366273dc459d6b34e7f67216c06eb56117a4a | |
| parent | 9843b76aae80293f5b5a0e275360627508595ce5 (diff) | |
split invalidate_inodes()
Pull removal of fsnotify marks into generic_shutdown_super().
Split umount-time work into a new function - evict_inodes().
Make sure that invalidate_inodes() will be able to cope with
I_FREEING once we change locking in iput().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/inode.c | 46 | ||||
| -rw-r--r-- | fs/internal.h | 1 | ||||
| -rw-r--r-- | fs/notify/inode_mark.c | 2 | ||||
| -rw-r--r-- | fs/super.c | 8 |
4 files changed, 51 insertions, 6 deletions
diff --git a/fs/inode.c b/fs/inode.c index f6b3b52f1278..a6d60682f0fd 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -478,6 +478,49 @@ static void dispose_list(struct list_head *head) | |||
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | /** | 480 | /** |
| 481 | * evict_inodes - evict all evictable inodes for a superblock | ||
| 482 | * @sb: superblock to operate on | ||
| 483 | * | ||
| 484 | * Make sure that no inodes with zero refcount are retained. This is | ||
| 485 | * called by superblock shutdown after having MS_ACTIVE flag removed, | ||
| 486 | * so any inode reaching zero refcount during or after that call will | ||
| 487 | * be immediately evicted. | ||
| 488 | */ | ||
| 489 | void evict_inodes(struct super_block *sb) | ||
| 490 | { | ||
| 491 | struct inode *inode, *next; | ||
| 492 | LIST_HEAD(dispose); | ||
| 493 | |||
| 494 | down_write(&iprune_sem); | ||
| 495 | |||
| 496 | spin_lock(&inode_lock); | ||
| 497 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | ||
| 498 | if (atomic_read(&inode->i_count)) | ||
| 499 | continue; | ||
| 500 | |||
| 501 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { | ||
| 502 | WARN_ON(1); | ||
| 503 | continue; | ||
| 504 | } | ||
| 505 | |||
| 506 | inode->i_state |= I_FREEING; | ||
| 507 | |||
| 508 | /* | ||
| 509 | * Move the inode off the IO lists and LRU once I_FREEING is | ||
| 510 | * set so that it won't get moved back on there if it is dirty. | ||
| 511 | */ | ||
| 512 | list_move(&inode->i_lru, &dispose); | ||
| 513 | list_del_init(&inode->i_wb_list); | ||
| 514 | if (!(inode->i_state & (I_DIRTY | I_SYNC))) | ||
| 515 | percpu_counter_dec(&nr_inodes_unused); | ||
| 516 | } | ||
| 517 | spin_unlock(&inode_lock); | ||
| 518 | |||
| 519 | dispose_list(&dispose); | ||
| 520 | up_write(&iprune_sem); | ||
| 521 | } | ||
| 522 | |||
| 523 | /** | ||
| 481 | * invalidate_inodes - attempt to free all inodes on a superblock | 524 | * invalidate_inodes - attempt to free all inodes on a superblock |
| 482 | * @sb: superblock to operate on | 525 | * @sb: superblock to operate on |
| 483 | * | 526 | * |
| @@ -493,9 +536,8 @@ int invalidate_inodes(struct super_block *sb) | |||
| 493 | down_write(&iprune_sem); | 536 | down_write(&iprune_sem); |
| 494 | 537 | ||
| 495 | spin_lock(&inode_lock); | 538 | spin_lock(&inode_lock); |
| 496 | fsnotify_unmount_inodes(&sb->s_inodes); | ||
| 497 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | 539 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { |
| 498 | if (inode->i_state & I_NEW) | 540 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) |
| 499 | continue; | 541 | continue; |
| 500 | if (atomic_read(&inode->i_count)) { | 542 | if (atomic_read(&inode->i_count)) { |
| 501 | busy = 1; | 543 | busy = 1; |
diff --git a/fs/internal.h b/fs/internal.h index 4cc67eb6ed56..ebad3b90752d 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
| @@ -106,4 +106,5 @@ extern void release_open_intent(struct nameidata *); | |||
| 106 | * inode.c | 106 | * inode.c |
| 107 | */ | 107 | */ |
| 108 | extern int get_nr_dirty_inodes(void); | 108 | extern int get_nr_dirty_inodes(void); |
| 109 | extern int evict_inodes(struct super_block *); | ||
| 109 | extern int invalidate_inodes(struct super_block *); | 110 | extern int invalidate_inodes(struct super_block *); |
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 33297c005060..21ed10660b80 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
| @@ -240,6 +240,7 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
| 240 | { | 240 | { |
| 241 | struct inode *inode, *next_i, *need_iput = NULL; | 241 | struct inode *inode, *next_i, *need_iput = NULL; |
| 242 | 242 | ||
| 243 | spin_lock(&inode_lock); | ||
| 243 | list_for_each_entry_safe(inode, next_i, list, i_sb_list) { | 244 | list_for_each_entry_safe(inode, next_i, list, i_sb_list) { |
| 244 | struct inode *need_iput_tmp; | 245 | struct inode *need_iput_tmp; |
| 245 | 246 | ||
| @@ -297,4 +298,5 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
| 297 | 298 | ||
| 298 | spin_lock(&inode_lock); | 299 | spin_lock(&inode_lock); |
| 299 | } | 300 | } |
| 301 | spin_unlock(&inode_lock); | ||
| 300 | } | 302 | } |
diff --git a/fs/super.c b/fs/super.c index 8819e3a7ff20..b9c9869165db 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -273,14 +273,14 @@ void generic_shutdown_super(struct super_block *sb) | |||
| 273 | get_fs_excl(); | 273 | get_fs_excl(); |
| 274 | sb->s_flags &= ~MS_ACTIVE; | 274 | sb->s_flags &= ~MS_ACTIVE; |
| 275 | 275 | ||
| 276 | /* bad name - it should be evict_inodes() */ | 276 | fsnotify_unmount_inodes(&sb->s_inodes); |
| 277 | invalidate_inodes(sb); | 277 | |
| 278 | evict_inodes(sb); | ||
| 278 | 279 | ||
| 279 | if (sop->put_super) | 280 | if (sop->put_super) |
| 280 | sop->put_super(sb); | 281 | sop->put_super(sb); |
| 281 | 282 | ||
| 282 | /* Forget any remaining inodes */ | 283 | if (!list_empty(&sb->s_inodes)) { |
| 283 | if (invalidate_inodes(sb)) { | ||
| 284 | printk("VFS: Busy inodes after unmount of %s. " | 284 | printk("VFS: Busy inodes after unmount of %s. " |
| 285 | "Self-destruct in 5 seconds. Have a nice day...\n", | 285 | "Self-destruct in 5 seconds. Have a nice day...\n", |
| 286 | sb->s_id); | 286 | sb->s_id); |
