mdadm-1.4.0

This commit is contained in:
Neil Brown 2003-10-28 23:20:01 +00:00
parent aa88f531b4
commit feb716e9c3
13 changed files with 168 additions and 24 deletions

29
ANNOUNCE-1.4.0 Normal file
View File

@ -0,0 +1,29 @@
Subject: ANNOUNCE: mdadm 1.4.0 - A tools for managing Soft RAID under Linux
I am pleased to announce the availability of
mdadm version 1.4.0
It is available at
http://www.cse.unsw.edu.au/~neilb/source/mdadm/
and
http://www.{countrycode}.kernel.org/pub/utils/raid/mdadm/
as a source tar-ball and (at the first site) as an SRPM, and as an RPM for i386.
mdadm is a tool for creating, managing and monitoring
device arrays using the "md" driver in Linux, also
known as Software RAID arrays.
Release 1.4.0 adds:
SparesMissing event in --monitor mode if a number of spares is declared
in mdadm.conf, but that number of spares isn't found.
--update=summaries option for --assemble mode to update some summary information
in the superblock
--test option for --detail to get a useful exit status.
Development of mdadm is sponsored by CSE@UNSW:
The School of Computer Science and Engineering
at
The University of New South Wales
NeilBrown 29 Oct 2003

View File

@ -292,6 +292,33 @@ int Assemble(char *mddev, int mdfd,
fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
devname, super.md_minor);
}
if (strcmp(update, "summaries") == 0) {
/* set nr_disks, active_disks, working_disks,
* failed_disks, spare_disks based on disks[]
* array in superblock.
* Also make sure extra slots aren't 'failed'
*/
super.nr_disks = super.active_disks =
super.working_disks = super.failed_disks =
super.spare_disks = 0;
for (i=0; i < MD_SB_DISKS ; i++)
if (super.disks[i].major ||
super.disks[i].minor) {
int state = super.disks[i].state;
if (state & (1<<MD_DISK_REMOVED))
continue;
super.nr_disks++;
if (state & (1<<MD_DISK_ACTIVE))
super.active_disks++;
if (state & (1<<MD_DISK_FAULTY))
super.failed_disks++;
else
super.working_disks++;
if (state == 0)
super.spare_disks++;
} else if (i >= super.raid_disks && super.disks[i].number == 0)
super.disks[i].state = 0;
}
super.sb_csum = calc_sb_csum(&super);
dfd = open(devname, O_RDWR, 0);
if (dfd < 0)

View File

@ -1,3 +1,15 @@
Changes Prior to 1.4.0 release
- Document fact that creating a raid5 array really creates a
degraded array with a spare.
- Add "spares=" tag to config file and generate it wit --detail and
--examine
- Add "SparesMissing" event when --monitor first sees an array and
it doesn't have the enough spare devices.
- Add --update=summaries for --assemble to update summary
information in superblock, and correct other inconsistancies in
the superblock.
- Add --test option to --detail to set a meaningful exit status.
Changes Prior to 1.3.0 release
- Make 'size' and unsigned long in Create to allow creation of
larger arrays.

View File

@ -31,7 +31,7 @@
#include "md_p.h"
#include "md_u.h"
int Detail(char *dev, int brief)
int Detail(char *dev, int brief, int test)
{
/*
* Print out details for an md array by using
@ -45,27 +45,29 @@ int Detail(char *dev, int brief)
time_t atime;
char *c;
char *devices = NULL;
int spares = 0;
mdp_super_t super;
int have_super = 0;
int rv = test ? 4 : 1;
if (fd < 0) {
fprintf(stderr, Name ": cannot open %s: %s\n",
dev, strerror(errno));
return 1;
return rv;
}
vers = md_get_version(fd);
if (vers < 0) {
fprintf(stderr, Name ": %s does not appear to be an md device\n",
dev);
close(fd);
return 1;
return rv;
}
if (vers < 9000) {
fprintf(stderr, Name ": cannot get detail for md device %s: driver version too old.\n",
dev);
close(fd);
return 1;
return rv;
}
if (ioctl(fd, GET_ARRAY_INFO, &array)<0) {
if (errno == ENODEV)
@ -75,8 +77,9 @@ int Detail(char *dev, int brief)
fprintf(stderr, Name ": cannot get array detail for %s: %s\n",
dev, strerror(errno));
close(fd);
return 1;
return rv;
}
rv = 0;
/* Ok, we have some info to print... */
c = map_num(pers, array.level);
if (brief)
@ -162,7 +165,12 @@ int Detail(char *dev, int brief)
if (disk.state & (1<<MD_DISK_ACTIVE)) printf(" active");
if (disk.state & (1<<MD_DISK_SYNC)) printf(" sync");
if (disk.state & (1<<MD_DISK_REMOVED)) printf(" removed");
if (disk.state == 0) printf(" spare");
if (disk.state == 0) { printf(" spare"); spares++; }
}
if (test && d < array.raid_disks && disk.state & (1<<MD_DISK_FAULTY)) {
if ((rv & 1) && (array.level ==4 || array.level == 5))
rv |= 2;
rv |= 1;
}
if ((dv=map_dev(disk.major, disk.minor))) {
if (brief) {
@ -188,6 +196,7 @@ int Detail(char *dev, int brief)
}
if (!brief) printf("\n");
}
if (spares && brief) printf(" spares=%d", spares);
if (have_super) {
if (brief) printf(" UUID=");
else printf(" UUID : ");
@ -201,5 +210,6 @@ int Detail(char *dev, int brief)
}
if (brief && devices) printf("\n devices=%s", devices);
if (brief) printf("\n");
return 0;
if (test && (rv&2)) rv &= ~1;
return rv;
}

View File

@ -60,6 +60,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
char *c;
int rv = 0;
int err;
int spares = 0;
struct array {
mdp_super_t super;
@ -205,7 +206,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
if (dp->state == 0) printf(" spare");
if (dp->state == 0) { printf(" spare"); spares++; }
if ((dv=map_dev(dp->major, dp->minor)))
printf(" %s", dv);
printf("\n");
@ -237,6 +238,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
char *d;
printf("ARRAY /dev/md%d level=%s num-devices=%d UUID=",
ap->super.md_minor, c?c:"-unknown-", ap->super.raid_disks);
if (spares) printf(" spares=%d", spares);
if (ap->super.minor_version >= 90)
printf("%08x:%08x:%08x:%08x", ap->super.set_uuid0, ap->super.set_uuid1,
ap->super.set_uuid2, ap->super.set_uuid3);

View File

@ -96,7 +96,7 @@ install : mdadm mdadm.8 md.4 mdadm.conf.5
$(INSTALL) -D -m 644 mdadm.conf.5 $(DESTDIR)$(MAN5DIR)/mdadm.conf.5
clean :
rm -f mdadm $(OBJS) core *.man mdadm.tcc mdadm.uclibc mdadm.static *.orig *.porig *.rej
rm -f mdadm $(OBJS) core *.man mdadm.tcc mdadm.uclibc mdadm.static *.orig *.porig *.rej *.alt
dist : clean
./makedist

View File

@ -97,6 +97,7 @@ int Monitor(mddev_dev_t devlist,
int err;
char *spare_group;
int active, working, failed, spare, raid;
int expected_spares;
int devstate[MD_SB_DISKS];
int devid[MD_SB_DISKS];
int percent;
@ -151,6 +152,7 @@ int Monitor(mddev_dev_t devlist,
st->err = 0;
st->devnum = -1;
st->percent = -2;
st->expected_spares = mdlist->spare_disks;
if (mdlist->spare_group)
st->spare_group = strdup(mdlist->spare_group);
else
@ -169,6 +171,7 @@ int Monitor(mddev_dev_t devlist,
st->err = 0;
st->devnum = -1;
st->percent = -2;
st->expected_spares = -1;
st->spare_group = NULL;
statelist = st;
}
@ -248,6 +251,10 @@ int Monitor(mddev_dev_t devlist,
)
alert("DegradedArray", dev, NULL, mailaddr, alert_cmd);
if (st->utime == 0 && /* new array */
st->expected_spares > 0 &&
array.spare_disks < st->expected_spares)
alert("SparesMissing", dev, NULL, mailaddr, alert_cmd);
if (mse &&
st->percent == -1 &&
mse->percent >= 0)

View File

@ -29,7 +29,7 @@
#include "mdadm.h"
char Version[] = Name " - v1.3.0 - 29 Jul 2003\n";
char Version[] = Name " - v1.4.0 - 29 Oct 2003\n";
/*
* File: ReadMe.c
*
@ -86,7 +86,7 @@ char Version[] = Name " - v1.3.0 - 29 Jul 2003\n";
* This mode never exits but just monitors arrays and reports changes.
*/
char short_options[]="-ABCDEFGQhVvbc:l:p:m:n:x:u:c:d:z:U:sarfRSow1";
char short_options[]="-ABCDEFGQhVvbc:l:p:m:n:x:u:c:d:z:U:sarfRSow1t";
struct option long_options[] = {
{"manage", 0, 0, '@'},
{"misc", 0, 0, '#'},
@ -141,6 +141,7 @@ struct option long_options[] = {
/* For Detail/Examine */
{"brief", 0, 0, 'b'},
{"sparc2.2", 0, 0, 22},
{"test", 0, 0, 't'},
/* For Follow/monitor */
{"mail", 1, 0, 'm'},
@ -221,7 +222,7 @@ char OptionHelp[] =
" --config= -c : config file\n"
" --scan -s : scan config file for missing information\n"
" --force -f : Assemble the array even if some superblocks appear out-of-date\n"
" --update= -U : Update superblock: either sparc2.2 or super-minor\n"
" --update= -U : Update superblock: one of sparc2.2, super-minor or summaries\n"
"\n"
" For detail or examine:\n"
" --brief -b : Just print device name and UUID\n"
@ -344,7 +345,7 @@ char Help_assemble[] =
" for a full array are present\n"
" --force -f : Assemble the array even if some superblocks appear\n"
" : out-of-date. This involves modifying the superblocks.\n"
" --update= -U : Update superblock: either sparc2.2 or super-minor\n"
" --update= -U : Update superblock: one of sparc2.2, super-minor or summaries\n"
;
char Help_manage[] =
@ -385,6 +386,7 @@ char Help_misc[] =
" --stop -S : deactivate array, releasing all resources\n"
" --readonly -o : mark array as readonly\n"
" --readwrite -w : mark array as readwrite\n"
" --test -t : exit status 0 if ok, 1 if degrade, 2 if dead, 4 if missing\n"
;
char Help_monitor[] =

View File

@ -265,6 +265,7 @@ void arrayline(char *line)
mis.super_minor = -1;
mis.level = -10;
mis.raid_disks = -1;
mis.spare_disks = -1;
mis.devices = NULL;
mis.devname = NULL;
mis.spare_group = NULL;
@ -315,10 +316,13 @@ void arrayline(char *line)
mis.level = map_name(pers, w+6);
} else if (strncasecmp(w, "disks=", 6) == 0 ) {
/* again, for compat */
mis.raid_disks = atoi(w+6);
mis.raid_disks = atoi(w+6);
} else if (strncasecmp(w, "num-devices=", 12) == 0 ) {
/* again, for compat */
mis.raid_disks = atoi(w+12);
mis.raid_disks = atoi(w+12);
} else if (strncasecmp(w, "spares=", 7) == 0 ) {
/* for warning if not all spares present */
mis.spare_disks = atoi(w+7);
} else {
fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
w);

52
mdadm.8
View File

@ -1,5 +1,5 @@
.\" -*- nroff -*-
.TH MDADM 8 "" v1.3.0
.TH MDADM 8 "" v1.4.0
.SH NAME
mdadm \- manage MD devices
.I aka
@ -328,8 +328,9 @@ an attempt will be made to start it anyway.
.TP
.BR -U ", " --update=
Update the superblock on each device while assembling the array. The
argument given to this flag can be either
.B sparc2.2
argument given to this flag can be one of
.BR sparc2.2 ,
.BR summaries ,
or
.BR super-minor .
@ -348,9 +349,13 @@ The
option will update the
.B "prefered minor"
field on each superblock to match the minor number of the array being
assembled. This is not need on 2.6 and later kernels as they make
assembled. This is not needed on 2.6 and later kernels as they make
this adjustment automatically.
The
.B summaries
option will correct the summaries in the superblock. That is the
counts of total, working, active, failed, and spare devices.
.SH For Manage mode:
@ -412,6 +417,14 @@ over-written with zeros. With
the block where the superblock would be is over-written even if it
doesn't appear to be valid.
.TP
.BR -t ", " --test
When used with
.BR --detail ,
the exit status of
.I mdadm
is set to reflect the status of the device.
.SH For Monitor mode:
.TP
.BR -m ", " --mail
@ -582,6 +595,15 @@ For a RAID1 array, only one real device needs to be given. All of the
others can be
"\fBmissing\fP".
When creating a RAID5 array,
.B mdadm
will automatically create a degraded array with an extra spare drive.
This is because building the spare into a degraded array is in general faster than resyncing
the parity on a non-degraded, but not clean, array. This feature can
be over-ridden with the
-I --force
option.
'''If the
'''.B --size
'''option is given, it is not necessary to list any component-devices in this command.
@ -651,6 +673,28 @@ or
will cause the output to be less detailed and the format to be
suitable for inclusion in
.BR /etc/mdadm.conf .
The exit status of
.I mdadm
will normally be 0 unless
.I mdadm
failed to get useful information about the device(s). However if the
.B --test
option is given, then the exit status will be:
.RS
.TP
0
The array is functioning normally.
.TP
1
The array has at least one failed device.
.TP
2
The array has multiple failed devices and hence is unusable (raid4 or
raid5).
.TP
4
There was an error while trying to get information about the device.
.RE
.TP
--examine

12
mdadm.c
View File

@ -78,6 +78,7 @@ int main(int argc, char *argv[])
int verbose = 0;
int brief = 0;
int force = 0;
int test = 0;
char *mailaddr = NULL;
char *program = NULL;
@ -397,7 +398,9 @@ int main(int argc, char *argv[])
if (strcmp(update, "sparc2.2")==0) continue;
if (strcmp(update, "super-minor") == 0)
continue;
fprintf(stderr, Name ": '--update %s' invalid. Only 'sparc2.2' or 'super-minor' supported\n",update);
if (strcmp(update, "summaries")==0)
continue;
fprintf(stderr, Name ": '--update %s' invalid. Only 'sparc2.2', 'super-minor' or 'summaries' supported\n",update);
exit(2);
case O(ASSEMBLE,'c'): /* config file */
@ -517,6 +520,9 @@ int main(int argc, char *argv[])
}
devmode = opt;
continue;
case O(MISC,'t'):
test = 1;
continue;
case O(MISC, 22):
if (devmode != 'E') {
@ -683,7 +689,7 @@ int main(int argc, char *argv[])
continue;
}
if (devmode == 'D')
rv |= Detail(name, !verbose);
rv |= Detail(name, !verbose, test);
else if (devmode=='S') {
mdfd = open_mddev(name);
if (mdfd >= 0)
@ -699,7 +705,7 @@ int main(int argc, char *argv[])
for (dv=devlist ; dv; dv=dv->next) {
switch(dv->disposition) {
case 'D':
rv |= Detail(dv->devname, brief); continue;
rv |= Detail(dv->devname, brief, test); continue;
case 'K': /* Zero superblock */
rv |= Kill(dv->devname, force); continue;
case 'Q':

View File

@ -96,6 +96,7 @@ typedef struct mddev_ident_s {
*/
int level; /* -10 if not set */
int raid_disks; /* -1 if not set */
int spare_disks; /* -1 if not set */
char *spare_group;
struct mddev_ident_s *next;
} *mddev_ident_t;
@ -163,7 +164,7 @@ extern int Create(char *mddev, int mdfd,
int subdevs, mddev_dev_t devlist,
int runstop, int verbose, int force);
extern int Detail(char *dev, int brief);
extern int Detail(char *dev, int brief, int test);
extern int Query(char *dev);
extern int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust);
extern int Monitor(mddev_dev_t devlist,

View File

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