Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <snitzer@redhat.com>

+23 -9
+23 -9
drivers/md/dm-mpath.c
··· 128 128 #define MPATHF_PG_INIT_REQUIRED 5 /* pg_init needs calling? */ 129 129 #define MPATHF_PG_INIT_DELAY_RETRY 6 /* Delay pg_init retry? */ 130 130 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 + 131 145 /*----------------------------------------------- 132 146 * Allocation routines 133 147 *-----------------------------------------------*/ ··· 513 499 514 500 /* Do we need to select a new pgpath? */ 515 501 pgpath = READ_ONCE(m->current_pgpath); 516 - if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags)) 502 + if (!pgpath || !mpath_double_check_test_bit(MPATHF_QUEUE_IO, m)) 517 503 pgpath = choose_pgpath(m, nr_bytes); 518 504 519 505 if (!pgpath) { ··· 521 507 return DM_MAPIO_DELAY_REQUEUE; 522 508 dm_report_EIO(m); /* Failed */ 523 509 return DM_MAPIO_KILL; 524 - } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) || 525 - test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) { 510 + } else if (mpath_double_check_test_bit(MPATHF_QUEUE_IO, m) || 511 + mpath_double_check_test_bit(MPATHF_PG_INIT_REQUIRED, m)) { 526 512 pg_init_all_paths(m); 527 513 return DM_MAPIO_DELAY_REQUEUE; 528 514 } ··· 612 598 613 599 /* Do we need to select a new pgpath? */ 614 600 pgpath = READ_ONCE(m->current_pgpath); 615 - if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags)) 601 + if (!pgpath || !mpath_double_check_test_bit(MPATHF_QUEUE_IO, m)) 616 602 pgpath = choose_pgpath(m, bio->bi_iter.bi_size); 617 603 618 604 if (!pgpath) { ··· 623 609 } 624 610 spin_unlock_irqrestore(&m->lock, flags); 625 611 626 - } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) || 627 - test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) { 612 + } else if (mpath_double_check_test_bit(MPATHF_QUEUE_IO, m) || 613 + mpath_double_check_test_bit(MPATHF_PG_INIT_REQUIRED, m)) { 628 614 multipath_queue_bio(m, bio); 629 615 pg_init_all_paths(m); 630 616 return ERR_PTR(-EAGAIN); ··· 875 861 struct request_queue *q = bdev_get_queue(bdev); 876 862 int r; 877 863 878 - if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) { 864 + if (mpath_double_check_test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, m)) { 879 865 retain: 880 866 if (*attached_handler_name) { 881 867 /* ··· 1981 1967 int r; 1982 1968 1983 1969 pgpath = READ_ONCE(m->current_pgpath); 1984 - if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags)) 1970 + if (!pgpath || !mpath_double_check_test_bit(MPATHF_QUEUE_IO, m)) 1985 1971 pgpath = choose_pgpath(m, 0); 1986 1972 1987 1973 if (pgpath) { 1988 - if (!test_bit(MPATHF_QUEUE_IO, &m->flags)) { 1974 + if (!mpath_double_check_test_bit(MPATHF_QUEUE_IO, m)) { 1989 1975 *bdev = pgpath->path.dev->bdev; 1990 1976 r = 0; 1991 1977 } else {