rdev->desc_nr = sb->this_disk.number;
if (!refdev) {
- ret = 1;
+ /*
+ * Insist on good event counter while assembling, except
+ * for spares (which don't need an event count)
+ */
+ if (sb->disks[rdev->desc_nr].state & (
+ (1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE)))
+ ret = 1;
+ else
+ ret = 0;
} else {
__u64 ev1, ev2;
mdp_super_t *refsb = page_address(refdev->sb_page);
}
ev1 = md_event(sb);
ev2 = md_event(refsb);
- if (ev1 > ev2)
+
+ /*
+ * Insist on good event counter while assembling, except
+ * for spares (which don't need an event count)
+ */
+ if (sb->disks[rdev->desc_nr].state & (
+ (1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE)) &&
+ (ev1 > ev2))
ret = 1;
else
ret = 0;
sector_t sectors;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
int bmask;
+ __u64 role;
/*
* Calculate the position of the superblock in 512byte sectors.
sb->level != 0)
return -EINVAL;
+ role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
+
if (!refdev) {
- ret = 1;
+ /*
+ * Insist of good event counter while assembling, except for
+ * spares (which don't need an event count)
+ */
+ if (rdev->desc_nr >= 0 &&
+ rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
+ (role < MD_DISK_ROLE_MAX ||
+ role == MD_DISK_ROLE_JOURNAL))
+ ret = 1;
+ else
+ ret = 0;
} else {
__u64 ev1, ev2;
struct mdp_superblock_1 *refsb = page_address(refdev->sb_page);
ev1 = le64_to_cpu(sb->events);
ev2 = le64_to_cpu(refsb->events);
- if (ev1 > ev2)
+ /*
+ * Insist of good event counter while assembling, except for
+ * spares (which don't need an event count)
+ */
+ if (rdev->desc_nr >= 0 &&
+ rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
+ (role < MD_DISK_ROLE_MAX ||
+ role == MD_DISK_ROLE_JOURNAL) && ev1 > ev2)
ret = 1;
else
ret = 0;
* Check a full RAID array for plausibility
*/
-static void analyze_sbs(struct mddev *mddev)
+static int analyze_sbs(struct mddev *mddev)
{
int i;
struct md_rdev *rdev, *freshest, *tmp;
md_kick_rdev_from_array(rdev);
}
+ /* Cannot find a valid fresh disk */
+ if (!freshest) {
+ pr_warn("md: cannot find a valid disk\n");
+ return -EINVAL;
+ }
+
super_types[mddev->major_version].
validate_super(mddev, freshest);
clear_bit(In_sync, &rdev->flags);
}
}
+
+ return 0;
}
/* Read a fixed-point number.
if (!mddev->raid_disks) {
if (!mddev->persistent)
return -EINVAL;
- analyze_sbs(mddev);
+ err = analyze_sbs(mddev);
+ if (err)
+ return -EINVAL;
}
if (mddev->level != LEVEL_NONE)