aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-mpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-mpath.c')
-rw-r--r--drivers/md/dm-mpath.c95
1 files changed, 70 insertions, 25 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index dce971dbdfa3..e81345a1d08f 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -93,6 +93,10 @@ 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;
98
99 unsigned suspended; /* Don't create new I/O internally when set. */
96}; 100};
97 101
98/* 102/*
@@ -198,6 +202,7 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
198 m->queue_io = 1; 202 m->queue_io = 1;
199 INIT_WORK(&m->process_queued_ios, process_queued_ios); 203 INIT_WORK(&m->process_queued_ios, process_queued_ios);
200 INIT_WORK(&m->trigger_event, trigger_event); 204 INIT_WORK(&m->trigger_event, trigger_event);
205 mutex_init(&m->work_mutex);
201 m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); 206 m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
202 if (!m->mpio_pool) { 207 if (!m->mpio_pool) {
203 kfree(m); 208 kfree(m);
@@ -885,13 +890,18 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
885 return r; 890 return r;
886} 891}
887 892
888static void multipath_dtr(struct dm_target *ti) 893static void flush_multipath_work(void)
889{ 894{
890 struct multipath *m = (struct multipath *) ti->private;
891
892 flush_workqueue(kmpath_handlerd); 895 flush_workqueue(kmpath_handlerd);
893 flush_workqueue(kmultipathd); 896 flush_workqueue(kmultipathd);
894 flush_scheduled_work(); 897 flush_scheduled_work();
898}
899
900static void multipath_dtr(struct dm_target *ti)
901{
902 struct multipath *m = ti->private;
903
904 flush_multipath_work();
895 free_multipath(m); 905 free_multipath(m);
896} 906}
897 907
@@ -1261,6 +1271,16 @@ static void multipath_presuspend(struct dm_target *ti)
1261 queue_if_no_path(m, 0, 1); 1271 queue_if_no_path(m, 0, 1);
1262} 1272}
1263 1273
1274static void multipath_postsuspend(struct dm_target *ti)
1275{
1276 struct multipath *m = ti->private;
1277
1278 mutex_lock(&m->work_mutex);
1279 m->suspended = 1;
1280 flush_multipath_work();
1281 mutex_unlock(&m->work_mutex);
1282}
1283
1264/* 1284/*
1265 * Restore the queue_if_no_path setting. 1285 * Restore the queue_if_no_path setting.
1266 */ 1286 */
@@ -1269,6 +1289,10 @@ static void multipath_resume(struct dm_target *ti)
1269 struct multipath *m = (struct multipath *) ti->private; 1289 struct multipath *m = (struct multipath *) ti->private;
1270 unsigned long flags; 1290 unsigned long flags;
1271 1291
1292 mutex_lock(&m->work_mutex);
1293 m->suspended = 0;
1294 mutex_unlock(&m->work_mutex);
1295
1272 spin_lock_irqsave(&m->lock, flags); 1296 spin_lock_irqsave(&m->lock, flags);
1273 m->queue_if_no_path = m->saved_queue_if_no_path; 1297 m->queue_if_no_path = m->saved_queue_if_no_path;
1274 spin_unlock_irqrestore(&m->lock, flags); 1298 spin_unlock_irqrestore(&m->lock, flags);
@@ -1397,51 +1421,71 @@ static int multipath_status(struct dm_target *ti, status_type_t type,
1397 1421
1398static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) 1422static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
1399{ 1423{
1400 int r; 1424 int r = -EINVAL;
1401 struct dm_dev *dev; 1425 struct dm_dev *dev;
1402 struct multipath *m = (struct multipath *) ti->private; 1426 struct multipath *m = (struct multipath *) ti->private;
1403 action_fn action; 1427 action_fn action;
1404 1428
1429 mutex_lock(&m->work_mutex);
1430
1431 if (m->suspended) {
1432 r = -EBUSY;
1433 goto out;
1434 }
1435
1436 if (dm_suspended(ti)) {
1437 r = -EBUSY;
1438 goto out;
1439 }
1440
1405 if (argc == 1) { 1441 if (argc == 1) {
1406 if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) 1442 if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) {
1407 return queue_if_no_path(m, 1, 0); 1443 r = queue_if_no_path(m, 1, 0);
1408 else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) 1444 goto out;
1409 return queue_if_no_path(m, 0, 0); 1445 } else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) {
1446 r = queue_if_no_path(m, 0, 0);
1447 goto out;
1448 }
1410 } 1449 }
1411 1450
1412 if (argc != 2) 1451 if (argc != 2) {
1413 goto error; 1452 DMWARN("Unrecognised multipath message received.");
1453 goto out;
1454 }
1414 1455
1415 if (!strnicmp(argv[0], MESG_STR("disable_group"))) 1456 if (!strnicmp(argv[0], MESG_STR("disable_group"))) {
1416 return bypass_pg_num(m, argv[1], 1); 1457 r = bypass_pg_num(m, argv[1], 1);
1417 else if (!strnicmp(argv[0], MESG_STR("enable_group"))) 1458 goto out;
1418 return bypass_pg_num(m, argv[1], 0); 1459 } else if (!strnicmp(argv[0], MESG_STR("enable_group"))) {
1419 else if (!strnicmp(argv[0], MESG_STR("switch_group"))) 1460 r = bypass_pg_num(m, argv[1], 0);
1420 return switch_pg_num(m, argv[1]); 1461 goto out;
1421 else if (!strnicmp(argv[0], MESG_STR("reinstate_path"))) 1462 } else if (!strnicmp(argv[0], MESG_STR("switch_group"))) {
1463 r = switch_pg_num(m, argv[1]);
1464 goto out;
1465 } else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
1422 action = reinstate_path; 1466 action = reinstate_path;
1423 else if (!strnicmp(argv[0], MESG_STR("fail_path"))) 1467 else if (!strnicmp(argv[0], MESG_STR("fail_path")))
1424 action = fail_path; 1468 action = fail_path;
1425 else 1469 else {
1426 goto error; 1470 DMWARN("Unrecognised multipath message received.");
1471 goto out;
1472 }
1427 1473
1428 r = dm_get_device(ti, argv[1], ti->begin, ti->len, 1474 r = dm_get_device(ti, argv[1], ti->begin, ti->len,
1429 dm_table_get_mode(ti->table), &dev); 1475 dm_table_get_mode(ti->table), &dev);
1430 if (r) { 1476 if (r) {
1431 DMWARN("message: error getting device %s", 1477 DMWARN("message: error getting device %s",
1432 argv[1]); 1478 argv[1]);
1433 return -EINVAL; 1479 goto out;
1434 } 1480 }
1435 1481
1436 r = action_dev(m, dev, action); 1482 r = action_dev(m, dev, action);
1437 1483
1438 dm_put_device(ti, dev); 1484 dm_put_device(ti, dev);
1439 1485
1486out:
1487 mutex_unlock(&m->work_mutex);
1440 return r; 1488 return r;
1441
1442error:
1443 DMWARN("Unrecognised multipath message received.");
1444 return -EINVAL;
1445} 1489}
1446 1490
1447static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, 1491static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
@@ -1567,13 +1611,14 @@ out:
1567 *---------------------------------------------------------------*/ 1611 *---------------------------------------------------------------*/
1568static struct target_type multipath_target = { 1612static struct target_type multipath_target = {
1569 .name = "multipath", 1613 .name = "multipath",
1570 .version = {1, 1, 0}, 1614 .version = {1, 1, 1},
1571 .module = THIS_MODULE, 1615 .module = THIS_MODULE,
1572 .ctr = multipath_ctr, 1616 .ctr = multipath_ctr,
1573 .dtr = multipath_dtr, 1617 .dtr = multipath_dtr,
1574 .map_rq = multipath_map, 1618 .map_rq = multipath_map,
1575 .rq_end_io = multipath_end_io, 1619 .rq_end_io = multipath_end_io,
1576 .presuspend = multipath_presuspend, 1620 .presuspend = multipath_presuspend,
1621 .postsuspend = multipath_postsuspend,
1577 .resume = multipath_resume, 1622 .resume = multipath_resume,
1578 .status = multipath_status, 1623 .status = multipath_status,
1579 .message = multipath_message, 1624 .message = multipath_message,