diff options
author | Neil Brown <neilb@suse.de> | 2004-08-11 04:16:01 +0200 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2004-08-11 04:16:01 +0200 |
commit | e5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1 (patch) | |
tree | 889e38efabcc146f7ee4c59f39c79aae7c783d8d | |
parent | mdadm-1.6.0 (diff) | |
download | mdadm-e5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1.tar.xz mdadm-e5329c3747a4e9eb7addbfaa59b8d5e8688ce2a1.zip |
mdadm-1.7.0mdadm-1.7.0
-rw-r--r-- | ANNOUNCE-1.7.0 | 46 | ||||
-rw-r--r-- | Assemble.c | 5 | ||||
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | Create.c | 15 | ||||
-rw-r--r-- | Detail.c | 113 | ||||
-rw-r--r-- | Examine.c | 10 | ||||
-rw-r--r-- | Grow.c | 192 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | Monitor.c | 9 | ||||
-rw-r--r-- | ReadMe.c | 8 | ||||
-rw-r--r-- | config.c | 2 | ||||
-rw-r--r-- | inventory | 43 | ||||
-rwxr-xr-x | makedist | 12 | ||||
-rw-r--r-- | md_p.h | 7 | ||||
-rw-r--r-- | mdadm.8 | 12 | ||||
-rw-r--r-- | mdadm.c | 53 | ||||
-rw-r--r-- | mdadm.h | 2 | ||||
-rw-r--r-- | mdadm.spec | 2 | ||||
-rwxr-xr-x | mdassemble | bin | 62213 -> 0 bytes | |||
-rw-r--r-- | mdstat.c | 6 | ||||
-rw-r--r-- | t | 1 | ||||
-rw-r--r-- | test | 2 | ||||
-rw-r--r-- | util.c | 53 |
23 files changed, 539 insertions, 76 deletions
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 + @@ -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) @@ -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 @@ -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 */ @@ -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; } @@ -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) { @@ -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; +} @@ -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 @@ -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); @@ -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} }; @@ -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 @@ -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-*" \ @@ -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 @@ -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. @@ -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); @@ -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, @@ -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 Binary files differdeleted file mode 100755 index cd8f0422..00000000 --- a/mdassemble +++ /dev/null @@ -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' && @@ -1 +0,0 @@ -ARRAY /dev/fred auto=parti /dev/fred @@ -1,2 +0,0 @@ -dev partitions -array /dev/md0 super-minor=6 @@ -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 |