diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-25 14:13:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-02-25 14:13:26 -0500 |
commit | 638691a7a46a4ae9a7b56c603299e42d7f6e722e (patch) | |
tree | f744b3fbdd4704ef9ae122b67a14785b4a7a6b65 | |
parent | 0a93ea2e897bd793cc0aaaddc397eff32ac8d6fe (diff) | |
parent | f0b4f7e2f29af678bd9af43422c537dcb6008603 (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
-rw-r--r-- | block/genhd.c | 2 | ||||
-rw-r--r-- | drivers/block/floppy.c | 2 | ||||
-rw-r--r-- | drivers/md/linear.c | 1 | ||||
-rw-r--r-- | drivers/md/md.c | 31 | ||||
-rw-r--r-- | drivers/md/md.h | 2 | ||||
-rw-r--r-- | drivers/md/multipath.c | 1 | ||||
-rw-r--r-- | drivers/md/raid0.c | 2 | ||||
-rw-r--r-- | drivers/md/raid1.c | 6 | ||||
-rw-r--r-- | drivers/md/raid10.c | 7 | ||||
-rw-r--r-- | drivers/md/raid5.c | 1 | ||||
-rw-r--r-- | fs/block_dev.c | 12 | ||||
-rw-r--r-- | fs/inode.c | 9 | ||||
-rw-r--r-- | fs/internal.h | 2 | ||||
-rw-r--r-- | include/linux/fs.h | 2 |
14 files changed, 56 insertions, 24 deletions
diff --git a/block/genhd.c b/block/genhd.c index 6a5b772aa201..cbf1112a885c 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -1355,7 +1355,7 @@ int invalidate_partition(struct gendisk *disk, int partno) | |||
1355 | struct block_device *bdev = bdget_disk(disk, partno); | 1355 | struct block_device *bdev = bdget_disk(disk, partno); |
1356 | if (bdev) { | 1356 | if (bdev) { |
1357 | fsync_bdev(bdev); | 1357 | fsync_bdev(bdev); |
1358 | res = __invalidate_device(bdev); | 1358 | res = __invalidate_device(bdev, true); |
1359 | bdput(bdev); | 1359 | bdput(bdev); |
1360 | } | 1360 | } |
1361 | return res; | 1361 | return res; |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b9ba04fc2b34..77fc76f8aea9 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -3281,7 +3281,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, | |||
3281 | struct block_device *bdev = opened_bdev[cnt]; | 3281 | struct block_device *bdev = opened_bdev[cnt]; |
3282 | if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) | 3282 | if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) |
3283 | continue; | 3283 | continue; |
3284 | __invalidate_device(bdev); | 3284 | __invalidate_device(bdev, true); |
3285 | } | 3285 | } |
3286 | mutex_unlock(&open_lock); | 3286 | mutex_unlock(&open_lock); |
3287 | } else { | 3287 | } else { |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 8a2f767f26d8..0ed7f6bc2a7f 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -216,7 +216,6 @@ static int linear_run (mddev_t *mddev) | |||
216 | 216 | ||
217 | if (md_check_no_bitmap(mddev)) | 217 | if (md_check_no_bitmap(mddev)) |
218 | return -EINVAL; | 218 | return -EINVAL; |
219 | mddev->queue->queue_lock = &mddev->queue->__queue_lock; | ||
220 | conf = linear_conf(mddev, mddev->raid_disks); | 219 | conf = linear_conf(mddev, mddev->raid_disks); |
221 | 220 | ||
222 | if (!conf) | 221 | if (!conf) |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 0cc30ecda4c1..818313e277e7 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -553,6 +553,9 @@ static mddev_t * mddev_find(dev_t unit) | |||
553 | { | 553 | { |
554 | mddev_t *mddev, *new = NULL; | 554 | mddev_t *mddev, *new = NULL; |
555 | 555 | ||
556 | if (unit && MAJOR(unit) != MD_MAJOR) | ||
557 | unit &= ~((1<<MdpMinorShift)-1); | ||
558 | |||
556 | retry: | 559 | retry: |
557 | spin_lock(&all_mddevs_lock); | 560 | spin_lock(&all_mddevs_lock); |
558 | 561 | ||
@@ -4138,10 +4141,10 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len) | |||
4138 | } | 4141 | } |
4139 | 4142 | ||
4140 | mddev->array_sectors = sectors; | 4143 | mddev->array_sectors = sectors; |
4141 | set_capacity(mddev->gendisk, mddev->array_sectors); | 4144 | if (mddev->pers) { |
4142 | if (mddev->pers) | 4145 | set_capacity(mddev->gendisk, mddev->array_sectors); |
4143 | revalidate_disk(mddev->gendisk); | 4146 | revalidate_disk(mddev->gendisk); |
4144 | 4147 | } | |
4145 | return len; | 4148 | return len; |
4146 | } | 4149 | } |
4147 | 4150 | ||
@@ -4624,6 +4627,7 @@ static int do_md_run(mddev_t *mddev) | |||
4624 | } | 4627 | } |
4625 | set_capacity(mddev->gendisk, mddev->array_sectors); | 4628 | set_capacity(mddev->gendisk, mddev->array_sectors); |
4626 | revalidate_disk(mddev->gendisk); | 4629 | revalidate_disk(mddev->gendisk); |
4630 | mddev->changed = 1; | ||
4627 | kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); | 4631 | kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); |
4628 | out: | 4632 | out: |
4629 | return err; | 4633 | return err; |
@@ -4712,6 +4716,7 @@ static void md_clean(mddev_t *mddev) | |||
4712 | mddev->sync_speed_min = mddev->sync_speed_max = 0; | 4716 | mddev->sync_speed_min = mddev->sync_speed_max = 0; |
4713 | mddev->recovery = 0; | 4717 | mddev->recovery = 0; |
4714 | mddev->in_sync = 0; | 4718 | mddev->in_sync = 0; |
4719 | mddev->changed = 0; | ||
4715 | mddev->degraded = 0; | 4720 | mddev->degraded = 0; |
4716 | mddev->safemode = 0; | 4721 | mddev->safemode = 0; |
4717 | mddev->bitmap_info.offset = 0; | 4722 | mddev->bitmap_info.offset = 0; |
@@ -4827,6 +4832,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
4827 | 4832 | ||
4828 | set_capacity(disk, 0); | 4833 | set_capacity(disk, 0); |
4829 | mutex_unlock(&mddev->open_mutex); | 4834 | mutex_unlock(&mddev->open_mutex); |
4835 | mddev->changed = 1; | ||
4830 | revalidate_disk(disk); | 4836 | revalidate_disk(disk); |
4831 | 4837 | ||
4832 | if (mddev->ro) | 4838 | if (mddev->ro) |
@@ -6011,7 +6017,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) | |||
6011 | atomic_inc(&mddev->openers); | 6017 | atomic_inc(&mddev->openers); |
6012 | mutex_unlock(&mddev->open_mutex); | 6018 | mutex_unlock(&mddev->open_mutex); |
6013 | 6019 | ||
6014 | check_disk_size_change(mddev->gendisk, bdev); | 6020 | check_disk_change(bdev); |
6015 | out: | 6021 | out: |
6016 | return err; | 6022 | return err; |
6017 | } | 6023 | } |
@@ -6026,6 +6032,21 @@ static int md_release(struct gendisk *disk, fmode_t mode) | |||
6026 | 6032 | ||
6027 | return 0; | 6033 | return 0; |
6028 | } | 6034 | } |
6035 | |||
6036 | static int md_media_changed(struct gendisk *disk) | ||
6037 | { | ||
6038 | mddev_t *mddev = disk->private_data; | ||
6039 | |||
6040 | return mddev->changed; | ||
6041 | } | ||
6042 | |||
6043 | static int md_revalidate(struct gendisk *disk) | ||
6044 | { | ||
6045 | mddev_t *mddev = disk->private_data; | ||
6046 | |||
6047 | mddev->changed = 0; | ||
6048 | return 0; | ||
6049 | } | ||
6029 | static const struct block_device_operations md_fops = | 6050 | static const struct block_device_operations md_fops = |
6030 | { | 6051 | { |
6031 | .owner = THIS_MODULE, | 6052 | .owner = THIS_MODULE, |
@@ -6036,6 +6057,8 @@ static const struct block_device_operations md_fops = | |||
6036 | .compat_ioctl = md_compat_ioctl, | 6057 | .compat_ioctl = md_compat_ioctl, |
6037 | #endif | 6058 | #endif |
6038 | .getgeo = md_getgeo, | 6059 | .getgeo = md_getgeo, |
6060 | .media_changed = md_media_changed, | ||
6061 | .revalidate_disk= md_revalidate, | ||
6039 | }; | 6062 | }; |
6040 | 6063 | ||
6041 | static int md_thread(void * arg) | 6064 | static int md_thread(void * arg) |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 7e90b8593b2a..12215d437fcc 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
@@ -274,6 +274,8 @@ struct mddev_s | |||
274 | atomic_t active; /* general refcount */ | 274 | atomic_t active; /* general refcount */ |
275 | atomic_t openers; /* number of active opens */ | 275 | atomic_t openers; /* number of active opens */ |
276 | 276 | ||
277 | int changed; /* True if we might need to | ||
278 | * reread partition info */ | ||
277 | int degraded; /* whether md should consider | 279 | int degraded; /* whether md should consider |
278 | * adding a spare | 280 | * adding a spare |
279 | */ | 281 | */ |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 6d7ddf32ef2e..3a62d440e27b 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -435,7 +435,6 @@ static int multipath_run (mddev_t *mddev) | |||
435 | * bookkeeping area. [whatever we allocate in multipath_run(), | 435 | * bookkeeping area. [whatever we allocate in multipath_run(), |
436 | * should be freed in multipath_stop()] | 436 | * should be freed in multipath_stop()] |
437 | */ | 437 | */ |
438 | mddev->queue->queue_lock = &mddev->queue->__queue_lock; | ||
439 | 438 | ||
440 | conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL); | 439 | conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL); |
441 | mddev->private = conf; | 440 | mddev->private = conf; |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 637a96855edb..c0ac457f1218 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -361,7 +361,6 @@ static int raid0_run(mddev_t *mddev) | |||
361 | if (md_check_no_bitmap(mddev)) | 361 | if (md_check_no_bitmap(mddev)) |
362 | return -EINVAL; | 362 | return -EINVAL; |
363 | blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); | 363 | blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); |
364 | mddev->queue->queue_lock = &mddev->queue->__queue_lock; | ||
365 | 364 | ||
366 | /* if private is not null, we are here after takeover */ | 365 | /* if private is not null, we are here after takeover */ |
367 | if (mddev->private == NULL) { | 366 | if (mddev->private == NULL) { |
@@ -670,6 +669,7 @@ static void *raid0_takeover_raid1(mddev_t *mddev) | |||
670 | mddev->new_layout = 0; | 669 | mddev->new_layout = 0; |
671 | mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */ | 670 | mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */ |
672 | mddev->delta_disks = 1 - mddev->raid_disks; | 671 | mddev->delta_disks = 1 - mddev->raid_disks; |
672 | mddev->raid_disks = 1; | ||
673 | /* make sure it will be not marked as dirty */ | 673 | /* make sure it will be not marked as dirty */ |
674 | mddev->recovery_cp = MaxSector; | 674 | mddev->recovery_cp = MaxSector; |
675 | 675 | ||
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a23ffa397ba9..06cd712807d0 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -593,7 +593,10 @@ static int flush_pending_writes(conf_t *conf) | |||
593 | if (conf->pending_bio_list.head) { | 593 | if (conf->pending_bio_list.head) { |
594 | struct bio *bio; | 594 | struct bio *bio; |
595 | bio = bio_list_get(&conf->pending_bio_list); | 595 | bio = bio_list_get(&conf->pending_bio_list); |
596 | /* Only take the spinlock to quiet a warning */ | ||
597 | spin_lock(conf->mddev->queue->queue_lock); | ||
596 | blk_remove_plug(conf->mddev->queue); | 598 | blk_remove_plug(conf->mddev->queue); |
599 | spin_unlock(conf->mddev->queue->queue_lock); | ||
597 | spin_unlock_irq(&conf->device_lock); | 600 | spin_unlock_irq(&conf->device_lock); |
598 | /* flush any pending bitmap writes to | 601 | /* flush any pending bitmap writes to |
599 | * disk before proceeding w/ I/O */ | 602 | * disk before proceeding w/ I/O */ |
@@ -959,7 +962,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) | |||
959 | atomic_inc(&r1_bio->remaining); | 962 | atomic_inc(&r1_bio->remaining); |
960 | spin_lock_irqsave(&conf->device_lock, flags); | 963 | spin_lock_irqsave(&conf->device_lock, flags); |
961 | bio_list_add(&conf->pending_bio_list, mbio); | 964 | bio_list_add(&conf->pending_bio_list, mbio); |
962 | blk_plug_device(mddev->queue); | 965 | blk_plug_device_unlocked(mddev->queue); |
963 | spin_unlock_irqrestore(&conf->device_lock, flags); | 966 | spin_unlock_irqrestore(&conf->device_lock, flags); |
964 | } | 967 | } |
965 | r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL); | 968 | r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL); |
@@ -2021,7 +2024,6 @@ static int run(mddev_t *mddev) | |||
2021 | if (IS_ERR(conf)) | 2024 | if (IS_ERR(conf)) |
2022 | return PTR_ERR(conf); | 2025 | return PTR_ERR(conf); |
2023 | 2026 | ||
2024 | mddev->queue->queue_lock = &conf->device_lock; | ||
2025 | list_for_each_entry(rdev, &mddev->disks, same_set) { | 2027 | list_for_each_entry(rdev, &mddev->disks, same_set) { |
2026 | disk_stack_limits(mddev->gendisk, rdev->bdev, | 2028 | disk_stack_limits(mddev->gendisk, rdev->bdev, |
2027 | rdev->data_offset << 9); | 2029 | rdev->data_offset << 9); |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 3b607b28741b..747d061d8e05 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -662,7 +662,10 @@ static int flush_pending_writes(conf_t *conf) | |||
662 | if (conf->pending_bio_list.head) { | 662 | if (conf->pending_bio_list.head) { |
663 | struct bio *bio; | 663 | struct bio *bio; |
664 | bio = bio_list_get(&conf->pending_bio_list); | 664 | bio = bio_list_get(&conf->pending_bio_list); |
665 | /* Spinlock only taken to quiet a warning */ | ||
666 | spin_lock(conf->mddev->queue->queue_lock); | ||
665 | blk_remove_plug(conf->mddev->queue); | 667 | blk_remove_plug(conf->mddev->queue); |
668 | spin_unlock(conf->mddev->queue->queue_lock); | ||
666 | spin_unlock_irq(&conf->device_lock); | 669 | spin_unlock_irq(&conf->device_lock); |
667 | /* flush any pending bitmap writes to disk | 670 | /* flush any pending bitmap writes to disk |
668 | * before proceeding w/ I/O */ | 671 | * before proceeding w/ I/O */ |
@@ -971,7 +974,7 @@ static int make_request(mddev_t *mddev, struct bio * bio) | |||
971 | atomic_inc(&r10_bio->remaining); | 974 | atomic_inc(&r10_bio->remaining); |
972 | spin_lock_irqsave(&conf->device_lock, flags); | 975 | spin_lock_irqsave(&conf->device_lock, flags); |
973 | bio_list_add(&conf->pending_bio_list, mbio); | 976 | bio_list_add(&conf->pending_bio_list, mbio); |
974 | blk_plug_device(mddev->queue); | 977 | blk_plug_device_unlocked(mddev->queue); |
975 | spin_unlock_irqrestore(&conf->device_lock, flags); | 978 | spin_unlock_irqrestore(&conf->device_lock, flags); |
976 | } | 979 | } |
977 | 980 | ||
@@ -2304,8 +2307,6 @@ static int run(mddev_t *mddev) | |||
2304 | if (!conf) | 2307 | if (!conf) |
2305 | goto out; | 2308 | goto out; |
2306 | 2309 | ||
2307 | mddev->queue->queue_lock = &conf->device_lock; | ||
2308 | |||
2309 | mddev->thread = conf->thread; | 2310 | mddev->thread = conf->thread; |
2310 | conf->thread = NULL; | 2311 | conf->thread = NULL; |
2311 | 2312 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 702812824195..78536fdbd87f 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -5204,7 +5204,6 @@ static int run(mddev_t *mddev) | |||
5204 | 5204 | ||
5205 | mddev->queue->backing_dev_info.congested_data = mddev; | 5205 | mddev->queue->backing_dev_info.congested_data = mddev; |
5206 | mddev->queue->backing_dev_info.congested_fn = raid5_congested; | 5206 | mddev->queue->backing_dev_info.congested_fn = raid5_congested; |
5207 | mddev->queue->queue_lock = &conf->device_lock; | ||
5208 | mddev->queue->unplug_fn = raid5_unplug_queue; | 5207 | mddev->queue->unplug_fn = raid5_unplug_queue; |
5209 | 5208 | ||
5210 | chunk_size = mddev->chunk_sectors << 9; | 5209 | chunk_size = mddev->chunk_sectors << 9; |
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); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 97d08d8a7de8..e38b50a4b9d2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2140,7 +2140,7 @@ extern void check_disk_size_change(struct gendisk *disk, | |||
2140 | struct block_device *bdev); | 2140 | struct block_device *bdev); |
2141 | extern int revalidate_disk(struct gendisk *); | 2141 | extern int revalidate_disk(struct gendisk *); |
2142 | extern int check_disk_change(struct block_device *); | 2142 | extern int check_disk_change(struct block_device *); |
2143 | extern int __invalidate_device(struct block_device *); | 2143 | extern int __invalidate_device(struct block_device *, bool); |
2144 | extern int invalidate_partition(struct gendisk *, int); | 2144 | extern int invalidate_partition(struct gendisk *, int); |
2145 | #endif | 2145 | #endif |
2146 | unsigned long invalidate_mapping_pages(struct address_space *mapping, | 2146 | unsigned long invalidate_mapping_pages(struct address_space *mapping, |