Merge branch 'mymd/for-next' into mymd/for-linus
[cascardo/linux.git] / drivers / md / multipath.c
index 72ea98e..4974682 100644 (file)
@@ -43,7 +43,8 @@ static int multipath_map (struct mpconf *conf)
        rcu_read_lock();
        for (i = 0; i < disks; i++) {
                struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
-               if (rdev && test_bit(In_sync, &rdev->flags)) {
+               if (rdev && test_bit(In_sync, &rdev->flags) &&
+                   !test_bit(Faulty, &rdev->flags)) {
                        atomic_inc(&rdev->nr_pending);
                        rcu_read_unlock();
                        return i;
@@ -141,17 +142,19 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
        return;
 }
 
-static void multipath_status (struct seq_file *seq, struct mddev *mddev)
+static void multipath_status(struct seq_file *seq, struct mddev *mddev)
 {
        struct mpconf *conf = mddev->private;
        int i;
 
        seq_printf (seq, " [%d/%d] [", conf->raid_disks,
                    conf->raid_disks - mddev->degraded);
-       for (i = 0; i < conf->raid_disks; i++)
-               seq_printf (seq, "%s",
-                              conf->multipaths[i].rdev &&
-                              test_bit(In_sync, &conf->multipaths[i].rdev->flags) ? "U" : "_");
+       rcu_read_lock();
+       for (i = 0; i < conf->raid_disks; i++) {
+               struct md_rdev *rdev = rcu_dereference(conf->multipaths[i].rdev);
+               seq_printf (seq, "%s", rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
+       }
+       rcu_read_unlock();
        seq_printf (seq, "]");
 }
 
@@ -295,12 +298,14 @@ static int multipath_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
                        goto abort;
                }
                p->rdev = NULL;
-               synchronize_rcu();
-               if (atomic_read(&rdev->nr_pending)) {
-                       /* lost the race, try later */
-                       err = -EBUSY;
-                       p->rdev = rdev;
-                       goto abort;
+               if (!test_bit(RemoveSynchronized, &rdev->flags)) {
+                       synchronize_rcu();
+                       if (atomic_read(&rdev->nr_pending)) {
+                               /* lost the race, try later */
+                               err = -EBUSY;
+                               p->rdev = rdev;
+                               goto abort;
+                       }
                }
                err = md_integrity_register(mddev);
        }