MD: when RAID journal is missing/faulty, block RESTART_ARRAY_RW
authorSong Liu <songliubraving@fb.com>
Fri, 9 Oct 2015 04:54:13 +0000 (21:54 -0700)
committerNeilBrown <neilb@suse.com>
Sun, 1 Nov 2015 02:48:29 +0000 (13:48 +1100)
When RAID-4/5/6 array suffers from missing journal device, we put
the array in read only state. We should not allow trasition to
read-write states (clean and active) before replacing journal device.

Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: NeilBrown <neilb@suse.com>
drivers/md/md.c

index b5057596b630420dea63b57b07f1a6abc509705d..08a4034351deeefa0e4d641b9100d492dfee1425 100644 (file)
@@ -3970,7 +3970,9 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
                break;
        case clean:
                if (mddev->pers) {
-                       restart_array(mddev);
+                       err = restart_array(mddev);
+                       if (err)
+                               break;
                        spin_lock(&mddev->lock);
                        if (atomic_read(&mddev->writes_pending) == 0) {
                                if (mddev->in_sync == 0) {
@@ -3988,7 +3990,9 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
                break;
        case active:
                if (mddev->pers) {
-                       restart_array(mddev);
+                       err = restart_array(mddev);
+                       if (err)
+                               break;
                        clear_bit(MD_CHANGE_PENDING, &mddev->flags);
                        wake_up(&mddev->sb_wait);
                        err = 0;
@@ -5351,6 +5355,25 @@ static int restart_array(struct mddev *mddev)
                return -EINVAL;
        if (!mddev->ro)
                return -EBUSY;
+       if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) {
+               struct md_rdev *rdev;
+               bool has_journal = false;
+
+               rcu_read_lock();
+               rdev_for_each_rcu(rdev, mddev) {
+                       if (test_bit(Journal, &rdev->flags) &&
+                           !test_bit(Faulty, &rdev->flags)) {
+                               has_journal = true;
+                               break;
+                       }
+               }
+               rcu_read_unlock();
+
+               /* Don't restart rw with journal missing/faulty */
+               if (!has_journal)
+                       return -EINVAL;
+       }
+
        mddev->safemode = 0;
        mddev->ro = 0;
        set_disk_ro(disk, 0);