summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2005-08-09 04:25:27 +0000
committerNeil Brown <neilb@suse.de>2005-08-09 04:25:27 +0000
commit586ed40547a380b9f8bd58aa87c12fbaf6eabf65 (patch)
treee075277fb987eeba9e18ca0ed1e21aee4cd61a46
parent8068890f1116c6fc5ae87596bb6b8272f79d2d1c (diff)
downloadmdadm-586ed40547a380b9f8bd58aa87c12fbaf6eabf65.tar.gz
mdadm-586ed40547a380b9f8bd58aa87c12fbaf6eabf65.tar.xz
mdadm-586ed40547a380b9f8bd58aa87c12fbaf6eabf65.zip
Support fixing of byte-swapped superblocks.
Good for moving between little-endian and big-endian. Still needs documentation. Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
-rw-r--r--Assemble.c3
-rw-r--r--ChangeLog4
-rw-r--r--mdadm.813
-rw-r--r--mdadm.c14
-rw-r--r--super0.c40
-rw-r--r--test2
-rw-r--r--tests/06r5swap22
7 files changed, 96 insertions, 2 deletions
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 .
@@ -556,6 +557,18 @@ 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
counts of total, working, active, failed, and spare devices.
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
+
+
+