]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdadm-1.7.0 mdadm-1.7.0
authorNeil Brown <neilb@suse.de>
Wed, 11 Aug 2004 02:16:01 +0000 (02:16 +0000)
committerNeil Brown <neilb@suse.de>
Wed, 11 Aug 2004 02:16:01 +0000 (02:16 +0000)
23 files changed:
ANNOUNCE-1.7.0 [new file with mode: 0644]
Assemble.c
ChangeLog
Create.c
Detail.c
Examine.c
Grow.c [new file with mode: 0644]
Makefile
Monitor.c
ReadMe.c
config.c
inventory [new file with mode: 0644]
makedist
md_p.h
mdadm.8
mdadm.c
mdadm.h
mdadm.spec
mdassemble [deleted file]
mdstat.c
t [deleted file]
test [deleted file]
util.c

diff --git a/ANNOUNCE-1.7.0 b/ANNOUNCE-1.7.0
new file mode 100644 (file)
index 0000000..86c4aac
--- /dev/null
@@ -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
+
index 0d222512d0c271fc1a904ab37709ae8a283c2258..3f22ae96bf515753a1a7eecc72e5507b8246f47b 100644 (file)
@@ -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) 
index a505a74fa4b959ea0fa22fd1706042a7bfad4519..df5b25b1b5e86b83dedb444bfcf04b26d1aaeb49 100644 (file)
--- 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
index fb9857b551d785f800ab36e38134554d5b98d88c..64bf0e2fbf64383841c2ee4be46cb7bb1fb4cab7 100644 (file)
--- 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 */
index 5028ae29c40346c0991c4e33a3deb1f1d04a1077..76556682ca58ebb9d5bc451d49c1d9d6ffbaa5f6 100644 (file)
--- 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;
 }
index 1f2374586fae5373854fff437a03867b1ddfdf7b..7dec8d8756bab95ac56117fc7327fa5d2836fcc2 100644 (file)
--- 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 (file)
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;
+}
index af2aa7c8b4d3327e7763a2c96df32e70fad792e1..a35c6f7aae593349ff4318d5b47e36d5f286c36f 100644 (file)
--- 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
 
index 021a9677aa5f87ee5de8723e9cdd2cac79dae76a..ce0087cfac0c7f7ddeee6eba063640aebf4cbc11 100644 (file)
--- 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);
index 6ba33ba15367ddb615e3caf52f158676c9496563..21a6543ac279ce63803d4fe9fc57556015f2618a 100644 (file)
--- 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}
 };
 
index 1671d266ef55bb3a2fb7e078de76fb7aa9cc028c..550bb80aed4f5be15dbf034a9726345d98fd1978 100644 (file)
--- 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 (file)
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
index 0c307f9f2f6c6d591499ec29bdd6a306c9c869ad..fb14ad40d001610facdb57bea637928181a22710 100755 (executable)
--- 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 bd9ccb169171873b8b74a2333ce85297fdc95ee0..aeaf87889ff5ce18155f6881a1794028852b4909 100644 (file)
--- 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 6e20b7ea93b5f49b2876cb89b03e3defa75926d7..b9f5bfae4b66a5a884d3b35384a29a127b3c23ba 100644 (file)
--- 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 827f334d9da146437f3c4c07c8dc9080ba687f91..e18167375a2c6e720dcc1bbde48fb41a2149a31a 100644 (file)
--- 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 90d3a094712d8d27f68423c4a84f2c998309d940..831e26716fa3d67f9076528f21b9003750d489ee 100644 (file)
--- 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,
index 7465b3406c7a7489a62b0197a3ba878900e0f1d7..f55d9339bb8dc12542cbcbfa244d0448b16f1647 100644 (file)
@@ -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 (executable)
index cd8f042..0000000
Binary files a/mdassemble and /dev/null differ
index 3204d2e468f08d30e4f5753ef2e10115d365f121..9a7327988e198bf5f74a9a5d4ed0ba7e11733485 100644 (file)
--- 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 (file)
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 (file)
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 2f4ad9638e71fd2c9ed757d0bd1cdc1d227ded81..5ef59c088d8091c3da3451abb874ab7be80cefa7 100644 (file)
--- 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