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

Commit 6380f26f authored by Mike Anderson's avatar Mike Anderson Committed by Alasdair G Kergon
Browse files

dm mpath: add mutex to synchronize adding and flushing work



Add a mutex to allow possible creators of new work to synchronize with
flushing work queues.

Signed-off-by: default avatarMike Anderson <andmike@linux.vnet.ibm.com>
Acked-by: default avatarKiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent c50abeb3
Loading
Loading
Loading
Loading
+38 −21
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ struct multipath {
	 * can resubmit bios on error.
	 */
	mempool_t *mpio_pool;

	struct mutex work_mutex;
};

/*
@@ -198,6 +200,7 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
		m->queue_io = 1;
		INIT_WORK(&m->process_queued_ios, process_queued_ios);
		INIT_WORK(&m->trigger_event, trigger_event);
		mutex_init(&m->work_mutex);
		m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
		if (!m->mpio_pool) {
			kfree(m);
@@ -1268,7 +1271,11 @@ static void multipath_presuspend(struct dm_target *ti)

static void multipath_postsuspend(struct dm_target *ti)
{
	struct multipath *m = ti->private;

	mutex_lock(&m->work_mutex);
	flush_multipath_work();
	mutex_unlock(&m->work_mutex);
}

/*
@@ -1407,51 +1414,61 @@ static int multipath_status(struct dm_target *ti, status_type_t type,

static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
{
	int r;
	int r = -EINVAL;
	struct dm_dev *dev;
	struct multipath *m = (struct multipath *) ti->private;
	action_fn action;

	mutex_lock(&m->work_mutex);

	if (argc == 1) {
		if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
			return queue_if_no_path(m, 1, 0);
		else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
			return queue_if_no_path(m, 0, 0);
	}

	if (argc != 2)
		goto error;

	if (!strnicmp(argv[0], MESG_STR("disable_group")))
		return bypass_pg_num(m, argv[1], 1);
	else if (!strnicmp(argv[0], MESG_STR("enable_group")))
		return bypass_pg_num(m, argv[1], 0);
	else if (!strnicmp(argv[0], MESG_STR("switch_group")))
		return switch_pg_num(m, argv[1]);
	else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
		if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) {
			r = queue_if_no_path(m, 1, 0);
			goto out;
		} else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) {
			r = queue_if_no_path(m, 0, 0);
			goto out;
		}
	}

	if (argc != 2) {
		DMWARN("Unrecognised multipath message received.");
		goto out;
	}

	if (!strnicmp(argv[0], MESG_STR("disable_group"))) {
		r = bypass_pg_num(m, argv[1], 1);
		goto out;
	} else if (!strnicmp(argv[0], MESG_STR("enable_group"))) {
		r = bypass_pg_num(m, argv[1], 0);
		goto out;
	} else if (!strnicmp(argv[0], MESG_STR("switch_group"))) {
		r = switch_pg_num(m, argv[1]);
		goto out;
	} else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
		action = reinstate_path;
	else if (!strnicmp(argv[0], MESG_STR("fail_path")))
		action = fail_path;
	else
		goto error;
	else {
		DMWARN("Unrecognised multipath message received.");
		goto out;
	}

	r = dm_get_device(ti, argv[1], ti->begin, ti->len,
			  dm_table_get_mode(ti->table), &dev);
	if (r) {
		DMWARN("message: error getting device %s",
		       argv[1]);
		return -EINVAL;
		goto out;
	}

	r = action_dev(m, dev, action);

	dm_put_device(ti, dev);

out:
	mutex_unlock(&m->work_mutex);
	return r;

error:
	DMWARN("Unrecognised multipath message received.");
	return -EINVAL;
}

static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,