From feb716e9c3568a45b8815bf2c59e417d30635f89 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Tue, 28 Oct 2003 23:20:01 +0000 Subject: mdadm-1.4.0 --- ANNOUNCE-1.4.0 | 29 +++++++++++++++++++++++++++++ Assemble.c | 27 +++++++++++++++++++++++++++ ChangeLog | 12 ++++++++++++ Detail.c | 24 +++++++++++++++++------- Examine.c | 4 +++- Makefile | 2 +- Monitor.c | 7 +++++++ ReadMe.c | 10 ++++++---- config.c | 8 ++++++-- mdadm.8 | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- mdadm.c | 12 +++++++++--- mdadm.h | 3 ++- mdadm.spec | 2 +- 13 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 ANNOUNCE-1.4.0 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<= 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<state & (1<state & (1<state & (1<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/ -- cgit