aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 64b35cbf3159..bad324171cad 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -590,14 +590,41 @@ abort:
590 return ret; 590 return ret;
591} 591}
592 592
593
594static u32 md_csum_fold(u32 csum)
595{
596 csum = (csum & 0xffff) + (csum >> 16);
597 return (csum & 0xffff) + (csum >> 16);
598}
599
593static unsigned int calc_sb_csum(mdp_super_t * sb) 600static unsigned int calc_sb_csum(mdp_super_t * sb)
594{ 601{
602 u64 newcsum = 0;
603 u32 *sb32 = (u32*)sb;
604 int i;
595 unsigned int disk_csum, csum; 605 unsigned int disk_csum, csum;
596 606
597 disk_csum = sb->sb_csum; 607 disk_csum = sb->sb_csum;
598 sb->sb_csum = 0; 608 sb->sb_csum = 0;
599 csum = csum_partial((void *)sb, MD_SB_BYTES, 0); 609
610 for (i = 0; i < MD_SB_BYTES/4 ; i++)
611 newcsum += sb32[i];
612 csum = (newcsum & 0xffffffff) + (newcsum>>32);
613
614
615#ifdef CONFIG_ALPHA
616 /* This used to use csum_partial, which was wrong for several
617 * reasons including that different results are returned on
618 * different architectures. It isn't critical that we get exactly
619 * the same return value as before (we always csum_fold before
620 * testing, and that removes any differences). However as we
621 * know that csum_partial always returned a 16bit value on
622 * alphas, do a fold to maximise conformity to previous behaviour.
623 */
624 sb->sb_csum = md_csum_fold(disk_csum);
625#else
600 sb->sb_csum = disk_csum; 626 sb->sb_csum = disk_csum;
627#endif
601 return csum; 628 return csum;
602} 629}
603 630
@@ -685,7 +712,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
685 if (sb->raid_disks <= 0) 712 if (sb->raid_disks <= 0)
686 goto abort; 713 goto abort;
687 714
688 if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) { 715 if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) {
689 printk(KERN_WARNING "md: invalid superblock checksum on %s\n", 716 printk(KERN_WARNING "md: invalid superblock checksum on %s\n",
690 b); 717 b);
691 goto abort; 718 goto abort;