From: Hannes Reinecke <hare@suse.de>
To: Alasdair Kergon <agk@redhat.com>
Cc: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>,
dm-devel@redhat.com, Mike Snitzer <snitzer@redhat.com>
Subject: [PATCH 4/6] dm-multipath: remove process_queued_ios()
Date: Mon, 3 Feb 2014 13:34:55 +0100 [thread overview]
Message-ID: <1391430897-102094-5-git-send-email-hare@suse.de> (raw)
In-Reply-To: <1391430897-102094-1-git-send-email-hare@suse.de>
process_queued_ios() has served 3 functions:
1) select pg and pgpath if none is selected
2) start pg_init if requested
3) dispatch queued IOs when pg is ready
Basically, a call to queue_work(process_queued_ios) can be
replaced by dm_table_run_queue(), which runs request queue
and ends up calling map_io(), which does 1), 2) and 3).
Exception is when !pg_ready() (= either pg_init is running
or requested), then multipath_busy() prevents map_io() being
called from request_fn.
If pg_init is running, it should be ok as far as pg_init_done() does
the right thing when pg_init is completed. I.e. restart pg_init if
!pg_ready() or call dm_table_run_queue() to kick map_io().
If pg_init is requested, we have to make sure the request is detected
and pg_init will be started.
pg_init is requested in 3 places:
a) __choose_pgpath() in map_io()
b) __choose_pgpath() in multipath_ioctl()
c) pg_init retry in pg_init_done()
a) is ok because map_io() calls __pg_init_all_paths(), which does 2).
b) needs a call to __pg_init_all_paths(), which does 2).
c) needs a call to __pg_init_all_paths(), which does 2).
So this patch removes process_queued_ios() and ensures that
__pg_init_all_paths() is called at the appropriate locations.
We only need to take care to add a small delay when calling
__pg_init_all_paths() to move processing off to a workqueue;
pg_init_done() might end up calling scsi_dh_activate() directly,
which might use non-atomic memory allocations.
Not to speak of issuing I/O, too.
Cc: Mike Snitzer <snitzer@redhat.com>
Cc: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/md/dm-mpath.c | 63 +++++++++++++++++----------------------------------
1 file changed, 21 insertions(+), 42 deletions(-)
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 5373ca9..ff3bf3d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -93,8 +93,6 @@ struct multipath {
unsigned pg_init_count; /* Number of times pg_init called */
unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
- struct work_struct process_queued_ios;
-
struct work_struct trigger_event;
/*
@@ -119,7 +117,6 @@ typedef int (*action_fn) (struct pgpath *pgpath);
static struct kmem_cache *_mpio_cache;
static struct workqueue_struct *kmultipathd, *kmpath_handlerd;
-static void process_queued_ios(struct work_struct *work);
static void trigger_event(struct work_struct *work);
static void activate_path(struct work_struct *work);
static int __pgpath_busy(struct pgpath *pgpath);
@@ -197,7 +194,6 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
spin_lock_init(&m->lock);
m->queue_io = 1;
m->pg_init_delay_msecs = DM_PG_INIT_DELAY_DEFAULT;
- INIT_WORK(&m->process_queued_ios, process_queued_ios);
INIT_WORK(&m->trigger_event, trigger_event);
init_waitqueue_head(&m->pg_init_wait);
mutex_init(&m->work_mutex);
@@ -254,10 +250,10 @@ static void clear_mapinfo(struct multipath *m, union map_info *info)
* Path selection
*-----------------------------------------------*/
-static void __pg_init_all_paths(struct multipath *m)
+static void __pg_init_all_paths(struct multipath *m, unsigned long min_delay)
{
struct pgpath *pgpath;
- unsigned long pg_init_delay = 0;
+ unsigned long pg_init_delay = min_delay;
if (m->pg_init_in_progress || m->pg_init_disabled)
return;
@@ -406,7 +402,7 @@ static int map_io(struct multipath *m, struct request *clone,
&pgpath->path,
nr_bytes);
} else {
- __pg_init_all_paths(m);
+ __pg_init_all_paths(m, 0);
r = DM_MAPIO_REQUEUE;
}
} else {
@@ -438,41 +434,13 @@ static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
m->saved_queue_if_no_path = queue_if_no_path;
m->queue_if_no_path = queue_if_no_path;
if (!m->queue_if_no_path)
- queue_work(kmultipathd, &m->process_queued_ios);
+ dm_table_run_md_queue_async(m->ti->table);
spin_unlock_irqrestore(&m->lock, flags);
return 0;
}
-static void process_queued_ios(struct work_struct *work)
-{
- struct multipath *m =
- container_of(work, struct multipath, process_queued_ios);
- struct pgpath *pgpath = NULL;
- unsigned must_queue = 1;
- unsigned long flags;
-
- spin_lock_irqsave(&m->lock, flags);
-
- if (!m->current_pgpath)
- __choose_pgpath(m, 0);
-
- pgpath = m->current_pgpath;
-
- if ((pgpath && !m->queue_io) ||
- (!pgpath && !m->queue_if_no_path))
- must_queue = 0;
-
- if (m->pg_init_required && !m->pg_init_in_progress && pgpath &&
- !m->pg_init_disabled)
- __pg_init_all_paths(m);
-
- spin_unlock_irqrestore(&m->lock, flags);
- if (!must_queue)
- dm_table_run_md_queue_async(m->ti->table);
-}
-
/*
* An event is triggered whenever a path is taken out of use.
* Includes path failure and PG bypass.
@@ -1019,7 +987,7 @@ static int reinstate_path(struct pgpath *pgpath)
if (!m->nr_valid_paths++) {
m->current_pgpath = NULL;
- queue_work(kmultipathd, &m->process_queued_ios);
+ dm_table_run_md_queue_async(m->ti->table);
} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
if (queue_work(kmpath_handlerd, &pgpath->activate_path.work))
m->pg_init_in_progress++;
@@ -1217,9 +1185,11 @@ static void pg_init_done(void *data, int errors)
if (!m->pg_init_required)
m->queue_io = 0;
-
- m->pg_init_delay_retry = delay_retry;
- queue_work(kmultipathd, &m->process_queued_ios);
+ else if (m->current_pg) {
+ m->pg_init_delay_retry = delay_retry;
+ __pg_init_all_paths(m, 50/HZ);
+ goto out;
+ }
/*
* Wake up any thread waiting to suspend.
@@ -1593,8 +1563,17 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
r = scsi_verify_blk_ioctl(NULL, cmd);
- if (r == -ENOTCONN && !fatal_signal_pending(current))
- queue_work(kmultipathd, &m->process_queued_ios);
+ if (r == -ENOTCONN && !fatal_signal_pending(current)) {
+ spin_lock_irqsave(&m->lock, flags);
+ if (!m->current_pg) {
+ /* Path status changed, redo selection */
+ __choose_pgpath(m, 0);
+ }
+ if (m->current_pg && m->pg_init_required)
+ __pg_init_all_paths(m, 0);
+ spin_unlock_irqrestore(&m->lock, flags);
+ dm_table_run_md_queue_async(m->ti->table);
+ }
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
--
1.7.12.4
next prev parent reply other threads:[~2014-02-03 12:34 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-03 12:34 [PATCHv5 0/6] dm-multipath: push back requests instead of queueing Hannes Reinecke
2014-02-03 12:34 ` [PATCH 1/6] dm-multipath: Do not call pg_init twice Hannes Reinecke
2014-02-03 12:34 ` [PATCH 2/6] dm: implement dm_md_get_queue() Hannes Reinecke
2014-02-03 12:34 ` [PATCH 3/6] dm-multipath: push back requests instead of queueing Hannes Reinecke
2014-02-03 12:34 ` Hannes Reinecke [this message]
2014-02-03 12:34 ` [PATCH 5/6] dm-multipath: reduce memory pressure during requeuing Hannes Reinecke
2014-02-03 12:34 ` [PATCH 6/6] dm-multipath: remove map_io() Hannes Reinecke
-- strict thread matches above, loose matches on Subject: below --
2014-02-03 8:18 [PATCHv4 0/6] dm-multipath: push back requests instead of queueing Hannes Reinecke
2014-02-03 8:18 ` [PATCH 4/6] dm-multipath: remove process_queued_ios() Hannes Reinecke
2014-02-03 11:30 ` Junichi Nomura
2014-02-03 11:39 ` Hannes Reinecke
2014-02-03 12:08 ` Junichi Nomura
2014-02-03 12:18 ` Hannes Reinecke
2014-02-03 12:39 ` Junichi Nomura
2014-02-03 12:57 ` Hannes Reinecke
2014-02-04 3:21 ` Junichi Nomura
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1391430897-102094-5-git-send-email-hare@suse.de \
--to=hare@suse.de \
--cc=agk@redhat.com \
--cc=dm-devel@redhat.com \
--cc=j-nomura@ce.jp.nec.com \
--cc=snitzer@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.