Release 1.8.1 after some man page updates and other fixes.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
This commit is contained in:
Neil Brown 2005-06-07 23:16:36 +00:00
parent 024ce7fe2b
commit 570c054247
9 changed files with 134 additions and 32 deletions

View File

@ -205,9 +205,9 @@ int Create(struct supertype *st, char *mddev, int mdfd,
} }
else { else {
ldsize = dsize; ldsize = dsize;
dsize <<= 9; ldsize <<= 9;
} }
freesize = st->ss->avail_size(ldsize); freesize = st->ss->avail_size(ldsize >> 9);
if (freesize == 0) { if (freesize == 0) {
fprintf(stderr, Name ": %s is too small: %luK\n", fprintf(stderr, Name ": %s is too small: %luK\n",
dname, (unsigned long)(ldsize>>10)); dname, (unsigned long)(ldsize>>10));

View File

@ -62,7 +62,7 @@ OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o \
SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c \ SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c \
Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c mdopen.c super0.c super1.c Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c mdopen.c super0.c super1.c
ASSEMBLE_SRCS := mdassemble.c Assemble.c config.c dlink.c util.c ASSEMBLE_SRCS := mdassemble.c Assemble.c config.c dlink.c util.c super0.c super1.c
ifdef MDASSEMBLE_AUTO ifdef MDASSEMBLE_AUTO
ASSEMBLE_SRCS += mdopen.c mdstat.c ASSEMBLE_SRCS += mdopen.c mdstat.c
ASSEMBLE_FLAGS = -DMDASSEMBLE_AUTO ASSEMBLE_FLAGS = -DMDASSEMBLE_AUTO

71
md.4
View File

@ -16,7 +16,7 @@ Array of Independent Devices.
.B md .B md
supports RAID levels 1 (mirroring) 4 (striped array with parity supports RAID levels 1 (mirroring) 4 (striped array with parity
device), 5 (striped array with distributed parity information) and 6 device), 5 (striped array with distributed parity information) and 6
(striped array with distributed dual redundancy information.) If a (striped array with distributed dual redundancy information.) If
some number of underlying devices fails while using one of these some number of underlying devices fails while using one of these
levels, the array will continue to function; this number is one for levels, the array will continue to function; this number is one for
RAID levels 4 and 5, two for RAID level 6, and all but one (N-1) for RAID levels 4 and 5, two for RAID level 6, and all but one (N-1) for
@ -24,24 +24,42 @@ RAID level 1.
.PP .PP
.B md .B md
also supports a number of pseudo RAID (non-redundant) configurations also supports a number of pseudo RAID (non-redundant) configurations
including RAID0 (striped array), LINEAR (catenated array) and including RAID0 (striped array), LINEAR (catenated array),
MULTIPATH (a set of different interfaces to the same device). MULTIPATH (a set of different interfaces to the same device),
and FAULTY (a layer over a single device into which errors can be injected).
.SS MD SUPER BLOCK .SS MD SUPER BLOCK
With the exception of Legacy Arrays described below, each device that Each device in an array may have a
is incorporated into an MD array has a .I superblock
.I super block which records information about the structure and state of the array.
written towards the end of the device. This superblock records This allows the array to be reliably re-assembled after a shutdown.
information about the structure and state of the array so that the
array can be reliably re-assembled after a shutdown.
The superblock is 4K long and is written into a 64K aligned block that From Linux kernel version 2.6.10,
.B md
provides support for two different formats of this superblock, and
other formats can be added. Prior to this release, only one format is
supported.
The common format - known as version 0.90 - has
a superblock that is 4K long and is written into a 64K aligned block that
starts at least 64K and less than 128K from the end of the device starts at least 64K and less than 128K from the end of the device
(i.e. to get the address of the superblock round the size of the (i.e. to get the address of the superblock round the size of the
device down to a multiple of 64K and then subtract 64K). device down to a multiple of 64K and then subtract 64K).
The available size of each device is the amount of space before the The available size of each device is the amount of space before the
super block, so between 64K and 128K is lost when a device in super block, so between 64K and 128K is lost when a device in
incorporated into an MD array. incorporated into an MD array.
This superblock stores multi-byte fields in a processor-dependant
manner, so arrays cannot easily be moved between computers with
different processors.
The new format - known as version 1 - has a superblock that is
normally 1K long, but can be longer. It is normally stored between 8K
and 12K from the end of the device, on a 4K boundary, though
variations can be stored at the start of the device (version 1.1) or 4K from
the start of the device (version 1.2).
This superblock format stores multibyte data in a
processor-independant format and has supports upto hundreds of
component devices (version 0.90 only supports 28).
The superblock contains, among other things: The superblock contains, among other things:
.TP .TP
@ -53,17 +71,34 @@ UUID
a 128 bit Universally Unique Identifier that identifies the array that a 128 bit Universally Unique Identifier that identifies the array that
this device is part of. this device is part of.
.SS LEGACY ARRAYS .SS ARRAYS WITHOUT SUPERBLOCKS
While it is usually best to create arrays with superblocks so that
they can be assembled reliably, there are some circumstances where an
array without superblocks in preferred. This include:
.TP
LEGACY ARRAYS
Early versions of the Early versions of the
.B md .B md
driver only supported Linear and Raid0 configurations and so driver only supported Linear and Raid0 configurations and did not use
did not use an MD superblock (as there is no state that needs to be a superblock (which is less critical with these configurations).
recorded). While it is strongly recommended that all newly created While such arrays should be rebuilt with superblocks if possible,
arrays utilise a superblock to help ensure that they are assembled
properly, the
.B md .B md
driver still supports legacy linear and raid0 md arrays that continues to support them.
do not have a superblock. .TP
FAULTY
Being a largely transparent layer over a different device, the FAULTY
personality doesn't gain anything from having a superblock.
.TP
MULTIPATH
It is often possible to detect devices which are different paths to
the same storage directly rather than having a distinctive superblock
written to the device and searched for on all paths. In this case,
a MULTIPATH array with no superblock makes sense.
.TP
RAID1
In some configurations it might be desired to create a raid1
configuration that does use a superblock, and to maintain the state of
the array elsewhere. While not encouraged, this is supported.
.SS LINEAR .SS LINEAR

22
mdadm.8
View File

@ -1,5 +1,5 @@
.\" -*- nroff -*- .\" -*- nroff -*-
.TH MDADM 8 "" v1.11.0 .TH MDADM 8 "" v1.11.1
.SH NAME .SH NAME
mdadm \- manage MD devices mdadm \- manage MD devices
.I aka .I aka
@ -92,7 +92,7 @@ information so as to assemble a faulty array.
.TP .TP
.B Build .B Build
Build a legacy array without per-device superblocks. Build an array without per-device superblocks.
.TP .TP
.B Create .B Create
@ -234,6 +234,24 @@ in which case
says to get a list of array devices from says to get a list of array devices from
.BR /proc/mdstat . .BR /proc/mdstat .
.TP
.B -e ", " --metadata=
Declare the style of superblock (raid metadata) to be used. The
default is 0.90 for --create, and to guess for other operations.
Options are:
.RS
.IP "0, 0.90, default"
Use the original 0.90 format superblock. This format limits arrays to
28 componenet devices and limits component devices of levels 1 and
greater to 2 terabytes.
.IP "1, 1.0, 1.1, 1.2"
Use the new version-1 format superblock. This has few restrictions.
The different subversion store the superblock at different locations
on the device, either at the end (for 1.0), at the start (for 1.1) or
4K from the start (for 1.2).
.RE
.SH For create or build: .SH For create or build:
.TP .TP

View File

@ -1,6 +1,6 @@
Summary: mdadm is used for controlling Linux md devices (aka RAID arrays) Summary: mdadm is used for controlling Linux md devices (aka RAID arrays)
Name: mdadm Name: mdadm
Version: 1.11.0 Version: 1.11.1
Release: 1 Release: 1
Source: http://www.cse.unsw.edu.au/~neilb/source/mdadm/mdadm-%{version}.tgz Source: http://www.cse.unsw.edu.au/~neilb/source/mdadm/mdadm-%{version}.tgz
URL: http://www.cse.unsw.edu.au/~neilb/source/mdadm/ URL: http://www.cse.unsw.edu.au/~neilb/source/mdadm/

View File

@ -95,7 +95,7 @@ int main() {
if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0) if (ioctl(mdfd, GET_ARRAY_INFO, &array)>=0)
/* already assembled, skip */ /* already assembled, skip */
continue; continue;
rv |= Assemble(array_list->devname, mdfd, rv |= Assemble(array_list->st, array_list->devname, mdfd,
array_list, configfile, array_list, configfile,
NULL, NULL,
readonly, runstop, NULL, verbose, force); readonly, runstop, NULL, verbose, force);

View File

@ -415,6 +415,7 @@ static int store_super0(int fd, void *sbv)
if (write(fd, super, sizeof(*super)) != sizeof(*super)) if (write(fd, super, sizeof(*super)) != sizeof(*super))
return 4; return 4;
fsync(fd);
return 0; return 0;
} }

View File

@ -83,7 +83,9 @@ struct mdp_superblock_1 {
__u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ __u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
}; };
#ifndef offsetof
#define offsetof(t,f) ((int)&(((t*)0)->f)) #define offsetof(t,f) ((int)&(((t*)0)->f))
#endif
static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
{ {
unsigned int disk_csum, csum; unsigned int disk_csum, csum;
@ -139,11 +141,11 @@ static void examine_super1(void *sbv)
printf(" Raid Level : %s\n", c?c:"-unknown-"); printf(" Raid Level : %s\n", c?c:"-unknown-");
printf(" Raid Devices : %d\n", __le32_to_cpu(sb->raid_disks)); printf(" Raid Devices : %d\n", __le32_to_cpu(sb->raid_disks));
printf("\n"); printf("\n");
printf(" Device Size : %llu%s\n", sb->data_size, human_size(sb->data_size<<9)); printf(" Device Size : %llu%s\n", (unsigned long long)sb->data_size, human_size(sb->data_size<<9));
if (sb->data_offset) if (sb->data_offset)
printf(" Data Offset : %llu sectors\n", __le64_to_cpu(sb->data_offset)); printf(" Data Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->data_offset));
if (sb->super_offset) if (sb->super_offset)
printf(" Super Offset : %llu sectors\n", __le64_to_cpu(sb->super_offset)); printf(" Super Offset : %llu sectors\n", (unsigned long long)__le64_to_cpu(sb->super_offset));
printf(" Device UUID : "); printf(" Device UUID : ");
for (i=0; i<16; i++) { for (i=0; i<16; i++) {
printf("%02x", sb->set_uuid[i]); printf("%02x", sb->set_uuid[i]);
@ -159,7 +161,7 @@ static void examine_super1(void *sbv)
else else
printf(" Checksum : %x - expected %x\n", __le32_to_cpu(sb->sb_csum), printf(" Checksum : %x - expected %x\n", __le32_to_cpu(sb->sb_csum),
__le32_to_cpu(calc_sb_1_csum(sb))); __le32_to_cpu(calc_sb_1_csum(sb)));
printf(" Events : %llu\n", __le64_to_cpu(sb->events)); printf(" Events : %llu\n", (unsigned long long)__le64_to_cpu(sb->events));
printf("\n"); printf("\n");
if (__le32_to_cpu(sb->level) == 5) { if (__le32_to_cpu(sb->level) == 5) {
c = map_num(r5layout, __le32_to_cpu(sb->layout)); c = map_num(r5layout, __le32_to_cpu(sb->layout));
@ -235,7 +237,7 @@ static void detail_super1(void *sbv)
printf("%02x", sb->set_uuid[i]); printf("%02x", sb->set_uuid[i]);
if ((i&3)==0 && i != 0) printf(":"); if ((i&3)==0 && i != 0) printf(":");
} }
printf("\n Events : %llu\n\n", __le64_to_cpu(sb->events)); printf("\n Events : %llu\n\n", (unsigned long long)__le64_to_cpu(sb->events));
} }
static void brief_detail_super1(void *sbv) static void brief_detail_super1(void *sbv)
@ -452,6 +454,7 @@ static int store_super1(int fd, void *sbv)
if (write(fd, sb, sbsize) != sbsize) if (write(fd, sb, sbsize) != sbsize)
return 4; return 4;
fsync(fd);
return 0; return 0;
} }
@ -575,15 +578,33 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
if (st->ss == NULL) { if (st->ss == NULL) {
/* guess... */ int bestvers = -1;
__u64 bestctime = 0;
/* guess... choose latest ctime */
st->ss = &super1; st->ss = &super1;
for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) { for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) {
switch(load_super1(st, fd, sbp, devname)) { switch(load_super1(st, fd, sbp, devname)) {
case 0: return 0; /* good */ case 0: super = *sbp;
if (bestvers == -1 ||
bestctime < __le64_to_cpu(super->ctime)) {
bestvers = st->minor_version;
bestctime = __le64_to_cpu(super->ctime);
}
free(super);
*sbp = NULL;
break;
case 1: st->ss = NULL; return 1; /*bad device */ case 1: st->ss = NULL; return 1; /*bad device */
case 2: break; /* bad, try next */ case 2: break; /* bad, try next */
} }
} }
if (bestvers != -1) {
int rv;
st->minor_version = bestvers;
st->ss = &super1;
rv = load_super1(st, fd, sbp, devname);
if (rv) st->ss = NULL;
return rv;
}
st->ss = NULL; st->ss = NULL;
return 2; return 2;
} }

27
util.c
View File

@ -386,6 +386,15 @@ unsigned long calc_csum(void *super, int bytes)
for(i=0; i<bytes/4; i++) for(i=0; i<bytes/4; i++)
newcsum+= superc[i]; newcsum+= superc[i];
csum = (newcsum& 0xffffffff) + (newcsum>>32); csum = (newcsum& 0xffffffff) + (newcsum>>32);
#ifdef __alpha__
/* The in-kernel checksum calculation is always 16bit on
* the alpha, though it is 32 bit on i386...
* I wonder what it is elsewhere... (it uses and API in
* a way that it shouldn't).
*/
csum = (csum & 0xffff) + (csum >> 16);
csum = (csum & 0xffff) + (csum >> 16);
#endif
return csum; return csum;
} }
@ -544,6 +553,8 @@ struct supertype *guess_super(int fd)
*/ */
struct superswitch *ss; struct superswitch *ss;
struct supertype *st; struct supertype *st;
unsigned long besttime = 0;
int bestsuper = -1;
void *sbp = NULL; void *sbp = NULL;
int i; int i;
@ -554,10 +565,26 @@ struct supertype *guess_super(int fd)
int rv; int rv;
ss = superlist[i]; ss = superlist[i];
rv = ss->load_super(st, fd, &sbp, NULL); rv = ss->load_super(st, fd, &sbp, NULL);
if (rv == 0) {
struct mdinfo info;
ss->getinfo_super(&info, sbp);
if (bestsuper == -1 ||
besttime < info.array.ctime) {
bestsuper = i;
besttime = info.array.ctime;
st->ss = NULL;
}
free(sbp);
}
}
if (bestsuper != -1) {
int rv;
rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
if (rv == 0) { if (rv == 0) {
free(sbp); free(sbp);
return st; return st;
} }
} }
free(st);
return NULL; return NULL;
} }