aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-07-19 01:59:18 -0400
committerNeilBrown <neilb@suse.de>2012-07-19 01:59:18 -0400
commita05b7ea03d72f36edb0cec05e8893803335c61a0 (patch)
tree2b35d0dd6d5edebf22f8ab2ff3eca5f28af6e7c8 /drivers/md/md.c
parent25f7fd470bc97bb93d3a674e8c56c4a29063ec97 (diff)
md: avoid crash when stopping md array races with closing other open fds.
md will refuse to stop an array if any other fd (or mounted fs) is using it. When any fs is unmounted of when the last open fd is closed all pending IO will be flushed (e.g. sync_blockdev call in __blkdev_put) so there will be no pending IO to worry about when the array is stopped. However in order to send the STOP_ARRAY ioctl to stop the array one must first get and open fd on the block device. If some fd is being used to write to the block device and it is closed after mdadm open the block device, but before mdadm issues the STOP_ARRAY ioctl, then there will be no last-close on the md device so __blkdev_put will not call sync_blockdev. If this happens, then IO can still be in-flight while md tears down the array and bad things can happen (use-after-free and subsequent havoc). So in the case where do_md_stop is being called from an open file descriptor, call sync_block after taking the mutex to ensure there will be no new openers. This is needed when setting a read-write device to read-only too. Cc: stable@vger.kernel.org Reported-by: majianpeng <majianpeng@gmail.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 0c1fe4cbce6b..d5ab4493c8be 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3927,8 +3927,8 @@ array_state_show(struct mddev *mddev, char *page)
3927 return sprintf(page, "%s\n", array_states[st]); 3927 return sprintf(page, "%s\n", array_states[st]);
3928} 3928}
3929 3929
3930static int do_md_stop(struct mddev * mddev, int ro, int is_open); 3930static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev);
3931static int md_set_readonly(struct mddev * mddev, int is_open); 3931static int md_set_readonly(struct mddev * mddev, struct block_device *bdev);
3932static int do_md_run(struct mddev * mddev); 3932static int do_md_run(struct mddev * mddev);
3933static int restart_array(struct mddev *mddev); 3933static int restart_array(struct mddev *mddev);
3934 3934
@@ -3944,14 +3944,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
3944 /* stopping an active array */ 3944 /* stopping an active array */
3945 if (atomic_read(&mddev->openers) > 0) 3945 if (atomic_read(&mddev->openers) > 0)
3946 return -EBUSY; 3946 return -EBUSY;
3947 err = do_md_stop(mddev, 0, 0); 3947 err = do_md_stop(mddev, 0, NULL);
3948 break; 3948 break;
3949 case inactive: 3949 case inactive:
3950 /* stopping an active array */ 3950 /* stopping an active array */
3951 if (mddev->pers) { 3951 if (mddev->pers) {
3952 if (atomic_read(&mddev->openers) > 0) 3952 if (atomic_read(&mddev->openers) > 0)
3953 return -EBUSY; 3953 return -EBUSY;
3954 err = do_md_stop(mddev, 2, 0); 3954 err = do_md_stop(mddev, 2, NULL);
3955 } else 3955 } else
3956 err = 0; /* already inactive */ 3956 err = 0; /* already inactive */
3957 break; 3957 break;
@@ -3959,7 +3959,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
3959 break; /* not supported yet */ 3959 break; /* not supported yet */
3960 case readonly: 3960 case readonly:
3961 if (mddev->pers) 3961 if (mddev->pers)
3962 err = md_set_readonly(mddev, 0); 3962 err = md_set_readonly(mddev, NULL);
3963 else { 3963 else {
3964 mddev->ro = 1; 3964 mddev->ro = 1;
3965 set_disk_ro(mddev->gendisk, 1); 3965 set_disk_ro(mddev->gendisk, 1);
@@ -3969,7 +3969,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
3969 case read_auto: 3969 case read_auto:
3970 if (mddev->pers) { 3970 if (mddev->pers) {
3971 if (mddev->ro == 0) 3971 if (mddev->ro == 0)
3972 err = md_set_readonly(mddev, 0); 3972 err = md_set_readonly(mddev, NULL);
3973 else if (mddev->ro == 1) 3973 else if (mddev->ro == 1)
3974 err = restart_array(mddev); 3974 err = restart_array(mddev);
3975 if (err == 0) { 3975 if (err == 0) {
@@ -5352,15 +5352,17 @@ void md_stop(struct mddev *mddev)
5352} 5352}
5353EXPORT_SYMBOL_GPL(md_stop); 5353EXPORT_SYMBOL_GPL(md_stop);
5354 5354
5355static int md_set_readonly(struct mddev *mddev, int is_open) 5355static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
5356{ 5356{
5357 int err = 0; 5357 int err = 0;
5358 mutex_lock(&mddev->open_mutex); 5358 mutex_lock(&mddev->open_mutex);
5359 if (atomic_read(&mddev->openers) > is_open) { 5359 if (atomic_read(&mddev->openers) > !!bdev) {
5360 printk("md: %s still in use.\n",mdname(mddev)); 5360 printk("md: %s still in use.\n",mdname(mddev));
5361 err = -EBUSY; 5361 err = -EBUSY;
5362 goto out; 5362 goto out;
5363 } 5363 }
5364 if (bdev)
5365 sync_blockdev(bdev);
5364 if (mddev->pers) { 5366 if (mddev->pers) {
5365 __md_stop_writes(mddev); 5367 __md_stop_writes(mddev);
5366 5368
@@ -5382,18 +5384,26 @@ out:
5382 * 0 - completely stop and dis-assemble array 5384 * 0 - completely stop and dis-assemble array
5383 * 2 - stop but do not disassemble array 5385 * 2 - stop but do not disassemble array
5384 */ 5386 */
5385static int do_md_stop(struct mddev * mddev, int mode, int is_open) 5387static int do_md_stop(struct mddev * mddev, int mode,
5388 struct block_device *bdev)
5386{ 5389{
5387 struct gendisk *disk = mddev->gendisk; 5390 struct gendisk *disk = mddev->gendisk;
5388 struct md_rdev *rdev; 5391 struct md_rdev *rdev;
5389 5392
5390 mutex_lock(&mddev->open_mutex); 5393 mutex_lock(&mddev->open_mutex);
5391 if (atomic_read(&mddev->openers) > is_open || 5394 if (atomic_read(&mddev->openers) > !!bdev ||
5392 mddev->sysfs_active) { 5395 mddev->sysfs_active) {
5393 printk("md: %s still in use.\n",mdname(mddev)); 5396 printk("md: %s still in use.\n",mdname(mddev));
5394 mutex_unlock(&mddev->open_mutex); 5397 mutex_unlock(&mddev->open_mutex);
5395 return -EBUSY; 5398 return -EBUSY;
5396 } 5399 }
5400 if (bdev)
5401 /* It is possible IO was issued on some other
5402 * open file which was closed before we took ->open_mutex.
5403 * As that was not the last close __blkdev_put will not
5404 * have called sync_blockdev, so we must.
5405 */
5406 sync_blockdev(bdev);
5397 5407
5398 if (mddev->pers) { 5408 if (mddev->pers) {
5399 if (mddev->ro) 5409 if (mddev->ro)
@@ -5467,7 +5477,7 @@ static void autorun_array(struct mddev *mddev)
5467 err = do_md_run(mddev); 5477 err = do_md_run(mddev);
5468 if (err) { 5478 if (err) {
5469 printk(KERN_WARNING "md: do_md_run() returned %d\n", err); 5479 printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
5470 do_md_stop(mddev, 0, 0); 5480 do_md_stop(mddev, 0, NULL);
5471 } 5481 }
5472} 5482}
5473 5483
@@ -6482,11 +6492,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
6482 goto done_unlock; 6492 goto done_unlock;
6483 6493
6484 case STOP_ARRAY: 6494 case STOP_ARRAY:
6485 err = do_md_stop(mddev, 0, 1); 6495 err = do_md_stop(mddev, 0, bdev);
6486 goto done_unlock; 6496 goto done_unlock;
6487 6497
6488 case STOP_ARRAY_RO: 6498 case STOP_ARRAY_RO:
6489 err = md_set_readonly(mddev, 1); 6499 err = md_set_readonly(mddev, bdev);
6490 goto done_unlock; 6500 goto done_unlock;
6491 6501
6492 case BLKROSET: 6502 case BLKROSET: