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: take m->lock spinlock when testing QUEUE_IF_NO_PATH

Fix multipath_end_io, multipath_end_io_bio and multipath_busy to take
m->lock while testing if MPATHF_QUEUE_IF_NO_PATH bit is set. These are
all slow-path cases when no paths are available so extra locking isn't a
performance hit. Correctness matters most.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>

+34 -18
+34 -18
drivers/md/dm-mpath.c
··· 1621 1621 if (pgpath) 1622 1622 fail_path(pgpath); 1623 1623 1624 - if (atomic_read(&m->nr_valid_paths) == 0 && 1625 - !must_push_back_rq(m)) { 1626 - if (error == BLK_STS_IOERR) 1627 - dm_report_EIO(m); 1628 - /* complete with the original error */ 1629 - r = DM_ENDIO_DONE; 1624 + if (!atomic_read(&m->nr_valid_paths)) { 1625 + unsigned long flags; 1626 + spin_lock_irqsave(&m->lock, flags); 1627 + if (!must_push_back_rq(m)) { 1628 + if (error == BLK_STS_IOERR) 1629 + dm_report_EIO(m); 1630 + /* complete with the original error */ 1631 + r = DM_ENDIO_DONE; 1632 + } 1633 + spin_unlock_irqrestore(&m->lock, flags); 1630 1634 } 1631 1635 } 1632 1636 ··· 1660 1656 if (pgpath) 1661 1657 fail_path(pgpath); 1662 1658 1663 - if (atomic_read(&m->nr_valid_paths) == 0 && 1664 - !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { 1665 - if (__must_push_back(m)) { 1666 - r = DM_ENDIO_REQUEUE; 1667 - } else { 1668 - dm_report_EIO(m); 1669 - *error = BLK_STS_IOERR; 1659 + if (!atomic_read(&m->nr_valid_paths)) { 1660 + spin_lock_irqsave(&m->lock, flags); 1661 + if (!test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { 1662 + if (__must_push_back(m)) { 1663 + r = DM_ENDIO_REQUEUE; 1664 + } else { 1665 + dm_report_EIO(m); 1666 + *error = BLK_STS_IOERR; 1667 + } 1668 + spin_unlock_irqrestore(&m->lock, flags); 1669 + goto done; 1670 1670 } 1671 - goto done; 1671 + spin_unlock_irqrestore(&m->lock, flags); 1672 1672 } 1673 1673 1674 1674 spin_lock_irqsave(&m->lock, flags); ··· 1970 1962 } 1971 1963 } else { 1972 1964 /* No path is available */ 1965 + r = -EIO; 1966 + spin_lock_irqsave(&m->lock, flags); 1973 1967 if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) 1974 1968 r = -ENOTCONN; 1975 - else 1976 - r = -EIO; 1969 + spin_unlock_irqrestore(&m->lock, flags); 1977 1970 } 1978 1971 1979 1972 if (r == -ENOTCONN) { ··· 2045 2036 return true; 2046 2037 2047 2038 /* no paths available, for blk-mq: rely on IO mapping to delay requeue */ 2048 - if (!atomic_read(&m->nr_valid_paths) && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) 2049 - return (m->queue_mode != DM_TYPE_REQUEST_BASED); 2039 + if (!atomic_read(&m->nr_valid_paths)) { 2040 + unsigned long flags; 2041 + spin_lock_irqsave(&m->lock, flags); 2042 + if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) { 2043 + spin_unlock_irqrestore(&m->lock, flags); 2044 + return (m->queue_mode != DM_TYPE_REQUEST_BASED); 2045 + } 2046 + spin_unlock_irqrestore(&m->lock, flags); 2047 + } 2050 2048 2051 2049 /* Guess which priority_group will be used at next mapping time */ 2052 2050 pg = READ_ONCE(m->current_pg);