aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c43
1 files changed, 16 insertions, 27 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 1bf2be41257..f6b3b52f127 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 */
483static int invalidate_list(struct list_head *head, struct list_head *dispose) 487int 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 */
518int 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;