summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2016-07-26 01:08:51 (GMT)
committerMike Snitzer <snitzer@redhat.com>2016-08-02 20:21:34 (GMT)
commit1814f2e3fb95b58490e56a38fefe462ffe8fb9ad (patch)
treebc878dcc44bb1e04a0ceb44bf4bcbcf8d82e98b3 /drivers
parent99f3c90d0d85708e7401a81ce3314e50bf7f2819 (diff)
downloadlinux-1814f2e3fb95b58490e56a38fefe462ffe8fb9ad.tar.xz
dm mpath: add locking to multipath_resume and must_push_back
Multiple flags were being tested without locking. Protect against non-atomic bit changes in m->flags by holding m->lock (while testing or setting the queue_if_no_path related flags). Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/dm-mpath.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 7eac080..d7107d2 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -507,13 +507,27 @@ static bool __must_push_back(struct multipath *m)
static bool must_push_back_rq(struct multipath *m)
{
- return (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) ||
- __must_push_back(m));
+ bool r;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+ r = (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) ||
+ __must_push_back(m));
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return r;
}
static bool must_push_back_bio(struct multipath *m)
{
- return __must_push_back(m);
+ bool r;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+ r = __must_push_back(m);
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return r;
}
/*
@@ -1680,12 +1694,14 @@ 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);
if (test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags))
set_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
else
clear_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
- smp_mb__after_atomic();
+ spin_unlock_irqrestore(&m->lock, flags);
}
/*