aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-02-25 14:13:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-02-25 14:13:26 -0500
commit638691a7a46a4ae9a7b56c603299e42d7f6e722e (patch)
treef744b3fbdd4704ef9ae122b67a14785b4a7a6b65 /fs
parent0a93ea2e897bd793cc0aaaddc397eff32ac8d6fe (diff)
parentf0b4f7e2f29af678bd9af43422c537dcb6008603 (diff)
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md: md: Fix - again - partition detection when array becomes active Fix over-zealous flush_disk when changing device size. md: avoid spinlock problem in blk_throtl_exit md: correctly handle probe of an 'mdp' device. md: don't set_capacity before array is active. md: Fix raid1->raid0 takeover
Diffstat (limited to 'fs')
-rw-r--r--fs/block_dev.c12
-rw-r--r--fs/inode.c9
-rw-r--r--fs/internal.h2
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 */
936static void flush_disk(struct block_device *bdev) 936static 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}
978EXPORT_SYMBOL(check_disk_size_change); 978EXPORT_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}
1607EXPORT_SYMBOL(lookup_bdev); 1607EXPORT_SYMBOL(lookup_bdev);
1608 1608
1609int __invalidate_device(struct block_device *bdev) 1609int __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 */
555int invalidate_inodes(struct super_block *sb) 558int 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 */
113extern int get_nr_dirty_inodes(void); 113extern int get_nr_dirty_inodes(void);
114extern void evict_inodes(struct super_block *); 114extern void evict_inodes(struct super_block *);
115extern int invalidate_inodes(struct super_block *); 115extern int invalidate_inodes(struct super_block *, bool);