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 00000000..86c4aacf --- /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 0d222512..3f22ae96 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 5028ae29..76556682 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 1f237458..7dec8d87 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 00000000..82283bc8 --- /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 af2aa7c8..a35c6f7a 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 021a9677..ce0087cf 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 6ba33ba1..21a6543a 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 1671d266..550bb80a 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 00000000..fac793b8 --- /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 0c307f9f..fb14ad40 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 bd9ccb16..aeaf8788 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 6e20b7ea..b9f5bfae 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 827f334d..e1816737 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 90d3a094..831e2671 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 7465b340..f55d9339 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 Hc-jL100001 literal 62213 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�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 b%gfRzEf!A&_lj~@u-=xp;*N}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 baf4ab55..00000000 --- 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 fac0f331..00000000 --- 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 2f4ad963..5ef59c08 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 -- 2.39.2