]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdadm-1.8.0 mdadm-1.8.0
authorNeil Brown <neilb@suse.de>
Mon, 1 Nov 2004 04:49:34 +0000 (04:49 +0000)
committerNeil Brown <neilb@suse.de>
Mon, 1 Nov 2004 04:49:34 +0000 (04:49 +0000)
19 files changed:
ANNOUNCE-1.8.0 [new file with mode: 0644]
Build.c
ChangeLog
Create.c
Examine.c
Makefile
Manage.c
Monitor.c
ReadMe.c
inventory
md.4
mdadm.8
mdadm.c
mdadm.h
mdadm.spec
mdassemble.c
mdopen.c [new file with mode: 0644]
misc/syslog-events [new file with mode: 0644]
util.c

diff --git a/ANNOUNCE-1.8.0 b/ANNOUNCE-1.8.0
new file mode 100644 (file)
index 0000000..f4f36d7
--- /dev/null
@@ -0,0 +1,37 @@
+Subject:  ANNOUNCE: mdadm 1.8.0 - A tool for managing Soft RAID under Linux
+
+
+I am pleased to announce the availability of 
+   mdadm version 1.8.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.8.0 adds:
+    -   --pid-file option to declare a file to record the pid in for 
+       --monitor --daemonise
+    -   Support for new "faulty" personalitiy (see md.4) - not submited to
+        kernel.org yet.
+    -   support for raid0 and linear over devices larger than 2 Terabytes.
+    -   assorted bug fixes.
+
+It is hoped 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.
+1.8.1 may be released soon which contains much of this functionality.
+
+Development of mdadm is sponsored by CSE@UNSW: 
+  The School of Computer Science and Engineering
+at
+  The University of New South Wales
+
+NeilBrown  01 November 2004
+
diff --git a/Build.c b/Build.c
index 3e182f8c8b63d11e15541a442fb974c18e8a53a1..bf9753378c01f57f86368502e4843f79b498be3a 100644 (file)
--- a/Build.c
+++ b/Build.c
@@ -33,7 +33,7 @@
 #define START_MD               _IO (MD_MAJOR, 2)
 #define STOP_MD                _IO (MD_MAJOR, 3)
 
-int Build(char *mddev, int mdfd, int chunk, int level,
+int Build(char *mddev, int mdfd, int chunk, int level, int layout,
          int raiddisks,
          mddev_dev_t devlist, int assume_clean)
 {
@@ -50,6 +50,7 @@ int Build(char *mddev, int mdfd, int chunk, int level,
         * SET_ARRAY_INFO,  ADD_NEW_DISK, RUN_ARRAY
         *
         */
+       int verbose = 0;
        int i;
        int vers;
        struct stat stb;
@@ -77,6 +78,34 @@ int Build(char *mddev, int mdfd, int chunk, int level,
                return 1;
        }
 
+       if (layout == UnSet)
+               switch(level) {
+               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");
+                       if (verbose)
+                               fprintf(stderr,
+                                       Name ": layout defaults to %s\n", map_num(r5layout, layout));
+                       break;
+               case LEVEL_FAULTY:
+                       layout = map_name(faultylayout, "default");
+
+                       if (verbose)
+                               fprintf(stderr,
+                                       Name ": layout defaults to %s\n", map_num(faultylayout, layout));
+                       break;
+               }
+
+
        vers = md_get_version(mdfd);
        
        /* looks Ok, go for it */
@@ -100,6 +129,7 @@ int Build(char *mddev, int mdfd, int chunk, int level,
                if (chunk == 0)  
                        chunk = 64;
                array.chunk_size = chunk*1024;
+               array.layout = layout;
                if (ioctl(mdfd, SET_ARRAY_INFO, &array)) {
                        fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
                                mddev, strerror(errno));
index df5b25b1b5e86b83dedb444bfcf04b26d1aaeb49..6e0ca01c7394750d788cfef87bed6d55b6118265 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,14 @@
-Changes Prior to this release
+Changes Prior to 1.8.0 release
+    -   Makefile cleanup from  Luca Berra <bluca@comedia.it>
+    -   --pid-file (-i) to set a pid file to use with --monitor --daemonise
+    -   Fix typo in mdadm man page
+    -   Fix coredump when "-s" used with no config file present.
+    -   Support new "faulty" personality which can inject synthetic
+        faults. (Not in kernel.org yet at 1Nov2004)
+    -   Support raid0/linear on devices > 2 Terabytes
+    -   Make sure raid6 resyncs when created with one missing device
+
+Changes Prior to 1.7.0 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.
index 64bf0e2fbf64383841c2ee4be46cb7bb1fb4cab7..7b4988e64c9d514eaa72d8efcdcaa6b20f7065a6 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -52,7 +52,7 @@ int Create(char *mddev, int mdfd,
         * if runstop==run, or raiddisks diskswere used,
         * RUN_ARRAY
         */
-       unsigned long minsize=0, maxsize=0;
+       unsigned long long minsize=0, maxsize=0;
        char *mindisc = NULL;
        char *maxdisc = NULL;
        int dnum;
@@ -130,6 +130,13 @@ int Create(char *mddev, int mdfd,
                                fprintf(stderr,
                                        Name ": layout defaults to %s\n", map_num(r5layout, layout));
                        break;
+               case LEVEL_FAULTY:
+                       layout = map_name(faultylayout, "default");
+
+                       if (verbose)
+                               fprintf(stderr,
+                                       Name ": layout defaults to %s\n", map_num(faultylayout, layout));
+                       break;
                }
 
        if (level == 10)
@@ -168,7 +175,8 @@ int Create(char *mddev, int mdfd,
        dnum = 0;
        for (dv=devlist; dv; dv=dv->next, dnum++) {
                char *dname = dv->devname;
-               unsigned long dsize, freesize;
+               unsigned long dsize;
+               unsigned long long ldsize, freesize;
                int fd;
                if (strcasecmp(dname, "missing")==0) {
                        if (first_missing > dnum)
@@ -186,6 +194,11 @@ int Create(char *mddev, int mdfd,
                        fail=1;
                        continue;
                }
+#ifdef BLKGETSIZE64
+               if (ioctl(fd, BLKGETSIZE64, &ldsize)==0)
+                       ;
+               else
+#endif
                if (ioctl(fd, BLKGETSIZE, &dsize)) {
                        fprintf(stderr, Name ": Cannot get size of %s: %s\n",
                                dname, strerror(errno));
@@ -193,19 +206,23 @@ int Create(char *mddev, int mdfd,
                        close(fd);
                        continue;
                }
-               if (dsize < MD_RESERVED_SECTORS*2) {
+               else {
+                       ldsize = dsize;
+                       dsize <<= 9;
+               }
+               if (ldsize < MD_RESERVED_SECTORS*2LL*512LL) {
                        fprintf(stderr, Name ": %s is too small: %luK\n",
-                               dname, dsize/2);
+                               dname, (unsigned long)(ldsize>>10));
                        fail = 1;
                        close(fd);
                        continue;
                }
-               freesize = MD_NEW_SIZE_SECTORS(dsize);
+               freesize = MD_NEW_SIZE_SECTORS((ldsize>>9));
                freesize /= 2;
 
                if (size && freesize < size) {
                        fprintf(stderr, Name ": %s is smaller that given size."
-                               " %luK < %luK + superblock\n", dname, freesize, size);
+                               " %lluK < %luK + superblock\n", dname, freesize, size);
                        fail = 1;
                        close(fd);
                        continue;
@@ -232,11 +249,18 @@ int Create(char *mddev, int mdfd,
                        fprintf(stderr, Name ": no size and no drives given - aborting create.\n");
                        return 1;
                }
-               size = minsize;
-               if (verbose && level>0)
-                       fprintf(stderr, Name ": size set to %luK\n", size);
+               if (level > 0) {
+                       /* size is meaningful */
+                       if (minsize > 0x100000000ULL) {
+                               fprintf(stderr, Name ": devices too large for RAID level %d\n", level); 
+                               return 1;
+                       }
+                       size = minsize;
+                       if (verbose)
+                               fprintf(stderr, Name ": size set to %luK\n", size);
+               }
        }
-       if (level >= 1 && ((maxsize-size)*100 > maxsize)) {
+       if (level > 0 && ((maxsize-size)*100 > maxsize)) {
                fprintf(stderr, Name ": largest drive (%s) exceed size (%luK) by more than 1%%\n",
                        maxdisc, size);
                warn = 1;
@@ -284,8 +308,11 @@ int Create(char *mddev, int mdfd,
                array.md_minor = MINOR(stb.st_rdev);
        array.not_persistent = 0;
        /*** FIX: Need to do something about RAID-6 here ***/
-       if ( (level == 5 || level == 6) &&
-            (insert_point < raiddisks || first_missing < raiddisks) )
+       if ( ( (level == 5) &&
+              (insert_point < raiddisks || first_missing < raiddisks) )
+            ||
+            ( level == 6 && missing_disks == 2)
+               )
                array.state = 1; /* clean, but one+ drive will be missing */
        else
                array.state = 0; /* not clean, but no errors */
index 7dec8d8756bab95ac56117fc7327fa5d2836fcc2..749bc7c1d2d8189910755c4fb46e434a7fc61a1b 100644 (file)
--- a/Examine.c
+++ b/Examine.c
@@ -145,7 +145,8 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                        printf("  Creation Time : %.24s\n", ctime(&atime));
                        c=map_num(pers, super.level);
                        printf("     Raid Level : %s\n", c?c:"-unknown-");
-                       printf("    Device Size : %d%s\n", super.size, human_size((long long)super.size<<10));
+                       if (super.level <= 0)
+                               printf("    Device Size : %u%s\n", super.size, human_size((long long)super.size<<10));
                        printf("   Raid Devices : %d\n", super.raid_disks);
                        printf("  Total Devices : %d\n", super.nr_disks);
                        printf("Preferred Minor : %d\n", super.md_minor);
index a35c6f7aae593349ff4318d5b47e36d5f286c36f..8f0547b9d2dbeb9f048bfc8c8c284d6150a29823 100644 (file)
--- a/Makefile
+++ b/Makefile
 # e.g.  make CXFLAGS=-O to optimise
 TCC = tcc
 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 )
+DIET_GCC = diet gcc
+
+KLIBC=/home/src/klibc/klibc-0.77
+
+KLIBC_GCC = gcc -nostdinc -iwithprefix include -I$(KLIBC)/klibc/include -I$(KLIBC)/linux/include -I$(KLIBC)/klibc/arch/i386/include -I$(KLIBC)/klibc/include/bits32
 
 CC = gcc
 CXFLAGS = -ggdb
@@ -52,11 +57,15 @@ MAN4DIR = $(MANDIR)/man4
 MAN5DIR = $(MANDIR)/man5
 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 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
+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 mdopen.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 mdopen.c
+ASSEMBLE_SRCS := mdassemble.c Assemble.c config.c dlink.c util.c
+ifdef MDASSEMBLE_AUTO
+ASSEMBLE_SRCS += mdopen.c mdstat.c
+ASSEMBLE_FLAGS = -DMDASSEMBLE_AUTO
+endif
 
 all : mdadm mdadm.man md.man mdadm.conf.man
 
@@ -66,7 +75,7 @@ mdadm : $(OBJS)
        $(CC) $(LDFLAGS) -o mdadm $^
 
 mdadm.static : $(OBJS)
-       $(CC) $(LDFLAGS) --static -o mdadm.static $^
+       $(CC) $(LDFLAGS) -static -o mdadm.static $^
 
 mdadm.tcc : $(SRCS) mdadm.h
        $(TCC) -o mdadm.tcc $(SRCS)
@@ -78,15 +87,22 @@ mdadm.klibc : $(SRCS) mdadm.h
        rm -f $(OBJS) 
        gcc -nostdinc -iwithprefix include -I$(KLIBC)/klibc/include -I$(KLIBC)/linux/include -I$(KLIBC)/klibc/arch/i386/include -I$(KLIBC)/klibc/include/bits32 $(CFLAGS) $(SRCS)
 
-mdassemble : mdassemble.c Assemble.c config.c dlink.c util.c mdadm.h
+mdassemble : $(ASSEMBLE_SRCS) mdadm.h
        rm -f $(OBJS)
-       diet gcc -o mdassemble mdassemble.c Assemble.c config.c dlink.c util.c
+       $(DIET_GCC) $(ASSEMBLE_FLAGS) -o mdassemble $(ASSEMBLE_SRCS) 
 
-# This doesn't work
-mdassemble.klibc : mdassemble.c Assemble.c config.c dlink.c util.c mdadm.h
+mdassemble.static : $(ASSEMBLE_SRCS) mdadm.h
+       rm -f $(OBJS)
+       $(CC) $(LDFLAGS) $(ASSEMBLE_FLAGS) -static -o mdassemble $(ASSEMBLE_SRCS)
+
+mdassemble.uclibc : $(ASSEMBLE_SRCS) mdadm.h
        rm -f $(OBJS)
-       gcc -nostdinc -iwithprefix include -I$(KLIBC)/klibc/include -I$(KLIBC)/linux/include -I$(KLIBC)/klibc/arch/i386/include -I$(KLIBC)/klibc/include/bits32 $(CFLAGS) -o mdassemble mdassemble.c Assemble.c config.c dlink.c util.c
+       $(UCLIBC_GCC) $(ASSEMBLE_FLAGS) -DUCLIBC -static -o mdassemble.uclibc $(ASSEMBLE_SRCS) 
 
+# This doesn't work
+mdassemble.klibc : $(ASSEMBLE_SRCS) mdadm.h
+       rm -f $(OBJS)
+       $(KLIBC_GCC) $(CFLAGS) $(ASSEMBLE_FLAGS) -o mdassemble $(ASSEMBLE_SRCS)
 
 mdadm.man : mdadm.8
        nroff -man mdadm.8 > mdadm.man
@@ -106,7 +122,8 @@ install : mdadm mdadm.8 md.4 mdadm.conf.5
        $(INSTALL) -D -m 644 mdadm.conf.5 $(DESTDIR)$(MAN5DIR)/mdadm.conf.5
 
 clean : 
-       rm -f mdadm $(OBJS) core *.man mdadm.tcc mdadm.uclibc mdadm.static *.orig *.porig *.rej *.alt
+       rm -f mdadm $(OBJS) core *.man mdadm.tcc mdadm.uclibc mdadm.static *.orig *.porig *.rej *.alt \
+       mdassemble mdassemble.static mdassemble.uclibc mdassemble.klibc
 
 dist : clean
        ./makedist
index 624c775d530d6c0aad6a90810f84af0bf8a6de01..56cc1ad7ff1ffc77c331333590a26f05fabe7f5c 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -134,6 +134,23 @@ int Manage_resize(char *devname, int fd, long long size, int raid_disks)
        return 0;
 }
 
+int Manage_reconfig(char *devname, int fd, int layout)
+{
+       mdu_array_info_t info;
+       if (ioctl(fd, GET_ARRAY_INFO, &info) != 0) {
+               fprintf(stderr, Name ": Cannot get array information for %s: %s\n",
+                       devname, strerror(errno));
+               return 1;
+       }
+       info.layout = layout;
+       printf("layout set to %d\n", info.layout);
+       if (ioctl(fd, SET_ARRAY_INFO, &info) != 0) {
+               fprintf(stderr, Name ": Cannot set layout for %s: %s\n",
+                       devname, strerror(errno));
+               return 1;
+       }
+       return 0;
+}
 
 int Manage_subdevs(char *devname, int fd,
                   mddev_dev_t devlist)
index ce0087cfac0c7f7ddeee6eba063640aebf4cbc11..036c47f757329992770136015dd8a3a2183f6640 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -47,7 +47,7 @@ static char *percentalerts[] = {
 int Monitor(mddev_dev_t devlist,
            char *mailaddr, char *alert_cmd,
            int period, int daemonise, int scan, int oneshot,
-           char *config, int test)
+           char *config, int test, char* pidfile)
 {
        /*
         * Every few seconds, scan every md device looking for changes
@@ -127,7 +127,18 @@ int Monitor(mddev_dev_t devlist,
        if (daemonise) {
                int pid = fork();
                if (pid > 0) {
-                       printf("%d\n", pid);
+                       if (!pidfile)
+                               printf("%d\n", pid);
+                       else {
+                               FILE *pid_file;
+                               pid_file=fopen(pidfile, "w");
+                               if (!pid_file)
+                                       perror("cannot create pid file");
+                               else {
+                                       fprintf(pid_file,"%d\n", pid);
+                                       fclose(pid_file);
+                               }
+                       }
                        return 0;
                }
                if (pid < 0) {
@@ -428,6 +439,8 @@ int Monitor(mddev_dev_t devlist,
                }
                test = 0;
        }
+       if (pidfile)
+               unlink(pidfile);
        return 0;
 }
 
index 21a6543ac279ce63803d4fe9fc57556015f2618a..687752bc69443a22a097587ae8a2f8dc8e843940 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -29,7 +29,7 @@
 
 #include "mdadm.h"
 
-char Version[] = Name " - v1.7.0 - 11 August 2004\n";
+char Version[] = Name " - v1.8.0 - 01 November 2004\n";
 /*
  * File: ReadMe.c
  *
@@ -90,7 +90,7 @@ char Version[] = Name " - v1.7.0 - 11 August 2004\n";
  *     At the time if writing, there is only minimal support.
  */
 
-char short_options[]="-ABCDEFGQhVvbc:l:p:m:n:x:u:c:d:z:U:sa::rfRSow1t";
+char short_options[]="-ABCDEFGQhVvbc:i:l:p:m:n:x:u:c:d:z:U:sa::rfRSow1t";
 struct option long_options[] = {
     {"manage",    0, 0, '@'},
     {"misc",      0, 0, '#'},
@@ -157,6 +157,7 @@ struct option long_options[] = {
     {"daemonise", 0, 0, 'f'},
     {"daemonize", 0, 0, 'f'},
     {"oneshot",   0, 0, '1'},
+    {"pid-file",  1, 0, 'i'},
     
     {0, 0, 0, 0}
 };
@@ -418,6 +419,7 @@ char Help_monitor[] =
 "  --config=     -c   : specify a different config file\n"
 "  --scan        -s   : find mail-address/program in config file\n"
 "  --daemonise   -f   : Fork and continue in child, parent exits\n"
+"  --pid-file=   -i   : In daemon mode write pid to specified file instead of stdout\n"
 "  --oneshot     -1   : Check for degraded arrays, then exit\n"
 "  --test        -t   : Generate a TestMessage event against each array at startup\n"
 ;
@@ -510,6 +512,7 @@ mapping_t pers[] = {
        { "6", 6},
        { "raid10", 10},
        { "10", 10},
+       { "faulty", -5},
        { NULL, 0}
 };
 
@@ -523,3 +526,24 @@ mapping_t modes[] = {
        { "monitor", MONITOR},
        { "grow", GROW},
 };
+
+mapping_t faultylayout[] = {
+       { "write-transient", WriteTransient },
+       { "wt", WriteTransient },
+       { "read-transient", ReadTransient },
+       { "rt", ReadTransient },
+       { "write-persistent", WritePersistent },
+       { "wp", WritePersistent },
+       { "read-persistent", ReadPersistent },
+       { "rp", ReadPersistent },
+       { "write-all", WriteAll },
+       { "wa", WriteAll },
+       { "read-fixable", ReadFixable },
+       { "rf", ReadFixable },
+
+       { "clear", ClearErrors},
+       { "flush", ClearFaults},
+       { "none", ClearErrors},
+       { "default", ClearErrors},
+       { NULL, 0}
+};
index fac793b81280a5d019b3b26636d31cdfb2a0018e..0fe1afcd72be8e39c22295eb8d097aea0e1511cb 100644 (file)
--- a/inventory
+++ b/inventory
@@ -7,6 +7,7 @@ ANNOUNCE-1.4.0
 ANNOUNCE-1.5.0
 ANNOUNCE-1.6.0
 ANNOUNCE-1.7.0
+ANNOUNCE-1.8.0
 Assemble.c
 Build.c
 COPYING
@@ -38,6 +39,9 @@ mdadm.conf.5
 mdadm.h
 mdadm.spec
 mdassemble.c
+mdopen.c
 mdstat.c
+misc/
+misc/syslog-events
 raid5extend.c
 util.c
diff --git a/md.4 b/md.4
index cb8027a76315f702500bd75d9e6efca785add741..4643dd2598f1cae9843c24cac1c578f7a9b2646f 100644 (file)
--- a/md.4
+++ b/md.4
@@ -166,6 +166,33 @@ real device. If one of these interfaces fails (e.g. due to cable
 problems), the multipath driver to attempt to redirect requests to
 another interface. 
 
+.SS FAULTY
+The FAULTY md module is provided for testing purposes.  A faulty array
+has exactly one component device and is normally assembled without a
+superblock, so the md array created provides direct access to all of
+the data in the component device.
+
+The FAULTY module may be requested to simulate faults to allow testing
+of other md levels or of filesystem.  Faults can be chosen to trigger
+on read requests or write requests, and can be transient (a subsequent
+read/write at the address will probably succeed) or persistant
+(subsequent read/write of the same address will fail).  Further, read
+faults can be "fixable" meaning that they persist until a write
+request at the same address.
+
+Fault types can be requested with a period.  In this case the fault
+will recur repeatedly after the given number of request of the
+relevant time.  For example if persistent read faults have a period of
+100, then ever 100th read request would generate a fault, and the
+faulty sector would be recorded so that subsequent reads on that
+sector would also fail.
+
+There is a limit to the number of faulty sectors that are remembered.
+Faults generated after this limit is exhausted are treated as
+transient.
+
+It list of faulty sectors can be flushed, and the active list of
+failure modes can be cleared.
 
 .SS UNCLEAN SHUTDOWN
 
diff --git a/mdadm.8 b/mdadm.8
index b9f5bfae4b66a5a884d3b35384a29a127b3c23ba..44318e1c26a4cf3d48161dd06e92dd1ad4aa6ec0 100644 (file)
--- a/mdadm.8
+++ b/mdadm.8
@@ -1,5 +1,5 @@
 .\" -*- nroff -*-
-.TH MDADM 8 "" v1.7.0
+.TH MDADM 8 "" v1.8.0
 .SH NAME
 mdadm \- manage MD devices
 .I aka
@@ -30,14 +30,17 @@ md devices,
 .BR RAID4 ,
 .BR RAID5 ,
 .BR RAID6 ,
+.BR MULTIPATH ,
 and
-.BR MULTIPATH .
+.BR FAULTY .
 
 .B MULTIPATH is not a Software RAID mechanism, but does involve
 multiple devices.  For
 .B MULTIPATH
 each device is a path to one common physical storage device.
 
+.B FAULTY is also no true RAID, and it only involves one device.  It
+provides a layer over a true device that can be used to inject faults.
 
 .B mdadm
 is a program that can be used to create, manage, and monitor
@@ -246,7 +249,7 @@ Specify rounding factor for linear array (==chunk size)
 Set raid level.  When used with
 .IR --create ,
 options are: linear, raid0, 0, stripe, raid1, 1, mirror, raid4, 4,
-raid5, 5, raid6, 6, multipath, mp.  Obviously some of these are synonymous.
+raid5, 5, raid6, 6, multipath, mp, fautly.  Obviously some of these are synonymous.
 
 When used with
 .IR --build ,
@@ -261,6 +264,39 @@ right-asymmetric,
 right-symmetric,
 la, ra, ls, rs.  The default is left-symmetric.
 
+This option is also used to set the failure mode for
+.IR faulty .
+The options are:
+write-transient,
+wt,
+read-transient,
+rt,
+write-presistent,
+wp,
+read-persistent,
+rp,
+write-all,
+read-fixable,
+rf,
+clear,
+flush,
+none.
+
+Each mode can be followed by a number which is used as a period
+between fault generation.  Without a number, the fault is generated
+once on the first relevant request.  With a number, the fault will be
+generated after that many request, and will continue to be generated
+every time the period elapses.
+
+Multiple failure modes can be current simultaneously by using the
+"--grow" option to set subsequent failure modes.
+
+"clear" or "none" will remove any pending or periodic failure modes,
+and "flush" will clear any persistant faults.
+
+To set the parity with "--grow", the level of the array ("faulty")
+must be specified before the fault mode is specified.
+
 .TP
 .BR --layout=
 same as --parity
@@ -539,6 +575,13 @@ This is useful with
 which will only continue monitoring if a mail address or alert program
 is found in the config file.
 
+.TP
+.BR -i ", " --pid-file
+When
+.B mdadm
+is running in daemon mode, write the pid of the daemon process to
+the specified file, instead of printing it on standard output.
+
 .TP
 .BR -1 ", " --oneshot
 Check arrays only once.  This will generate
@@ -741,7 +784,7 @@ will automatically create a degraded array with an extra spare drive.
 This is because building the spare into a degraded array is in general faster than resyncing
 the parity on a non-degraded, but not clean, array.  This feature can
 be over-ridden with the
--I --force
+.I --force
 option.
 
 '''If the 
@@ -793,7 +836,7 @@ Usage:
 .I devices  ...
 .PP
 
-MISC mode includes a number if distinct operations that
+MISC mode includes a number of distinct operations that
 operate on distinct devices.  The operations are:
 .TP
 --query
diff --git a/mdadm.c b/mdadm.c
index e18167375a2c6e720dcc1bbde48fb41a2149a31a..d40008ea578d696857e372c887a0d9e1079469d9 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
 #include <ctype.h>
 
 
-void make_parts(char *dev, int cnt)
-{
-       /* make 'cnt' partition devices for 'dev'
-        * We use the major/minor from dev and add 1..cnt
-        * If dev ends with a digit, we add "_p%d" else "%d"
-        * If the name exists, we use it's owner/mode,
-        * else that of dev
-        */
-       struct stat stb;
-       int major, minor;
-       int i;
-       char *name = malloc(strlen(dev) + 20);
-       int dig = isdigit(dev[strlen(dev)-1]);
-
-       if (stat(dev, &stb)!= 0)
-               return;
-       if (!S_ISBLK(stb.st_mode))
-               return;
-       major = MAJOR(stb.st_rdev);
-       minor = MINOR(stb.st_rdev);
-       for (i=1; i <= cnt ; i++) {
-               struct stat stb2;
-               sprintf(name, "%s%s%d", dev, dig?"_p":"", i);
-               if (stat(name, &stb2)==0) {
-                       if (!S_ISBLK(stb2.st_mode))
-                               continue;
-                       if (stb2.st_rdev == MKDEV(major, minor+i))
-                               continue;
-                       unlink(name);
-               } else {
-                       stb2 = stb;
-               }
-               mknod(name, S_IFBLK | 0600, MKDEV(major, minor+i));
-               chown(name, stb2.st_uid, stb2.st_gid);
-               chmod(name, stb2.st_mode & 07777);
-       }
-}
-
-/*
- * Open a given md device, and check that it really is one.
- * If 'autof' is given, then we need to create, or recreate, the md device.
- * If the name already exists, and is not a block device, we fail.
- * If it exists and is not an md device, is not the right type (partitioned or not),
- * or is currently in-use, we remove the device, but remember the owner and mode.
- * If it now doesn't exist, we find a few md array and create the device.
- * Default ownership is user=0, group=0 perm=0600
- */
-int open_mddev(char *dev, int autof)
-{
-       int mdfd;
-       struct stat stb;
-       int major = MD_MAJOR;
-       int minor;
-       int must_remove = 0;
-       struct mdstat_ent *mdlist;
-       int num;
-
-       if (autof) {
-               /* autof is set, so we need to check that the name is ok,
-                * and possibly create one if not
-                */
-               stb.st_mode = 0;
-               if (lstat(dev, &stb)==0 && ! S_ISBLK(stb.st_mode)) {
-                       fprintf(stderr, Name ": %s is not a block device.\n",
-                               dev);
-                       return -1;
-               }
-               /* check major number is correct */
-               if (autof>0)
-                       major = get_mdp_major();
-               if (stb.st_mode && MAJOR(stb.st_rdev) != major)
-                       must_remove = 1;
-               if (stb.st_mode && !must_remove) {
-                       mdu_array_info_t array;
-                       /* looks ok, see if it is available */
-                       mdfd = open(dev, O_RDWR, 0);
-                       if (mdfd < 0) {
-                               fprintf(stderr, Name ": error opening %s: %s\n",
-                                       dev, strerror(errno));
-                               return -1;
-                       } else if (md_get_version(mdfd) <= 0) {
-                               fprintf(stderr, Name ": %s does not appear to be an md device\n",
-                                       dev);
-                               close(mdfd);
-                               return -1;
-                       }
-                       if (ioctl(mdfd, GET_ARRAY_INFO, &array)==0) {
-                               /* already active */
-                               must_remove = 1;
-                               close(mdfd);
-                       } else {
-                               if (autof > 0)
-                                       make_parts(dev, autof);
-                               return mdfd;
-                       }
-               }
-               /* Ok, need to find a minor that is not in use.
-                * Easiest to read /proc/mdstat, and hunt through for
-                * an unused number 
-                */
-               mdlist = mdstat_read(0);
-               for (num= (autof>0)?-1:0 ; ; num+= (autof>2)?-1:1) {
-                       struct mdstat_ent *me;
-                       for (me=mdlist; me; me=me->next)
-                               if (me->devnum == num)
-                                       break;
-                       if (!me) {
-                               /* doesn't exist if mdstat.
-                                * make sure it is new to /dev too
-                                */
-                               char *dn;
-                               if (autof > 0) 
-                                       minor = (-1-num) << MdpMinorShift;
-                               else
-                                       minor = num;
-                               dn = map_dev(major,minor);
-                               if (dn==NULL || is_standard(dn)) {
-                                       /* this number only used by a 'standard' name,
-                                        * so it is safe to use
-                                        */
-                                       break;
-                               }
-                       }
-               }
-               /* 'num' is the number to use, >=0 for md, <0 for mdp */
-               if (must_remove) {
-                       /* never remove a device name that ends /mdNN or /dNN,
-                        * that would be confusing 
-                        */
-                       if (is_standard(dev)) {
-                               fprintf(stderr, Name ": --auto refusing to remove %s as it looks like a standard name.\n",
-                                       dev);
-                               return -1;
-                       }
-                       unlink(dev);
-               }
-
-               if (mknod(dev, S_IFBLK|0600, MKDEV(major, minor))!= 0) {
-                       fprintf(stderr, Name ": failed to create %s\n", dev);
-                       return -1;
-               }
-               if (must_remove) {
-                       chown(dev, stb.st_uid, stb.st_gid);
-                       chmod(dev, stb.st_mode & 07777);
-               }
-               make_parts(dev,autof);
-       }
-       mdfd = open(dev, O_RDWR, 0);
-       if (mdfd < 0)
-               fprintf(stderr, Name ": error opening %s: %s\n",
-                       dev, strerror(errno));
-       else if (md_get_version(mdfd) <= 0) {
-               fprintf(stderr, Name ": %s does not appear to be an md device\n",
-                       dev);
-               close(mdfd);
-               mdfd = -1;
-       }
-       return mdfd;
-}
-
-
 
 int main(int argc, char *argv[])
 {
@@ -233,6 +72,7 @@ int main(int argc, char *argv[])
        char *program = NULL;
        int delay = 0;
        int daemonise = 0;
+       char *pidfile = NULL;
        int oneshot = 0;
 
        int copies;
@@ -420,6 +260,7 @@ int main(int argc, char *argv[])
                        }
                        continue;
 
+               case O(GROW,'l'): /* hack - needed to understand layout */
                case O(CREATE,'l'):
                case O(BUILD,'l'): /* set raid level*/
                        if (level != UnSet) {
@@ -433,7 +274,7 @@ int main(int argc, char *argv[])
                                        optarg);
                                exit(2);
                        }
-                       if (level != 0 && level != -1 && level != 1 && level != -4 && mode == BUILD) {
+                       if (level != 0 && level != -1 && level != 1 && level != -4 && level != -5 && mode == BUILD) {
                                fprintf(stderr, Name ": Raid level %s not permitted with --build.\n",
                                        optarg);
                                exit(2);
@@ -447,6 +288,8 @@ int main(int argc, char *argv[])
                        continue;
 
                case O(CREATE,'p'): /* raid5 layout */
+               case O(BUILD,'p'): /* faulty layout */
+               case O(GROW, 'p'): /* faulty reconfig */
                        if (layout != UnSet) {
                                fprintf(stderr,Name ": layout may only be sent once.  "
                                        "Second value was %s\n", optarg);
@@ -485,6 +328,23 @@ int main(int argc, char *argv[])
                                else
                                        layout = 1 + (copies<<8);
                                break;
+                       case -5: /* Faulty
+                                 * modeNNN
+                                 */
+                                   
+                       {
+                               int ln = strcspn(optarg, "0123456789");
+                               char *m = strdup(optarg);
+                               int mode;
+                               m[ln] = 0;
+                               mode = map_name(faultylayout, m);
+                               if (mode == UnSet) {
+                                       fprintf(stderr, Name ": layout %s not understood for faulty.\n",
+                                               optarg);
+                                       exit(2);
+                               }
+                               layout = mode | (atoi(optarg+ln)<< ModeShift);
+                       }
                        }
                        continue;
 
@@ -507,7 +367,7 @@ int main(int argc, char *argv[])
                                        optarg);
                                exit(2);
                        }
-                       if (raiddisks == 1 &&  !force) {
+                       if (raiddisks == 1 &&  !force && level != -5) {
                                fprintf(stderr, Name ": '1' is an unusual number of drives for an array, so it is probably\n"
                                        "     a mistake.  If you really mean it you will need to specify --force before\n"
                                        "     setting the number of drives.\n");
@@ -677,6 +537,13 @@ int main(int argc, char *argv[])
                case O(MONITOR,'f'): /* daemonise */
                        daemonise = 1;
                        continue;
+               case O(MONITOR,'i'): /* pid */
+                       if (pidfile)
+                               fprintf(stderr, Name ": only specify one pid file. %s ignored.\n",
+                                       optarg);
+                       else
+                               pidfile = optarg;
+                       continue;
                case O(MONITOR,'1'): /* oneshot */
                        oneshot = 1;
                        continue;
@@ -820,19 +687,20 @@ int main(int argc, char *argv[])
                    ident.super_minor == UnSet && !scan ) {
                        /* Only a device has been given, so get details from config file */
                        mddev_ident_t array_ident = conf_get_ident(configfile, devlist->devname);
-                       mdfd = open_mddev(devlist->devname, array_ident->autof);
-                       if (mdfd < 0)
+                       if (array_ident == NULL) {
+                               fprintf(stderr, Name ": %s not identified in config file.\n",
+                                       devlist->devname);
                                rv |= 1;
-                       else {
-                               if (array_ident == NULL) {
-                                       fprintf(stderr, Name ": %s not identified in config file.\n",
-                                               devlist->devname);
+                       } else {
+                               mdfd = open_mddev(devlist->devname, array_ident->autof);
+                               if (mdfd < 0)
                                        rv |= 1;
-                               }
-                               else 
+                               else {
                                        rv |= Assemble(devlist->devname, mdfd, array_ident, configfile,
                                                       NULL,
                                                       readonly, runstop, update, verbose, force);
+                                       close(mdfd);
+                               }
                        }
                } else if (!scan)
                        rv = Assemble(devlist->devname, mdfd, &ident, configfile,
@@ -845,20 +713,21 @@ int main(int argc, char *argv[])
                        }
                        for (dv = devlist ; dv ; dv=dv->next) {
                                mddev_ident_t array_ident = conf_get_ident(configfile, dv->devname);
-                               mdfd = open_mddev(dv->devname, array_ident->autof);
-                               if (mdfd < 0) {
-                                       rv |= 1;
-                                       continue;
-                               }
                                if (array_ident == NULL) {
                                        fprintf(stderr, Name ": %s not identified in config file.\n",
                                                dv->devname);
                                        rv |= 1;
                                        continue;
                                }
+                               mdfd = open_mddev(dv->devname, array_ident->autof);
+                               if (mdfd < 0) {
+                                       rv |= 1;
+                                       continue;
+                               }
                                rv |= Assemble(dv->devname, mdfd, array_ident, configfile,
                                               NULL,
                                               readonly, runstop, update, verbose, force);
+                               close(mdfd);
                        }
                } else {
                        mddev_ident_t array_list =  conf_get_ident(configfile, NULL);
@@ -884,7 +753,7 @@ int main(int argc, char *argv[])
                }
                break;
        case BUILD:
-               rv = Build(devlist->devname, mdfd, chunk, level, raiddisks, devlist->next, assume_clean);
+               rv = Build(devlist->devname, mdfd, chunk, level, layout, raiddisks, devlist->next, assume_clean);
                break;
        case CREATE:
                rv = Create(devlist->devname, mdfd, chunk, level, layout, size<0 ? 0 : size,
@@ -963,8 +832,13 @@ int main(int argc, char *argv[])
                        rv = 1;
                        break;
                }
+               if (pidfile && !daemonise) {
+                       fprintf(stderr, Name ": Cannot write a pid file when not in daemon mode\n");
+                       rv = 1;
+                       break;
+               }
                rv= Monitor(devlist, mailaddr, program,
-                           delay?delay:60, daemonise, scan, oneshot, configfile, test);
+                           delay?delay:60, daemonise, scan, oneshot, configfile, test, pidfile);
                break;
 
        case GROW:
@@ -981,12 +855,16 @@ int main(int argc, char *argv[])
                                if (rv)
                                        break;
                        }
-               } else if (size >= 0 && raiddisks) {
-                       fprintf(stderr, Name ": can only grow size OR raiddisks, not both\n");
+               } else if ((size >= 0) + (raiddisks != 0) +  (layout != UnSet) > 1) {
+                       fprintf(stderr, Name ": can change at most one of size, raiddisks, and layout\n");
                        rv = 1;
                        break;
-               } else 
+               } else if (layout != UnSet)
+                       rv = Manage_reconfig(devlist->devname, mdfd, layout);
+               else if (size >= 0 || raiddisks)
                        rv = Manage_resize(devlist->devname, mdfd, size, raiddisks);
+               else 
+                       fprintf(stderr, Name ": no changes to --grow\n");
                break;
        }
        exit(rv);
diff --git a/mdadm.h b/mdadm.h
index 831e26716fa3d67f9076528f21b9003750d489ee..a816846ccba68271ba07f0c16accea5b1b31be60 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -150,7 +150,7 @@ extern void mdstat_wait(int seconds);
 
 extern char *map_num(mapping_t *map, int num);
 extern int map_name(mapping_t *map, char *name);
-extern mapping_t r5layout[], pers[], modes[];
+extern mapping_t r5layout[], pers[], modes[], faultylayout[];
 
 extern char *map_dev(int major, int minor);
 
@@ -158,6 +158,7 @@ extern char *map_dev(int major, int minor);
 extern int Manage_ro(char *devname, int fd, int readonly);
 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_reconfig(char *devname, int fd, int layout);
 extern int Manage_subdevs(char *devname, int fd,
                          mddev_dev_t devlist);
 extern int Grow_Add_device(char *devname, int fd, char *newdev);
@@ -171,7 +172,7 @@ extern int Assemble(char *mddev, int mdfd,
                    char *update,
                    int verbose, int force);
 
-extern int Build(char *mddev, int mdfd, int chunk, int level,
+extern int Build(char *mddev, int mdfd, int chunk, int level, int layout,
                 int raiddisks,
                 mddev_dev_t devlist, int assume_clean);
 
@@ -187,7 +188,7 @@ extern int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust);
 extern int Monitor(mddev_dev_t devlist,
                   char *mailaddr, char *alert_cmd,
                   int period, int daemonise, int scan, int oneshot,
-                  char *config, int test);
+                  char *config, int test, char *pidfile);
 
 extern int Kill(char *dev, int force);
 
@@ -227,3 +228,30 @@ extern void put_md_name(char *name);
 extern char *get_md_name(int dev);
 
 extern char DefaultConfFile[];
+
+extern int open_mddev(char *dev, int autof);
+
+
+#define        LEVEL_MULTIPATH         (-4)
+#define        LEVEL_LINEAR            (-1)
+#define        LEVEL_FAULTY            (-5)
+
+
+/* faulty stuff */
+
+#define        WriteTransient  0
+#define        ReadTransient   1
+#define        WritePersistent 2
+#define        ReadPersistent  3
+#define        WriteAll        4 /* doesn't go to device */
+#define        ReadFixable     5
+#define        Modes   6
+
+#define        ClearErrors     31
+#define        ClearFaults     30
+
+#define AllPersist     100 /* internal use only */
+#define        NoPersist       101
+
+#define        ModeMask        0x1f
+#define        ModeShift       5
index f55d9339bb8dc12542cbcbfa244d0448b16f1647..621ca6ac408894cb5fea864de764d1882bec63a9 100644 (file)
@@ -1,6 +1,6 @@
 Summary:     mdadm is used for controlling Linux md devices (aka RAID arrays)
 Name:        mdadm
-Version:     1.7.0
+Version:     1.8.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/
index 55055dd18386d97797ee6dd14239c06ef656a064..43aed3c8377e1a2695d7be483f28157b93447601 100644 (file)
@@ -46,11 +46,16 @@ mapping_t pers[] = {
        { "5", 5},
        { "multipath", -4},
        { "mp", -4},
+       { "raid6", 6},
+       { "6", 6},
+       { "raid10", 10},
+       { "10", 10},
        { NULL, 0}
 };
 
+#ifndef MDASSEMBLE_AUTO
 /* from mdadm.c */
-int open_mddev(char *dev)
+int open_mddev(char *dev, int autof/*unused */)
 {
        int mdfd = open(dev, O_RDWR, 0);
        if (mdfd < 0)
@@ -64,6 +69,7 @@ int open_mddev(char *dev)
        }
        return mdfd;
 }
+#endif
 
 char *configfile = NULL;
 int rv;
@@ -81,7 +87,7 @@ int main() {
        } else
                for (; array_list; array_list = array_list->next) {
                        mdu_array_info_t array;
-                       mdfd = open_mddev(array_list->devname);
+                       mdfd = open_mddev(array_list->devname, array_list->autof);
                        if (mdfd < 0) {
                                rv |= 1;
                                continue;
diff --git a/mdopen.c b/mdopen.c
new file mode 100644 (file)
index 0000000..69c4a23
--- /dev/null
+++ b/mdopen.c
@@ -0,0 +1,193 @@
+/*
+ * mdadm - manage Linux "md" devices aka RAID arrays.
+ *
+ * Copyright (C) 2001-2002 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 "md_p.h"
+#include <ctype.h>
+
+void make_parts(char *dev, int cnt)
+{
+       /* make 'cnt' partition devices for 'dev'
+        * We use the major/minor from dev and add 1..cnt
+        * If dev ends with a digit, we add "_p%d" else "%d"
+        * If the name exists, we use it's owner/mode,
+        * else that of dev
+        */
+       struct stat stb;
+       int major, minor;
+       int i;
+       char *name = malloc(strlen(dev) + 20);
+       int dig = isdigit(dev[strlen(dev)-1]);
+
+       if (stat(dev, &stb)!= 0)
+               return;
+       if (!S_ISBLK(stb.st_mode))
+               return;
+       major = MAJOR(stb.st_rdev);
+       minor = MINOR(stb.st_rdev);
+       for (i=1; i <= cnt ; i++) {
+               struct stat stb2;
+               sprintf(name, "%s%s%d", dev, dig?"_p":"", i);
+               if (stat(name, &stb2)==0) {
+                       if (!S_ISBLK(stb2.st_mode))
+                               continue;
+                       if (stb2.st_rdev == MKDEV(major, minor+i))
+                               continue;
+                       unlink(name);
+               } else {
+                       stb2 = stb;
+               }
+               mknod(name, S_IFBLK | 0600, MKDEV(major, minor+i));
+               chown(name, stb2.st_uid, stb2.st_gid);
+               chmod(name, stb2.st_mode & 07777);
+       }
+}
+
+/*
+ * Open a given md device, and check that it really is one.
+ * If 'autof' is given, then we need to create, or recreate, the md device.
+ * If the name already exists, and is not a block device, we fail.
+ * If it exists and is not an md device, is not the right type (partitioned or not),
+ * or is currently in-use, we remove the device, but remember the owner and mode.
+ * If it now doesn't exist, we find a few md array and create the device.
+ * Default ownership is user=0, group=0 perm=0600
+ */
+int open_mddev(char *dev, int autof)
+{
+       int mdfd;
+       struct stat stb;
+       int major = MD_MAJOR;
+       int minor;
+       int must_remove = 0;
+       struct mdstat_ent *mdlist;
+       int num;
+
+       if (autof) {
+               /* autof is set, so we need to check that the name is ok,
+                * and possibly create one if not
+                */
+               stb.st_mode = 0;
+               if (lstat(dev, &stb)==0 && ! S_ISBLK(stb.st_mode)) {
+                       fprintf(stderr, Name ": %s is not a block device.\n",
+                               dev);
+                       return -1;
+               }
+               /* check major number is correct */
+               if (autof>0)
+                       major = get_mdp_major();
+               if (stb.st_mode && MAJOR(stb.st_rdev) != major)
+                       must_remove = 1;
+               if (stb.st_mode && !must_remove) {
+                       mdu_array_info_t array;
+                       /* looks ok, see if it is available */
+                       mdfd = open(dev, O_RDWR, 0);
+                       if (mdfd < 0) {
+                               fprintf(stderr, Name ": error opening %s: %s\n",
+                                       dev, strerror(errno));
+                               return -1;
+                       } else if (md_get_version(mdfd) <= 0) {
+                               fprintf(stderr, Name ": %s does not appear to be an md device\n",
+                                       dev);
+                               close(mdfd);
+                               return -1;
+                       }
+                       if (ioctl(mdfd, GET_ARRAY_INFO, &array)==0) {
+                               /* already active */
+                               must_remove = 1;
+                               close(mdfd);
+                       } else {
+                               if (autof > 0)
+                                       make_parts(dev, autof);
+                               return mdfd;
+                       }
+               }
+               /* Ok, need to find a minor that is not in use.
+                * Easiest to read /proc/mdstat, and hunt through for
+                * an unused number 
+                */
+               mdlist = mdstat_read(0);
+               for (num= (autof>0)?-1:0 ; ; num+= (autof>2)?-1:1) {
+                       struct mdstat_ent *me;
+                       for (me=mdlist; me; me=me->next)
+                               if (me->devnum == num)
+                                       break;
+                       if (!me) {
+                               /* doesn't exist if mdstat.
+                                * make sure it is new to /dev too
+                                */
+                               char *dn;
+                               if (autof > 0) 
+                                       minor = (-1-num) << MdpMinorShift;
+                               else
+                                       minor = num;
+                               dn = map_dev(major,minor);
+                               if (dn==NULL || is_standard(dn)) {
+                                       /* this number only used by a 'standard' name,
+                                        * so it is safe to use
+                                        */
+                                       break;
+                               }
+                       }
+               }
+               /* 'num' is the number to use, >=0 for md, <0 for mdp */
+               if (must_remove) {
+                       /* never remove a device name that ends /mdNN or /dNN,
+                        * that would be confusing 
+                        */
+                       if (is_standard(dev)) {
+                               fprintf(stderr, Name ": --auto refusing to remove %s as it looks like a standard name.\n",
+                                       dev);
+                               return -1;
+                       }
+                       unlink(dev);
+               }
+
+               if (mknod(dev, S_IFBLK|0600, MKDEV(major, minor))!= 0) {
+                       fprintf(stderr, Name ": failed to create %s\n", dev);
+                       return -1;
+               }
+               if (must_remove) {
+                       chown(dev, stb.st_uid, stb.st_gid);
+                       chmod(dev, stb.st_mode & 07777);
+               }
+               make_parts(dev,autof);
+       }
+       mdfd = open(dev, O_RDWR, 0);
+       if (mdfd < 0)
+               fprintf(stderr, Name ": error opening %s: %s\n",
+                       dev, strerror(errno));
+       else if (md_get_version(mdfd) <= 0) {
+               fprintf(stderr, Name ": %s does not appear to be an md device\n",
+                       dev);
+               close(mdfd);
+               mdfd = -1;
+       }
+       return mdfd;
+}
+
diff --git a/misc/syslog-events b/misc/syslog-events
new file mode 100644 (file)
index 0000000..fe8c14e
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# sample event handling script for mdadm
+# e.g. mdadm --follow --program=/sbin/syslog-events --scan
+#
+# License: GPL ver.2
+# Copyright (C) 2004 SEKINE Tatsuo <tsekine@sdri.co.jp>
+
+event="$1"
+dev="$2"
+disc="$3"
+
+facility="kern"
+tag="mdmonitor"
+
+case x"${event}" in
+    xFail*) priority="error" ;;
+    xTest*) priority="debug" ;;
+    x*)     priority="info"  ;;
+esac
+
+msg="${event} event on ${dev}"
+if [ x"${disc}" != x ]; then
+     msg="${msg}, related to disc ${disc}"
+fi
+
+exec logger -t "${tag}" -p "${facility}.${priority}" -- "${msg}"
diff --git a/util.c b/util.c
index 5ef59c088d8091c3da3451abb874ab7be80cefa7..121ddbb731a28db5a4d890beaab2bf4031a22d01 100644 (file)
--- a/util.c
+++ b/util.c
@@ -212,15 +212,23 @@ int load_super(int fd, mdp_super_t *super)
         *   6 - wrong major version
         */
        unsigned long size;
+       unsigned long long dsize;
        unsigned long long offset;
     
-       if (ioctl(fd, BLKGETSIZE, &size))
-               return 1;
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+       {
+               if (ioctl(fd, BLKGETSIZE, &size))
+                       return 1;
+               else
+                       dsize = size << 9;
+       }
 
-       if (size < MD_RESERVED_SECTORS*2)
+       if (dsize < MD_RESERVED_SECTORS*2)
                return 2;
        
-       offset = MD_NEW_SIZE_SECTORS(size);
+       offset = MD_NEW_SIZE_SECTORS(dsize>>9);
 
        offset *= 512;
 
@@ -242,16 +250,25 @@ int load_super(int fd, mdp_super_t *super)
 
 int store_super(int fd, mdp_super_t *super)
 {
-       long size;
+       unsigned long size;
+       unsigned long long dsize;
+       
        long long offset;
     
-       if (ioctl(fd, BLKGETSIZE, &size))
-               return 1;
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+       {
+               if (ioctl(fd, BLKGETSIZE, &size))
+                       return 1;
+               else
+                       dsize = ((unsigned long long)size) << 9;
+       }
 
-       if (size < MD_RESERVED_SECTORS*2)
+       if (dsize < MD_RESERVED_SECTORS*2)
                return 2;
        
-       offset = MD_NEW_SIZE_SECTORS(size);
+       offset = MD_NEW_SIZE_SECTORS(dsize>>9);
 
        offset *= 512;