From 586ed40547a380b9f8bd58aa87c12fbaf6eabf65 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 9 Aug 2005 04:25:27 +0000 Subject: Support fixing of byte-swapped superblocks. Good for moving between little-endian and big-endian. Still needs documentation. Signed-off-by: Neil Brown --- Assemble.c | 3 +++ ChangeLog | 4 ++++ mdadm.8 | 13 +++++++++++++ mdadm.c | 14 ++++++++++++++ super0.c | 40 +++++++++++++++++++++++++++++++++++++++- test | 2 +- tests/06r5swap | 22 ++++++++++++++++++++++ 7 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 tests/06r5swap diff --git a/Assemble.c b/Assemble.c index 20183ae..739db51 100644 --- a/Assemble.c +++ b/Assemble.c @@ -334,6 +334,9 @@ int Assemble(struct supertype *st, char *mddev, int mdfd, free(super); super = NULL; + if (update && strcmp(update, "byteorder")==0) + st->minor_version = 90; + if (devcnt == 0) { fprintf(stderr, Name ": no devices found for %s\n", mddev); diff --git a/ChangeLog b/ChangeLog index c70bda1..2cb01c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Changes Prior to this release + - Support assembling from byte-swapped superblocks + metadata type "0.swap" and --update=byteorder + Changes Prior to 2.0-devel-3 release - Assorted fixes for multiple bugs... - Add test suite diff --git a/mdadm.8 b/mdadm.8 index b0ac74a..1ecdac2 100644 --- a/mdadm.8 +++ b/mdadm.8 @@ -525,6 +525,7 @@ argument given to this flag can be one of .BR sparc2.2 , .BR summaries , .BR resync , +.BR byteorder , or .BR super-minor . @@ -555,6 +556,18 @@ copies for raid1) may be incorrect. This will cause the raid system to perform a "resync" pass to make sure that all redundant information is correct. +The +.B byteorder +option allows arrays to be moved between machines with different +byte-order. +When assembling such an array for the first time after a move, giving +.B "--update=byteorder" +will cause +.I mdadm +to expect superblocks to have their byteorder reversed, and will +correct that order before assembling the array. This is only valid +with original (Verion 0.90) superblocks. + The .B summaries option will correct the summaries in the superblock. That is the diff --git a/mdadm.c b/mdadm.c index 45c59b3..2b2b9be 100644 --- a/mdadm.c +++ b/mdadm.c @@ -547,6 +547,20 @@ int main(int argc, char *argv[]) continue; if (strcmp(update, "resync")==0) continue; + if (strcmp(update, "byteorder")==0) { + if (ss) { + fprintf(stderr, Name ": must not set metadata type with --update=byteorder.\n"); + exit(2); + } + for(i=0; !ss && superlist[i]; i++) + ss = superlist[i]->match_metadata_desc("0.swap"); + if (!ss) { + fprintf(stderr, Name ": INTERNAL ERROR cannot find 0.swap\n"); + exit(2); + } + + continue; + } fprintf(stderr, Name ": '--update %s' invalid. Only 'sparc2.2', 'super-minor', 'resync' or 'summaries' supported\n",update); exit(2); diff --git a/super0.c b/super0.c index 7ff5ff4..7a306b5 100644 --- a/super0.c +++ b/super0.c @@ -52,7 +52,39 @@ static unsigned long calc_sb0_csum(mdp_super_t *super) return newcsum; } + +void super0_swap_endian(struct mdp_superblock_s *sb) +{ + /* as super0 superblocks are host-endian, it is sometimes + * useful to be able to swap the endianness + * as (almost) everything is u32's we byte-swap every 4byte + * number. + * We then also have to swap the events_hi and events_lo + */ + char *sbc = (char *)sb; + __u32 t32; + int i; + + for (i=0; i < MD_SB_BYTES ; i+=4) { + char t = sbc[i]; + sbc[i] = sbc[i+3]; + sbc[i+3] = t; + t=sbc[i+1]; + sbc[i+1]=sbc[i+2]; + sbc[i+2]=t; + } + t32 = sb->events_hi; + sb->events_hi = sb->events_lo; + sb->events_lo = t32; + + t32 = sb->cp_events_hi; + sb->cp_events_hi = sb->cp_events_lo; + sb->cp_events_lo = t32; + +} + #ifndef MDASSEMBLE + static void examine_super0(void *sbv) { mdp_super_t *sb = sbv; @@ -572,6 +604,9 @@ static int load_super0(struct supertype *st, int fd, void **sbp, char *devname) return 1; } + if (st->ss && st->minor_version == 9) + super0_swap_endian(super); + if (super->md_magic != MD_SB_MAGIC) { if (devname) fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n", @@ -611,6 +646,10 @@ static struct supertype *match_metadata_desc0(char *arg) ) return st; + st->minor_version = 9; /* flag for 'byte-swapped' */ + if (strcmp(arg, "0.swap")==0) + return st; + free(st); return NULL; } @@ -742,7 +781,6 @@ int write_bitmap0(struct supertype *st, int fd, void *sbv) return rv; } - struct superswitch super0 = { #ifndef MDASSEMBLE diff --git a/test b/test index ea1851c..3e79909 100644 --- a/test +++ b/test @@ -28,7 +28,7 @@ export md0=/dev/md0 md1=/dev/md1 md2=/dev/md2 # We test mdadm on loop-back block devices. # dir for storing files should be settable by command line maybe targetdir=/tmp -export targetdir +export targetdir dir size=20000 mdsize0=19904 mdsize1=19992 diff --git a/tests/06r5swap b/tests/06r5swap new file mode 100644 index 0000000..01f4718 --- /dev/null +++ b/tests/06r5swap @@ -0,0 +1,22 @@ +set -e + +# make a raid5 array, byte swap the superblocks, then assemble... + +$mdadm -CR $md0 -l5 -n4 $dev0 $dev1 $dev2 $dev3 +sleep 4 +$mdadm -S $md0 + +$mdadm -E --metadata=0 $dev1 | grep -v Events > $targetdir/d1 +for d in $dev0 $dev1 $dev2 $dev3 +do $dir/swap_super $d +done +$mdadm -E --metadata=0.swap $dev1 | grep -v Events > $targetdir/d1s +diff -u $targetdir/d1 $targetdir/d1s + +$mdadm --assemble --update=byteorder $md0 $dev0 $dev1 $dev2 $dev3 +sleep 3 +cat /proc/mdstat +exit 1 + + + -- cgit