diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/block_dev.c | 12 | ||||
-rw-r--r-- | fs/inode.c | 9 | ||||
-rw-r--r-- | fs/internal.h | 2 |
3 files changed, 15 insertions, 8 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 94d41db62004..f05bf16cd979 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -933,9 +933,9 @@ EXPORT_SYMBOL_GPL(bd_unlink_disk_holder); | |||
933 | * when a disk has been changed -- either by a media change or online | 933 | * when a disk has been changed -- either by a media change or online |
934 | * resize. | 934 | * resize. |
935 | */ | 935 | */ |
936 | static void flush_disk(struct block_device *bdev) | 936 | static void flush_disk(struct block_device *bdev, bool kill_dirty) |
937 | { | 937 | { |
938 | if (__invalidate_device(bdev)) { | 938 | if (__invalidate_device(bdev, kill_dirty)) { |
939 | char name[BDEVNAME_SIZE] = ""; | 939 | char name[BDEVNAME_SIZE] = ""; |
940 | 940 | ||
941 | if (bdev->bd_disk) | 941 | if (bdev->bd_disk) |
@@ -972,7 +972,7 @@ void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) | |||
972 | "%s: detected capacity change from %lld to %lld\n", | 972 | "%s: detected capacity change from %lld to %lld\n", |
973 | name, bdev_size, disk_size); | 973 | name, bdev_size, disk_size); |
974 | i_size_write(bdev->bd_inode, disk_size); | 974 | i_size_write(bdev->bd_inode, disk_size); |
975 | flush_disk(bdev); | 975 | flush_disk(bdev, false); |
976 | } | 976 | } |
977 | } | 977 | } |
978 | EXPORT_SYMBOL(check_disk_size_change); | 978 | EXPORT_SYMBOL(check_disk_size_change); |
@@ -1025,7 +1025,7 @@ int check_disk_change(struct block_device *bdev) | |||
1025 | if (!(events & DISK_EVENT_MEDIA_CHANGE)) | 1025 | if (!(events & DISK_EVENT_MEDIA_CHANGE)) |
1026 | return 0; | 1026 | return 0; |
1027 | 1027 | ||
1028 | flush_disk(bdev); | 1028 | flush_disk(bdev, true); |
1029 | if (bdops->revalidate_disk) | 1029 | if (bdops->revalidate_disk) |
1030 | bdops->revalidate_disk(bdev->bd_disk); | 1030 | bdops->revalidate_disk(bdev->bd_disk); |
1031 | return 1; | 1031 | return 1; |
@@ -1606,7 +1606,7 @@ fail: | |||
1606 | } | 1606 | } |
1607 | EXPORT_SYMBOL(lookup_bdev); | 1607 | EXPORT_SYMBOL(lookup_bdev); |
1608 | 1608 | ||
1609 | int __invalidate_device(struct block_device *bdev) | 1609 | int __invalidate_device(struct block_device *bdev, bool kill_dirty) |
1610 | { | 1610 | { |
1611 | struct super_block *sb = get_super(bdev); | 1611 | struct super_block *sb = get_super(bdev); |
1612 | int res = 0; | 1612 | int res = 0; |
@@ -1619,7 +1619,7 @@ int __invalidate_device(struct block_device *bdev) | |||
1619 | * hold). | 1619 | * hold). |
1620 | */ | 1620 | */ |
1621 | shrink_dcache_sb(sb); | 1621 | shrink_dcache_sb(sb); |
1622 | res = invalidate_inodes(sb); | 1622 | res = invalidate_inodes(sb, kill_dirty); |
1623 | drop_super(sb); | 1623 | drop_super(sb); |
1624 | } | 1624 | } |
1625 | invalidate_bdev(bdev); | 1625 | invalidate_bdev(bdev); |
diff --git a/fs/inode.c b/fs/inode.c index 9c2b795ccc93..0647d80accf6 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -548,11 +548,14 @@ void evict_inodes(struct super_block *sb) | |||
548 | /** | 548 | /** |
549 | * invalidate_inodes - attempt to free all inodes on a superblock | 549 | * invalidate_inodes - attempt to free all inodes on a superblock |
550 | * @sb: superblock to operate on | 550 | * @sb: superblock to operate on |
551 | * @kill_dirty: flag to guide handling of dirty inodes | ||
551 | * | 552 | * |
552 | * Attempts to free all inodes for a given superblock. If there were any | 553 | * Attempts to free all inodes for a given superblock. If there were any |
553 | * busy inodes return a non-zero value, else zero. | 554 | * busy inodes return a non-zero value, else zero. |
555 | * If @kill_dirty is set, discard dirty inodes too, otherwise treat | ||
556 | * them as busy. | ||
554 | */ | 557 | */ |
555 | int invalidate_inodes(struct super_block *sb) | 558 | int invalidate_inodes(struct super_block *sb, bool kill_dirty) |
556 | { | 559 | { |
557 | int busy = 0; | 560 | int busy = 0; |
558 | struct inode *inode, *next; | 561 | struct inode *inode, *next; |
@@ -564,6 +567,10 @@ int invalidate_inodes(struct super_block *sb) | |||
564 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | 567 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { |
565 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) | 568 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) |
566 | continue; | 569 | continue; |
570 | if (inode->i_state & I_DIRTY && !kill_dirty) { | ||
571 | busy = 1; | ||
572 | continue; | ||
573 | } | ||
567 | if (atomic_read(&inode->i_count)) { | 574 | if (atomic_read(&inode->i_count)) { |
568 | busy = 1; | 575 | busy = 1; |
569 | continue; | 576 | continue; |
diff --git a/fs/internal.h b/fs/internal.h index 0663568b1247..9b976b57d7fe 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -112,4 +112,4 @@ extern void release_open_intent(struct nameidata *); | |||
112 | */ | 112 | */ |
113 | extern int get_nr_dirty_inodes(void); | 113 | extern int get_nr_dirty_inodes(void); |
114 | extern void evict_inodes(struct super_block *); | 114 | extern void evict_inodes(struct super_block *); |
115 | extern int invalidate_inodes(struct super_block *); | 115 | extern int invalidate_inodes(struct super_block *, bool); |