Commit df5b20cf authored by Neil Brown's avatar Neil Brown

md: Better control of when do_md_stop is allowed to stop the array.

do_md_stop check the number of active users before allowing the array
to be stopped.
Two problems:
  1/ it assumes the request is coming through an open file descriptor
     (via ioctl) so it allows for that.  This is not always the case.
  2/ it doesn't do the check it the array hasn't been activated.
     This is not good for cases when we use an inactive array to hold
     some devices in a container.
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
parent 26ef379f
...@@ -2688,7 +2688,7 @@ array_state_show(mddev_t *mddev, char *page) ...@@ -2688,7 +2688,7 @@ array_state_show(mddev_t *mddev, char *page)
return sprintf(page, "%s\n", array_states[st]); return sprintf(page, "%s\n", array_states[st]);
} }
static int do_md_stop(mddev_t * mddev, int ro); static int do_md_stop(mddev_t * mddev, int ro, int is_open);
static int do_md_run(mddev_t * mddev); static int do_md_run(mddev_t * mddev);
static int restart_array(mddev_t *mddev); static int restart_array(mddev_t *mddev);
...@@ -2704,14 +2704,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) ...@@ -2704,14 +2704,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
/* stopping an active array */ /* stopping an active array */
if (atomic_read(&mddev->active) > 1) if (atomic_read(&mddev->active) > 1)
return -EBUSY; return -EBUSY;
err = do_md_stop(mddev, 0); err = do_md_stop(mddev, 0, 0);
break; break;
case inactive: case inactive:
/* stopping an active array */ /* stopping an active array */
if (mddev->pers) { if (mddev->pers) {
if (atomic_read(&mddev->active) > 1) if (atomic_read(&mddev->active) > 1)
return -EBUSY; return -EBUSY;
err = do_md_stop(mddev, 2); err = do_md_stop(mddev, 2, 0);
} else } else
err = 0; /* already inactive */ err = 0; /* already inactive */
break; break;
...@@ -2719,7 +2719,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) ...@@ -2719,7 +2719,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
break; /* not supported yet */ break; /* not supported yet */
case readonly: case readonly:
if (mddev->pers) if (mddev->pers)
err = do_md_stop(mddev, 1); err = do_md_stop(mddev, 1, 0);
else { else {
mddev->ro = 1; mddev->ro = 1;
set_disk_ro(mddev->gendisk, 1); set_disk_ro(mddev->gendisk, 1);
...@@ -2729,7 +2729,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) ...@@ -2729,7 +2729,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
case read_auto: case read_auto:
if (mddev->pers) { if (mddev->pers) {
if (mddev->ro != 1) if (mddev->ro != 1)
err = do_md_stop(mddev, 1); err = do_md_stop(mddev, 1, 0);
else else
err = restart_array(mddev); err = restart_array(mddev);
if (err == 0) { if (err == 0) {
...@@ -3818,17 +3818,18 @@ static void restore_bitmap_write_access(struct file *file) ...@@ -3818,17 +3818,18 @@ static void restore_bitmap_write_access(struct file *file)
* 1 - switch to readonly * 1 - switch to readonly
* 2 - stop but do not disassemble array * 2 - stop but do not disassemble array
*/ */
static int do_md_stop(mddev_t * mddev, int mode) static int do_md_stop(mddev_t * mddev, int mode, int is_open)
{ {
int err = 0; int err = 0;
struct gendisk *disk = mddev->gendisk; struct gendisk *disk = mddev->gendisk;
if (mddev->pers) { if (atomic_read(&mddev->active) > 1 + is_open) {
if (atomic_read(&mddev->active)>2) {
printk("md: %s still in use.\n",mdname(mddev)); printk("md: %s still in use.\n",mdname(mddev));
return -EBUSY; return -EBUSY;
} }
if (mddev->pers) {
if (mddev->sync_thread) { if (mddev->sync_thread) {
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
set_bit(MD_RECOVERY_INTR, &mddev->recovery); set_bit(MD_RECOVERY_INTR, &mddev->recovery);
...@@ -3976,7 +3977,7 @@ static void autorun_array(mddev_t *mddev) ...@@ -3976,7 +3977,7 @@ static void autorun_array(mddev_t *mddev)
err = do_md_run (mddev); err = do_md_run (mddev);
if (err) { if (err) {
printk(KERN_WARNING "md: do_md_run() returned %d\n", err); printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
do_md_stop (mddev, 0); do_md_stop (mddev, 0, 0);
} }
} }
...@@ -4931,11 +4932,11 @@ static int md_ioctl(struct inode *inode, struct file *file, ...@@ -4931,11 +4932,11 @@ static int md_ioctl(struct inode *inode, struct file *file,
goto done_unlock; goto done_unlock;
case STOP_ARRAY: case STOP_ARRAY:
err = do_md_stop (mddev, 0); err = do_md_stop (mddev, 0, 1);
goto done_unlock; goto done_unlock;
case STOP_ARRAY_RO: case STOP_ARRAY_RO:
err = do_md_stop (mddev, 1); err = do_md_stop (mddev, 1, 1);
goto done_unlock; goto done_unlock;
} }
...@@ -6226,7 +6227,7 @@ static int md_notify_reboot(struct notifier_block *this, ...@@ -6226,7 +6227,7 @@ static int md_notify_reboot(struct notifier_block *this,
for_each_mddev(mddev, tmp) for_each_mddev(mddev, tmp)
if (mddev_trylock(mddev)) { if (mddev_trylock(mddev)) {
do_md_stop (mddev, 1); do_md_stop (mddev, 1, 0);
mddev_unlock(mddev); mddev_unlock(mddev);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment