From: Neil Brown Date: Wed, 12 Feb 2003 00:17:26 +0000 (+0000) Subject: mdadm-1.0.9 X-Git-Tag: mdadm-1.0.9 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=commitdiff_plain;h=5787fa490612387a43c1897eb807b0c5612b5cd2 mdadm-1.0.9 --- diff --git a/Assemble.c b/Assemble.c index 78688022..a2ff5023 100644 --- a/Assemble.c +++ b/Assemble.c @@ -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) { 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>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< 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 diff --git a/Monitor.c b/Monitor.c index fa0d7088..d994dbe9 100644 --- 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; diff --git a/ReadMe.c b/ReadMe.c index 5c67eeba..390fee43 100644 --- 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 8c484abf..3cafb8c9 100644 --- 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 + +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 diff --git a/config.c b/config.c index eef32480..1f252449 100644 --- 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; diff --git a/makedist b/makedist index 89567daa..7ead17af 100755 --- 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 d3010c21..1ac98a3c 100644 --- 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 99479b43..bd9ccb16 100644 --- 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 a64ae656..c25dd7d3 100644 --- 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 95e7005a..c4373787 100644 --- 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; diff --git a/mdadm.conf-example b/mdadm.conf-example index 65c97b70..09c79893 100644 --- a/mdadm.conf-example +++ b/mdadm.conf-example @@ -32,14 +32,14 @@ # 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 # #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 diff --git a/mdadm.conf.5 b/mdadm.conf.5 index e11f9d59..90ff6ccb 100644 --- a/mdadm.conf.5 +++ b/mdadm.conf.5 @@ -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 50860ed5..2f813c1f 100644 --- 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, diff --git a/mdadm.spec b/mdadm.spec index 04d6ec26..0657c768 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,6 +1,6 @@ Summary: mdadm is used for controlling Linux md devices (aka RAID arrays) Name: mdadm -Version: 1.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 index 00000000..cd31ad70 Binary files /dev/null and b/mdadm.static differ diff --git a/test b/test new file mode 100644 index 00000000..fac0f331 --- /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 f2d16be1..e65d2383 100644 --- 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 @@ -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; }