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>
This commit is contained in:
Neil Brown 2005-08-09 04:25:27 +00:00
parent 8068890f11
commit 586ed40547
7 changed files with 96 additions and 2 deletions

View File

@ -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);

View File

@ -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

13
mdadm.8
View File

@ -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

14
mdadm.c
View File

@ -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);

View File

@ -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

2
test
View File

@ -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

22
tests/06r5swap Normal file
View File

@ -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