diff options
| -rw-r--r-- | fs/inode.c | 43 |
1 files changed, 16 insertions, 27 deletions
diff --git a/fs/inode.c b/fs/inode.c index 1bf2be41257a..f6b3b52f1278 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -477,15 +477,24 @@ static void dispose_list(struct list_head *head) | |||
| 477 | } | 477 | } |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | /* | 480 | /** |
| 481 | * Invalidate all inodes for a device. | 481 | * invalidate_inodes - attempt to free all inodes on a superblock |
| 482 | * @sb: superblock to operate on | ||
| 483 | * | ||
| 484 | * Attempts to free all inodes for a given superblock. If there were any | ||
| 485 | * busy inodes return a non-zero value, else zero. | ||
| 482 | */ | 486 | */ |
| 483 | static int invalidate_list(struct list_head *head, struct list_head *dispose) | 487 | int invalidate_inodes(struct super_block *sb) |
| 484 | { | 488 | { |
| 485 | struct inode *inode, *next; | ||
| 486 | int busy = 0; | 489 | int busy = 0; |
| 490 | struct inode *inode, *next; | ||
| 491 | LIST_HEAD(dispose); | ||
| 487 | 492 | ||
| 488 | list_for_each_entry_safe(inode, next, head, i_sb_list) { | 493 | down_write(&iprune_sem); |
| 494 | |||
| 495 | 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) { | ||
| 489 | if (inode->i_state & I_NEW) | 498 | if (inode->i_state & I_NEW) |
| 490 | continue; | 499 | continue; |
| 491 | if (atomic_read(&inode->i_count)) { | 500 | if (atomic_read(&inode->i_count)) { |
| @@ -499,34 +508,14 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose) | |||
| 499 | * Move the inode off the IO lists and LRU once I_FREEING is | 508 | * Move the inode off the IO lists and LRU once I_FREEING is |
| 500 | * set so that it won't get moved back on there if it is dirty. | 509 | * set so that it won't get moved back on there if it is dirty. |
| 501 | */ | 510 | */ |
| 502 | list_move(&inode->i_lru, dispose); | 511 | list_move(&inode->i_lru, &dispose); |
| 503 | list_del_init(&inode->i_wb_list); | 512 | list_del_init(&inode->i_wb_list); |
| 504 | if (!(inode->i_state & (I_DIRTY | I_SYNC))) | 513 | if (!(inode->i_state & (I_DIRTY | I_SYNC))) |
| 505 | percpu_counter_dec(&nr_inodes_unused); | 514 | percpu_counter_dec(&nr_inodes_unused); |
| 506 | } | 515 | } |
| 507 | return busy; | ||
| 508 | } | ||
| 509 | |||
| 510 | /** | ||
| 511 | * invalidate_inodes - discard the inodes on a device | ||
| 512 | * @sb: superblock | ||
| 513 | * | ||
| 514 | * Discard all of the inodes for a given superblock. If the discard | ||
| 515 | * fails because there are busy inodes then a non zero value is returned. | ||
| 516 | * If the discard is successful all the inodes have been discarded. | ||
| 517 | */ | ||
| 518 | int invalidate_inodes(struct super_block *sb) | ||
| 519 | { | ||
| 520 | int busy; | ||
| 521 | LIST_HEAD(throw_away); | ||
| 522 | |||
| 523 | down_write(&iprune_sem); | ||
| 524 | spin_lock(&inode_lock); | ||
| 525 | fsnotify_unmount_inodes(&sb->s_inodes); | ||
| 526 | busy = invalidate_list(&sb->s_inodes, &throw_away); | ||
| 527 | spin_unlock(&inode_lock); | 516 | spin_unlock(&inode_lock); |
| 528 | 517 | ||
| 529 | dispose_list(&throw_away); | 518 | dispose_list(&dispose); |
| 530 | up_write(&iprune_sem); | 519 | up_write(&iprune_sem); |
| 531 | 520 | ||
| 532 | return busy; | 521 | return busy; |
