|
@@ -93,9 +93,7 @@ struct multipath {
|
|
|
unsigned pg_init_count; /* Number of times pg_init called */
|
|
unsigned pg_init_count; /* Number of times pg_init called */
|
|
|
unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
|
|
unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
|
|
|
|
|
|
|
|
- unsigned queue_size;
|
|
|
|
|
struct work_struct process_queued_ios;
|
|
struct work_struct process_queued_ios;
|
|
|
- struct list_head queued_ios;
|
|
|
|
|
|
|
|
|
|
struct work_struct trigger_event;
|
|
struct work_struct trigger_event;
|
|
|
|
|
|
|
@@ -124,6 +122,7 @@ static struct workqueue_struct *kmultipathd, *kmpath_handlerd;
|
|
|
static void process_queued_ios(struct work_struct *work);
|
|
static void process_queued_ios(struct work_struct *work);
|
|
|
static void trigger_event(struct work_struct *work);
|
|
static void trigger_event(struct work_struct *work);
|
|
|
static void activate_path(struct work_struct *work);
|
|
static void activate_path(struct work_struct *work);
|
|
|
|
|
+static int __pgpath_busy(struct pgpath *pgpath);
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------
|
|
/*-----------------------------------------------
|
|
@@ -195,7 +194,6 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
|
|
|
m = kzalloc(sizeof(*m), GFP_KERNEL);
|
|
m = kzalloc(sizeof(*m), GFP_KERNEL);
|
|
|
if (m) {
|
|
if (m) {
|
|
|
INIT_LIST_HEAD(&m->priority_groups);
|
|
INIT_LIST_HEAD(&m->priority_groups);
|
|
|
- INIT_LIST_HEAD(&m->queued_ios);
|
|
|
|
|
spin_lock_init(&m->lock);
|
|
spin_lock_init(&m->lock);
|
|
|
m->queue_io = 1;
|
|
m->queue_io = 1;
|
|
|
m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
|
|
m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
|
|
@@ -368,12 +366,15 @@ failed:
|
|
|
*/
|
|
*/
|
|
|
static int __must_push_back(struct multipath *m)
|
|
static int __must_push_back(struct multipath *m)
|
|
|
{
|
|
{
|
|
|
- return (m->queue_if_no_path != m->saved_queue_if_no_path &&
|
|
|
|
|
- dm_noflush_suspending(m->ti));
|
|
|
|
|
|
|
+ return (m->queue_if_no_path ||
|
|
|
|
|
+ (m->queue_if_no_path != m->saved_queue_if_no_path &&
|
|
|
|
|
+ dm_noflush_suspending(m->ti)));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#define pg_ready(m) (!(m)->queue_io && !(m)->pg_init_required)
|
|
|
|
|
+
|
|
|
static int map_io(struct multipath *m, struct request *clone,
|
|
static int map_io(struct multipath *m, struct request *clone,
|
|
|
- union map_info *map_context, unsigned was_queued)
|
|
|
|
|
|
|
+ union map_info *map_context)
|
|
|
{
|
|
{
|
|
|
int r = DM_MAPIO_REMAPPED;
|
|
int r = DM_MAPIO_REMAPPED;
|
|
|
size_t nr_bytes = blk_rq_bytes(clone);
|
|
size_t nr_bytes = blk_rq_bytes(clone);
|
|
@@ -391,37 +392,28 @@ static int map_io(struct multipath *m, struct request *clone,
|
|
|
|
|
|
|
|
pgpath = m->current_pgpath;
|
|
pgpath = m->current_pgpath;
|
|
|
|
|
|
|
|
- if (was_queued)
|
|
|
|
|
- m->queue_size--;
|
|
|
|
|
-
|
|
|
|
|
- if (m->pg_init_required) {
|
|
|
|
|
- if (!m->pg_init_in_progress)
|
|
|
|
|
- queue_work(kmultipathd, &m->process_queued_ios);
|
|
|
|
|
- r = DM_MAPIO_REQUEUE;
|
|
|
|
|
- } else if ((pgpath && m->queue_io) ||
|
|
|
|
|
- (!pgpath && m->queue_if_no_path)) {
|
|
|
|
|
- /* Queue for the daemon to resubmit */
|
|
|
|
|
- list_add_tail(&clone->queuelist, &m->queued_ios);
|
|
|
|
|
- m->queue_size++;
|
|
|
|
|
- if (!m->queue_io)
|
|
|
|
|
- queue_work(kmultipathd, &m->process_queued_ios);
|
|
|
|
|
- pgpath = NULL;
|
|
|
|
|
- r = DM_MAPIO_SUBMITTED;
|
|
|
|
|
- } else if (pgpath) {
|
|
|
|
|
- bdev = pgpath->path.dev->bdev;
|
|
|
|
|
- clone->q = bdev_get_queue(bdev);
|
|
|
|
|
- clone->rq_disk = bdev->bd_disk;
|
|
|
|
|
- } else if (__must_push_back(m))
|
|
|
|
|
- r = DM_MAPIO_REQUEUE;
|
|
|
|
|
- else
|
|
|
|
|
- r = -EIO; /* Failed */
|
|
|
|
|
-
|
|
|
|
|
- mpio->pgpath = pgpath;
|
|
|
|
|
- mpio->nr_bytes = nr_bytes;
|
|
|
|
|
-
|
|
|
|
|
- if (r == DM_MAPIO_REMAPPED && pgpath->pg->ps.type->start_io)
|
|
|
|
|
- pgpath->pg->ps.type->start_io(&pgpath->pg->ps, &pgpath->path,
|
|
|
|
|
- nr_bytes);
|
|
|
|
|
|
|
+ if (pgpath) {
|
|
|
|
|
+ if (pg_ready(m)) {
|
|
|
|
|
+ bdev = pgpath->path.dev->bdev;
|
|
|
|
|
+ clone->q = bdev_get_queue(bdev);
|
|
|
|
|
+ clone->rq_disk = bdev->bd_disk;
|
|
|
|
|
+ mpio->pgpath = pgpath;
|
|
|
|
|
+ mpio->nr_bytes = nr_bytes;
|
|
|
|
|
+ if (pgpath->pg->ps.type->start_io)
|
|
|
|
|
+ pgpath->pg->ps.type->start_io(&pgpath->pg->ps,
|
|
|
|
|
+ &pgpath->path,
|
|
|
|
|
+ nr_bytes);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ __pg_init_all_paths(m);
|
|
|
|
|
+ r = DM_MAPIO_REQUEUE;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ /* No path */
|
|
|
|
|
+ if (__must_push_back(m))
|
|
|
|
|
+ r = DM_MAPIO_REQUEUE;
|
|
|
|
|
+ else
|
|
|
|
|
+ r = -EIO; /* Failed */
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&m->lock, flags);
|
|
spin_unlock_irqrestore(&m->lock, flags);
|
|
|
|
|
|
|
@@ -443,7 +435,7 @@ static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
|
|
|
else
|
|
else
|
|
|
m->saved_queue_if_no_path = queue_if_no_path;
|
|
m->saved_queue_if_no_path = queue_if_no_path;
|
|
|
m->queue_if_no_path = queue_if_no_path;
|
|
m->queue_if_no_path = queue_if_no_path;
|
|
|
- if (!m->queue_if_no_path && m->queue_size)
|
|
|
|
|
|
|
+ if (!m->queue_if_no_path)
|
|
|
queue_work(kmultipathd, &m->process_queued_ios);
|
|
queue_work(kmultipathd, &m->process_queued_ios);
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&m->lock, flags);
|
|
spin_unlock_irqrestore(&m->lock, flags);
|
|
@@ -451,40 +443,6 @@ static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*-----------------------------------------------------------------
|
|
|
|
|
- * The multipath daemon is responsible for resubmitting queued ios.
|
|
|
|
|
- *---------------------------------------------------------------*/
|
|
|
|
|
-
|
|
|
|
|
-static void dispatch_queued_ios(struct multipath *m)
|
|
|
|
|
-{
|
|
|
|
|
- int r;
|
|
|
|
|
- unsigned long flags;
|
|
|
|
|
- union map_info *info;
|
|
|
|
|
- struct request *clone, *n;
|
|
|
|
|
- LIST_HEAD(cl);
|
|
|
|
|
-
|
|
|
|
|
- spin_lock_irqsave(&m->lock, flags);
|
|
|
|
|
- list_splice_init(&m->queued_ios, &cl);
|
|
|
|
|
- spin_unlock_irqrestore(&m->lock, flags);
|
|
|
|
|
-
|
|
|
|
|
- list_for_each_entry_safe(clone, n, &cl, queuelist) {
|
|
|
|
|
- list_del_init(&clone->queuelist);
|
|
|
|
|
-
|
|
|
|
|
- info = dm_get_rq_mapinfo(clone);
|
|
|
|
|
-
|
|
|
|
|
- r = map_io(m, clone, info, 1);
|
|
|
|
|
- if (r < 0) {
|
|
|
|
|
- clear_mapinfo(m, info);
|
|
|
|
|
- dm_kill_unmapped_request(clone, r);
|
|
|
|
|
- } else if (r == DM_MAPIO_REMAPPED)
|
|
|
|
|
- dm_dispatch_request(clone);
|
|
|
|
|
- else if (r == DM_MAPIO_REQUEUE) {
|
|
|
|
|
- clear_mapinfo(m, info);
|
|
|
|
|
- dm_requeue_unmapped_request(clone);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
static void process_queued_ios(struct work_struct *work)
|
|
static void process_queued_ios(struct work_struct *work)
|
|
|
{
|
|
{
|
|
|
struct multipath *m =
|
|
struct multipath *m =
|
|
@@ -509,7 +467,7 @@ static void process_queued_ios(struct work_struct *work)
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&m->lock, flags);
|
|
spin_unlock_irqrestore(&m->lock, flags);
|
|
|
if (!must_queue)
|
|
if (!must_queue)
|
|
|
- dispatch_queued_ios(m);
|
|
|
|
|
|
|
+ dm_table_run_md_queue_async(m->ti->table);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -987,7 +945,7 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
|
|
|
return DM_MAPIO_REQUEUE;
|
|
return DM_MAPIO_REQUEUE;
|
|
|
|
|
|
|
|
clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
|
|
clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
|
|
|
- r = map_io(m, clone, map_context, 0);
|
|
|
|
|
|
|
+ r = map_io(m, clone, map_context);
|
|
|
if (r < 0 || r == DM_MAPIO_REQUEUE)
|
|
if (r < 0 || r == DM_MAPIO_REQUEUE)
|
|
|
clear_mapinfo(m, map_context);
|
|
clear_mapinfo(m, map_context);
|
|
|
|
|
|
|
@@ -1056,7 +1014,7 @@ static int reinstate_path(struct pgpath *pgpath)
|
|
|
|
|
|
|
|
pgpath->is_active = 1;
|
|
pgpath->is_active = 1;
|
|
|
|
|
|
|
|
- if (!m->nr_valid_paths++ && m->queue_size) {
|
|
|
|
|
|
|
+ if (!m->nr_valid_paths++) {
|
|
|
m->current_pgpath = NULL;
|
|
m->current_pgpath = NULL;
|
|
|
queue_work(kmultipathd, &m->process_queued_ios);
|
|
queue_work(kmultipathd, &m->process_queued_ios);
|
|
|
} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
|
|
} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
|
|
@@ -1435,7 +1393,7 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
|
|
|
|
|
|
|
|
/* Features */
|
|
/* Features */
|
|
|
if (type == STATUSTYPE_INFO)
|
|
if (type == STATUSTYPE_INFO)
|
|
|
- DMEMIT("2 %u %u ", m->queue_size, m->pg_init_count);
|
|
|
|
|
|
|
+ DMEMIT("2 %u %u ", m->queue_io, m->pg_init_count);
|
|
|
else {
|
|
else {
|
|
|
DMEMIT("%u ", m->queue_if_no_path +
|
|
DMEMIT("%u ", m->queue_if_no_path +
|
|
|
(m->pg_init_retries > 0) * 2 +
|
|
(m->pg_init_retries > 0) * 2 +
|
|
@@ -1686,7 +1644,7 @@ static int multipath_busy(struct dm_target *ti)
|
|
|
spin_lock_irqsave(&m->lock, flags);
|
|
spin_lock_irqsave(&m->lock, flags);
|
|
|
|
|
|
|
|
/* pg_init in progress, requeue until done */
|
|
/* pg_init in progress, requeue until done */
|
|
|
- if (m->pg_init_in_progress) {
|
|
|
|
|
|
|
+ if (!pg_ready(m)) {
|
|
|
busy = 1;
|
|
busy = 1;
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
@@ -1739,7 +1697,7 @@ out:
|
|
|
*---------------------------------------------------------------*/
|
|
*---------------------------------------------------------------*/
|
|
|
static struct target_type multipath_target = {
|
|
static struct target_type multipath_target = {
|
|
|
.name = "multipath",
|
|
.name = "multipath",
|
|
|
- .version = {1, 6, 0},
|
|
|
|
|
|
|
+ .version = {1, 7, 0},
|
|
|
.module = THIS_MODULE,
|
|
.module = THIS_MODULE,
|
|
|
.ctr = multipath_ctr,
|
|
.ctr = multipath_ctr,
|
|
|
.dtr = multipath_dtr,
|
|
.dtr = multipath_dtr,
|