From: Benjamin Marzinski <bmarzins@redhat.com>
To: Mikulas Patocka <mpatocka@redhat.com>
Cc: Mike Snitzer <snitzer@redhat.com>,
dm-devel@lists.linux.dev, Kevin Wolf <kwolf@redhat.com>,
Hanna Czenczek <hreitz@redhat.com>,
Martin Wilck <martin.wilck@suse.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Christoph Hellwig <hch@infradead.org>,
Hannes Reinecke <hare@suse.de>
Subject: Re: [PATCH] dm mpath: replace spin_lock_irqsave with spin_lock_irq
Date: Mon, 19 May 2025 23:56:11 -0400 [thread overview]
Message-ID: <aCv9W5KgT4akZBBq@redhat.com> (raw)
In-Reply-To: <5f348c81-5f69-089c-4092-86703f0b87a3@redhat.com>
On Mon, May 19, 2025 at 03:50:15PM +0200, Mikulas Patocka wrote:
>
>
> On Fri, 16 May 2025, Mikulas Patocka wrote:
>
> >
> >
> > On Thu, 15 May 2025, Benjamin Marzinski wrote:
> >
> > > @@ -2077,35 +2095,55 @@ static int probe_path(struct pgpath *pgpath)
> > > static int probe_active_paths(struct multipath *m)
> > > {
> > > struct pgpath *pgpath;
> > > - struct priority_group *pg;
> > > + struct priority_group *pg = NULL;
> > > unsigned long flags;
> > > int r = 0;
> > >
> > > - mutex_lock(&m->work_mutex);
> > > -
> > > spin_lock_irqsave(&m->lock, flags);
> >
> > Hi
> >
> > I suggest replacing spin_lock_irqsave/spin_unlock_irqrestore with
> > spin_lock_irq/spin_unlock_irq here and in some other places where it is
> > known that interrupts are enabled (for example __map_bio,
> > process_queued_bios, multipath_ctr, flush_multipath_work,
> > multipath_resume, multipath_status, multipath_prepare_ioctl, ...).
> >
> > I accepted this patch, so you can send the spinlock changes in a follow-up
> > patch.
> >
> > Mikulas
>
> Hi
>
> I've created a patch for this. Please test it (with spinlock debugging
> enabled), if it passes the tests, I'll stage it.
I tested this with CONFIG_DEBUG_SPINLOCK=y and everything looks fine.
Actually, I tested a slightly different patch. Your patch applies on top
of dm-6.15, but that means it doesn't clean up the spin_lock_irqsave()
calls in my last patch. I tested using a version of your patch that goes
on top of dm-for-next, and changes the spinlocks in probe_active_paths()
and multipath_presuspend(), both of which can also only be called with
interrupts enabled. Here it is:
From: Mikulas Patocka <mpatocka@redhat.com>
Replace spin_lock_irqsave/spin_unlock_irqrestore with
spin_lock_irq/spin_unlock_irq at places where it is known that interrupts
are enabled.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
drivers/md/dm-mpath.c | 75 ++++++++++++++++++-------------------------
1 file changed, 31 insertions(+), 44 deletions(-)
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 12b7bcae490c..81fec2e1e0ef 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -617,7 +617,6 @@ static void multipath_queue_bio(struct multipath *m, struct bio *bio)
static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
{
struct pgpath *pgpath;
- unsigned long flags;
/* Do we need to select a new pgpath? */
pgpath = READ_ONCE(m->current_pgpath);
@@ -625,12 +624,12 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
if (!pgpath) {
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
__multipath_queue_bio(m, bio);
pgpath = ERR_PTR(-EAGAIN);
}
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
} else if (mpath_double_check_test_bit(MPATHF_QUEUE_IO, m) ||
mpath_double_check_test_bit(MPATHF_PG_INIT_REQUIRED, m)) {
@@ -693,7 +692,6 @@ static void process_queued_io_list(struct multipath *m)
static void process_queued_bios(struct work_struct *work)
{
int r;
- unsigned long flags;
struct bio *bio;
struct bio_list bios;
struct blk_plug plug;
@@ -702,16 +700,16 @@ static void process_queued_bios(struct work_struct *work)
bio_list_init(&bios);
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
if (bio_list_empty(&m->queued_bios)) {
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
return;
}
bio_list_merge_init(&bios, &m->queued_bios);
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
blk_start_plug(&plug);
while ((bio = bio_list_pop(&bios))) {
@@ -1195,7 +1193,6 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, char **argv)
struct dm_arg_set as;
unsigned int pg_count = 0;
unsigned int next_pg_num;
- unsigned long flags;
as.argc = argc;
as.argv = argv;
@@ -1260,9 +1257,9 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
enable_nopath_timeout(m);
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
ti->num_flush_bios = 1;
ti->num_discard_bios = 1;
@@ -1297,23 +1294,21 @@ static void multipath_wait_for_pg_init_completion(struct multipath *m)
static void flush_multipath_work(struct multipath *m)
{
if (m->hw_handler_name) {
- unsigned long flags;
-
if (!atomic_read(&m->pg_init_in_progress))
goto skip;
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
if (atomic_read(&m->pg_init_in_progress) &&
!test_and_set_bit(MPATHF_PG_INIT_DISABLED, &m->flags)) {
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
flush_workqueue(kmpath_handlerd);
multipath_wait_for_pg_init_completion(m);
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
}
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
}
skip:
if (m->queue_mode == DM_TYPE_BIO_BASED)
@@ -1375,11 +1370,10 @@ static int fail_path(struct pgpath *pgpath)
static int reinstate_path(struct pgpath *pgpath)
{
int r = 0, run_queue = 0;
- unsigned long flags;
struct multipath *m = pgpath->pg->m;
unsigned int nr_valid_paths;
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
if (pgpath->is_active)
goto out;
@@ -1409,7 +1403,7 @@ static int reinstate_path(struct pgpath *pgpath)
schedule_work(&m->trigger_event);
out:
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
if (run_queue) {
dm_table_run_md_queue_async(m->ti->table);
process_queued_io_list(m);
@@ -1470,7 +1464,6 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
{
struct priority_group *pg;
unsigned int pgnum;
- unsigned long flags;
char dummy;
if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
@@ -1479,7 +1472,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
return -EINVAL;
}
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
list_for_each_entry(pg, &m->priority_groups, list) {
pg->bypassed = false;
if (--pgnum)
@@ -1493,7 +1486,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
}
m->next_pg = pg;
}
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
schedule_work(&m->trigger_event);
return 0;
@@ -1754,11 +1747,10 @@ static int multipath_end_io_bio(struct dm_target *ti, struct bio *clone,
static void multipath_presuspend(struct dm_target *ti)
{
struct multipath *m = ti->private;
- unsigned long flags;
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
m->is_suspending = true;
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
/* FIXME: bio-based shouldn't need to always disable queue_if_no_path */
if (m->queue_mode == DM_TYPE_BIO_BASED || !dm_noflush_suspending(m->ti))
queue_if_no_path(m, false, true, __func__);
@@ -1779,9 +1771,8 @@ static void multipath_postsuspend(struct dm_target *ti)
static void multipath_resume(struct dm_target *ti)
{
struct multipath *m = ti->private;
- unsigned long flags;
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
m->is_suspending = false;
if (test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags)) {
set_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
@@ -1793,7 +1784,7 @@ static void multipath_resume(struct dm_target *ti)
test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags),
test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags));
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
}
/*
@@ -1816,14 +1807,13 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
unsigned int status_flags, char *result, unsigned int maxlen)
{
int sz = 0, pg_counter, pgpath_counter;
- unsigned long flags;
struct multipath *m = ti->private;
struct priority_group *pg;
struct pgpath *p;
unsigned int pg_num;
char state;
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
/* Features */
if (type == STATUSTYPE_INFO)
@@ -1969,7 +1959,7 @@ static void multipath_status(struct dm_target *ti, status_type_t type,
break;
}
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
}
static int multipath_message(struct dm_target *ti, unsigned int argc, char **argv,
@@ -1979,7 +1969,6 @@ static int multipath_message(struct dm_target *ti, unsigned int argc, char **arg
dev_t dev;
struct multipath *m = ti->private;
action_fn action;
- unsigned long flags;
mutex_lock(&m->work_mutex);
@@ -1991,9 +1980,9 @@ static int multipath_message(struct dm_target *ti, unsigned int argc, char **arg
if (argc == 1) {
if (!strcasecmp(argv[0], "queue_if_no_path")) {
r = queue_if_no_path(m, true, false, __func__);
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
enable_nopath_timeout(m);
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
goto out;
} else if (!strcasecmp(argv[0], "fail_if_no_path")) {
r = queue_if_no_path(m, false, false, __func__);
@@ -2096,10 +2085,9 @@ static int probe_active_paths(struct multipath *m)
{
struct pgpath *pgpath;
struct priority_group *pg = NULL;
- unsigned long flags;
int r = 0;
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
if (test_bit(MPATHF_DELAY_PG_SWITCH, &m->flags)) {
wait_event_lock_irq(m->probe_wait,
!test_bit(MPATHF_DELAY_PG_SWITCH, &m->flags),
@@ -2117,7 +2105,7 @@ static int probe_active_paths(struct multipath *m)
goto skip_probe;
set_bit(MPATHF_DELAY_PG_SWITCH, &m->flags);
pg = m->last_probed_pg = m->current_pg;
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
list_for_each_entry(pgpath, &pg->pgpaths, list) {
if (pg != READ_ONCE(m->current_pg) ||
@@ -2132,7 +2120,7 @@ static int probe_active_paths(struct multipath *m)
}
out:
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
clear_bit(MPATHF_DELAY_PG_SWITCH, &m->flags);
if (test_and_clear_bit(MPATHF_NEED_PG_SWITCH, &m->flags)) {
m->current_pgpath = NULL;
@@ -2141,7 +2129,7 @@ static int probe_active_paths(struct multipath *m)
skip_probe:
if (r == 0 && !atomic_read(&m->nr_valid_paths))
r = -ENOTCONN;
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
if (pg)
wake_up(&m->probe_wait);
return r;
@@ -2154,7 +2142,6 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
{
struct multipath *m = ti->private;
struct pgpath *pgpath;
- unsigned long flags;
int r;
if (_IOC_TYPE(cmd) == DM_IOCTL) {
@@ -2182,10 +2169,10 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
} else {
/* No path is available */
r = -EIO;
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
r = -ENOTCONN;
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
}
if (r == -ENOTCONN) {
@@ -2193,10 +2180,10 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
/* Path status changed, redo selection */
(void) choose_pgpath(m, 0);
}
- spin_lock_irqsave(&m->lock, flags);
+ spin_lock_irq(&m->lock);
if (test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags))
(void) __pg_init_all_paths(m);
- spin_unlock_irqrestore(&m->lock, flags);
+ spin_unlock_irq(&m->lock);
dm_table_run_md_queue_async(m->ti->table);
process_queued_io_list(m);
}
--
2.46.1
prev parent reply other threads:[~2025-05-20 3:56 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-16 1:55 [PATCH] dm-mpath: Don't grab work_mutex while probing paths Benjamin Marzinski
2025-05-16 11:35 ` Mikulas Patocka
2025-05-16 19:16 ` Benjamin Marzinski
2025-05-19 13:50 ` [PATCH] dm mpath: replace spin_lock_irqsave with spin_lock_irq Mikulas Patocka
2025-05-20 3:56 ` Benjamin Marzinski [this message]
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=aCv9W5KgT4akZBBq@redhat.com \
--to=bmarzins@redhat.com \
--cc=dm-devel@lists.linux.dev \
--cc=hare@suse.de \
--cc=hch@infradead.org \
--cc=hreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=martin.wilck@suse.com \
--cc=mpatocka@redhat.com \
--cc=pbonzini@redhat.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.