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 333a7bb4cb9c..5e23152d04ad 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -927,9 +927,9 @@ EXPORT_SYMBOL_GPL(bd_unlink_disk_holder); | |||
927 | * when a disk has been changed -- either by a media change or online | 927 | * when a disk has been changed -- either by a media change or online |
928 | * resize. | 928 | * resize. |
929 | */ | 929 | */ |
930 | static void flush_disk(struct block_device *bdev) | 930 | static void flush_disk(struct block_device *bdev, bool kill_dirty) |
931 | { | 931 | { |
932 | if (__invalidate_device(bdev)) { | 932 | if (__invalidate_device(bdev, kill_dirty)) { |
933 | char name[BDEVNAME_SIZE] = ""; | 933 | char name[BDEVNAME_SIZE] = ""; |
934 | 934 | ||
935 | if (bdev->bd_disk) | 935 | if (bdev->bd_disk) |
@@ -966,7 +966,7 @@ void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) | |||
966 | "%s: detected capacity change from %lld to %lld\n", | 966 | "%s: detected capacity change from %lld to %lld\n", |
967 | name, bdev_size, disk_size); | 967 | name, bdev_size, disk_size); |
968 | i_size_write(bdev->bd_inode, disk_size); | 968 | i_size_write(bdev->bd_inode, disk_size); |
969 | flush_disk(bdev); | 969 | flush_disk(bdev, false); |
970 | } | 970 | } |
971 | } | 971 | } |
972 | EXPORT_SYMBOL(check_disk_size_change); | 972 | EXPORT_SYMBOL(check_disk_size_change); |
@@ -1019,7 +1019,7 @@ int check_disk_change(struct block_device *bdev) | |||
1019 | if (!(events & DISK_EVENT_MEDIA_CHANGE)) | 1019 | if (!(events & DISK_EVENT_MEDIA_CHANGE)) |
1020 | return 0; | 1020 | return 0; |
1021 | 1021 | ||
1022 | flush_disk(bdev); | 1022 | flush_disk(bdev, true); |
1023 | if (bdops->revalidate_disk) | 1023 | if (bdops->revalidate_disk) |
1024 | bdops->revalidate_disk(bdev->bd_disk); | 1024 | bdops->revalidate_disk(bdev->bd_disk); |
1025 | return 1; | 1025 | return 1; |
@@ -1601,7 +1601,7 @@ fail: | |||
1601 | } | 1601 | } |
1602 | EXPORT_SYMBOL(lookup_bdev); | 1602 | EXPORT_SYMBOL(lookup_bdev); |
1603 | 1603 | ||
1604 | int __invalidate_device(struct block_device *bdev) | 1604 | int __invalidate_device(struct block_device *bdev, bool kill_dirty) |
1605 | { | 1605 | { |
1606 | struct super_block *sb = get_super(bdev); | 1606 | struct super_block *sb = get_super(bdev); |
1607 | int res = 0; | 1607 | int res = 0; |
@@ -1614,7 +1614,7 @@ int __invalidate_device(struct block_device *bdev) | |||
1614 | * hold). | 1614 | * hold). |
1615 | */ | 1615 | */ |
1616 | shrink_dcache_sb(sb); | 1616 | shrink_dcache_sb(sb); |
1617 | res = invalidate_inodes(sb); | 1617 | res = invalidate_inodes(sb, kill_dirty); |
1618 | drop_super(sb); | 1618 | drop_super(sb); |
1619 | } | 1619 | } |
1620 | invalidate_bdev(bdev); | 1620 | invalidate_bdev(bdev); |
diff --git a/fs/inode.c b/fs/inode.c index da85e56378f3..c50d7feb87b1 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -540,11 +540,14 @@ void evict_inodes(struct super_block *sb) | |||
540 | /** | 540 | /** |
541 | * invalidate_inodes - attempt to free all inodes on a superblock | 541 | * invalidate_inodes - attempt to free all inodes on a superblock |
542 | * @sb: superblock to operate on | 542 | * @sb: superblock to operate on |
543 | * @kill_dirty: flag to guide handling of dirty inodes | ||
543 | * | 544 | * |
544 | * Attempts to free all inodes for a given superblock. If there were any | 545 | * Attempts to free all inodes for a given superblock. If there were any |
545 | * busy inodes return a non-zero value, else zero. | 546 | * busy inodes return a non-zero value, else zero. |
547 | * If @kill_dirty is set, discard dirty inodes too, otherwise treat | ||
548 | * them as busy. | ||
546 | */ | 549 | */ |
547 | int invalidate_inodes(struct super_block *sb) | 550 | int invalidate_inodes(struct super_block *sb, bool kill_dirty) |
548 | { | 551 | { |
549 | int busy = 0; | 552 | int busy = 0; |
550 | struct inode *inode, *next; | 553 | struct inode *inode, *next; |
@@ -556,6 +559,10 @@ int invalidate_inodes(struct super_block *sb) | |||
556 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | 559 | list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { |
557 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) | 560 | if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) |
558 | continue; | 561 | continue; |
562 | if (inode->i_state & I_DIRTY && !kill_dirty) { | ||
563 | busy = 1; | ||
564 | continue; | ||
565 | } | ||
559 | if (atomic_read(&inode->i_count)) { | 566 | if (atomic_read(&inode->i_count)) { |
560 | busy = 1; | 567 | busy = 1; |
561 | continue; | 568 | 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); |