diff options
author | Mike Anderson <andmike@linux.vnet.ibm.com> | 2009-12-10 18:52:21 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-12-10 18:52:21 -0500 |
commit | 6380f26f0424034345461cabaab9a7030d905b59 (patch) | |
tree | cc9fbd6e8d990bf3ee2f577ae7f842a4df1d5ef6 | |
parent | c50abeb38026ea721a812cf8a9b2fac5d3b7684b (diff) |
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: Mike Anderson <andmike@linux.vnet.ibm.com>
Acked-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r-- | drivers/md/dm-mpath.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 5b23f2df9bde..700154e21483 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -93,6 +93,8 @@ struct multipath { | |||
93 | * can resubmit bios on error. | 93 | * can resubmit bios on error. |
94 | */ | 94 | */ |
95 | mempool_t *mpio_pool; | 95 | mempool_t *mpio_pool; |
96 | |||
97 | struct mutex work_mutex; | ||
96 | }; | 98 | }; |
97 | 99 | ||
98 | /* | 100 | /* |
@@ -198,6 +200,7 @@ static struct multipath *alloc_multipath(struct dm_target *ti) | |||
198 | m->queue_io = 1; | 200 | m->queue_io = 1; |
199 | INIT_WORK(&m->process_queued_ios, process_queued_ios); | 201 | INIT_WORK(&m->process_queued_ios, process_queued_ios); |
200 | INIT_WORK(&m->trigger_event, trigger_event); | 202 | INIT_WORK(&m->trigger_event, trigger_event); |
203 | mutex_init(&m->work_mutex); | ||
201 | m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); | 204 | m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); |
202 | if (!m->mpio_pool) { | 205 | if (!m->mpio_pool) { |
203 | kfree(m); | 206 | kfree(m); |
@@ -1268,7 +1271,11 @@ static void multipath_presuspend(struct dm_target *ti) | |||
1268 | 1271 | ||
1269 | static void multipath_postsuspend(struct dm_target *ti) | 1272 | static void multipath_postsuspend(struct dm_target *ti) |
1270 | { | 1273 | { |
1274 | struct multipath *m = ti->private; | ||
1275 | |||
1276 | mutex_lock(&m->work_mutex); | ||
1271 | flush_multipath_work(); | 1277 | flush_multipath_work(); |
1278 | mutex_unlock(&m->work_mutex); | ||
1272 | } | 1279 | } |
1273 | 1280 | ||
1274 | /* | 1281 | /* |
@@ -1407,51 +1414,61 @@ static int multipath_status(struct dm_target *ti, status_type_t type, | |||
1407 | 1414 | ||
1408 | static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) | 1415 | static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) |
1409 | { | 1416 | { |
1410 | int r; | 1417 | int r = -EINVAL; |
1411 | struct dm_dev *dev; | 1418 | struct dm_dev *dev; |
1412 | struct multipath *m = (struct multipath *) ti->private; | 1419 | struct multipath *m = (struct multipath *) ti->private; |
1413 | action_fn action; | 1420 | action_fn action; |
1414 | 1421 | ||
1422 | mutex_lock(&m->work_mutex); | ||
1423 | |||
1415 | if (argc == 1) { | 1424 | if (argc == 1) { |
1416 | if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) | 1425 | if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) { |
1417 | return queue_if_no_path(m, 1, 0); | 1426 | r = queue_if_no_path(m, 1, 0); |
1418 | else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) | 1427 | goto out; |
1419 | return queue_if_no_path(m, 0, 0); | 1428 | } else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) { |
1429 | r = queue_if_no_path(m, 0, 0); | ||
1430 | goto out; | ||
1431 | } | ||
1420 | } | 1432 | } |
1421 | 1433 | ||
1422 | if (argc != 2) | 1434 | if (argc != 2) { |
1423 | goto error; | 1435 | DMWARN("Unrecognised multipath message received."); |
1436 | goto out; | ||
1437 | } | ||
1424 | 1438 | ||
1425 | if (!strnicmp(argv[0], MESG_STR("disable_group"))) | 1439 | if (!strnicmp(argv[0], MESG_STR("disable_group"))) { |
1426 | return bypass_pg_num(m, argv[1], 1); | 1440 | r = bypass_pg_num(m, argv[1], 1); |
1427 | else if (!strnicmp(argv[0], MESG_STR("enable_group"))) | 1441 | goto out; |
1428 | return bypass_pg_num(m, argv[1], 0); | 1442 | } else if (!strnicmp(argv[0], MESG_STR("enable_group"))) { |
1429 | else if (!strnicmp(argv[0], MESG_STR("switch_group"))) | 1443 | r = bypass_pg_num(m, argv[1], 0); |
1430 | return switch_pg_num(m, argv[1]); | 1444 | goto out; |
1431 | else if (!strnicmp(argv[0], MESG_STR("reinstate_path"))) | 1445 | } else if (!strnicmp(argv[0], MESG_STR("switch_group"))) { |
1446 | r = switch_pg_num(m, argv[1]); | ||
1447 | goto out; | ||
1448 | } else if (!strnicmp(argv[0], MESG_STR("reinstate_path"))) | ||
1432 | action = reinstate_path; | 1449 | action = reinstate_path; |
1433 | else if (!strnicmp(argv[0], MESG_STR("fail_path"))) | 1450 | else if (!strnicmp(argv[0], MESG_STR("fail_path"))) |
1434 | action = fail_path; | 1451 | action = fail_path; |
1435 | else | 1452 | else { |
1436 | goto error; | 1453 | DMWARN("Unrecognised multipath message received."); |
1454 | goto out; | ||
1455 | } | ||
1437 | 1456 | ||
1438 | r = dm_get_device(ti, argv[1], ti->begin, ti->len, | 1457 | r = dm_get_device(ti, argv[1], ti->begin, ti->len, |
1439 | dm_table_get_mode(ti->table), &dev); | 1458 | dm_table_get_mode(ti->table), &dev); |
1440 | if (r) { | 1459 | if (r) { |
1441 | DMWARN("message: error getting device %s", | 1460 | DMWARN("message: error getting device %s", |
1442 | argv[1]); | 1461 | argv[1]); |
1443 | return -EINVAL; | 1462 | goto out; |
1444 | } | 1463 | } |
1445 | 1464 | ||
1446 | r = action_dev(m, dev, action); | 1465 | r = action_dev(m, dev, action); |
1447 | 1466 | ||
1448 | dm_put_device(ti, dev); | 1467 | dm_put_device(ti, dev); |
1449 | 1468 | ||
1469 | out: | ||
1470 | mutex_unlock(&m->work_mutex); | ||
1450 | return r; | 1471 | return r; |
1451 | |||
1452 | error: | ||
1453 | DMWARN("Unrecognised multipath message received."); | ||
1454 | return -EINVAL; | ||
1455 | } | 1472 | } |
1456 | 1473 | ||
1457 | static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, | 1474 | static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, |