diff options
| -rw-r--r-- | drivers/md/md.c | 18 | ||||
| -rw-r--r-- | drivers/md/md.h | 10 |
2 files changed, 20 insertions, 8 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 5b98bea4ff9b..5614500092e3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -359,6 +359,7 @@ static mddev_t * mddev_find(dev_t unit) | |||
| 359 | else | 359 | else |
| 360 | new->md_minor = MINOR(unit) >> MdpMinorShift; | 360 | new->md_minor = MINOR(unit) >> MdpMinorShift; |
| 361 | 361 | ||
| 362 | mutex_init(&new->open_mutex); | ||
| 362 | mutex_init(&new->reconfig_mutex); | 363 | mutex_init(&new->reconfig_mutex); |
| 363 | INIT_LIST_HEAD(&new->disks); | 364 | INIT_LIST_HEAD(&new->disks); |
| 364 | INIT_LIST_HEAD(&new->all_mddevs); | 365 | INIT_LIST_HEAD(&new->all_mddevs); |
| @@ -4304,12 +4305,11 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
| 4304 | struct gendisk *disk = mddev->gendisk; | 4305 | struct gendisk *disk = mddev->gendisk; |
| 4305 | mdk_rdev_t *rdev; | 4306 | mdk_rdev_t *rdev; |
| 4306 | 4307 | ||
| 4308 | mutex_lock(&mddev->open_mutex); | ||
| 4307 | if (atomic_read(&mddev->openers) > is_open) { | 4309 | if (atomic_read(&mddev->openers) > is_open) { |
| 4308 | printk("md: %s still in use.\n",mdname(mddev)); | 4310 | printk("md: %s still in use.\n",mdname(mddev)); |
| 4309 | return -EBUSY; | 4311 | err = -EBUSY; |
| 4310 | } | 4312 | } else if (mddev->pers) { |
| 4311 | |||
| 4312 | if (mddev->pers) { | ||
| 4313 | 4313 | ||
| 4314 | if (mddev->sync_thread) { | 4314 | if (mddev->sync_thread) { |
| 4315 | set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 4315 | set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
| @@ -4367,7 +4367,10 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
| 4367 | set_disk_ro(disk, 1); | 4367 | set_disk_ro(disk, 1); |
| 4368 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 4368 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
| 4369 | } | 4369 | } |
| 4370 | 4370 | out: | |
| 4371 | mutex_unlock(&mddev->open_mutex); | ||
| 4372 | if (err) | ||
| 4373 | return err; | ||
| 4371 | /* | 4374 | /* |
| 4372 | * Free resources if final stop | 4375 | * Free resources if final stop |
| 4373 | */ | 4376 | */ |
| @@ -4433,7 +4436,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
| 4433 | blk_integrity_unregister(disk); | 4436 | blk_integrity_unregister(disk); |
| 4434 | md_new_event(mddev); | 4437 | md_new_event(mddev); |
| 4435 | sysfs_notify_dirent(mddev->sysfs_state); | 4438 | sysfs_notify_dirent(mddev->sysfs_state); |
| 4436 | out: | ||
| 4437 | return err; | 4439 | return err; |
| 4438 | } | 4440 | } |
| 4439 | 4441 | ||
| @@ -5518,12 +5520,12 @@ static int md_open(struct block_device *bdev, fmode_t mode) | |||
| 5518 | } | 5520 | } |
| 5519 | BUG_ON(mddev != bdev->bd_disk->private_data); | 5521 | BUG_ON(mddev != bdev->bd_disk->private_data); |
| 5520 | 5522 | ||
| 5521 | if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1))) | 5523 | if ((err = mutex_lock_interruptible(&mddev->open_mutex))) |
| 5522 | goto out; | 5524 | goto out; |
| 5523 | 5525 | ||
| 5524 | err = 0; | 5526 | err = 0; |
| 5525 | atomic_inc(&mddev->openers); | 5527 | atomic_inc(&mddev->openers); |
| 5526 | mddev_unlock(mddev); | 5528 | mutex_unlock(&mddev->open_mutex); |
| 5527 | 5529 | ||
| 5528 | check_disk_change(bdev); | 5530 | check_disk_change(bdev); |
| 5529 | out: | 5531 | out: |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 78f03168baf9..f8fc188bc762 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
| @@ -223,6 +223,16 @@ struct mddev_s | |||
| 223 | * so we don't loop trying */ | 223 | * so we don't loop trying */ |
| 224 | 224 | ||
| 225 | int in_sync; /* know to not need resync */ | 225 | int in_sync; /* know to not need resync */ |
| 226 | /* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so | ||
| 227 | * that we are never stopping an array while it is open. | ||
| 228 | * 'reconfig_mutex' protects all other reconfiguration. | ||
| 229 | * These locks are separate due to conflicting interactions | ||
| 230 | * with bdev->bd_mutex. | ||
| 231 | * Lock ordering is: | ||
| 232 | * reconfig_mutex -> bd_mutex : e.g. do_md_run -> revalidate_disk | ||
| 233 | * bd_mutex -> open_mutex: e.g. __blkdev_get -> md_open | ||
| 234 | */ | ||
| 235 | struct mutex open_mutex; | ||
| 226 | struct mutex reconfig_mutex; | 236 | struct mutex reconfig_mutex; |
| 227 | atomic_t active; /* general refcount */ | 237 | atomic_t active; /* general refcount */ |
| 228 | atomic_t openers; /* number of active opens */ | 238 | atomic_t openers; /* number of active opens */ |
