]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdadm-1.0.9 mdadm-1.0.9
authorNeil Brown <neilb@suse.de>
Wed, 12 Feb 2003 00:17:26 +0000 (00:17 +0000)
committerNeil Brown <neilb@suse.de>
Wed, 12 Feb 2003 00:17:26 +0000 (00:17 +0000)
21 files changed:
Assemble.c
ChangeLog
Detail.c
Examine.c
Makefile
Monitor.c
ReadMe.c
TODO
config.c
makedist
md.4
md_p.h
mdadm.8
mdadm.c
mdadm.conf-example
mdadm.conf.5
mdadm.h
mdadm.spec
mdadm.static [new file with mode: 0755]
test [new file with mode: 0644]
util.c

index 786880221a1d24ffe2589c035b132923b8407cd1..a2ff502390089664ca4a242ddf1b4676879652a1 100644 (file)
@@ -35,6 +35,7 @@ int Assemble(char *mddev, int mdfd,
             mddev_ident_t ident, char *conffile,
             mddev_dev_t devlist,
             int readonly, int runstop,
+            char *update,
             int verbose, int force)
 {
        /*
@@ -72,7 +73,7 @@ int Assemble(char *mddev, int mdfd,
         * For each device:
         *   Check superblock - discard if bad
         *   Check uuid (set if we don't have one) - discard if no match
-        *   Check superblock similarity if we have a superbloc - discard if different
+        *   Check superblock similarity if we have a superblock - discard if different
         *   Record events, devicenum, utime
         * This should give us a list of devices for the array
         * We should collect the most recent event and utime numbers
@@ -103,8 +104,8 @@ int Assemble(char *mddev, int mdfd,
                time_t utime;
                int uptodate;
                int raid_disk;
-       } devices[MD_SB_DISKS];
-       int best[MD_SB_DISKS]; /* indexed by raid_disk */
+       } *devices;
+       int *best; /* indexed by raid_disk */
        int devcnt = 0, okcnt, sparecnt;
        int i;
        int most_recent = 0;
@@ -112,6 +113,8 @@ int Assemble(char *mddev, int mdfd,
        int change = 0;
        int inargv = 0;
        int start_partial_ok = force || devlist==NULL;
+       int num_devs;
+       mddev_dev_t tmpdev;
        
        vers = md_get_version(mdfd);
        if (vers <= 0) {
@@ -153,8 +156,16 @@ int Assemble(char *mddev, int mdfd,
                devlist = conf_get_devs(conffile);
        else inargv = 1;
 
+       tmpdev = devlist; num_devs = 0;
+       while (tmpdev) {
+               num_devs++;
+               tmpdev = tmpdev->next;
+       }
+       best = malloc(num_devs * sizeof(*best));
+       devices = malloc(num_devs * sizeof(*devices));
+
        first_super.md_magic = 0;
-       for (i=0; i<MD_SB_DISKS; i++)
+       for (i=0; i<num_devs; i++)
                best[i] = -1;
 
        if (verbose)
@@ -245,11 +256,48 @@ int Assemble(char *mddev, int mdfd,
                        return 1;
                }
 
+
+               /* this is needed until we get a more relaxed super block format */
                if (devcnt >= MD_SB_DISKS) {
                    fprintf(stderr, Name ": ouch - too many devices appear to be in this array. Ignoring %s\n",
                            devname);
                    continue;
                }
+               
+               /* looks like a good enough match to update the super block if needed */
+               if (update) {
+                       if (strcmp(update, "sparc2.2")==0 ) {
+                               /* 2.2 sparc put the events in the wrong place
+                                * So we copy the tail of the superblock
+                                * up 4 bytes before continuing
+                                */
+                               __u32 *sb32 = (__u32*)&super;
+                               memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
+                                      sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
+                                      (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
+                               fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
+                                        devname);
+                       }
+                       if (strcmp(update, "super-minor") ==0) {
+                               struct stat stb2;
+                               fstat(mdfd, &stb2);
+                               super.md_minor = MINOR(stb2.st_rdev);
+                               if (verbose)
+                                       fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
+                                               devname, super.md_minor);
+                       }
+                       super.sb_csum = calc_sb_csum(&super);
+                       dfd = open(devname, O_RDWR, 0);
+                       if (dfd < 0) 
+                               fprintf(stderr, Name ": Cannot open %s for superblock update\n",
+                                       devname);
+                       else if (store_super(dfd, &super))
+                               fprintf(stderr, Name ": Could not re-write superblock on %s.\n",
+                                       devname);
+                       if (dfd >= 0)
+                               close(dfd);
+               }
+
                if (verbose)
                        fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
                                devname, mddev, super.this_disk.raid_disk);
@@ -267,8 +315,12 @@ int Assemble(char *mddev, int mdfd,
                            > devices[most_recent].events)
                                most_recent = devcnt;
                }
-               i = devices[devcnt].raid_disk;
-               if (i>=0 && i < MD_SB_DISKS)
+               if (super.level == -4) 
+                       /* with multipath, the raid_disk from the superblock is meaningless */
+                       i = devcnt;
+               else
+                       i = devices[devcnt].raid_disk;
+               if (i>=0 && i < num_devs)
                        if (best[i] == -1
                            || devices[best[i]].events < devices[devcnt].events)
                                best[i] = devcnt;
@@ -286,7 +338,7 @@ int Assemble(char *mddev, int mdfd,
         */
        okcnt = 0;
        sparecnt=0;
-       for (i=0; i< MD_SB_DISKS;i++) {
+       for (i=0; i< num_devs ;i++) {
                int j = best[i];
                int event_margin = !force;
                if (j < 0) continue;
@@ -337,6 +389,10 @@ int Assemble(char *mddev, int mdfd,
                }
                super.events_hi = (devices[most_recent].events>>32)&0xFFFFFFFF;
                super.events_lo = (devices[most_recent].events)&0xFFFFFFFF;
+               if (super.level == 5 || super.level == 4) {
+                       /* need to force clean */
+                       super.state = 0;
+               }
                super.sb_csum = calc_sb_csum(&super);
 /*DRYRUN*/     if (store_super(fd, &super)) {
                        close(fd);
@@ -358,7 +414,7 @@ int Assemble(char *mddev, int mdfd,
         * superblock.
         */
        chosen_drive = -1;
-       for (i=0; chosen_drive < 0 && i<MD_SB_DISKS; i++) {
+       for (i=0; chosen_drive < 0 && i<num_devs; i++) {
                int j = best[i];
                int fd;
                if (j<0)
@@ -380,7 +436,7 @@ int Assemble(char *mddev, int mdfd,
                close(fd);
        }
 
-       for (i=0; i<MD_SB_DISKS; i++) {
+       for (i=0; i<num_devs; i++) {
                int j = best[i];
                int desired_state;
 
@@ -457,9 +513,9 @@ This doesnt work yet
                        return 1;
                }
                /* First, add the raid disks, but add the chosen one last */
-               for (i=0; i<=MD_SB_DISKS; i++) {
+               for (i=0; i<= num_devs; i++) {
                        int j;
-                       if (i < MD_SB_DISKS) {
+                       if (i < num_devs) {
                                j = best[i];
                                if (j == chosen_drive)
                                        continue;
index 43adfa24390fbf316a56d71df936045d7c6f44b3..bc0653f78f5131fcbfe0e3cbda4ea99ee2e1a594 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,37 @@
 Changes Prior to this release
+Changes Prior to 1.0.9 release
+    -   Documentation updates including kernel parameters documented
+       in md.4
+    -   --assemble --force for raid4/5 will mark clean, needed for 2.5
+    -   --detail prints out the events counter as well
+    -   flush device before reading superblock to be sure to get
+       current data
+    -   added mdadm.static target to makefile for static linking
+    -  --monitor was ignoring  /dev/md0 due to off-by-one error
+    -  Fix assorted typos
+    -   Fix printing of Gibibytes - calc was wrong.
+    -   Fix printing of Array Size in --detail when very big.
+    -   --monitor no longer tries to work for raid0 or linear as these
+       have nothing to be monitors.
+    -   The word 'partitions' on a DEVICE line will cause all partitions
+       listed in /proc/partitions to be considered
+    -   If the config file is called 'partitions' then it will be treated
+        as though it contained exactly 'device partitions' so e.g.
+         mdadm -Ebsc partitions
+       will fill all raid partitions easily.   
+    -  successfully assemble multipath devices by ignoring raid_disk
+       value from superblock (it is always the same).
+    -   --assemble not tied to MD_SB_DISKS limit quite so much
+    -   Support compiling with tcc
+    -   Support compiling with uclibc - just skip scan of /dev
+    -   Add --update= option for Assemble mode.  Either sparc2.2
+       or super-minor updates are possible.  See mdadm.8
+       
+Changes Prior to 1.0.1 release
     -   Round off MB/GiB etc values instead of round down.
     -   Add --sparc2.2 option to examine to shift superblock around
        and --sparc2.2update to rewrite the superblock
+    -   Fix assorted typos in online help
        
 Changes Prior to 1.0.0 release
     -   Allow --config with Misc mode (for --examine --scan)
index 55e6eb0d3057bab9536bf11c3c507a1f4838efc7..e675eda7cd35cedc6fdd1a41c2dd902d9c26a8cf 100644 (file)
--- a/Detail.c
+++ b/Detail.c
@@ -102,7 +102,7 @@ int Detail(char *dev, int brief)
                printf("  Creation Time : %.24s\n", ctime(&atime));
                printf("     Raid Level : %s\n", c?c:"-unknown-");
                if (larray_size)
-               printf("     Array Size : %ld%s\n", (long)(larray_size>>10), human_size(larray_size));
+               printf("     Array Size : %llu%s\n", (larray_size>>10), human_size(larray_size));
                if (array.level >= 1)
                        printf("    Device Size : %d%s\n", array.size, human_size((long long)array.size<<10));
                printf("   Raid Devices : %d\n", array.raid_disks);
@@ -164,7 +164,7 @@ int Detail(char *dev, int brief)
                }
                if ((dv=map_dev(disk.major, disk.minor))) {
                        if (!brief) printf("   %s", dv);
-                       if (!have_super) {
+                       if (!have_super && (disk.state & (1<<MD_DISK_ACTIVE))) {
                                /* try to read the superblock from this device
                                 * to get more info
                                 */
@@ -186,7 +186,8 @@ int Detail(char *dev, int brief)
                               super.set_uuid2, super.set_uuid3);
                else
                        printf("%08x", super.set_uuid0);
-               if (!brief) printf("\n");
+               if (!brief) 
+                       printf("\n         Events : %d.%d\n", super.events_hi, super.events_lo);
        }
        if (brief) printf("\n");
        return 0;
index b886afc27f75612646b836c42cd3bd155f0cb63c..0270108924355a98ebdc330b814a6e6fffc18a66 100644 (file)
--- a/Examine.c
+++ b/Examine.c
@@ -170,7 +170,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
                                __u32 *sb32 = (__u32*)&super;
                                memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
                                       sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
-                                      MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1));
+                                      (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
                                printf (" --- adjusting superblock for 2.2/sparc compatability ---\n");
                        }
                        printf("         Events : %d.%d\n", super.events_hi, super.events_lo);
index e355e96857936222aa4dc3e5a729e68bdea2d9aa..82efc4cb336c0516ae09d49cf5a2faa0617b381b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -29,6 +29,9 @@
 
 # define "CXFLAGS" to give extra flags to CC.
 # e.g.  make CXFLAGS=-O to optimise
+TCC = tcc
+UCLIBC_GCC = i386-uclibc-gcc
+
 CC = gcc
 CXFLAGS = -ggdb
 SYSCONFDIR = /etc
@@ -48,12 +51,24 @@ MAN5DIR = $(MANDIR)/man5
 MAN8DIR = $(MANDIR)/man8
 
 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
 
 all : mdadm mdadm.man md.man mdadm.conf.man
 
+everything: all mdadm.static mdadm.tcc mdadm.uclibc
+
 mdadm : $(OBJS)
        $(CC) $(LDFLAGS) -o mdadm $^
 
+mdadm.static : $(OBJS)
+       $(CC) $(LDFLAGS) --static -o mdadm.static $^
+
+mdadm.tcc : $(SRCS) mdadm.h
+       $(TCC) -o mdadm.tcc $(SRCS)
+
+mdadm.uclibc : $(SRCS) mdadm.h
+       $(UCLIBC_GCC) -DUCLIBC -o mdadm.uclibc $(SRCS)
+
 mdadm.man : mdadm.8
        nroff -man mdadm.8 > mdadm.man
 
@@ -72,7 +87,7 @@ 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
+       rm -f mdadm $(OBJS) core *.man mdadm.tcc mdadm.uclibc
 
 dist : clean
        ./makedist
index fa0d7088df03425535eb7323c13af1ae21e0e7f2..d994dbe95445d0e694a1196ae35e49b136b4a2e8 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -182,6 +182,14 @@ int Monitor(mddev_dev_t devlist,
                                close(fd);
                                continue;
                        }
+                       if (array.level != 1 && array.level != 5 && array.level != -4) {
+                               if (!st->err)
+                                       alert("DeviceDisappeared", dev, "Wrong-Level",
+                                             mailaddr, alert_cmd);
+                               st->err = 1;
+                               close(fd);
+                               continue;
+                       }
                        if (st->devnum < 0) {
                                struct stat stb;
                                if (fstat(fd, &stb) == 0 &&
@@ -229,7 +237,7 @@ int Monitor(mddev_dev_t devlist,
                                if (ioctl(fd, GET_DISK_INFO, &disc)>= 0) {
                                        newstate = disc.state;
                                        dv = map_dev(disc.major, disc.minor);
-                               } else if (mse && i < strlen(mse->pattern))
+                               } else if (mse &&  mse->pattern && i < strlen(mse->pattern))
                                        switch(mse->pattern[i]) {
                                        case 'U': newstate = 6 /* ACTIVE/SYNC */; break;
                                        case '_': newstate = 0; break;
@@ -271,7 +279,11 @@ int Monitor(mddev_dev_t devlist,
                if (scan) {
                        struct mdstat_ent *mse;
                        for (mse=mdstat; mse; mse=mse->next) 
-                               if (mse->devnum > 0) {
+                               if (mse->devnum >= 0 &&
+                                   (strcmp(mse->level, "raid1")==0 ||
+                                    strcmp(mse->level, "raid5")==0 ||
+                                    strcmp(mse->level, "multipath")==0)
+                                       ) {
                                        struct state *st = malloc(sizeof *st);
                                        if (st == NULL)
                                                continue;
index 5c67eebaf950bc3de87d1296c12904c2a8cc2193..390fee43045731a07a986e88769bb5003b088ae1 100644 (file)
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -29,7 +29,7 @@
 
 #include "mdadm.h"
 
-char Version[] = Name " - v1.0.1 - 20 May 2002\n";
+char Version[] = Name " - v1.0.9 - 12 Feb 2003\n";
 /*
  * File: ReadMe.c
  *
@@ -60,14 +60,14 @@ char Version[] = Name " - v1.0.1 - 20 May 2002\n";
 /*
  * mdadm has 6 major modes of operation:
  * 1/ Create
- *     This mode is used to create a new array with a superbock
+ *     This mode is used to create a new array with a superblock
  *     It can progress in several step create-add-add-run
  *     or it can all happen with one command
  * 2/ Assemble
  *     This mode is used to assemble the parts of a previously created
  *     array into an active array.  Components can be explicitly given
  *     or can be searched for.  mdadm (optionally) check that the components
- *     do form a bonafide array, and can, on request, fiddle superblock
+ *     do form a bona-fide array, and can, on request, fiddle superblock
  *     version numbers so as to assemble a faulty array.
  * 3/ Build
  *     This is for building legacy arrays without superblocks
@@ -86,7 +86,7 @@ char Version[] = Name " - v1.0.1 - 20 May 2002\n";
  *     This mode never exits but just monitors arrays and reports changes.
  */
 
-char short_options[]="-ABCDEFGQhVvbc:l:p:m:n:x:u:c:d:z:sarfRSow";
+char short_options[]="-ABCDEFGQhVvbc:l:p:m:n:x:u:c:d:z:U:sarfRSow";
 struct option long_options[] = {
     {"manage",    0, 0, '@'},
     {"misc",      0, 0, '#'},
@@ -112,7 +112,7 @@ struct option long_options[] = {
     {"chunk",    1, 0, 'c'},
     {"rounding",  1, 0, 'c'}, /* for linear, chunk is really a rounding number */
     {"level",     1, 0, 'l'}, /* 0,1,4,5,linear */
-    {"parity",    1, 0, 'p'}, /* {left,right}-{a,}symetric */
+    {"parity",    1, 0, 'p'}, /* {left,right}-{a,}symmetric */
     {"layout",    1, 0, 'p'},
     {"raid-disks",1, 0, 'n'},
     {"raid-devices",1, 0, 'n'},
@@ -126,6 +126,7 @@ struct option long_options[] = {
     {"config",    1, 0, 'c'},
     {"scan",      0, 0, 's'},
     {"force",    0, 0, 'f'},
+    {"update",   1, 0, 'U'},
     /* Management */
     {"add",       0, 0, 'a'},
     {"remove",    0, 0, 'r'},
@@ -139,7 +140,6 @@ struct option long_options[] = {
     /* For Detail/Examine */
     {"brief",    0, 0, 'b'},
     {"sparc2.2",  0, 0, 22},
-    {"sparc2.2update", 0, 0, 23},
 
     /* For Follow/monitor */
     {"mail",      1, 0, 'm'},
@@ -164,7 +164,7 @@ char Help[] =
 "       mdadm --misc options... devices\n"
 "       mdadm --monitor options...\n"
 "       mdadm device options...\n"
-" mdadm is used for building, manageing, and monitoring\n"
+" mdadm is used for building, managing, and monitoring\n"
 "      Linux md devices (aka RAID arrays)\n"
 " For detail help on the above major modes use --help after the mode\n"
 " e.g.\n"
@@ -186,7 +186,7 @@ char Help[] =
 "  --build       -B   : Build a legacy array\n"
 "  --create      -C   : Create a new array\n"
 "  --detail      -D   : Display details of an array\n"
-"  --examine     -E   : Examine superblock on an array componenet\n"
+"  --examine     -E   : Examine superblock on an array component\n"
 "  --monitor     -F   : monitor (follow) some arrays\n"
 "  --query       -Q   : Display general information about how a\n"
 "                       device relates to the md driver\n"
@@ -195,9 +195,9 @@ char Help[] =
 "\n"
 " For create or build:\n"
 "  --chunk=      -c   : chunk size of kibibytes\n"
-"  --rounding=        : rounding factor for linear array (==chunck size)\n"
+"  --rounding=        : rounding factor for linear array (==chunk size)\n"
 "  --level=      -l   : raid level: 0,1,4,5,linear,mp.  0 or linear for build\n"
-"  --paritiy=    -p   : raid5 parity algorith: {left,right}-{,a}symmetric\n"
+"  --parity=     -p   : raid5 parity algorithm: {left,right}-{,a}symmetric\n"
 "  --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"
@@ -213,6 +213,7 @@ char Help[] =
 "  --config=     -c   : config file\n"
 "  --scan        -s   : scan config file for missing information\n"
 "  --force       -f   : Assemble the array even if some superblocks appear out-of-date\n"
+"  --update=     -U   : Update superblock: either sparc2.2 or super-minor\n"
 "\n"
 " For detail or examine:\n"
 "  --brief       -b   : Just print device name and UUID\n"
@@ -229,7 +230,7 @@ char Help[] =
 "  --fail        -f   : mark subsequent devices a faulty\n"
 "  --set-faulty       : same as --fail\n"
 "  --run         -R   : start a partially built array\n"
-"  --stop        -S   : deactive array, releasing all resources\n"
+"  --stop        -S   : deactivate array, releasing all resources\n"
 "  --readonly    -o   : mark array as readonly\n"
 "  --readwrite   -w   : mark array as readwrite\n"
 "  --zero-superblock  : erase the MD superblock from a device.\n"
@@ -259,9 +260,9 @@ char Help_create[] =
 "\n"
 " Options that are valid with --create (-C) are:\n"
 "  --chunk=      -c   : chunk size of kibibytes\n"
-"  --rounding=        : rounding factor for linear array (==chunck size)\n"
+"  --rounding=        : rounding factor for linear array (==chunk size)\n"
 "  --level=      -l   : raid level: 0,1,4,5,linear,multipath and synonyms\n"
-"  --paritiy=    -p   : raid5 parity algorith: {left,right}-{,a}symmetric\n"
+"  --parity=    -p   : raid5 parity algorithm: {left,right}-{,a}symmetric\n"
 "  --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"
@@ -287,7 +288,7 @@ char Help_build[] =
 " All devices must be listed and the array will be started once complete.\n"
 " Options that are valid with --build (-B) are:\n"
 "  --chunk=      -c   : chunk size of kibibytes\n"
-"  --rounding=        : rounding factor for linear array (==chunck size)\n"
+"  --rounding=        : rounding factor for linear array (==chunk size)\n"
 "  --level=      -l   : 0, raid0, or linear\n"
 "  --raid-devices= -n   : number of active devices in array\n"
 ;
@@ -335,6 +336,7 @@ char Help_assemble[] =
 "                       for a full array are present\n"
 "  --force       -f   : Assemble the array even if some superblocks appear\n"
 "                     : out-of-date.  This involves modifying the superblocks.\n"
+"  --update=     -U   : Update superblock: either sparc2.2 or super-minor\n"
 ;
 
 char Help_manage[] =
@@ -352,7 +354,7 @@ char Help_manage[] =
 "  --fail        -f   : mark subsequent devices a faulty\n"
 "  --set-faulty       : same as --fail\n"
 "  --run         -R   : start a partially built array\n"
-"  --stop        -S   : deactive array, releasing all resources\n"
+"  --stop        -S   : deactivate array, releasing all resources\n"
 "  --readonly    -o   : mark array as readonly\n"
 "  --readwrite   -w   : mark array as readwrite\n"
 ;
@@ -369,10 +371,10 @@ char Help_misc[] =
 "  --query       -Q   : Display general information about how a\n"
 "                       device relates to the md driver\n"
 "  --detail      -D   : Display details of an array\n"
-"  --examine     -E   : Examine superblock on an array componenet\n"
+"  --examine     -E   : Examine superblock on an array component\n"
 "  --zero-superblock  : erase the MD superblock from a device.\n"
 "  --run         -R   : start a partially built array\n"
-"  --stop        -S   : deactive array, releasing all resources\n"
+"  --stop        -S   : deactivate array, releasing all resources\n"
 "  --readonly    -o   : mark array as readonly\n"
 "  --readwrite   -w   : mark array as readwrite\n"
 ;
@@ -422,7 +424,7 @@ char Help_config[] =
 " array.  The identity can be given as a UUID with a word starting 'uuid=', or\n"
 " as a minor-number stored in the superblock using 'super-minor=', or as a list\n"
 " of devices.  This is given as a comma separated list of names, possibly\n"
-" containing wildcards, preceeded by 'devices='. If multiple critea are given,\n"
+" containing wildcards, preceded by 'devices='. If multiple critea are given,\n"
 " than a device must match all of them to be considered.\n"
 "\n"
 " A mailaddr line starts with the word 'mailaddr' and should contain exactly\n"
diff --git a/TODO b/TODO
index 8c484abf5979458549a5b7335df49a4bb461fcbb..3cafb8c9a9608bdcbf9073d6269b83c7638db774 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,22 @@
+* --assemble could have a --update option.
+  following word can be:
+       sparc2.2
+       super-minor
+
+* mdadm /dev/md11, where md11 is raid0 can segfault, particularly when looking in the 
+   [UU_UUU] string ... which doesn't exist !
+It should be more sensible.  DONE
+
+Example:
+
+from  Raimund Sacherer <raimund.sacherer@ngit.at>
+
+mke2fs -m0 -q /dev/ram1 300
+mount -n -t ext2 /dev/ram1 /tmp
+echo DEVICE /dev/[sh]* >> /tmp/mdadm.conf
+mdadm -Esb /dev/[sh]* 2>/dev/null >> /tmp/mdadm.conf
+mdadm -ARsc /tmp/mdadm.conf
+umount /tmp
 
 
 ?? Allow -S /dev/md? - current complains subsequent not a/d/r - DONE
index eef32480076efb93247789ddf7efdca53bf30ed1..1f2524496fd7e6a8b039f75bbbb29d6d47bbbada 100644 (file)
--- a/config.c
+++ b/config.c
@@ -201,6 +201,33 @@ struct conf_dev {
     char *name;
 } *cdevlist = NULL;
 
+void load_partitions(void)
+{
+       FILE *f = fopen("/proc/partitions", "r");
+       char buf[1024];
+       if (f == NULL) {
+               fprintf(stderr, Name ": cannot open /proc/partitions\n");
+               return;
+       }
+       while (fgets(buf, 1024, f)) {
+               int major, minor;
+               char *name;
+               buf[1023] = '\0';
+               if (buf[0] != ' ')
+                       continue;
+               if (sscanf(buf, " %d %d ", &major, &minor) != 2)
+                       continue;
+               name = map_dev(major, minor);
+               if (name) {
+                       struct conf_dev *cd;
+
+                       cd = malloc(sizeof(*cd));
+                       cd->name = strdup(name);
+                       cd->next = cdevlist;
+                       cdevlist = cd;
+               }
+       }
+}
 
 
 void devline(char *line) 
@@ -214,6 +241,9 @@ void devline(char *line)
                        cd->name = strdup(w);
                        cd->next = cdevlist;
                        cdevlist = cd;
+               } else if (strcasecmp(w, "partitions") == 0) {
+                       /* read /proc/partitions, and look major/minor up in /dev */
+                       load_partitions();
                } else {
                        fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n",
                                w);
@@ -349,6 +379,10 @@ void load_conffile(char *conffile)
        if (conffile == NULL)
                conffile = DefaultConfFile;
 
+       if (strcmp(conffile, "partitions")==0) {
+               load_partitions();
+               return;
+       }
        f = fopen(conffile, "r");
        if (f ==NULL)
                return;
index 89567daa905ef617c4ac0ac4e6880f2dd641e552..7ead17afc097691e82d1bc38037012d776ddca64 100755 (executable)
--- a/makedist
+++ b/makedist
@@ -21,7 +21,7 @@ then
   exit 1
 fi
 trap "rm $target/$base; exit" 1 2 3
-( cd .. ; ln -s mdadm mdadm-$version ; tar czhvf - --exclude='*,v' --exclude='*.o' --exclude mdadm --exclude=RCS mdadm-$version ; rm mdadm-$version )  > $target/$base
+( cd .. ; ln -s mdadm mdadm-$version ; tar chvf - --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
 
diff --git a/md.4 b/md.4
index d3010c21fefcb941b5be0043edfd2a90457acddc..1ac98a3c14b274e91ed6c9d7c80355a9a0f47d1f 100644 (file)
--- a/md.4
+++ b/md.4
@@ -99,7 +99,7 @@ still have remaining space.
 .SS RAID1
 
 A RAID1 array is also known as a mirrored set (though mirrors tend to
-provide reflect images, which RAID1 does not) or a plex.
+provide reflected images, which RAID1 does not) or a plex.
 
 Once initialised, each device in a RAID1 array contains exactly the
 same data.  Changes are written to all devices in parallel.  Data is
@@ -171,13 +171,16 @@ correct any possibly inconsistency.  For RAID1, this involves copying
 the contents of the first drive onto all other drives.
 For RAID4 or RAID5 this involves recalculating the parity for each
 stripe and making sure that the parity block has the correct data.
+This process, known as "resynchronising" or "resync" is performed in
+the background.  The array can still be used, though possibly with
+reduced performance.
 
 If a RAID4 or RAID5 array is degraded (missing one drive) when it is
 restarted after an unclean shutdown, it cannot recalculate parity, and
 so it is possible that data might be undetectably corrupted.
-The md driver currently
+The 2.4 md driver 
 .B does not
-alert the operator to this condition.  It should probably fail to
+alert the operator to this condition.  The 2.5 md driver will fail to
 start an array in this condition without manual intervention.
 
 .SS RECOVERY
@@ -201,6 +204,39 @@ and
 .B speed_limit_max
 control files mentioned below.
 
+.SS KERNEL PARAMETERS
+
+The md driver recognised three different kernel parameters.
+.TP
+.B raid=noautodetect
+This will disable the normal detection of md arrays that happens at
+boot time.  If a drive is partitioned with MS-DOS style partitions,
+then if any of the 4 main partitions has a partition type of 0xFD,
+then that partition will normally be inspected to see if it is part of
+an MD array, and if any full arrays are found, they are started.  This
+kernel paramenter disables this behaviour.
+
+.TP
+.BI md= n , dev , dev ,...
+This tells the md driver to assemble
+.B /dev/md n
+from the listed devices.  It is only necessary to start the device
+holding the root filesystem this way.  Other arrays are best started
+once the system is booted.
+
+.TP
+.BI md= n , l , c , i , dev...
+This tells the md driver to assemble a legacy RAID0 or LINEAR array
+without a superblock.
+.I n
+gives the md device number,
+.I l
+gives the level, 0 for RAID0 or -1 for LINEAR,
+.I c
+gives the chunk size as a base-2 logarithm offset by twelve, so 0
+means 4K, 1 means 8K.
+.I i
+is ignored (legacy support).
 
 .SH FILES
 .TP
diff --git a/md_p.h b/md_p.h
index 99479b43b19832c33c154ddc36408e0dbc98ce3a..bd9ccb169171873b8b74a2333ce85297fdc95ee0 100644 (file)
--- a/md_p.h
+++ b/md_p.h
@@ -163,6 +163,10 @@ typedef struct mdp_superblock_s {
 
 } mdp_super_t;
 
+#ifdef __TINYC__
+typedef unsigned long long __u64;
+#endif
+
 static inline __u64 md_event(mdp_super_t *sb) {
        __u64 ev = sb->events_hi;
        return (ev<<32)| sb->events_lo;
diff --git a/mdadm.8 b/mdadm.8
index a64ae65651e1e5a8279e041407188a842f737048..c25dd7d3ace9a78909813e5a8f4e2380d3fb7a54 100644 (file)
--- a/mdadm.8
+++ b/mdadm.8
@@ -53,7 +53,7 @@ is a single program and not a collection of programs.
 .IP \(bu 4
 .B mdadm
 can perform (almost) all of its functions without having a
-configuration file.  Also
+configuration file and does not use one by default.  Also
 .B mdadm
 helps with management of the configuration
 file.
@@ -63,6 +63,14 @@ can provide information about your arrays (through Query, Detail, and Examine)
 that
 .B  raidtools
 cannot.
+.P
+.I mdadm
+does not use
+.IR /etc/raidtab ,
+the
+.B raidtools
+configuration file, at all.  It has a different configuration file
+with a different format and an different purpose.
 
 .SH MODES
 mdadm has 6 major modes of operation:
@@ -98,7 +106,11 @@ superblocks, erasing old superblocks and stopping active arrays.
 
 .TP
 .B "Follow or Monitor"
-Monitor one or more md devices and act on any state changes.
+Monitor one or more md devices and act on any state changes.  This is
+only meaningful for raid1, raid5 or multipath arrays as only these have
+interesting state.  raid0 or linear never have missing, spare, or
+failed drives, so there is nothing to monitor.  
+
 
 .SH OPTIONS
 
@@ -165,6 +177,15 @@ the exact meaning of this option in different contexts.
 .BR -c ", " --config=
 Specify the config file.  Default is
 .BR /etc/mdadm.conf .
+If the config file given is
+.B partitions
+then nothing will be read, but
+.I mdadm
+will act as though the config file contained exactly
+.B "DEVICE partitions"
+and will read
+.B /proc/partitions
+to find a list of devices to scan.
 
 .TP
 .BR -s ", " --scan
@@ -217,12 +238,21 @@ same as --parity
 
 .TP
 .BR -n ", " --raid-devices=
-number of active devices in array.
+Specify the number of active devices in the array.  This, plus the
+number of spare devices (see below) must equal the number of
+.I component-devices
+(including
+.B missing 
+devices) that are listed on the command line.
 
 .TP
 .BR -x ", " --spare-devices=
-number of spare (eXtra) devices in initial array.  Spares can be added
-and removed later.
+Specify the number of spare (eXtra) devices in the initial array.
+Spares can also be added
+and removed later.  The number of component devices listed
+on the command line must equal the number of raid devices plus the
+number of spare devices. 
+
 
 .TP
 .BR -z ", " --size=
@@ -262,6 +292,33 @@ With
 .B --run
 an attempt will be made to start it anyway.
 
+.TP
+.BR -U ", " --update=
+Update the superblock on each device while assembling the array.  The
+argument given to this flag can be either
+.B sparc2.2
+or
+.BR super-minor .
+
+The
+.B sparc2.2
+option will  adjust the superblock of an array what was created on a Sparc
+machine running a patched 2.2 Linux kernel.  This kernel got the
+alignment of part of the superblock wrong.  You can use the
+.B "--examine --sparc2.2"
+option to
+.I mdadm
+to see what effect this would have.
+
+The
+.B super-minor
+option will update the
+.B "prefered minor"
+field on each superblock to match the minor number of the array being
+assembled.  This is not need on 2.6 and later kernels as they make
+this adjustment automatically.
+
+
 .SH For Manage mode:
 
 .TP
@@ -282,6 +339,20 @@ mark listed devices as faulty.
 .BR --set-faulty
 same as --fail.
 
+.SH For Examine mode:
+
+.TP
+.B --sparc2.2
+In an array was created on a 2.2 Linux kernel patched with RAID
+support, the superblock will have been created incorrectly, or at
+least incompatibly with 2.4 and later kernels.  Using the
+.B --sparc2.2
+flag with
+.B --examine
+will fix the superblock before displaying it.  If this appears to do
+the right thing, then the array can be successfully assembled using
+.BR "--assemble --update=sparc2.2" .
+
 .SH For Misc mode:
 
 .TP
@@ -329,7 +400,11 @@ again.  The default is 60 seconds.
 .HP 12
 Usage:
 .B mdadm --assemble
-.I device options...
+.I md-device options-and-component-devices...
+.HP 12
+Usage:
+.B mdadm --assemble --scan
+.I  md-devices-and-options...
 .HP 12
 Usage:
 .B mdadm --assemble --scan
@@ -340,22 +415,26 @@ This usage assembles one or more raid arrays from pre-existing components.
 For each array, mdadm needs to know the md device, the identity of the
 array, and a number of component-devices. These can be found in a number of ways.
 
-The md device is either given before 
-.B --scan
-or is found from the config file. In the latter case, multiple md devices
-can be started with a single mdadm command.
+In the first usage example (without the
+.BR --scan )
+the first device given is the md device.
+In the second usage example, all devices listed are treated as md
+devices and assembly is attempted.
+In the third (where no devices are listed) all md devices that are
+listed in the configuration file are assembled.
 
 The identity can be given with the 
 .B --uuid
 option, with the
 .B --super-minor
-option, can be found in in the config file, or will be taken from the
+option, can be found  in the config file, or will be taken from the
 super block on the first component-device listed on the command line.
 
 Devices can be given on the 
 .B --assemble
-command line or from the config file. Only devices which have an md
-superblock which contains the right identity will be considered for any device.
+command line or in the config file. Only devices which have an md
+superblock which contains the right identity will be considered for
+any array.
 
 The config file is only used if explicitly named with 
 .B --config
@@ -470,7 +549,7 @@ This usage will allow individual devices in an array to be failed,
 removed or added.  It is possible to perform multiple operations with
 on command. For example:
 .br
-.B "  mdadm /dev/md0 -f /dev/hda1 -r /dev/hda1 /a /dev/hda1"
+.B "  mdadm /dev/md0 -f /dev/hda1 -r /dev/hda1 -a /dev/hda1"
 .br
 will firstly mark
 .B /dev/hda1
@@ -706,62 +785,83 @@ the original array.
 
 .SH EXAMPLES
 
-To find out if a devices is a raid array or part of one:
+.B "  mdadm --query /dev/name-of-device"
 .br
-.B "  mdadm -Q /dev/name-of-device"
+This will find out if a given device is a raid array, or is part of
+one, and will provide brief information about the device.
 
-To assemble and start all array listed in the standard config file:
+.B "  mdadm --assemble --scan"
 .br
-.B "  mdadm -As"
+This will assemble and start all arrays listed in the standard confile
+file.  This command will typically go in a system startup file.
 
-To shut down all arrays (that are not still in used):
-.br
 .B "  mdadm --stop --scan"
+.br
+This will shut down all array that can be shut down (i.e. are not
+currently in used).  This will typically going in a system shutdown script.
 
-To monitor all arrays if (and only if) an email address or program
-was given in the config file, but poll every 2 minutes:
+.B "  mdadm --follow --scan --delay=120"
 .br
-.B "  mdadm -Fs --delay=120"
+If (and only if) there is an Email address or program given in the
+standard config file, then
+monitor the status of all arrays listed in that file by
+polling them ever 2 minutes.
 
-To create /dev/md0 as a RAID1 array with /dev/hda1 and /dev/hdc1:
+.B "  mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/hd[ac]1"
 .br
-.B "  mdadm -C /dev/md0 -l1 -n2 /dev/hd[ac]1"
+Create /dev/md0 as a RAID1 array consisting of /dev/hda1 and /dev/hdc1.
 
-To create prototype a config file that describes currently
-active arrays that are known to be made from partitions of
-IDE or SCSI drives:
 .br
 .B "  echo 'DEVICE /dev/hd*[0-9] /dev/sd*[0-9]' > mdadm.conf"
 .br
 .B "  mdadm --detail --scan >> mdadm.conf"
 .br
+This will create a prototype config file that describes currently
+active arrays that are known to be made from partitions of IDE or SCSI drives.
 This file should be reviewed before being used as it may
 contain unwanted detail.
 
-To find out what raid arrays could be assembled from existing
-IDE and SCSI whole drives (not partitions):
-.br
 .B "  echo 'DEVICE /dev/hd[a-z] /dev/sd*[a-z]' > mdadm.conf"
 .br
-.B "  mdadm -Es -c mdadm.conf >> mdadm.conf"
+.B "  mdadm --examine --scan --config=mdadm.conf >> mdadm.conf"
+.ber
+This will find what arrays could be assembled from existign IDE and
+SCSI whole drives (not partitions) and store the information is the
+format of a config file.
 This file is very likely to contain unwanted detail, particularly
 the
 .B devices=
-entries.
+entries.  It should be reviewed and edited before being used as an
+actual config file.
 
-To get help about Create mode:
+.B "  mdadm --examine --brief --scan --config=partitions"
 .br
-.B "  mdadm --create --help"
+.B "  mdadm -Ebsc partitions"
+.br
+Create a list of devices by reading
+.BR /proc/partitions ,
+scan these for RAID superblocks, and printout a brief listing of all
+that was found.
 
-To get help about the format of the config file:
+.B "  mdadm -Ac partitions -m 0 /dev/md0"
 .br
-.B "  mdadm --config --help"
+Scan all partitions and devices listed in
+.BR /proc/partitions
+and assemble
+.B /dev/md0
+out of all such devices with a RAID superblock with a minor number of 0.
 
-To get general help:
+.B "  mdadm --create --help"
 .br
-.B "  mdadm --help"
+Providew help about the Create mode.
 
+.B "  mdadm --config --help"
+.br
+Provide help about the format of the config file.
 
+.B "  mdadm --help"
+.br
+Provide general help.
 
 
 .SH FILES
diff --git a/mdadm.c b/mdadm.c
index 95e7005a9c40920ca9132a973f94ec4390a2205d..c43737870937609e0347061727445a039b2fcae1 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -65,6 +65,7 @@ int main(int argc, char *argv[])
        struct mddev_ident_s ident;
        char *configfile = NULL;
        char *cp;
+       char *update = NULL;
        int scan = 0;
        char devmode = 0;
        int runstop = 0;
@@ -369,6 +370,19 @@ int main(int argc, char *argv[])
                        }
                        continue;
 
+               case O(ASSEMBLE,'U'): /* update the superblock */
+                       if (update) {
+                               fprintf(stderr, Name ": Can only update one aspect of superblock, both %s and %s given.\n",
+                                       update, optarg);
+                               exit(2);
+                       }
+                       update = optarg;
+                       if (strcmp(update, "sparc2.2")==0) continue;
+                       if (strcmp(update, "super-minor") == 0)
+                               continue;
+                       fprintf(stderr, Name ": '--update %s' invalid.  Only 'sparc2.2' or 'super-minor' supported\n",update);
+                       exit(2);
+
                case O(ASSEMBLE,'c'): /* config file */
                case O(MISC, 'c'):
                case O(MONITOR,'c'):
@@ -489,13 +503,6 @@ int main(int argc, char *argv[])
                        }
                        SparcAdjust = 1;
                        continue;
-               case O(MISC,23):
-                       if (devmode != 'E') {
-                               fprintf(stderr, Name ": --sparc2.2update only allowed with --examine\n");
-                               exit(2);
-                       }
-                       SparcAdjust = 2;
-                       continue;
                }
                /* We have now processed all the valid options. Anything else is
                 * an error
@@ -548,8 +555,12 @@ int main(int argc, char *argv[])
                if (!scan)
                        rv = Assemble(devlist->devname, mdfd, &ident, configfile,
                                      devlist->next,
-                                     readonly, runstop, verbose, force);
-               else if (devs_found>0)
+                                     readonly, runstop, update, verbose, force);
+               else if (devs_found>0) {
+                       if (update && devs_found > 1) {
+                               fprintf(stderr, Name ": can only update a single array at a time\n");
+                               exit(1);
+                       }
                        for (dv = devlist ; dv ; dv=dv->next) {
                                mddev_ident_t array_ident = conf_get_ident(configfile, dv->devname);
                                mdfd = open_mddev(dv->devname);
@@ -565,9 +576,9 @@ int main(int argc, char *argv[])
                                }
                                rv |= Assemble(dv->devname, mdfd, array_ident, configfile,
                                               NULL,
-                                              readonly, runstop, verbose, force);
+                                              readonly, runstop, update, verbose, force);
                        }
-               else {
+               else {
                        mddev_ident_t array_list =  conf_get_ident(configfile, NULL);
                        if (!array_list) {
                                fprintf(stderr, Name ": No arrays found in config file\n");
@@ -586,7 +597,7 @@ int main(int argc, char *argv[])
                                        rv |= Assemble(array_list->devname, mdfd,
                                                       array_list, configfile,
                                                       NULL,
-                                                      readonly, runstop, verbose, force);
+                                                      readonly, runstop, NULL, verbose, force);
                                }
                }
                break;
index 65c97b707073574219a9993b1b5320a4c093d55a..09c7989316d5dd22df230ccff942d4fde7d43bab 100644 (file)
 # Arrays can currently be identified by using a UUID, superblock minor number,
 # or a listing of devices.
 #
-#      super-minor is usally the minor number of the metadevice
+#      super-minor is usually the minor number of the metadevice
 #      UUID is the Universally Unique Identifier for the array
 # Each can be obtained using
 #
 #      mdadm -D <md>
 #
 #ARRAY /dev/md0 UUID=3aaa0122:29827cfa:5331ad66:ca767371
-#ARRAY /dev/md1 superminor=1
+#ARRAY /dev/md1 super-minor=1
 #ARRAY /dev/md2 devices=/dev/hda1,/dev/hda2
 #
 # ARRAY lines can also specify a "spare-group" for each array.  mdadm --monitor
index e11f9d5975efed61e53da3c643a0b9d898fe8788..90ff6ccbf1ca9d948f61944888cd4c5ff184797d 100644 (file)
@@ -45,6 +45,22 @@ and each device name can contain wild cards as defined by
 
 Also, there may be several device lines present in the file.
 
+Alternatively, a
+.B device
+line can contain the word
+.BR partitions .
+This will cause
+.I mdadm
+to read
+.I /proc/partitions
+and include all devices and partitions found there-in.
+.I mdadm
+does not use the names from
+.I /proc/partitions
+but only the major and minor device numbers.  It scans
+.I /dev
+to find the name that matches the numbers.
+
 For example:
 .IP
 DEVICE /dev/hda* /dev/hdc*
@@ -52,6 +68,8 @@ DEVICE /dev/hda* /dev/hdc*
 DEV    /dev/sd*
 .br
 DEVICE /dev/discs/disc*/disc
+.br
+DEVICE partitions
 
 .TP
 .B ARRAY
diff --git a/mdadm.h b/mdadm.h
index 50860ed5acee394eeb56767798dd98c241c247bf..2f813c1fe999621ad6ab5697b6fe0843fb46185c 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -150,6 +150,7 @@ extern int Assemble(char *mddev, int mdfd,
                    char *conffile,
                    mddev_dev_t devlist,
                    int readonly, int runstop,
+                   char *update,
                    int verbose, int force);
 
 extern int Build(char *mddev, int mdfd, int chunk, int level,
index 04d6ec260ce4c7b2a34d86606a194f3d5e67a27e..0657c76871ab5d8401b416ca6400a4376cc3f508 100644 (file)
@@ -1,6 +1,6 @@
 Summary:     mdadm is used for controlling Linux md devices (aka RAID arrays)
 Name:        mdadm
-Version:     1.0.1
+Version:     1.0.9
 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/mdadm.static b/mdadm.static
new file mode 100755 (executable)
index 0000000..cd31ad7
Binary files /dev/null and b/mdadm.static differ
diff --git a/test b/test
new file mode 100644 (file)
index 0000000..fac0f33
--- /dev/null
+++ b/test
@@ -0,0 +1,2 @@
+dev partitions
+array /dev/md0 super-minor=6
diff --git a/util.c b/util.c
index f2d16be149ff23750cd9204b98b6d69ec777c790..e65d23831fbf5ceb92236b82f513c02f4156340a 100644 (file)
--- a/util.c
+++ b/util.c
@@ -91,7 +91,8 @@ int md_get_version(int fd)
 
     if (ioctl(fd, RAID_VERSION, &vers) == 0)
        return  (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
-
+    if (errno == EACCES)
+           return -1;
     if (MAJOR(stb.st_rdev) == MD_MAJOR)
        return (3600);
     return -1;
@@ -212,6 +213,8 @@ int load_super(int fd, mdp_super_t *super)
 
        offset *= 512;
 
+       ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
+
        if (lseek64(fd, offset, 0)< 0LL)
                return 3;
 
@@ -314,7 +317,7 @@ int check_raid(int fd, char *name)
        if (load_super(fd, &super))
                return 0;
        /* Looks like a raid array .. */
-       fprintf(stderr, Name ": %s appear to be part of a raid array:\n",
+       fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
                name);
        crtime = super.ctime;
        fprintf(stderr, "    level=%d devices=%d ctime=%s",
@@ -375,6 +378,16 @@ struct devmap {
 } *devlist = NULL;
 int devlist_ready = 0;
 
+#ifdef UCLIBC
+char *map_dev(int major, int minor)
+{
+#if 0
+       fprintf(stderr, "Warning - fail to map %d,%d to a device name\n",
+               major, minor);
+#endif
+       return NULL;
+}
+#else
 #define  __USE_XOPEN_EXTENDED
 #include <ftw.h>
 
@@ -410,6 +423,7 @@ char *map_dev(int major, int minor)
     return NULL;
 }
 
+#endif
 
 int calc_sb_csum(mdp_super_t *super)
 {
@@ -446,7 +460,7 @@ char *human_size(long long bytes)
                        (long)(bytes>>30),
                        (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100),
                        (long)(bytes/1000LL/1000LL/1000LL),
-                       (long)((((bytes/1000)%1000000)+50000)/10000)
+                       (long)((((bytes/1000)%1000000)+5000)/10000)
                        );
        return buf;
 }