Skip to content

Commit 374117a

Browse files
committed
dm mpath: use double checked locking in fast path
Fast-path code biased toward lazy acknowledgement of bit being set (primarily only for initialization). Multipath code is very retry oriented so even if state is missed it'll recover. Signed-off-by: Mike Snitzer <[email protected]>
1 parent 564dbb1 commit 374117a

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

drivers/md/dm-mpath.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ static void queue_if_no_path_timeout_work(struct timer_list *t);
128128
#define MPATHF_PG_INIT_REQUIRED 5 /* pg_init needs calling? */
129129
#define MPATHF_PG_INIT_DELAY_RETRY 6 /* Delay pg_init retry? */
130130

131+
static bool mpath_double_check_test_bit(int MPATHF_bit, struct multipath *m)
132+
{
133+
bool r = test_bit(MPATHF_bit, &m->flags);
134+
135+
if (r) {
136+
unsigned long flags;
137+
spin_lock_irqsave(&m->lock, flags);
138+
r = test_bit(MPATHF_bit, &m->flags);
139+
spin_unlock_irqrestore(&m->lock, flags);
140+
}
141+
142+
return r;
143+
}
144+
131145
/*-----------------------------------------------
132146
* Allocation routines
133147
*-----------------------------------------------*/
@@ -499,16 +513,16 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
499513

500514
/* Do we need to select a new pgpath? */
501515
pgpath = READ_ONCE(m->current_pgpath);
502-
if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags))
516+
if (!pgpath || !mpath_double_check_test_bit(MPATHF_QUEUE_IO, m))
503517
pgpath = choose_pgpath(m, nr_bytes);
504518

505519
if (!pgpath) {
506520
if (must_push_back_rq(m))
507521
return DM_MAPIO_DELAY_REQUEUE;
508522
dm_report_EIO(m); /* Failed */
509523
return DM_MAPIO_KILL;
510-
} else if (test_bit(MPATHF_QUEUE_IO, &m->flags) ||
511-
test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) {
524+
} else if (mpath_double_check_test_bit(MPATHF_QUEUE_IO, m) ||
525+
mpath_double_check_test_bit(MPATHF_PG_INIT_REQUIRED, m)) {
512526
pg_init_all_paths(m);
513527
return DM_MAPIO_DELAY_REQUEUE;
514528
}
@@ -598,7 +612,7 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
598612

599613
/* Do we need to select a new pgpath? */
600614
pgpath = READ_ONCE(m->current_pgpath);
601-
if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags))
615+
if (!pgpath || !mpath_double_check_test_bit(MPATHF_QUEUE_IO, m))
602616
pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
603617

604618
if (!pgpath) {
@@ -609,8 +623,8 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
609623
}
610624
spin_unlock_irqrestore(&m->lock, flags);
611625

612-
} else if (test_bit(MPATHF_QUEUE_IO, &m->flags) ||
613-
test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) {
626+
} else if (mpath_double_check_test_bit(MPATHF_QUEUE_IO, m) ||
627+
mpath_double_check_test_bit(MPATHF_PG_INIT_REQUIRED, m)) {
614628
multipath_queue_bio(m, bio);
615629
pg_init_all_paths(m);
616630
return ERR_PTR(-EAGAIN);
@@ -861,7 +875,7 @@ static int setup_scsi_dh(struct block_device *bdev, struct multipath *m,
861875
struct request_queue *q = bdev_get_queue(bdev);
862876
int r;
863877

864-
if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) {
878+
if (mpath_double_check_test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, m)) {
865879
retain:
866880
if (*attached_handler_name) {
867881
/*
@@ -1967,11 +1981,11 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
19671981
int r;
19681982

19691983
pgpath = READ_ONCE(m->current_pgpath);
1970-
if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags))
1984+
if (!pgpath || !mpath_double_check_test_bit(MPATHF_QUEUE_IO, m))
19711985
pgpath = choose_pgpath(m, 0);
19721986

19731987
if (pgpath) {
1974-
if (!test_bit(MPATHF_QUEUE_IO, &m->flags)) {
1988+
if (!mpath_double_check_test_bit(MPATHF_QUEUE_IO, m)) {
19751989
*bdev = pgpath->path.dev->bdev;
19761990
r = 0;
19771991
} else {

0 commit comments

Comments
 (0)