--- linux-2.4.18-orig/drivers/md/md.c Wed Oct 2 11:59:00 2002 +++ linux-2.4.18/drivers/md/md.c Wed Oct 2 11:58:38 2002 @@ -395,6 +395,16 @@ static unsigned int calc_sb_csum(mdp_super_t * sb); +/* + * validate_sb + * This checks for obvious inconsistencies that may have occurred + * with values in the raid superblock. Further work needs to be + * done to find the root cause of each of these, but this at least + * keeps the superblock sane, so the system will boot. + * Currently this is called as a safeguard before a write of the sb. + * Along with any future work, the mddev->private values (e.g. raid1) + * need to stay sync'd up with the superblock. -- Andy Cress + */ int validate_sb(mdp_super_t *sb, int op) { int changed = 0; @@ -956,6 +966,10 @@ MD_BUG(); return 1; } + if (!rdev->dev) { + MD_BUG(); + return 1; + } dev = rdev->dev; sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1); @@ -1048,6 +1062,7 @@ int err, count = 100; struct md_list_head *tmp; mdk_rdev_t *rdev; + int i; if (!mddev->sb_dirty) { printk("hm, md_update_sb() called without ->sb_dirty == 1, from %p.\n", __builtin_return_address(0)); @@ -1055,6 +1070,10 @@ } mddev->sb_dirty = 0; repeat: + if (!mddev->sb) { + MD_BUG(); + return 1; + } mddev->sb->utime = CURRENT_TIME; if ((++mddev->sb->events_lo)==0) ++mddev->sb->events_hi; @@ -1082,6 +1101,7 @@ mdidx(mddev)); err = 0; + i = 0; ITERATE_RDEV(mddev,rdev,tmp) { printk(KERN_INFO "md: "); if (rdev->faulty) @@ -1090,12 +1110,18 @@ printk("(skipping alias "); printk("%s ", partition_name(rdev->dev)); - if (!rdev->faulty && !rdev->alias_device) { + /* check for rdev->sb NULL here also. ARC*/ + if (!rdev->faulty && !rdev->alias_device && rdev->sb) { printk("[events: %08lx]", (unsigned long)rdev->sb->events_lo); err += write_disk_sb(rdev); } else printk(")\n"); + if (i >= mddev->nb_dev) { /* ARC*/ + printk("md_update_sb: iterate_rdev limit reached\n"); + break; + } + i++; } if (err) { if (--count) { @@ -3847,7 +3873,7 @@ printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor); return 0; } else if (md_setup_args.device_names[minor]) { - printk(KERN_WARNING "md: md=%d, Specified more then once. " + printk(KERN_WARNING "md: md=%d, Specified more than once. " "Replacing previous definition.\n", minor); } switch (get_option(&str, &level)) { /* RAID Personality */