|
@@ -359,6 +359,7 @@ static mddev_t * mddev_find(dev_t unit)
|
|
|
else
|
|
|
new->md_minor = MINOR(unit) >> MdpMinorShift;
|
|
|
|
|
|
+ mutex_init(&new->open_mutex);
|
|
|
mutex_init(&new->reconfig_mutex);
|
|
|
INIT_LIST_HEAD(&new->disks);
|
|
|
INIT_LIST_HEAD(&new->all_mddevs);
|
|
@@ -1974,17 +1975,14 @@ repeat:
|
|
|
/* otherwise we have to go forward and ... */
|
|
|
mddev->events ++;
|
|
|
if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
|
|
|
- /* .. if the array isn't clean, insist on an odd 'events' */
|
|
|
- if ((mddev->events&1)==0) {
|
|
|
- mddev->events++;
|
|
|
+ /* .. if the array isn't clean, an 'even' event must also go
|
|
|
+ * to spares. */
|
|
|
+ if ((mddev->events&1)==0)
|
|
|
nospares = 0;
|
|
|
- }
|
|
|
} else {
|
|
|
- /* otherwise insist on an even 'events' (for clean states) */
|
|
|
- if ((mddev->events&1)) {
|
|
|
- mddev->events++;
|
|
|
+ /* otherwise an 'odd' event must go to spares */
|
|
|
+ if ((mddev->events&1))
|
|
|
nospares = 0;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3601,6 +3599,7 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
|
|
|
if (max < mddev->resync_min)
|
|
|
return -EINVAL;
|
|
|
if (max < mddev->resync_max &&
|
|
|
+ mddev->ro == 0 &&
|
|
|
test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
|
|
|
return -EBUSY;
|
|
|
|
|
@@ -4304,12 +4303,11 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
|
|
|
struct gendisk *disk = mddev->gendisk;
|
|
|
mdk_rdev_t *rdev;
|
|
|
|
|
|
+ mutex_lock(&mddev->open_mutex);
|
|
|
if (atomic_read(&mddev->openers) > is_open) {
|
|
|
printk("md: %s still in use.\n",mdname(mddev));
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
-
|
|
|
- if (mddev->pers) {
|
|
|
+ err = -EBUSY;
|
|
|
+ } else if (mddev->pers) {
|
|
|
|
|
|
if (mddev->sync_thread) {
|
|
|
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
|
@@ -4367,7 +4365,10 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
|
|
|
set_disk_ro(disk, 1);
|
|
|
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
|
|
}
|
|
|
-
|
|
|
+out:
|
|
|
+ mutex_unlock(&mddev->open_mutex);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
/*
|
|
|
* Free resources if final stop
|
|
|
*/
|
|
@@ -4433,7 +4434,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
|
|
|
blk_integrity_unregister(disk);
|
|
|
md_new_event(mddev);
|
|
|
sysfs_notify_dirent(mddev->sysfs_state);
|
|
|
-out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -5518,12 +5518,12 @@ static int md_open(struct block_device *bdev, fmode_t mode)
|
|
|
}
|
|
|
BUG_ON(mddev != bdev->bd_disk->private_data);
|
|
|
|
|
|
- if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
|
|
|
+ if ((err = mutex_lock_interruptible(&mddev->open_mutex)))
|
|
|
goto out;
|
|
|
|
|
|
err = 0;
|
|
|
atomic_inc(&mddev->openers);
|
|
|
- mddev_unlock(mddev);
|
|
|
+ mutex_unlock(&mddev->open_mutex);
|
|
|
|
|
|
check_disk_change(bdev);
|
|
|
out:
|