summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2004-08-11 02:16:01 +0000
committerNeil Brown <neilb@suse.de>2004-08-11 02:16:01 +0000
commite5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1 (patch)
tree889e38efabcc146f7ee4c59f39c79aae7c783d8d
parentdd0781e50555c32ff2f808ec46f4b03a5693ea47 (diff)
downloadmdadm-e5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1.tar.gz
mdadm-e5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1.tar.xz
mdadm-e5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1.zip
mdadm-1.7.0mdadm-1.7.0
-rw-r--r--ANNOUNCE-1.7.046
-rw-r--r--Assemble.c5
-rw-r--r--ChangeLog16
-rw-r--r--Create.c15
-rw-r--r--Detail.c113
-rw-r--r--Examine.c10
-rw-r--r--Grow.c192
-rw-r--r--Makefile6
-rw-r--r--Monitor.c9
-rw-r--r--ReadMe.c8
-rw-r--r--config.c2
-rw-r--r--inventory43
-rwxr-xr-xmakedist12
-rw-r--r--md_p.h7
-rw-r--r--mdadm.812
-rw-r--r--mdadm.c53
-rw-r--r--mdadm.h2
-rw-r--r--mdadm.spec2
-rwxr-xr-xmdassemblebin62213 -> 0 bytes
-rw-r--r--mdstat.c6
-rw-r--r--t1
-rw-r--r--test2
-rw-r--r--util.c53
23 files changed, 539 insertions, 76 deletions
diff --git a/ANNOUNCE-1.7.0 b/ANNOUNCE-1.7.0
new file mode 100644
index 0000000..86c4aac
--- /dev/null
+++ b/ANNOUNCE-1.7.0
@@ -0,0 +1,46 @@
+Subject: ANNOUNCE: mdadm 1.7.0 - A tool for managing Soft RAID under Linux
+
+
+I am pleased to announce the availability of
+ mdadm version 1.7.0
+It is available at
+ http://www.cse.unsw.edu.au/~neilb/source/mdadm/
+and
+ http://www.{countrycode}.kernel.org/pub/linux/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.7.0 adds:
+ - Support "--grow --add" to add a device to a linear array, if the
+ kernel supports it. Not documented yet.
+ - Restore support for uclibc which was broken recently.
+ - Several improvements to the output of --detail, including
+ reporting "resyncing" or "recovering" in the state.
+ - Close filedescriptor at end of --detail (exit would have closed it
+ anyway, so this isn't abig deal).
+ - Report "Sync checkpoint" in --examine output if appropriate.
+ - Add --update=resync for --assemble mode to for a resync when the
+ array is assembled.
+ - Add support for "raid10", which is under development in 2.6.
+ Not documented yet.
+ - --monitor now reads spare-group and spares info from config file
+ even when names of arrays to scan are given on the command line
+
+It is expected that the next full release of mdadm will be 2.0.0
+and it will have substantially re-written handling for superblocks and
+array creation. In particular, it will be able to work with the new
+superblock format (version 1) supported by 2.6.
+Prior to that, some point releases (1.7.1, 1.7.2 ...) may be released
+so that the changes can be tested by interrested parties.
+
+Development of mdadm is sponsored by CSE@UNSW:
+ The School of Computer Science and Engineering
+at
+ The University of New South Wales
+
+NeilBrown 11 August 2004
+
diff --git a/Assemble.c b/Assemble.c
index 0d22251..3f22ae9 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -320,6 +320,11 @@ int Assemble(char *mddev, int mdfd,
} else if (i >= super.raid_disks && super.disks[i].number == 0)
super.disks[i].state = 0;
}
+ if (strcmp(update, "resync") == 0) {
+ /* make sure resync happens */
+ super.state &= ~(1<<MD_SB_CLEAN);
+ super.recovery_cp = 0;
+ }
super.sb_csum = calc_sb_csum(&super);
dfd = open(devname, O_RDWR, 0);
if (dfd < 0)
diff --git a/ChangeLog b/ChangeLog
index a505a74..df5b25b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Changes Prior to this release
+ - Support "--grow --add" to add a device to a linear array, if the
+ kernel supports it. Not documented yet.
+ - Restore support for uclibc which was broken recently.
+ - Several improvements to the output of --detail, including
+ reporting "resyncing" or "recovering" in the state.
+ - Close filedescriptor at end of --detail (exit would have closed it
+ anyway, so this isn't abig deal).
+ - Report "Sync checkpoint" in --examine output if appropriate.
+ - Add --update=resync for --assemble mode to for a resync when the
+ array is assembled.
+ - Add support for "raid10", which is under development in 2.6.
+ Not documented yet.
+ - --monitor now reads spare-group and spares info from config file
+ even when names of arrays to scan are given on the command line
+
Changes Prior to 1.6.0 release
- Device name given in -Eb is determined by examining /dev rather
than assuming /dev/md%d
diff --git a/Create.c b/Create.c
index fb9857b..64bf0e2 100644
--- a/Create.c
+++ b/Create.c
@@ -117,6 +117,12 @@ int Create(char *mddev, int mdfd,
default: /* no layout */
layout = 0;
break;
+ case 10:
+ layout = 0x102; /* near=2, far=1 */
+ if (verbose)
+ fprintf(stderr,
+ Name ": layout defaults to n1\n");
+ break;
case 5:
case 6:
layout = map_name(r5layout, "default");
@@ -126,9 +132,18 @@ int Create(char *mddev, int mdfd,
break;
}
+ if (level == 10)
+ /* check layout fits in array*/
+ if ((layout&255) * ((layout>>8)&255) > raiddisks) {
+ fprintf(stderr, Name ": that layout requires at least %d devices\n",
+ (layout&255) * ((layout>>8)&255));
+ return 1;
+ }
+
switch(level) {
case 4:
case 5:
+ case 10:
case 6:
case 0:
case -1: /* linear */
diff --git a/Detail.c b/Detail.c
index 5028ae2..7655668 100644
--- a/Detail.c
+++ b/Detail.c
@@ -47,6 +47,9 @@ int Detail(char *dev, int brief, int test)
char *devices = NULL;
int spares = 0;
struct stat stb;
+ int is_26 = get_linux_version() >= 2006000;
+ int is_rebuilding = 0;
+ int failed = 0;
mdp_super_t super;
int have_super = 0;
@@ -83,6 +86,34 @@ int Detail(char *dev, int brief, int test)
if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode))
stb.st_rdev = 0;
rv = 0;
+
+ /* try to load a superblock */
+ for (d= 0; d<MD_SB_DISKS; d++) {
+ mdu_disk_info_t disk;
+ char *dv;
+ disk.number = d;
+ if (ioctl(fd, GET_DISK_INFO, &disk) < 0)
+ continue;
+ if (d >= array.raid_disks &&
+ disk.major == 0 &&
+ disk.minor == 0)
+ continue;
+ if ((dv=map_dev(disk.major, disk.minor))) {
+ if (!have_super && (disk.state & (1<<MD_DISK_ACTIVE))) {
+ /* try to read the superblock from this device
+ * to get more info
+ */
+ int fd2 = open(dv, O_RDONLY);
+ if (fd2 >=0 &&
+ load_super(fd2, &super) ==0 &&
+ (unsigned long)super.ctime == (unsigned long)array.ctime &&
+ (unsigned int)super.level == (unsigned int)array.level)
+ have_super = 1;
+ if (fd2 >= 0) close(fd2);
+ }
+ }
+ }
+
/* Ok, we have some info to print... */
c = map_num(pers, array.level);
if (brief)
@@ -132,7 +163,8 @@ int Detail(char *dev, int brief, int test)
printf(" State : %s%s%s\n",
(array.state&(1<<MD_SB_CLEAN))?"clean":"dirty",
array.active_disks < array.raid_disks? ", degraded":"",
- (e && e->percent >= 0) ? ", recovering": "");
+ (!e || e->percent < 0) ? "" :
+ (e->resync) ? ", resyncing": ", recovering");
printf(" Active Devices : %d\n", array.active_disks);
printf("Working Devices : %d\n", array.working_disks);
printf(" Failed Devices : %d\n", array.failed_disks);
@@ -142,24 +174,40 @@ int Detail(char *dev, int brief, int test)
c = map_num(r5layout, array.layout);
printf(" Layout : %s\n", c?c:"-unknown-");
}
+ if (array.level == 10) {
+ printf(" Layout : near=%d, far=%d\n",
+ array.layout&255, (array.layout>>8)&255);
+ }
switch (array.level) {
case 0:
case 4:
case 5:
- printf(" Chunk Size : %dK\n", array.chunk_size/1024);
+ case 10:
+ case 6:
+ printf(" Chunk Size : %dK\n\n", array.chunk_size/1024);
break;
case -1:
- printf(" Rounding : %dK\n", array.chunk_size/1024);
+ printf(" Rounding : %dK\n\n", array.chunk_size/1024);
break;
default: break;
}
- printf("\n");
-
- if (e && e->percent >= 0)
+ if (e && e->percent >= 0) {
printf(" Rebuild Status : %d%% complete\n\n", e->percent);
+ is_rebuilding = 1;
+ }
free_mdstat(ms);
+ if (have_super) {
+ printf(" UUID : ");
+ if (super.minor_version >= 90)
+ printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
+ super.set_uuid2, super.set_uuid3);
+ else
+ printf("%08x", super.set_uuid0);
+ printf("\n Events : %d.%d\n\n", super.events_hi, super.events_lo);
+ }
+
printf(" Number Major Minor RaidDevice State\n");
}
for (d= 0; d<MD_SB_DISKS; d++) {
@@ -177,14 +225,40 @@ int Detail(char *dev, int brief, int test)
disk.minor == 0)
continue;
if (!brief) {
- printf(" %5d %5d %5d %5d ",
- disk.number, disk.major, disk.minor, disk.raid_disk);
- if (disk.state & (1<<MD_DISK_FAULTY)) printf(" faulty");
+ if (disk.number == array.raid_disks) printf("\n");
+ if (disk.raid_disk < 0)
+ printf(" %5d %5d %5d - ",
+ disk.number, disk.major, disk.minor);
+ else
+ printf(" %5d %5d %5d %5d ",
+ disk.number, disk.major, disk.minor, disk.raid_disk);
+ if (disk.state & (1<<MD_DISK_FAULTY)) {
+ printf(" faulty");
+ if (disk.raid_disk < array.raid_disks &&
+ disk.raid_disk >= 0)
+ failed++;
+ }
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"); spares++; }
+ if (disk.state == 0) printf(" spare");
+ if (disk.state == 0) {
+ if (is_26) {
+ if (disk.raid_disk < array.raid_disks && disk.raid_disk >= 0)
+ printf(" rebuilding");
+ } else if (is_rebuilding && failed) {
+ /* Taking a bit of a risk here, we remove the
+ * device from the array, and then put it back.
+ * If this fails, we are rebuilding
+ */
+ int err = ioctl(fd, HOT_REMOVE_DISK, MKDEV(disk.major, disk.minor));
+ if (err == 0) ioctl(fd, HOT_ADD_DISK, MKDEV(disk.major, disk.minor));
+ if (err && errno == EBUSY)
+ printf(" rebuilding");
+ }
+ }
}
+ if (disk.state == 0) spares++;
if (test && d < array.raid_disks && disk.state & (1<<MD_DISK_FAULTY)) {
if ((rv & 1) && (array.level ==4 || array.level == 5))
rv |= 2;
@@ -200,34 +274,21 @@ int Detail(char *dev, int brief, int test)
devices = strdup(dv);
} else
printf(" %s", dv);
- if (!have_super && (disk.state & (1<<MD_DISK_ACTIVE))) {
- /* try to read the superblock from this device
- * to get more info
- */
- int fd = open(dv, O_RDONLY);
- if (fd >=0 &&
- load_super(fd, &super) ==0 &&
- (unsigned long)super.ctime == (unsigned long)array.ctime &&
- (unsigned int)super.level == (unsigned int)array.level)
- have_super = 1;
- }
}
if (!brief) printf("\n");
}
if (spares && brief) printf(" spares=%d", spares);
- if (have_super) {
- if (brief) printf(" UUID=");
- else printf(" UUID : ");
+ if (have_super && brief) {
+ printf(" UUID=");
if (super.minor_version >= 90)
printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
super.set_uuid2, super.set_uuid3);
else
printf("%08x", super.set_uuid0);
- if (!brief)
- printf("\n Events : %d.%d\n", super.events_hi, super.events_lo);
}
if (brief && devices) printf("\n devices=%s", devices);
if (brief) printf("\n");
if (test && (rv&2)) rv &= ~1;
+ close(fd);
return rv;
}
diff --git a/Examine.c b/Examine.c
index 1f23745..7dec8d8 100644
--- a/Examine.c
+++ b/Examine.c
@@ -174,11 +174,20 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
printf (" --- adjusting superblock for 2.2/sparc compatability ---\n");
}
printf(" Events : %d.%d\n", super.events_hi, super.events_lo);
+ if (super.events_hi == super.cp_events_hi &&
+ super.events_lo == super.cp_events_lo &&
+ super.recovery_cp > 0 &&
+ (super.state & (1<<MD_SB_CLEAN)) == 0 )
+ printf("Sync checkpoint : %d KB (%d%%)\n", super.recovery_cp/2, super.recovery_cp/(super.size/100*2));
printf("\n");
if (super.level == 5) {
c = map_num(r5layout, super.layout);
printf(" Layout : %s\n", c?c:"-unknown-");
}
+ if (super.level == 10)
+ printf(" Layout : near=%d, far=%d\n",
+ super.layout&255, (super.layout>>8) & 255);
+
switch(super.level) {
case 0:
case 4:
@@ -209,6 +218,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
if ((dv=map_dev(dp->major, dp->minor)))
printf(" %s", dv);
printf("\n");
+ if (d == -1) printf("\n");
}
}
if (SparcAdjust == 2) {
diff --git a/Grow.c b/Grow.c
new file mode 100644
index 0000000..82283bc
--- /dev/null
+++ b/Grow.c
@@ -0,0 +1,192 @@
+/*
+ * mdadm - manage Linux "md" devices aka RAID arrays.
+ *
+ * Copyright (C) 2001-2004 Neil Brown <neilb@cse.unsw.edu.au>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Neil Brown
+ * Email: <neilb@cse.unsw.edu.au>
+ * Paper: Neil Brown
+ * School of Computer Science and Engineering
+ * The University of New South Wales
+ * Sydney, 2052
+ * Australia
+ */
+#include "mdadm.h"
+#include "dlink.h"
+
+#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
+#error no endian defined
+#endif
+#include "md_u.h"
+#include "md_p.h"
+
+int Grow_Add_device(char *devname, int fd, char *newdev)
+{
+ /* Add a device to an active array.
+ * Currently, just extend a linear array.
+ * This requires writing a new superblock on the
+ * new device, calling the kernel to add the device,
+ * and if that succeeds, update the superblock on
+ * all other devices.
+ * This means that we need to *find* all other devices.
+ */
+ mdu_array_info_t array;
+ mdu_disk_info_t disk;
+ mdp_super_t super;
+ struct stat stb;
+ int nfd, fd2;
+ int d, nd;
+
+
+ if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
+ fprintf(stderr, Name ": cannot get array info for %s\n", devname);
+ return 1;
+ }
+
+ if (array.level != -1) {
+ fprintf(stderr, Name ": can only add devices to linear arrays\n");
+ return 1;
+ }
+
+ nfd = open(newdev, O_RDWR|O_EXCL);
+ if (nfd < 0) {
+ fprintf(stderr, Name ": cannot open %s\n", newdev);
+ return 1;
+ }
+ fstat(nfd, &stb);
+ if ((stb.st_mode & S_IFMT) != S_IFBLK) {
+ fprintf(stderr, Name ": %s is not a block device!\n", newdev);
+ close(nfd);
+ return 1;
+ }
+ /* now check out all the devices and make sure we can read the superblock */
+ for (d=0 ; d < array.raid_disks ; d++) {
+ mdu_disk_info_t disk;
+ char *dv;
+
+ disk.number = d;
+ if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
+ fprintf(stderr, Name ": cannot get device detail for device %d\n",
+ d);
+ return 1;
+ }
+ dv = map_dev(disk.major, disk.minor);
+ if (!dv) {
+ fprintf(stderr, Name ": cannot find device file for device %d\n",
+ d);
+ return 1;
+ }
+ fd2 = open(dv, O_RDWR);
+ if (!fd2) {
+ fprintf(stderr, Name ": cannot open device file %s\n", dv);
+ return 1;
+ }
+ if (load_super(fd2, &super)) {
+ fprintf(stderr, Name ": cannot find super block on %s\n", dv);
+ close(fd2);
+ return 1;
+ }
+ close(fd2);
+ }
+ /* Ok, looks good. Lets update the superblock and write it out to
+ * newdev.
+ */
+
+ memset(&super.disks[d], 0, sizeof(super.disks[d]));
+ super.disks[d].number = d;
+ super.disks[d].major = MAJOR(stb.st_rdev);
+ super.disks[d].minor = MINOR(stb.st_rdev);
+ super.disks[d].raid_disk = d;
+ super.disks[d].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
+
+ super.this_disk = super.disks[d];
+ super.sb_csum = calc_sb_csum(&super);
+ if (store_super(nfd, &super)) {
+ fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
+ close(nfd);
+ return 1;
+ }
+ disk.number = d;
+ disk.major = MAJOR(stb.st_rdev);
+ disk.minor = MINOR(stb.st_rdev);
+ disk.raid_disk = d;
+ disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
+ close(nfd);
+ if (ioctl(fd, ADD_NEW_DISK, &disk) != 0) {
+ fprintf(stderr, Name ": Cannot add new disk to this array\n");
+ return 1;
+ }
+ /* Well, that seems to have worked.
+ * Now go through and update all superblocks
+ */
+
+ if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
+ fprintf(stderr, Name ": cannot get array info for %s\n", devname);
+ return 1;
+ }
+
+ nd = d;
+ for (d=0 ; d < array.raid_disks ; d++) {
+ mdu_disk_info_t disk;
+ char *dv;
+
+ disk.number = d;
+ if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
+ fprintf(stderr, Name ": cannot get device detail for device %d\n",
+ d);
+ return 1;
+ }
+ dv = map_dev(disk.major, disk.minor);
+ if (!dv) {
+ fprintf(stderr, Name ": cannot find device file for device %d\n",
+ d);
+ return 1;
+ }
+ fd2 = open(dv, O_RDWR);
+ if (fd2 < 0) {
+ fprintf(stderr, Name ": cannot open device file %s\n", dv);
+ return 1;
+ }
+ if (load_super(fd2, &super)) {
+ fprintf(stderr, Name ": cannot find super block on %s\n", dv);
+ close(fd);
+ return 1;
+ }
+ super.raid_disks = nd+1;
+ super.nr_disks = nd+1;
+ super.active_disks = nd+1;
+ super.working_disks = nd+1;
+ memset(&super.disks[nd], 0, sizeof(super.disks[nd]));
+ super.disks[nd].number = nd;
+ super.disks[nd].major = MAJOR(stb.st_rdev);
+ super.disks[nd].minor = MINOR(stb.st_rdev);
+ super.disks[nd].raid_disk = nd;
+ super.disks[nd].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
+
+ super.this_disk = super.disks[d];
+ super.sb_csum = calc_sb_csum(&super);
+ if (store_super(fd2, &super)) {
+ fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
+ close(fd2);
+ return 1;
+ }
+ close(fd2);
+ }
+
+ return 0;
+}
diff --git a/Makefile b/Makefile
index af2aa7c..a35c6f7 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@
# define "CXFLAGS" to give extra flags to CC.
# e.g. make CXFLAGS=-O to optimise
TCC = tcc
-UCLIBC_GCC = i386-uclibc-gcc
+UCLIBC_GCC = $(shell for nm in i386-uclibc-linux-gcc i386-uclibc-gcc; do which $$nm > /dev/null && { echo $$nm ; exit; } ; done; echo false No uclibc found )
CC = gcc
CXFLAGS = -ggdb
@@ -55,8 +55,8 @@ MAN8DIR = $(MANDIR)/man8
KLIBC=/home/src/klibc/klibc-0.77
-OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o Create.o Detail.o Examine.o Monitor.o dlink.o Kill.o Query.o
-SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c Create.c Detail.c Examine.c Monitor.c dlink.c Kill.c Query.c
+OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o
+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
all : mdadm mdadm.man md.man mdadm.conf.man
diff --git a/Monitor.c b/Monitor.c
index 021a967..ce0087c 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -163,6 +163,7 @@ int Monitor(mddev_dev_t devlist,
} else {
mddev_dev_t dv;
for (dv=devlist ; dv; dv=dv->next) {
+ mddev_ident_t mdlist = conf_get_ident(config, dv->devname);
struct state *st = malloc(sizeof *st);
if (st == NULL)
continue;
@@ -174,6 +175,11 @@ int Monitor(mddev_dev_t devlist,
st->percent = -2;
st->expected_spares = -1;
st->spare_group = NULL;
+ if (mdlist) {
+ st->expected_spares = mdlist->spare_disks;
+ if (mdlist->spare_group)
+ st->spare_group = strdup(mdlist->spare_group);
+ }
statelist = st;
}
}
@@ -216,7 +222,8 @@ int Monitor(mddev_dev_t devlist,
close(fd);
continue;
}
- if (array.level != 1 && array.level != 5 && array.level != -4) {
+ if (array.level != 1 && array.level != 5 && array.level != -4 &&
+ array.level != 6 && array.level != 10) {
if (!st->err)
alert("DeviceDisappeared", dev, "Wrong-Level",
mailaddr, alert_cmd);
diff --git a/ReadMe.c b/ReadMe.c
index 6ba33ba..21a6543 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -29,7 +29,7 @@
#include "mdadm.h"
-char Version[] = Name " - v1.6.0 - 4 June 2004\n";
+char Version[] = Name " - v1.7.0 - 11 August 2004\n";
/*
* File: ReadMe.c
*
@@ -216,7 +216,7 @@ char OptionHelp[] =
" --layout= : same as --parity\n"
" --raid-devices= -n : number of active devices in array\n"
" --spare-devices= -x: number of spares (eXtras) devices in initial array\n"
-" --size= -z : Size (in K) of each drive in RAID1/4/5/6 - optional\n"
+" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n"
" --force -f : Honour devices as listed on command line. Don't\n"
" : insert a missing drive for RAID5.\n"
" --auto(=p) -a : Automatically allocate new (partitioned) md array if needed.\n"
@@ -284,7 +284,7 @@ char Help_create[] =
" --layout= : same as --parity\n"
" --raid-devices= -n : number of active devices in array\n"
" --spare-devices= -x: number of spares (eXtras) devices in initial array\n"
-" --size= -z : Size (in K) of each drive in RAID1/4/5/6 - optional\n"
+" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n"
" --force -f : Honour devices as listed on command line. Don't\n"
" : insert a missing drive for RAID5.\n"
" --run -R : insist of running the array even if not all\n"
@@ -508,6 +508,8 @@ mapping_t pers[] = {
{ "mp", -4},
{ "raid6", 6},
{ "6", 6},
+ { "raid10", 10},
+ { "10", 10},
{ NULL, 0}
};
diff --git a/config.c b/config.c
index 1671d26..550bb80 100644
--- a/config.c
+++ b/config.c
@@ -364,7 +364,7 @@ void arrayline(char *line)
}
if (mis.devname == NULL)
fprintf(stderr, Name ": ARRAY line with no device\n");
- else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor < 0)
+ else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet)
fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname);
else {
mi = malloc(sizeof(*mi));
diff --git a/inventory b/inventory
new file mode 100644
index 0000000..fac793b
--- /dev/null
+++ b/inventory
@@ -0,0 +1,43 @@
+
+ANNOUNCE-1.0.0
+ANNOUNCE-1.1.0
+ANNOUNCE-1.2.0
+ANNOUNCE-1.3.0
+ANNOUNCE-1.4.0
+ANNOUNCE-1.5.0
+ANNOUNCE-1.6.0
+ANNOUNCE-1.7.0
+Assemble.c
+Build.c
+COPYING
+ChangeLog
+Create.c
+Detail.c
+Examine.c
+Grow.c
+INSTALL
+Kill.c
+Makefile
+Manage.c
+Monitor.c
+Query.c
+ReadMe.c
+TODO
+config.c
+dlink.c
+dlink.h
+inventory
+makedist
+md.4
+md_p.h
+md_u.h
+mdadm.8
+mdadm.c
+mdadm.conf-example
+mdadm.conf.5
+mdadm.h
+mdadm.spec
+mdassemble.c
+mdstat.c
+raid5extend.c
+util.c
diff --git a/makedist b/makedist
index 0c307f9..fb14ad4 100755
--- a/makedist
+++ b/makedist
@@ -21,9 +21,13 @@ grep "^Version: *$version$" mdadm.spec > /dev/null 2>&1 ||
if [ -f ANNOUNCE-$version ]
then :
else
- echo ANNONCE-$version does not exist
+ echo ANNOUNCE-$version does not exist
exit 1
fi
+if grep "^ANNOUNCE-$version\$" inventory
+then :
+else { cat inventory ; echo ANNOUNCE-$version ; } | sort -o inventory
+fi
echo version = $version
base=mdadm-$version.tgz
@@ -38,6 +42,12 @@ then
( cd .. ; ln -s mdadm mdadm-$version ; tar chvf - --exclude="TAGS" --exclude='*~' --exclude=.patches --exclude='*,v' --exclude='*.o' --exclude mdadm --exclude=mdadm'.[^ch0-9]' --exclude=RCS mdadm-$version ; rm mdadm-$version ) | gzip --best > $target/$base
chmod a+r $target/$base
ls -l $target/$base
+ if tar tzf $target/$base | sed 's,[^/]*/,,' | sort | diff -u inventory -
+ then : correct files found
+ else echo "Extra files, or invertory is out-of-date"
+ rm $target/$base
+ exit 1
+ fi
rpm -ta $target/$base
find /home/neilb/src/RPM -name "*mdadm-$version-*" \
diff --git a/md_p.h b/md_p.h
index bd9ccb1..aeaf878 100644
--- a/md_p.h
+++ b/md_p.h
@@ -131,11 +131,16 @@ typedef struct mdp_superblock_s {
#if __BYTE_ORDER == __BIG_ENDIAN
__u32 events_hi; /* 7 high-order of superblock update count */
__u32 events_lo; /* 8 low-order of superblock update count */
+ __u32 cp_events_hi; /* 9 high-order of checkpoint update count */
+ __u32 cp_events_lo; /* 10 low-order of checkpoint update count */
#else
__u32 events_lo; /* 7 low-order of superblock update count */
__u32 events_hi; /* 8 high-order of superblock update count */
+ __u32 cp_events_lo; /* 9 low-order of checkpoint update count */
+ __u32 cp_events_hi; /* 10 high-order of checkpoint update count */
#endif
- __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 9];
+ __u32 recovery_cp; /* 11 recovery checkpoint sector count */
+ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12];
/*
* Personality information
diff --git a/mdadm.8 b/mdadm.8
index 6e20b7e..b9f5bfa 100644
--- a/mdadm.8
+++ b/mdadm.8
@@ -1,5 +1,5 @@
.\" -*- nroff -*-
-.TH MDADM 8 "" v1.6.0
+.TH MDADM 8 "" v1.7.0
.SH NAME
mdadm \- manage MD devices
.I aka
@@ -407,6 +407,7 @@ Update the superblock on each device while assembling the array. The
argument given to this flag can be one of
.BR sparc2.2 ,
.BR summaries ,
+.BR resync ,
or
.BR super-minor .
@@ -429,6 +430,15 @@ assembled. This is not needed on 2.6 and later kernels as they make
this adjustment automatically.
The
+.B resync
+option will cause the array to be marked
+.I dirty
+meaning that any redundancy in the array (e.g. parity for raid5,
+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 summaries
option will correct the summaries in the superblock. That is the
counts of total, working, active, failed, and spare devices.
diff --git a/mdadm.c b/mdadm.c
index 827f334..e181673 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -235,6 +235,8 @@ int main(int argc, char *argv[])
int daemonise = 0;
int oneshot = 0;
+ int copies;
+
int mdfd = -1;
ident.uuid_set=0;
@@ -361,6 +363,10 @@ int main(int argc, char *argv[])
fprintf(stderr, Name ": Must give one of -a/-r/-f for subsequent devices at %s\n", optarg);
exit(2);
}
+ if (devs_found > 0 && mode == 'G' && !devmode) {
+ fprintf(stderr, Name ": Must give one of -a for devices do add: %s\n", optarg);
+ exit(2);
+ }
dv = malloc(sizeof(*dv));
if (dv == NULL) {
fprintf(stderr, Name ": malloc failed\n");
@@ -441,7 +447,7 @@ int main(int argc, char *argv[])
continue;
case O(CREATE,'p'): /* raid5 layout */
- if (layout >= 0) {
+ if (layout != UnSet) {
fprintf(stderr,Name ": layout may only be sent once. "
"Second value was %s\n", optarg);
exit(2);
@@ -464,6 +470,21 @@ int main(int argc, char *argv[])
exit(2);
}
break;
+
+ case 10:
+ /* 'f' or 'n' followed by a number <= raid_disks */
+ if ((optarg[0] != 'n' && optarg[0] != 'f') ||
+ (copies = strtoul(optarg+1, &cp, 10)) < 1 ||
+ copies > 200 ||
+ *cp) {
+ fprintf(stderr, Name ": layout for raid10 must be 'nNN' or 'fNN' where NN is a number, not %s\n", optarg);
+ exit(2);
+ }
+ if (optarg[0] == 'n')
+ layout = 256 + copies;
+ else
+ layout = 1 + (copies<<8);
+ break;
}
continue;
@@ -596,12 +617,15 @@ int main(int argc, char *argv[])
exit(2);
}
update = optarg;
- if (strcmp(update, "sparc2.2")==0) continue;
+ if (strcmp(update, "sparc2.2")==0)
+ continue;
if (strcmp(update, "super-minor") == 0)
continue;
if (strcmp(update, "summaries")==0)
continue;
- fprintf(stderr, Name ": '--update %s' invalid. Only 'sparc2.2', 'super-minor' or 'summaries' supported\n",update);
+ if (strcmp(update, "resync")==0)
+ continue;
+ fprintf(stderr, Name ": '--update %s' invalid. Only 'sparc2.2', 'super-minor', 'resync' or 'summaries' supported\n",update);
exit(2);
case O(ASSEMBLE,'c'): /* config file */
@@ -663,6 +687,7 @@ int main(int argc, char *argv[])
/* now the general management options. Some are applicable
* to other modes. None have arguments.
*/
+ case O(GROW,'a'):
case O(MANAGE,'a'): /* add a drive */
devmode = 'a';
continue;
@@ -944,16 +969,24 @@ int main(int argc, char *argv[])
case GROW:
if (devs_found > 1) {
- fprintf(stderr, Name ": Only one device may be given for --grow\n");
- rv = 1;
- break;
- }
- if (size >= 0 && raiddisks) {
+
+ /* must be '-a'. */
+ if (size >= 0 || raiddisks) {
+ fprintf(stderr, Name ": --size, --raiddisks, and --add are exclusing in --grow mode\n");
+ rv = 1;
+ break;
+ }
+ for (dv=devlist->next; dv ; dv=dv->next) {
+ rv = Grow_Add_device(devlist->devname, mdfd, dv->devname);
+ if (rv)
+ break;
+ }
+ } else if (size >= 0 && raiddisks) {
fprintf(stderr, Name ": can only grow size OR raiddisks, not both\n");
rv = 1;
break;
- }
- rv = Manage_resize(devlist->devname, mdfd, size, raiddisks);
+ } else
+ rv = Manage_resize(devlist->devname, mdfd, size, raiddisks);
break;
}
exit(rv);
diff --git a/mdadm.h b/mdadm.h
index 90d3a09..831e267 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -136,6 +136,7 @@ struct mdstat_ent {
char *level;
char *pattern; /* U or up, _ for down */
int percent; /* -1 if no resync */
+ int resync; /* 1 if resync, 0 if recovery */
struct mdstat_ent *next;
};
@@ -159,6 +160,7 @@ extern int Manage_runstop(char *devname, int fd, int runstop);
extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
extern int Manage_subdevs(char *devname, int fd,
mddev_dev_t devlist);
+extern int Grow_Add_device(char *devname, int fd, char *newdev);
extern int Assemble(char *mddev, int mdfd,
diff --git a/mdadm.spec b/mdadm.spec
index 7465b34..f55d933 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.6.0
+Version: 1.7.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/
diff --git a/mdassemble b/mdassemble
deleted file mode 100755
index cd8f042..0000000
--- a/mdassemble
+++ /dev/null
Binary files differ
diff --git a/mdstat.c b/mdstat.c
index 3204d2e..9a73279 100644
--- a/mdstat.c
+++ b/mdstat.c
@@ -153,6 +153,7 @@ struct mdstat_ent *mdstat_read(int hold)
ent->next = NULL;
ent->percent = -1;
ent->active = -1;
+ ent->resync = 0;
ent->dev = strdup(line);
ent->devnum = devnum;
@@ -179,6 +180,11 @@ struct mdstat_ent *mdstat_read(int hold)
w[l-1] == '%' &&
(eq=strchr(w, '=')) != NULL ) {
ent->percent = atoi(eq+1);
+ if (strncmp(w,"resync", 4)==0)
+ ent->resync = 1;
+ } else if (ent->percent == -1 &&
+ strncmp(w, "resync", 4)==0) {
+ ent->resync = 1;
} else if (ent->percent == -1 &&
w[0] >= '0' &&
w[0] <= '9' &&
diff --git a/t b/t
deleted file mode 100644
index baf4ab5..0000000
--- a/t
+++ /dev/null
@@ -1 +0,0 @@
-ARRAY /dev/fred auto=parti /dev/fred
diff --git a/test b/test
deleted file mode 100644
index fac0f33..0000000
--- a/test
+++ /dev/null
@@ -1,2 +0,0 @@
-dev partitions
-array /dev/md0 super-minor=6
diff --git a/util.c b/util.c
index 2f4ad96..5ef59c0 100644
--- a/util.c
+++ b/util.c
@@ -121,6 +121,8 @@ int get_linux_version()
int enough(int level, int raid_disks, int avail_disks)
{
switch (level) {
+ case 10: return 1; /* a lie, but it is hard to tell */
+
case -4:
return avail_disks>= 1;
case -1:
@@ -375,6 +377,32 @@ int map_name(mapping_t *map, char *name)
return UnSet;
}
+
+int is_standard(char *dev)
+{
+ /* tests if dev is a "standard" md dev name.
+ * i.e if the last component is "/dNN" or "/mdNN",
+ * where NN is a string of digits
+ */
+ dev = strrchr(dev, '/');
+ if (!dev)
+ return 0;
+ if (strncmp(dev, "/d",2)==0)
+ dev += 2;
+ else if (strncmp(dev, "/md", 3)==0)
+ dev += 3;
+ else
+ return 0;
+ if (!*dev)
+ return 0;
+ while (isdigit(*dev))
+ dev++;
+ if (*dev)
+ return 0;
+ return 1;
+}
+
+
/*
* convert a major/minor pair for a block device into a name in /dev, if possible.
* On the first call, walk /dev collecting name.
@@ -421,31 +449,6 @@ int add_dev(const char *name, const struct stat *stb, int flag)
return 0;
}
-int is_standard(char *dev)
-{
- /* tests if dev is a "standard" md dev name.
- * i.e if the last component is "/dNN" or "/mdNN",
- * where NN is a string of digits
- */
- dev = strrchr(dev, '/');
- if (!dev)
- return 0;
- if (strncmp(dev, "/d",2)==0)
- dev += 2;
- else if (strncmp(dev, "/md", 3)==0)
- dev += 3;
- else
- return 0;
- if (!*dev)
- return 0;
- while (isdigit(*dev))
- dev++;
- if (*dev)
- return 0;
- return 1;
-}
-
-
/*
* Find a block device with the right major/minor number.
* Avoid /dev/mdNN and /dev/md/dNN is possible