summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2003-10-28 23:20:01 +0000
committerNeil Brown <neilb@suse.de>2003-10-28 23:20:01 +0000
commitfeb716e9c3568a45b8815bf2c59e417d30635f89 (patch)
tree0f8e3d3ad2ba688cf70c7655e86566a5fa27e753
parentaa88f531b468349982905ecacf11da2cb6678ce6 (diff)
downloadmdadm-feb716e9c3568a45b8815bf2c59e417d30635f89.tar.gz
mdadm-feb716e9c3568a45b8815bf2c59e417d30635f89.tar.xz
mdadm-feb716e9c3568a45b8815bf2c59e417d30635f89.zip
mdadm-1.4.0mdadm-1.4.0
-rw-r--r--ANNOUNCE-1.4.029
-rw-r--r--Assemble.c27
-rw-r--r--ChangeLog12
-rw-r--r--Detail.c24
-rw-r--r--Examine.c4
-rw-r--r--Makefile2
-rw-r--r--Monitor.c7
-rw-r--r--ReadMe.c10
-rw-r--r--config.c8
-rw-r--r--mdadm.852
-rw-r--r--mdadm.c12
-rw-r--r--mdadm.h3
-rw-r--r--mdadm.spec2
13 files changed, 168 insertions, 24 deletions
diff --git a/ANNOUNCE-1.4.0 b/ANNOUNCE-1.4.0
new file mode 100644
index 0000000..22d8952
--- /dev/null
+++ b/ANNOUNCE-1.4.0
@@ -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
diff --git a/Assemble.c b/Assemble.c
index cddb76f..794b00d 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -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)
diff --git a/ChangeLog b/ChangeLog
index 73dd5af..6cfea5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/Detail.c b/Detail.c
index 9b04efd..d508988 100644
--- a/Detail.c
+++ b/Detail.c
@@ -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;
}
diff --git a/Examine.c b/Examine.c
index 6263866..983f90a 100644
--- a/Examine.c
+++ b/Examine.c
@@ -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);
diff --git a/Makefile b/Makefile
index 986c979..6cbe0b0 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/Monitor.c b/Monitor.c
index 3bc3263..826eaa7 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -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)
diff --git a/ReadMe.c b/ReadMe.c
index 830a3b3..579a1a8 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -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[] =
diff --git a/config.c b/config.c
index 68b453c..f02697e 100644
--- a/config.c
+++ b/config.c
@@ -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);
diff --git a/mdadm.8 b/mdadm.8
index c9d164d..abe843e 100644
--- a/mdadm.8
+++ b/mdadm.8
@@ -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
diff --git a/mdadm.c b/mdadm.c
index f5da6fa..22c6835 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -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':
diff --git a/mdadm.h b/mdadm.h
index 6ce5fac..a8897da 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -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,
diff --git a/mdadm.spec b/mdadm.spec
index f8498ed..7c3d7c1 100644
--- a/mdadm.spec
+++ b/mdadm.spec
@@ -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/