md/raid5: use consistency_policy to remove journal feature
authorSong Liu <songliubraving@fb.com>
Mon, 27 Mar 2017 17:51:33 +0000 (10:51 -0700)
committerShaohua Li <shli@fb.com>
Mon, 27 Mar 2017 19:02:33 +0000 (12:02 -0700)
When journal device of an array fails, the array is forced into read-only
mode. To make the array normal without adding another journal device, we
need to remove journal _feature_ from the array.

This patch allows remove journal _feature_ from an array, For journal
existing journal should be either missing or faulty.

To remove journal feature, it is necessary to remove the journal device
first:

  mdadm --fail /dev/md0 /dev/sdb
  mdadm: set /dev/sdb faulty in /dev/md0
  mdadm --remove /dev/md0 /dev/sdb
  mdadm: hot removed /dev/sdb from /dev/md0

Then the journal feature can be removed by echoing into the sysfs file:

 cat /sys/block/md0/md/consistency_policy
 journal

 echo resync > /sys/block/md0/md/consistency_policy
 cat /sys/block/md0/md/consistency_policy
 resync

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

index 266d661..6036d5e 100644 (file)
@@ -8292,17 +8292,41 @@ static int raid5_change_consistency_policy(struct mddev *mddev, const char *buf)
        }
 
        if (strncmp(buf, "ppl", 3) == 0 && !raid5_has_ppl(conf)) {
-               mddev_suspend(mddev);
-               set_bit(MD_HAS_PPL, &mddev->flags);
-               err = log_init(conf, NULL);
-               if (!err)
+               /* ppl only works with RAID 5 */
+               if (conf->level == 5) {
+                       mddev_suspend(mddev);
+                       set_bit(MD_HAS_PPL, &mddev->flags);
+                       err = log_init(conf, NULL);
+                       if (!err)
+                               raid5_reset_stripe_cache(mddev);
+                       mddev_resume(mddev);
+               } else
+                       err = -EINVAL;
+       } else if (strncmp(buf, "resync", 6) == 0) {
+               if (raid5_has_ppl(conf)) {
+                       mddev_suspend(mddev);
+                       log_exit(conf);
                        raid5_reset_stripe_cache(mddev);
-               mddev_resume(mddev);
-       } else if (strncmp(buf, "resync", 6) == 0 && raid5_has_ppl(conf)) {
-               mddev_suspend(mddev);
-               log_exit(conf);
-               raid5_reset_stripe_cache(mddev);
-               mddev_resume(mddev);
+                       mddev_resume(mddev);
+               } else if (test_bit(MD_HAS_JOURNAL, &conf->mddev->flags) &&
+                          r5l_log_disk_error(conf)) {
+                       bool journal_dev_exists = false;
+                       struct md_rdev *rdev;
+
+                       rdev_for_each(rdev, mddev)
+                               if (test_bit(Journal, &rdev->flags)) {
+                                       journal_dev_exists = true;
+                                       break;
+                               }
+
+                       if (!journal_dev_exists) {
+                               mddev_suspend(mddev);
+                               clear_bit(MD_HAS_JOURNAL, &mddev->flags);
+                               mddev_resume(mddev);
+                       } else  /* need remove journal device first */
+                               err = -EBUSY;
+               } else
+                       err = -EINVAL;
        } else {
                err = -EINVAL;
        }
@@ -8337,6 +8361,7 @@ static struct md_personality raid6_personality =
        .quiesce        = raid5_quiesce,
        .takeover       = raid6_takeover,
        .congested      = raid5_congested,
+       .change_consistency_policy = raid5_change_consistency_policy,
 };
 static struct md_personality raid5_personality =
 {
@@ -8385,6 +8410,7 @@ static struct md_personality raid4_personality =
        .quiesce        = raid5_quiesce,
        .takeover       = raid4_takeover,
        .congested      = raid5_congested,
+       .change_consistency_policy = raid5_change_consistency_policy,
 };
 
 static int __init raid5_init(void)