|
@@ -1183,6 +1183,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|
|
desc->raid_disk < mddev->raid_disks */) {
|
|
|
set_bit(In_sync, &rdev->flags);
|
|
|
rdev->raid_disk = desc->raid_disk;
|
|
|
+ rdev->saved_raid_disk = desc->raid_disk;
|
|
|
} else if (desc->state & (1<<MD_DISK_ACTIVE)) {
|
|
|
/* active but not in sync implies recovery up to
|
|
|
* reshape position. We don't know exactly where
|
|
@@ -1681,10 +1682,14 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|
|
set_bit(Faulty, &rdev->flags);
|
|
|
break;
|
|
|
default:
|
|
|
+ rdev->saved_raid_disk = role;
|
|
|
if ((le32_to_cpu(sb->feature_map) &
|
|
|
- MD_FEATURE_RECOVERY_OFFSET))
|
|
|
+ MD_FEATURE_RECOVERY_OFFSET)) {
|
|
|
rdev->recovery_offset = le64_to_cpu(sb->recovery_offset);
|
|
|
- else
|
|
|
+ if (!(le32_to_cpu(sb->feature_map) &
|
|
|
+ MD_FEATURE_RECOVERY_BITMAP))
|
|
|
+ rdev->saved_raid_disk = -1;
|
|
|
+ } else
|
|
|
set_bit(In_sync, &rdev->flags);
|
|
|
rdev->raid_disk = role;
|
|
|
break;
|
|
@@ -1746,6 +1751,9 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
|
|
|
cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET);
|
|
|
sb->recovery_offset =
|
|
|
cpu_to_le64(rdev->recovery_offset);
|
|
|
+ if (rdev->saved_raid_disk >= 0 && mddev->bitmap)
|
|
|
+ sb->feature_map |=
|
|
|
+ cpu_to_le32(MD_FEATURE_RECOVERY_BITMAP);
|
|
|
}
|
|
|
if (test_bit(Replacement, &rdev->flags))
|
|
|
sb->feature_map |=
|
|
@@ -2487,8 +2495,7 @@ repeat:
|
|
|
if (rdev->sb_loaded != 1)
|
|
|
continue; /* no noise on spare devices */
|
|
|
|
|
|
- if (!test_bit(Faulty, &rdev->flags) &&
|
|
|
- rdev->saved_raid_disk == -1) {
|
|
|
+ if (!test_bit(Faulty, &rdev->flags)) {
|
|
|
md_super_write(mddev,rdev,
|
|
|
rdev->sb_start, rdev->sb_size,
|
|
|
rdev->sb_page);
|
|
@@ -2504,11 +2511,9 @@ repeat:
|
|
|
rdev->badblocks.size = 0;
|
|
|
}
|
|
|
|
|
|
- } else if (test_bit(Faulty, &rdev->flags))
|
|
|
+ } else
|
|
|
pr_debug("md: %s (skipping faulty)\n",
|
|
|
bdevname(rdev->bdev, b));
|
|
|
- else
|
|
|
- pr_debug("(skipping incremental s/r ");
|
|
|
|
|
|
if (mddev->level == LEVEL_MULTIPATH)
|
|
|
/* only need to write one superblock... */
|
|
@@ -2624,6 +2629,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|
|
* blocked - sets the Blocked flags
|
|
|
* -blocked - clears the Blocked and possibly simulates an error
|
|
|
* insync - sets Insync providing device isn't active
|
|
|
+ * -insync - clear Insync for a device with a slot assigned,
|
|
|
+ * so that it gets rebuilt based on bitmap
|
|
|
* write_error - sets WriteErrorSeen
|
|
|
* -write_error - clears WriteErrorSeen
|
|
|
*/
|
|
@@ -2672,6 +2679,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|
|
} else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
|
|
|
set_bit(In_sync, &rdev->flags);
|
|
|
err = 0;
|
|
|
+ } else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0) {
|
|
|
+ clear_bit(In_sync, &rdev->flags);
|
|
|
+ rdev->saved_raid_disk = rdev->raid_disk;
|
|
|
+ rdev->raid_disk = -1;
|
|
|
+ err = 0;
|
|
|
} else if (cmd_match(buf, "write_error")) {
|
|
|
set_bit(WriteErrorSeen, &rdev->flags);
|
|
|
err = 0;
|
|
@@ -5780,6 +5792,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
|
|
|
clear_bit(Bitmap_sync, &rdev->flags);
|
|
|
} else
|
|
|
rdev->raid_disk = -1;
|
|
|
+ rdev->saved_raid_disk = rdev->raid_disk;
|
|
|
} else
|
|
|
super_types[mddev->major_version].
|
|
|
validate_super(mddev, rdev);
|
|
@@ -5792,11 +5805,6 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- if (test_bit(In_sync, &rdev->flags))
|
|
|
- rdev->saved_raid_disk = rdev->raid_disk;
|
|
|
- else
|
|
|
- rdev->saved_raid_disk = -1;
|
|
|
-
|
|
|
clear_bit(In_sync, &rdev->flags); /* just to be sure */
|
|
|
if (info->state & (1<<MD_DISK_WRITEMOSTLY))
|
|
|
set_bit(WriteMostly, &rdev->flags);
|
|
@@ -7948,14 +7956,10 @@ void md_reap_sync_thread(struct mddev *mddev)
|
|
|
mddev->pers->finish_reshape(mddev);
|
|
|
|
|
|
/* If array is no-longer degraded, then any saved_raid_disk
|
|
|
- * information must be scrapped. Also if any device is now
|
|
|
- * In_sync we must scrape the saved_raid_disk for that device
|
|
|
- * do the superblock for an incrementally recovered device
|
|
|
- * written out.
|
|
|
+ * information must be scrapped.
|
|
|
*/
|
|
|
- rdev_for_each(rdev, mddev)
|
|
|
- if (!mddev->degraded ||
|
|
|
- test_bit(In_sync, &rdev->flags))
|
|
|
+ if (!mddev->degraded)
|
|
|
+ rdev_for_each(rdev, mddev)
|
|
|
rdev->saved_raid_disk = -1;
|
|
|
|
|
|
md_update_sb(mddev, 1);
|