dm mpath: add locking to multipath_resume and must_push_back
authorMike Snitzer <snitzer@redhat.com>
Tue, 26 Jul 2016 01:08:51 +0000 (21:08 -0400)
committerMike Snitzer <snitzer@redhat.com>
Tue, 2 Aug 2016 20:21:34 +0000 (16:21 -0400)
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>
drivers/md/dm-mpath.c

index 7eac080fcb18cd67110888d323c0c460068c21e1..d7107d23b89763c96861a43472ae5659491585ff 100644 (file)
@@ -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);
 }
 
 /*