Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df5b20cf authored by Neil Brown's avatar Neil Brown
Browse files

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
Loading
Loading
Loading
Loading
+15 −14
Original line number Diff line number Diff line
@@ -2688,7 +2688,7 @@ array_state_show(mddev_t *mddev, char *page)
	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 restart_array(mddev_t *mddev);

@@ -2704,14 +2704,14 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
		/* stopping an active array */
		if (atomic_read(&mddev->active) > 1)
			return -EBUSY;
		err = do_md_stop(mddev, 0);
		err = do_md_stop(mddev, 0, 0);
		break;
	case inactive:
		/* stopping an active array */
		if (mddev->pers) {
			if (atomic_read(&mddev->active) > 1)
				return -EBUSY;
			err = do_md_stop(mddev, 2);
			err = do_md_stop(mddev, 2, 0);
		} else
			err = 0; /* already inactive */
		break;
@@ -2719,7 +2719,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
		break; /* not supported yet */
	case readonly:
		if (mddev->pers)
			err = do_md_stop(mddev, 1);
			err = do_md_stop(mddev, 1, 0);
		else {
			mddev->ro = 1;
			set_disk_ro(mddev->gendisk, 1);
@@ -2729,7 +2729,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
	case read_auto:
		if (mddev->pers) {
			if (mddev->ro != 1)
				err = do_md_stop(mddev, 1);
				err = do_md_stop(mddev, 1, 0);
			else
				err = restart_array(mddev);
			if (err == 0) {
@@ -3818,17 +3818,18 @@ static void restore_bitmap_write_access(struct file *file)
 *   1 - switch to readonly
 *   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;
	struct gendisk *disk = mddev->gendisk;

	if (mddev->pers) {
		if (atomic_read(&mddev->active)>2) {
	if (atomic_read(&mddev->active) > 1 + is_open) {
		printk("md: %s still in use.\n",mdname(mddev));
		return -EBUSY;
	}

	if (mddev->pers) {

		if (mddev->sync_thread) {
			set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
@@ -3976,7 +3977,7 @@ static void autorun_array(mddev_t *mddev)
	err = do_md_run (mddev);
	if (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,
			goto done_unlock;

		case STOP_ARRAY:
			err = do_md_stop (mddev, 0);
			err = do_md_stop (mddev, 0, 1);
			goto done_unlock;

		case STOP_ARRAY_RO:
			err = do_md_stop (mddev, 1);
			err = do_md_stop (mddev, 1, 1);
			goto done_unlock;

	}
@@ -6226,7 +6227,7 @@ static int md_notify_reboot(struct notifier_block *this,

		for_each_mddev(mddev, tmp)
			if (mddev_trylock(mddev)) {
				do_md_stop (mddev, 1);
				do_md_stop (mddev, 1, 0);
				mddev_unlock(mddev);
			}
		/*