From e5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Wed, 11 Aug 2004 02:16:01 +0000 Subject: [PATCH] mdadm-1.7.0 --- ANNOUNCE-1.7.0 | 46 ++++++++++++ Assemble.c | 5 ++ ChangeLog | 16 +++++ Create.c | 15 ++++ Detail.c | 113 ++++++++++++++++++++++------- Examine.c | 10 +++ Grow.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 6 +- Monitor.c | 9 ++- ReadMe.c | 8 ++- config.c | 2 +- inventory | 43 +++++++++++ makedist | 12 +++- md_p.h | 7 +- mdadm.8 | 12 +++- mdadm.c | 53 +++++++++++--- mdadm.h | 2 + mdadm.spec | 2 +- mdassemble | Bin 62213 -> 0 bytes mdstat.c | 6 ++ t | 1 - test | 2 - util.c | 53 +++++++------- 23 files changed, 539 insertions(+), 76 deletions(-) create mode 100644 ANNOUNCE-1.7.0 create mode 100644 Grow.c create mode 100644 inventory delete mode 100755 mdassemble delete mode 100644 t delete mode 100644 test 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<>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= array.raid_disks && + disk.major == 0 && + disk.minor == 0) + continue; + if ((dv=map_dev(disk.major, disk.minor))) { + if (!have_super && (disk.state & (1<=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<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= 0) + failed++; + } if (disk.state & (1<= 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<=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<>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 + * + * + * 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: + * 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 . @@ -428,6 +429,15 @@ field on each superblock to match the minor number of the array being 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 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 cd8f042256af7972b95e96bd20642204e60ad31f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62213 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 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