mdadm-0.8
This commit is contained in:
parent
11a3e71da4
commit
e0d1903663
|
@ -115,7 +115,7 @@ int Assemble(char *mddev, int mdfd,
|
||||||
|
|
||||||
vers = md_get_version(mdfd);
|
vers = md_get_version(mdfd);
|
||||||
if (vers <= 0) {
|
if (vers <= 0) {
|
||||||
fprintf(stderr, Name ": %s appears not to be an md device.\n");
|
fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (vers < 9000) {
|
if (vers < 9000) {
|
||||||
|
@ -405,8 +405,8 @@ This doesnt work yet
|
||||||
if (devices[j].oldmajor != super.disks[i].major ||
|
if (devices[j].oldmajor != super.disks[i].major ||
|
||||||
devices[j].oldminor != super.disks[i].minor) {
|
devices[j].oldminor != super.disks[i].minor) {
|
||||||
change |= 2;
|
change |= 2;
|
||||||
super.disks[i].major = devices[i].oldmajor;
|
super.disks[i].major = devices[j].oldmajor;
|
||||||
super.disks[i].minor = devices[i].oldminor;
|
super.disks[i].minor = devices[j].oldminor;
|
||||||
}
|
}
|
||||||
if (devices[j].uptodate &&
|
if (devices[j].uptodate &&
|
||||||
(super.disks[i].state != desired_state)) {
|
(super.disks[i].state != desired_state)) {
|
||||||
|
@ -491,7 +491,7 @@ This doesnt work yet
|
||||||
if (runstop == 1 ||
|
if (runstop == 1 ||
|
||||||
(runstop == 0 &&
|
(runstop == 0 &&
|
||||||
( first_super.raid_disks == okcnt
|
( first_super.raid_disks == okcnt
|
||||||
|| start_partial_ok && enough(first_super.level, first_super.raid_disks, okcnt))
|
|| (start_partial_ok && enough(first_super.level, first_super.raid_disks, okcnt)))
|
||||||
)) {
|
)) {
|
||||||
if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
|
if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
|
||||||
fprintf(stderr, Name ": %s has been started with %d drive%s",
|
fprintf(stderr, Name ": %s has been started with %d drive%s",
|
||||||
|
@ -527,4 +527,5 @@ This doesnt work yet
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
2
Build.c
2
Build.c
|
@ -130,7 +130,7 @@ int Build(char *mddev, int mdfd, int chunk, int level,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ioctl(mdfd, REGISTER_DEV, &stb.st_rdev)) {
|
if (ioctl(mdfd, REGISTER_DEV, &stb.st_rdev)) {
|
||||||
fprintf(stderr, Name ": REGISTER_DEV failed for %s.\n",
|
fprintf(stderr, Name ": REGISTER_DEV failed for %s: %s.\n",
|
||||||
dv->devname, strerror(errno));
|
dv->devname, strerror(errno));
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
22
ChangeLog
22
ChangeLog
|
@ -1,4 +1,26 @@
|
||||||
Changes Prior to this release
|
Changes Prior to this release
|
||||||
|
- Fix another bug in Assemble.c due to confusing 'i' with 'j'
|
||||||
|
- Minimal, untested, support for multipath
|
||||||
|
- re-write of argument parsing to have more coherent modes,
|
||||||
|
- add --query,-Q option
|
||||||
|
- Update mdadm.8 to reflect arg processing change and --query
|
||||||
|
- Change "long" to "unsigned long" for device sizes
|
||||||
|
- Handle "mailaddr" and "program" lines in config file for follow/scan mode.
|
||||||
|
- --follow --scan will exit if no program or mail found
|
||||||
|
- Add MAILADDR and PROGRAM to mdadm.conf-example
|
||||||
|
- Spell check man pages
|
||||||
|
- consistently use "component devices" instead of "subdevices"
|
||||||
|
- Make -Wall -Werror really work and fix lots of errors.
|
||||||
|
- --detail and --stop can have --scan which chooses devices from /proc/mdstat
|
||||||
|
- --monitor detects 20% changes in resync, failed spares,
|
||||||
|
disappearing arrays,
|
||||||
|
- --monitor --scan will automatically add any devices found in /proc/mdstat
|
||||||
|
- --monitor will move spares between arrays with same spare-group if necessary
|
||||||
|
- Documentation for Monitor Mode
|
||||||
|
- --query notes if the array containing the given device is active or not
|
||||||
|
- Finished md.4 man page.
|
||||||
|
|
||||||
|
Changes Prior to 0.7.2 release
|
||||||
- mdadm.spec updates and ifdef BLKGETSIZE64 from Luca Berra -- bluca@comedia.it
|
- mdadm.spec updates and ifdef BLKGETSIZE64 from Luca Berra -- bluca@comedia.it
|
||||||
- more mdadm.spec updates from Gregory Leblanc <gleblanc@linuxweasel.com>
|
- more mdadm.spec updates from Gregory Leblanc <gleblanc@linuxweasel.com>
|
||||||
- make directory for mdadm.conf configurable in Makefile
|
- make directory for mdadm.conf configurable in Makefile
|
||||||
|
|
2
Create.c
2
Create.c
|
@ -194,7 +194,7 @@ int Create(char *mddev, int mdfd,
|
||||||
fprintf(stderr, Name ": size set to %dK\n", size);
|
fprintf(stderr, Name ": size set to %dK\n", size);
|
||||||
}
|
}
|
||||||
if (level >= 1 && ((maxsize-size)*100 > maxsize)) {
|
if (level >= 1 && ((maxsize-size)*100 > maxsize)) {
|
||||||
fprintf(stderr, Name ": largest drive (%s) exceed size (%dK) by more than 1%\n",
|
fprintf(stderr, Name ": largest drive (%s) exceed size (%dK) by more than 1%%\n",
|
||||||
maxdisc, size);
|
maxdisc, size);
|
||||||
warn = 1;
|
warn = 1;
|
||||||
}
|
}
|
||||||
|
|
15
Detail.c
15
Detail.c
|
@ -81,8 +81,8 @@ int Detail(char *dev, int brief)
|
||||||
if (brief)
|
if (brief)
|
||||||
printf("ARRAY %s level=%s disks=%d", dev, c?c:"-unknown-",array.raid_disks );
|
printf("ARRAY %s level=%s disks=%d", dev, c?c:"-unknown-",array.raid_disks );
|
||||||
else {
|
else {
|
||||||
long array_size;
|
unsigned long array_size;
|
||||||
long long larray_size;
|
unsigned long long larray_size;
|
||||||
#ifdef BLKGETSIZE64
|
#ifdef BLKGETSIZE64
|
||||||
if (ioctl(fd, BLKGETSIZE64, &larray_size)==0)
|
if (ioctl(fd, BLKGETSIZE64, &larray_size)==0)
|
||||||
;
|
;
|
||||||
|
@ -137,15 +137,20 @@ int Detail(char *dev, int brief)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" Number Major Minor RaidDisk State\n");
|
printf(" Number Major Minor RaidDisk State\n");
|
||||||
}
|
}
|
||||||
for (d= 0; d<array.raid_disks+array.spare_disks; d++) {
|
for (d= 0; d<MD_SB_DISKS; d++) {
|
||||||
mdu_disk_info_t disk;
|
mdu_disk_info_t disk;
|
||||||
char *dv;
|
char *dv;
|
||||||
disk.number = d;
|
disk.number = d;
|
||||||
if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
|
if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
|
||||||
fprintf(stderr, Name ": cannot get disk detail for disk %d: %s\n",
|
if (d < array.raid_disks)
|
||||||
d, strerror(errno));
|
fprintf(stderr, Name ": cannot get disk detail for disk %d: %s\n",
|
||||||
|
d, strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (d >= array.raid_disks &&
|
||||||
|
disk.major == 0 &&
|
||||||
|
disk.minor == 0)
|
||||||
|
continue;
|
||||||
if (!brief) {
|
if (!brief) {
|
||||||
printf(" %5d %5d %5d %5d ",
|
printf(" %5d %5d %5d %5d ",
|
||||||
disk.number, disk.major, disk.minor, disk.raid_disk);
|
disk.number, disk.major, disk.minor, disk.raid_disk);
|
||||||
|
|
12
Examine.c
12
Examine.c
|
@ -35,7 +35,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "md_u.h"
|
#include "md_u.h"
|
||||||
#include "md_p.h"
|
#include "md_p.h"
|
||||||
int Examine(mddev_dev_t devlist, int brief, char *conffile)
|
int Examine(mddev_dev_t devlist, int brief, int scan)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Read the raid superblock from a device and
|
/* Read the raid superblock from a device and
|
||||||
|
@ -60,7 +60,6 @@ int Examine(mddev_dev_t devlist, int brief, char *conffile)
|
||||||
char *c;
|
char *c;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
int err;
|
int err;
|
||||||
int scan= 0;
|
|
||||||
|
|
||||||
struct array {
|
struct array {
|
||||||
mdp_super_t super;
|
mdp_super_t super;
|
||||||
|
@ -68,15 +67,6 @@ int Examine(mddev_dev_t devlist, int brief, char *conffile)
|
||||||
struct array *next;
|
struct array *next;
|
||||||
} *arrays = NULL;
|
} *arrays = NULL;
|
||||||
|
|
||||||
if (devlist == NULL) {
|
|
||||||
devlist = conf_get_devs(conffile);
|
|
||||||
scan=1;
|
|
||||||
}
|
|
||||||
if (devlist == NULL) {
|
|
||||||
fprintf(stderr, Name ": No devices listed in %s\n", conffile);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; devlist ; devlist=devlist->next) {
|
for (; devlist ; devlist=devlist->next) {
|
||||||
fd = open(devlist->devname, O_RDONLY);
|
fd = open(devlist->devname, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -30,7 +30,7 @@
|
||||||
CC = gcc
|
CC = gcc
|
||||||
SYSCONFDIR = /etc
|
SYSCONFDIR = /etc
|
||||||
CONFFILE = $(SYSCONFDIR)/mdadm.conf
|
CONFFILE = $(SYSCONFDIR)/mdadm.conf
|
||||||
CFLAGS = -Wall,error,strict-prototypes -ggdb -DCONFFILE=\"$(CONFFILE)\"
|
CFLAGS = -Wall -Werror -Wstrict-prototypes -ggdb -DCONFFILE=\"$(CONFFILE)\"
|
||||||
|
|
||||||
# If you want a static binary, you might uncomment these
|
# If you want a static binary, you might uncomment these
|
||||||
# LDFLAGS = -static
|
# LDFLAGS = -static
|
||||||
|
@ -41,7 +41,7 @@ DESTDIR = /.
|
||||||
BINDIR = /sbin
|
BINDIR = /sbin
|
||||||
MANDIR = /usr/share/man/man8
|
MANDIR = /usr/share/man/man8
|
||||||
|
|
||||||
OBJS = mdadm.o config.o ReadMe.o util.o Manage.o Assemble.o Build.o Create.o Detail.o Examine.o Monitor.o dlink.o Kill.o
|
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
|
||||||
|
|
||||||
all : mdadm mdadm.man md.man mdadm.conf.man
|
all : mdadm mdadm.man md.man mdadm.conf.man
|
||||||
|
|
||||||
|
|
3
Manage.c
3
Manage.c
|
@ -77,7 +77,6 @@ int Manage_runstop(char *devname, int fd, int runstop)
|
||||||
/* Run or stop the array. array must already be configured
|
/* Run or stop the array. array must already be configured
|
||||||
* required >= 0.90.0
|
* required >= 0.90.0
|
||||||
*/
|
*/
|
||||||
mdu_array_info_t array;
|
|
||||||
mdu_param_t param; /* unused */
|
mdu_param_t param; /* unused */
|
||||||
|
|
||||||
if (runstop == -1 && md_get_version(fd) < 9000) {
|
if (runstop == -1 && md_get_version(fd) < 9000) {
|
||||||
|
@ -132,7 +131,7 @@ int Manage_subdevs(char *devname, int fd,
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
int i,j;
|
int i,j;
|
||||||
int save_errno;
|
int save_errno;
|
||||||
static buf[4096];
|
static char buf[4096];
|
||||||
|
|
||||||
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
|
if (ioctl(fd, GET_ARRAY_INFO, &array)) {
|
||||||
fprintf(stderr, Name ": cannot get array info for %s\n",
|
fprintf(stderr, Name ": cannot get array info for %s\n",
|
||||||
|
|
300
Monitor.c
300
Monitor.c
|
@ -30,13 +30,22 @@
|
||||||
#include "mdadm.h"
|
#include "mdadm.h"
|
||||||
#include "md_p.h"
|
#include "md_p.h"
|
||||||
#include "md_u.h"
|
#include "md_u.h"
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <sys/signal.h>
|
#include <sys/signal.h>
|
||||||
|
|
||||||
static void alert(char *event, char *dev, char *disc, char *mailaddr, char *cmd);
|
static void alert(char *event, char *dev, char *disc, char *mailaddr, char *cmd);
|
||||||
|
|
||||||
|
static char *percentalerts[] = {
|
||||||
|
"RebuildStarted",
|
||||||
|
"Rebuild20",
|
||||||
|
"Rebuild40",
|
||||||
|
"Rebuild60",
|
||||||
|
"Rebuild80",
|
||||||
|
};
|
||||||
|
|
||||||
int Monitor(mddev_dev_t devlist,
|
int Monitor(mddev_dev_t devlist,
|
||||||
char *mailaddr, char *alert_cmd,
|
char *mailaddr, char *alert_cmd,
|
||||||
int period,
|
int period, int scan,
|
||||||
char *config)
|
char *config)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -48,13 +57,27 @@ int Monitor(mddev_dev_t devlist,
|
||||||
* Update time
|
* Update time
|
||||||
* active/working/failed/spare drives
|
* active/working/failed/spare drives
|
||||||
* State of each device.
|
* State of each device.
|
||||||
|
* %rebuilt if rebuilding
|
||||||
*
|
*
|
||||||
* If the update time changes, check out all the data again
|
* If the update time changes, check out all the data again
|
||||||
* It is possible that we cannot get the state of each device
|
* It is possible that we cannot get the state of each device
|
||||||
* due to bugs in the md kernel module.
|
* due to bugs in the md kernel module.
|
||||||
|
* We also read /proc/mdstat to get rebuild percent,
|
||||||
|
* and to get state on all active devices incase of kernel bug.
|
||||||
*
|
*
|
||||||
* if active_drives decreases, generate a "Fail" event
|
* Events are:
|
||||||
* if active_drives increases, generate a "SpareActive" event
|
* Fail
|
||||||
|
* An active device had Faulty set or Active/Sync removed
|
||||||
|
* FailSpare
|
||||||
|
* A spare device had Faulty set
|
||||||
|
* SpareActive
|
||||||
|
* An active device had a reverse transition
|
||||||
|
* RebuildStarted
|
||||||
|
* percent went from -1 to +ve
|
||||||
|
* Rebuild20 Rebuild40 Rebuild60 Rebuild80
|
||||||
|
* percent went from below to not-below that number
|
||||||
|
* DeviceDisappeared
|
||||||
|
* Couldn't access a device which was previously visible
|
||||||
*
|
*
|
||||||
* if we detect an array with active<raid and spare==0
|
* if we detect an array with active<raid and spare==0
|
||||||
* we look at other arrays that have same spare-group
|
* we look at other arrays that have same spare-group
|
||||||
|
@ -62,100 +85,178 @@ int Monitor(mddev_dev_t devlist,
|
||||||
* and if we can get_disk_info and find a name
|
* and if we can get_disk_info and find a name
|
||||||
* Then we hot-remove and hot-add to the other array
|
* Then we hot-remove and hot-add to the other array
|
||||||
*
|
*
|
||||||
|
* If devlist is NULL, then we can monitor everything because --scan
|
||||||
|
* was given. We get an initial list from config file and add anything
|
||||||
|
* that appears in /proc/mdstat
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct state {
|
struct state {
|
||||||
char *devname;
|
char *devname;
|
||||||
|
int devnum; /* to sync with mdstat info */
|
||||||
long utime;
|
long utime;
|
||||||
int err;
|
int err;
|
||||||
int active, working, failed, spare;
|
char *spare_group;
|
||||||
|
int active, working, failed, spare, raid;
|
||||||
int devstate[MD_SB_DISKS];
|
int devstate[MD_SB_DISKS];
|
||||||
|
int devid[MD_SB_DISKS];
|
||||||
|
int percent;
|
||||||
struct state *next;
|
struct state *next;
|
||||||
} *statelist = NULL;
|
} *statelist = NULL;
|
||||||
int finished = 0;
|
int finished = 0;
|
||||||
while (! finished) {
|
struct mdstat_ent *mdstat = NULL;
|
||||||
mddev_ident_t mdlist = NULL;
|
|
||||||
|
if (!mailaddr && scan)
|
||||||
|
mailaddr = conf_get_mailaddr(config);
|
||||||
|
if (!alert_cmd && scan)
|
||||||
|
alert_cmd = conf_get_program(config);
|
||||||
|
if (scan && !mailaddr && !alert_cmd)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (devlist == NULL) {
|
||||||
|
mddev_ident_t mdlist = conf_get_ident(config, NULL);
|
||||||
|
for (; mdlist; mdlist=mdlist->next) {
|
||||||
|
struct state *st = malloc(sizeof *st);
|
||||||
|
if (st == NULL)
|
||||||
|
continue;
|
||||||
|
st->devname = strdup(mdlist->devname);
|
||||||
|
st->utime = 0;
|
||||||
|
st->next = statelist;
|
||||||
|
st->err = 1;
|
||||||
|
st->devnum = -1;
|
||||||
|
st->percent = -2;
|
||||||
|
if (mdlist->spare_group)
|
||||||
|
st->spare_group = strdup(mdlist->spare_group);
|
||||||
|
else
|
||||||
|
st->spare_group = NULL;
|
||||||
|
statelist = st;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
mddev_dev_t dv;
|
mddev_dev_t dv;
|
||||||
int dnum=0;
|
for (dv=devlist ; dv; dv=dv->next) {
|
||||||
if (devlist== NULL)
|
struct state *st = malloc(sizeof *st);
|
||||||
mdlist = conf_get_ident(config, NULL);
|
if (st == NULL)
|
||||||
dv = devlist;
|
continue;
|
||||||
while (dv || mdlist) {
|
st->devname = strdup(dv->devname);
|
||||||
mddev_ident_t mdident;
|
st->utime = 0;
|
||||||
struct state *st;
|
st->next = statelist;
|
||||||
|
st->err = 1;
|
||||||
|
st->devnum = -1;
|
||||||
|
st->percent = -2;
|
||||||
|
st->spare_group = NULL;
|
||||||
|
statelist = st;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while (! finished) {
|
||||||
|
struct state *st;
|
||||||
|
|
||||||
|
if (mdstat)
|
||||||
|
free_mdstat(mdstat);
|
||||||
|
mdstat = mdstat_read();
|
||||||
|
|
||||||
|
for (st=statelist; st; st=st->next) {
|
||||||
mdu_array_info_t array;
|
mdu_array_info_t array;
|
||||||
char *dev;
|
struct mdstat_ent *mse;
|
||||||
|
char *dev = st->devname;
|
||||||
int fd;
|
int fd;
|
||||||
char *event = NULL;
|
|
||||||
int i;
|
int i;
|
||||||
char *event_disc = NULL;
|
|
||||||
if (dv) {
|
|
||||||
dev = dv->devname;
|
|
||||||
mdident = conf_get_ident(config, dev);
|
|
||||||
dv = dv->next;
|
|
||||||
} else {
|
|
||||||
mdident = mdlist;
|
|
||||||
dev = mdident->devname;
|
|
||||||
mdlist = mdlist->next;
|
|
||||||
}
|
|
||||||
for (st=statelist; st ; st=st->next)
|
|
||||||
if (strcmp(st->devname, dev)==0)
|
|
||||||
break;
|
|
||||||
if (!st) {
|
|
||||||
st =malloc(sizeof *st);
|
|
||||||
if (st == NULL)
|
|
||||||
continue;
|
|
||||||
st->devname = strdup(dev);
|
|
||||||
st->utime = 0;
|
|
||||||
st->next = statelist;
|
|
||||||
st->err = 0;
|
|
||||||
statelist = st;
|
|
||||||
}
|
|
||||||
fd = open(dev, O_RDONLY);
|
fd = open(dev, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (!st->err)
|
if (!st->err)
|
||||||
fprintf(stderr, Name ": cannot open %s: %s\n",
|
alert("DeviceDisappeared", dev, NULL,
|
||||||
|
mailaddr, alert_cmd);
|
||||||
|
/* fprintf(stderr, Name ": cannot open %s: %s\n",
|
||||||
dev, strerror(errno));
|
dev, strerror(errno));
|
||||||
st->err=1;
|
*/ st->err=1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ioctl(fd, GET_ARRAY_INFO, &array)<0) {
|
if (ioctl(fd, GET_ARRAY_INFO, &array)<0) {
|
||||||
if (!st->err)
|
if (!st->err)
|
||||||
fprintf(stderr, Name ": cannot get array info for %s: %s\n",
|
alert("DeviceDisappeared", dev, NULL,
|
||||||
|
mailaddr, alert_cmd);
|
||||||
|
/* fprintf(stderr, Name ": cannot get array info for %s: %s\n",
|
||||||
dev, strerror(errno));
|
dev, strerror(errno));
|
||||||
st->err=1;
|
*/ st->err=1;
|
||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
st->err = 0;
|
if (st->devnum < 0) {
|
||||||
|
struct stat stb;
|
||||||
|
if (fstat(fd, &stb) == 0 &&
|
||||||
|
(S_IFMT&stb.st_mode)==S_IFBLK)
|
||||||
|
st->devnum = MINOR(stb.st_rdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mse = mdstat ; mse ; mse=mse->next)
|
||||||
|
if (mse->devnum == st->devnum) {
|
||||||
|
mse->devnum = -1; /* flag it as "used" */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (st->utime == array.utime &&
|
if (st->utime == array.utime &&
|
||||||
st->failed == array.failed_disks) {
|
st->failed == array.failed_disks &&
|
||||||
|
st->working == array.working_disks &&
|
||||||
|
st->spare == array.spare_disks &&
|
||||||
|
(mse == NULL || (
|
||||||
|
mse->percent == st->percent
|
||||||
|
))) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
st->err = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
event = NULL;
|
if (mse &&
|
||||||
if (st->utime) {
|
st->percent == -1 &&
|
||||||
int i;
|
mse->percent >= 0)
|
||||||
if (st->active > array.active_disks)
|
alert("RebuildStarted", dev, NULL, mailaddr, alert_cmd);
|
||||||
event = "Fail";
|
if (mse &&
|
||||||
else if (st->working > array.working_disks)
|
st->percent >= 0 &&
|
||||||
event = "FailSpare";
|
mse->percent >= 0 &&
|
||||||
else if (st->active < array.active_disks)
|
(mse->percent / 20) > (st->percent / 20))
|
||||||
event = "ActiveSpare";
|
alert(percentalerts[mse->percent/20],
|
||||||
}
|
dev, NULL, mailaddr, alert_cmd);
|
||||||
for (i=0; i<array.raid_disks+array.spare_disks; i++) {
|
|
||||||
|
if (mse)
|
||||||
|
st->percent = mse->percent;
|
||||||
|
|
||||||
|
for (i=0; i<MD_SB_DISKS; i++) {
|
||||||
mdu_disk_info_t disc;
|
mdu_disk_info_t disc;
|
||||||
|
int newstate=0;
|
||||||
|
int change;
|
||||||
|
char *dv = NULL;
|
||||||
disc.number = i;
|
disc.number = i;
|
||||||
if (ioctl(fd, GET_DISK_INFO, &disc)>= 0) {
|
if (ioctl(fd, GET_DISK_INFO, &disc)>= 0) {
|
||||||
if (event && event_disc == NULL &&
|
newstate = disc.state;
|
||||||
st->devstate[i] != disc.state) {
|
dv = map_dev(disc.major, disc.minor);
|
||||||
char * dv = map_dev(disc.major, disc.minor);
|
} else if (mse && i < strlen(mse->pattern))
|
||||||
if (dv)
|
switch(mse->pattern[i]) {
|
||||||
event_disc = strdup(dv);
|
case 'U': newstate = 6 /* ACTIVE/SYNC */; break;
|
||||||
|
case '_': newstate = 0; break;
|
||||||
}
|
}
|
||||||
st->devstate[i] = disc.state;
|
change = newstate ^ st->devstate[i];
|
||||||
|
if (st->utime && change && !st->err) {
|
||||||
|
if (i < array.raid_disks &&
|
||||||
|
(((newstate&change)&(1<<MD_DISK_FAULTY)) ||
|
||||||
|
((st->devstate[i]&change)&(1<<MD_DISK_ACTIVE)) ||
|
||||||
|
((st->devstate[i]&change)&(1<<MD_DISK_SYNC)))
|
||||||
|
)
|
||||||
|
alert("Fail", dev, dv, mailaddr, alert_cmd);
|
||||||
|
else if (i>=array.raid_disks &&
|
||||||
|
(disc.major || disc.minor) &&
|
||||||
|
st->devid[i] == MKDEV(disc.major, disc.minor) &&
|
||||||
|
((newstate&change)&(1<<MD_DISK_FAULTY))
|
||||||
|
)
|
||||||
|
alert("FailSpare", dev, dv, mailaddr, alert_cmd);
|
||||||
|
else if (i < array.raid_disks &&
|
||||||
|
(((st->devstate[i]&change)&(1<<MD_DISK_FAULTY)) ||
|
||||||
|
((newstate&change)&(1<<MD_DISK_ACTIVE)) ||
|
||||||
|
((newstate&change)&(1<<MD_DISK_SYNC)))
|
||||||
|
)
|
||||||
|
alert("SpareActive", dev, dv, mailaddr, alert_cmd);
|
||||||
}
|
}
|
||||||
|
st->devstate[i] = disc.state;
|
||||||
|
st->devid[i] = MKDEV(disc.major, disc.minor);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
st->active = array.active_disks;
|
st->active = array.active_disks;
|
||||||
|
@ -163,9 +264,78 @@ int Monitor(mddev_dev_t devlist,
|
||||||
st->spare = array.spare_disks;
|
st->spare = array.spare_disks;
|
||||||
st->failed = array.failed_disks;
|
st->failed = array.failed_disks;
|
||||||
st->utime = array.utime;
|
st->utime = array.utime;
|
||||||
if (event)
|
st->raid = array.raid_disks;
|
||||||
alert(event, dev, event_disc, mailaddr, alert_cmd);
|
st->err = 0;
|
||||||
}
|
}
|
||||||
|
/* now check if there are any new devices found in mdstat */
|
||||||
|
if (scan) {
|
||||||
|
struct mdstat_ent *mse;
|
||||||
|
for (mse=mdstat; mse; mse=mse->next)
|
||||||
|
if (mse->devnum > 0) {
|
||||||
|
struct state *st = malloc(sizeof *st);
|
||||||
|
if (st == NULL)
|
||||||
|
continue;
|
||||||
|
st->devname = strdup(get_md_name(mse->devnum));
|
||||||
|
st->utime = 0;
|
||||||
|
st->next = statelist;
|
||||||
|
st->err = 1;
|
||||||
|
st->devnum = mse->devnum;
|
||||||
|
st->percent = -2;
|
||||||
|
st->spare_group = NULL;
|
||||||
|
statelist = st;
|
||||||
|
alert("NewArray", st->devname, NULL, mailaddr, alert_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If an array has active < raid && spare == 0 && spare_group != NULL
|
||||||
|
* Look for another array with spare > 0 and active == raid and same spare_group
|
||||||
|
* if found, choose a device and hotremove/hotadd
|
||||||
|
*/
|
||||||
|
for (st = statelist; st; st=st->next)
|
||||||
|
if (st->active < st->raid &&
|
||||||
|
st->spare == 0 &&
|
||||||
|
st->spare_group != NULL) {
|
||||||
|
struct state *st2;
|
||||||
|
for (st2=statelist ; st2 ; st2=st2->next)
|
||||||
|
if (st2 != st &&
|
||||||
|
st2->spare > 0 &&
|
||||||
|
st2->active == st2->raid &&
|
||||||
|
st2->spare_group != NULL &&
|
||||||
|
strcmp(st->spare_group, st2->spare_group) == 0) {
|
||||||
|
/* try to remove and add */
|
||||||
|
int fd1 = open(st->devname, O_RDONLY);
|
||||||
|
int fd2 = open(st2->devname, O_RDONLY);
|
||||||
|
int dev = -1;
|
||||||
|
int d;
|
||||||
|
if (fd1 < 0 || fd2 < 0) {
|
||||||
|
if (fd1>=0) close(fd1);
|
||||||
|
if (fd2>=0) close(fd2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (d=st2->raid; d<MD_SB_DISKS; d++) {
|
||||||
|
if (st2->devid[d] > 0 &&
|
||||||
|
st2->devstate[d] == 0) {
|
||||||
|
dev = st2->devid[d];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dev > 0) {
|
||||||
|
if (ioctl(fd2, HOT_REMOVE_DISK,
|
||||||
|
(unsigned long)dev) == 0) {
|
||||||
|
if (ioctl(fd1, HOT_ADD_DISK,
|
||||||
|
(unsigned long)dev) == 0) {
|
||||||
|
alert("MoveSpare", st->devname, st2->devname, mailaddr, alert_cmd);
|
||||||
|
close(fd1);
|
||||||
|
close(fd2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else ioctl(fd2, HOT_ADD_DISK, (unsigned long) dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd1);
|
||||||
|
close(fd2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sleep(period);
|
sleep(period);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -177,7 +347,7 @@ static void alert(char *event, char *dev, char *disc, char *mailaddr, char *cmd)
|
||||||
if (!cmd && !mailaddr) {
|
if (!cmd && !mailaddr) {
|
||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
|
|
||||||
printf("%0.15s: %s on %s %s\n", ctime(&now)+4, event, dev, disc?disc:"unknown device");
|
printf("%1.15s: %s on %s %s\n", ctime(&now)+4, event, dev, disc?disc:"unknown device");
|
||||||
}
|
}
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* mdadm - manage Linux "md" devices aka RAID arrays.
|
||||||
|
*
|
||||||
|
* Copyright (C) 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 "md_u.h"
|
||||||
|
|
||||||
|
int Query(char *dev)
|
||||||
|
{
|
||||||
|
/* Give a brief description of the device,
|
||||||
|
* whether it is an md device and whether it has
|
||||||
|
* a superblock
|
||||||
|
*/
|
||||||
|
int fd = open(dev, O_RDONLY, 0);
|
||||||
|
int vers;
|
||||||
|
int ioctlerr;
|
||||||
|
int superror, superrno;
|
||||||
|
mdp_super_t super;
|
||||||
|
mdu_array_info_t array;
|
||||||
|
unsigned long long larray_size;
|
||||||
|
unsigned long array_size;
|
||||||
|
struct stat stb;
|
||||||
|
char *mddev;
|
||||||
|
mdu_disk_info_t disc;
|
||||||
|
char *activity;
|
||||||
|
|
||||||
|
if (fd < 0){
|
||||||
|
fprintf(stderr, Name ": cannot open %s: %s\n",
|
||||||
|
dev, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vers = md_get_version(fd);
|
||||||
|
if (ioctl(fd, GET_ARRAY_INFO, &array)<0)
|
||||||
|
ioctlerr = errno;
|
||||||
|
else ioctlerr = 0;
|
||||||
|
superror = load_super(fd, &super);
|
||||||
|
superrno = errno;
|
||||||
|
|
||||||
|
fstat(fd, &stb);
|
||||||
|
|
||||||
|
if (vers>=9000 && !ioctlerr) {
|
||||||
|
#ifdef BLKGETSIZE64
|
||||||
|
if (ioctl(fd, BLKGETSIZE64, &larray_size)==0)
|
||||||
|
;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (ioctl(fd, BLKGETSIZE, &array_size)==0)
|
||||||
|
larray_size = array_size<<9;
|
||||||
|
else larray_size = 0;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (vers < 0)
|
||||||
|
printf("%s: is not an md array\n", dev);
|
||||||
|
else if (vers < 9000)
|
||||||
|
printf("%s: is an md device, but kernel cannot provide details\n", dev);
|
||||||
|
else if (ioctlerr == ENODEV)
|
||||||
|
printf("%s: is an md device which is not active\n", dev);
|
||||||
|
else if (ioctlerr)
|
||||||
|
printf("%s: is an md device, but gives \"%s\" when queried\n",
|
||||||
|
dev, strerror(ioctlerr));
|
||||||
|
else {
|
||||||
|
printf("%s: %s %s %d devices, %d spare%s. Use mdadm --detail for more detail.\n",
|
||||||
|
dev,
|
||||||
|
human_size_brief(larray_size),
|
||||||
|
map_num(pers, array.level),
|
||||||
|
array.raid_disks,
|
||||||
|
array.spare_disks, array.spare_disks==1?"":"s");
|
||||||
|
}
|
||||||
|
switch(superror) {
|
||||||
|
case 1:
|
||||||
|
printf("%s: cannot find device size: %s\n",
|
||||||
|
dev, strerror(superrno));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("%s: is too small to be an md componenet.\n",
|
||||||
|
dev);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
printf("%s: Cannot seek to superblock: %s\n",
|
||||||
|
dev, strerror(superrno));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
printf("%s: Cannot read md superblock.\n",
|
||||||
|
dev);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
printf("%s: No md super block found, not an md component.\n",
|
||||||
|
dev);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
printf("%s: md superblock present with wrong version: %d\n",
|
||||||
|
dev, super.major_version);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* array might be active... */
|
||||||
|
mddev = get_md_name(super.md_minor);
|
||||||
|
disc.number = super.this_disk.number;
|
||||||
|
activity = "inactive";
|
||||||
|
if (mddev && (fd = open(mddev, O_RDONLY))>=0) {
|
||||||
|
if (md_get_version(fd) >= 9000 &&
|
||||||
|
ioctl(fd, GET_ARRAY_INFO, &array)>= 0) {
|
||||||
|
if (ioctl(fd, GET_DISK_INFO, &disc) >= 0 &&
|
||||||
|
MKDEV(disc.major,disc.minor) == stb.st_rdev)
|
||||||
|
activity = "active";
|
||||||
|
else
|
||||||
|
activity = "mismatch";
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
printf("%s: device %d in %d device %s %s md%d. Use mdadm --examine for more detail.\n",
|
||||||
|
dev,
|
||||||
|
super.this_disk.number, super.raid_disks,
|
||||||
|
activity,
|
||||||
|
map_num(pers, super.level),
|
||||||
|
super.md_minor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
254
ReadMe.c
254
ReadMe.c
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include "mdadm.h"
|
#include "mdadm.h"
|
||||||
|
|
||||||
char Version[] = Name " - v0.7.2 - 21 March 2002\n";
|
char Version[] = Name " - v0.8 - 4 April 2002\n";
|
||||||
/*
|
/*
|
||||||
* File: ReadMe.c
|
* File: ReadMe.c
|
||||||
*
|
*
|
||||||
|
@ -58,7 +58,7 @@ char Version[] = Name " - v0.7.2 - 21 March 2002\n";
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mdadm has 4 major modes of operation:
|
* mdadm has 6 major modes of operation:
|
||||||
* 1/ Create
|
* 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 superbock
|
||||||
* It can progress in several step create-add-add-run
|
* It can progress in several step create-add-add-run
|
||||||
|
@ -72,15 +72,24 @@ char Version[] = Name " - v0.7.2 - 21 March 2002\n";
|
||||||
* 3/ Build
|
* 3/ Build
|
||||||
* This is for building legacy arrays without superblocks
|
* This is for building legacy arrays without superblocks
|
||||||
* 4/ Manage
|
* 4/ Manage
|
||||||
* This is for odd bits an pieces like hotadd, hotremove, setfaulty,
|
* This is for doing something to one or more devices
|
||||||
* stop, readonly,readwrite
|
* in an array, such as add,remove,fail.
|
||||||
* If an array is only partially setup by the Create/Assemble/Build
|
* run/stop/readonly/readwrite are also available
|
||||||
* command, subsequent Manage commands can finish the job.
|
* 5/ Misc
|
||||||
|
* This is for doing things to individual devices.
|
||||||
|
* They might be parts of an array so
|
||||||
|
* zero-superblock, examine might be appropriate
|
||||||
|
* They might be md arrays so
|
||||||
|
* run,stop,rw,ro,detail might be appropriate
|
||||||
|
* Also query will treat it as either
|
||||||
|
* 6/ Monitor
|
||||||
|
* This mode never exits but just monitors arrays and reports changes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char short_options[]="-ABCDEFhVvbc:l:p:m:n:x:u:c:d:z:sarfRSow";
|
char short_options[]="-ABCDEFGQhVvbc:l:p:m:n:x:u:c:d:z:sarfRSow";
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
{"manage", 0, 0, '@'},
|
{"manage", 0, 0, '@'},
|
||||||
|
{"misc", 0, 0, '#'},
|
||||||
{"assemble", 0, 0, 'A'},
|
{"assemble", 0, 0, 'A'},
|
||||||
{"build", 0, 0, 'B'},
|
{"build", 0, 0, 'B'},
|
||||||
{"create", 0, 0, 'C'},
|
{"create", 0, 0, 'C'},
|
||||||
|
@ -88,7 +97,8 @@ struct option long_options[] = {
|
||||||
{"examine", 0, 0, 'E'},
|
{"examine", 0, 0, 'E'},
|
||||||
{"follow", 0, 0, 'F'},
|
{"follow", 0, 0, 'F'},
|
||||||
{"grow", 0, 0, 'G'}, /* not yet implemented */
|
{"grow", 0, 0, 'G'}, /* not yet implemented */
|
||||||
{"zero-superblock", 0, 0, 'H'},
|
{"zero-superblock", 0, 0, 'K'}, /* deliberately no a short_option */
|
||||||
|
{"query", 0, 0, 'Q'},
|
||||||
|
|
||||||
/* synonyms */
|
/* synonyms */
|
||||||
{"monitor", 0, 0, 'F'},
|
{"monitor", 0, 0, 'F'},
|
||||||
|
@ -146,31 +156,38 @@ char Help[] =
|
||||||
"Usage: mdadm --create device options...\n"
|
"Usage: mdadm --create device options...\n"
|
||||||
" mdadm --assemble device options...\n"
|
" mdadm --assemble device options...\n"
|
||||||
" mdadm --build device options...\n"
|
" mdadm --build device options...\n"
|
||||||
" mdadm --detail device\n"
|
" mdadm --manage device options...\n"
|
||||||
" mdadm --examine device\n"
|
" mdadm --misc options... devices\n"
|
||||||
" mdadm --follow options...\n"
|
" mdadm --monitor options...\n"
|
||||||
" mdadm device options...\n"
|
" mdadm device options...\n"
|
||||||
" mdadm is used for controlling Linux md devices (aka RAID arrays)\n"
|
" mdadm is used for building, manageing, and monitoring\n"
|
||||||
" For detail help on major modes use, e.g.\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"
|
||||||
" mdadm --assemble --help\n"
|
" mdadm --assemble --help\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Any parameter that does not start with '-' is treated as a device name\n"
|
"Any parameter that does not start with '-' is treated as a device name\n"
|
||||||
"The first such name is normally the name of an md device. Subsequent\n"
|
"The first such name is often the name of an md device. Subsequent\n"
|
||||||
"names are names of component devices."
|
"names are often names of component devices."
|
||||||
"\n"
|
|
||||||
"Available options are:\n"
|
|
||||||
" --create -C : Create a new array\n"
|
|
||||||
" --assemble -A : Assemble an existing array\n"
|
|
||||||
" --build -B : Build a legacy array without superblock\n"
|
|
||||||
" --detail -D : Print detail of a given md array\n"
|
|
||||||
" --examine -E : Print content of md superblock on device\n"
|
|
||||||
" --follow -F : Follow (monitor) any changes to devices and respond to them\n"
|
|
||||||
" --monitor : same as --follow\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
|
"Some common options are:\n"
|
||||||
" --help -h : This help message or, after above option,\n"
|
" --help -h : This help message or, after above option,\n"
|
||||||
" mode specific help message\n"
|
" mode specific help message\n"
|
||||||
" --version -V : Print version information for mdadm\n"
|
" --version -V : Print version information for mdadm\n"
|
||||||
" --verbose -v : Be more verbose about what is happening\n"
|
" --verbose -v : Be more verbose about what is happening\n"
|
||||||
|
" --brief -b : Be less verbose, more brief\n"
|
||||||
|
" --force -f : Override normal checks and be more forceful\n"
|
||||||
|
"\n"
|
||||||
|
" --assemble -A : Assemble an array\n"
|
||||||
|
" --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"
|
||||||
|
" --monitor -F : monitor (follow) some arrays\n"
|
||||||
|
" --query -Q : Display general information about how a\n"
|
||||||
|
" device relates to the md driver\n"
|
||||||
|
;
|
||||||
|
/*
|
||||||
"\n"
|
"\n"
|
||||||
" For create or build:\n"
|
" For create or build:\n"
|
||||||
" --chunk= -c : chunk size of kibibytes\n"
|
" --chunk= -c : chunk size of kibibytes\n"
|
||||||
|
@ -213,32 +230,43 @@ char Help[] =
|
||||||
" --readwrite -w : mark array as readwrite\n"
|
" --readwrite -w : mark array as readwrite\n"
|
||||||
" --zero-superblock : erase the MD superblock from a device.\n"
|
" --zero-superblock : erase the MD superblock from a device.\n"
|
||||||
;
|
;
|
||||||
|
*/
|
||||||
|
|
||||||
char Help_create[] =
|
char Help_create[] =
|
||||||
"Usage: mdadm --create device -chunk=X --level=Y --raid-disks=Z devices\n"
|
"Usage: mdadm --create device -chunk=X --level=Y --raid-disks=Z devices\n"
|
||||||
"\n"
|
"\n"
|
||||||
" This usage will initialise a new md array and possibly associate some\n"
|
" This usage will initialise a new md array and associate some\n"
|
||||||
" devices with it. If enough devices are given to complete the array,\n"
|
" devices with it. If enough devices are given to complete the array,\n"
|
||||||
" the array will be activated. Otherwise it will be left inactive\n"
|
" the array will be activated. Otherwise it will be left inactive\n"
|
||||||
" to be completed and activated by subsequent management commands.\n"
|
" to be completed and activated by subsequent management commands.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" As devices are added, they are checked to see if they contain\n"
|
" As devices are added, they are checked to see if they already contain\n"
|
||||||
" raid superblocks or filesystems. They are also check to see if\n"
|
" raid superblocks or filesystems. They are also checked to see if\n"
|
||||||
" the variance in device size exceeds 1%.\n"
|
" the variance in device size exceeds 1%.\n"
|
||||||
" If any discrepancy is found, the array will not automatically\n"
|
" If any discrepancy is found, the array will not automatically\n"
|
||||||
" be run, though the presence of a '--run' can override this\n"
|
" be run, though the presence of a '--run' can override this\n"
|
||||||
" caution.\n"
|
" caution.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" If the --size option is given, it is not necessary to list any subdevices\n"
|
" If the --size option is given then only that many kilobytes of each\n"
|
||||||
" in this command. They can be added later, before a --run.\n"
|
" device is used, no matter how big each device is.\n"
|
||||||
" If no --size is given, the apparent size of the smallest drive given\n"
|
" If no --size is given, the apparent size of the smallest drive given\n"
|
||||||
" is used.\n"
|
" is used for raid level 1 and greater, and the full device is used for\n"
|
||||||
|
" other levels.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" The General management options that are valid with --create are:\n"
|
" Options that are valid with --create (-C) are:\n"
|
||||||
" --run : insist of running the array even if not all devices\n"
|
" --chunk= -c : chunk size of kibibytes\n"
|
||||||
" are present or some look odd.\n"
|
" --rounding= : rounding factor for linear array (==chunck size)\n"
|
||||||
" --readonly: start the array readonly - not supported yet.\n"
|
" --level= -l : raid level: 0,1,4,5,linear,multipath and synonyms\n"
|
||||||
|
" --paritiy= -p : raid5 parity algorith: {left,right}-{,a}symmetric\n"
|
||||||
|
" --layout= : same as --parity\n"
|
||||||
|
" --raid-disks= -n : number of active devices in array\n"
|
||||||
|
" --spare-disks= -x : number of spares (eXtras) devices in initial array\n"
|
||||||
|
" --size= -z : Size (in K) of each drive in RAID1/4/5 - optional\n"
|
||||||
|
" --force -f : Honour devices as listed on command line. Don't\n"
|
||||||
|
" : insert a missing drive for RAID5.\n"
|
||||||
|
" --run : insist of running the array even if not all\n"
|
||||||
|
" : devices are present or some look odd.\n"
|
||||||
|
" --readonly : start the array readonly - not supported yet.\n"
|
||||||
"\n"
|
"\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -246,13 +274,18 @@ char Help_build[] =
|
||||||
"Usage: mdadm --build device -chunk=X --level=Y --raid-disks=Z devices\n"
|
"Usage: mdadm --build device -chunk=X --level=Y --raid-disks=Z devices\n"
|
||||||
"\n"
|
"\n"
|
||||||
" This usage is similar to --create. The difference is that it creates\n"
|
" This usage is similar to --create. The difference is that it creates\n"
|
||||||
" a legacy array with a superblock. With these arrays there is no\n"
|
" a legacy array without a superblock. With these arrays there is no\n"
|
||||||
" different between initially creating the array and subsequently\n"
|
" different between initially creating the array and subsequently\n"
|
||||||
" assembling the array, except that hopefully there is useful data\n"
|
" assembling the array, except that hopefully there is useful data\n"
|
||||||
" there in the second case.\n"
|
" there in the second case.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" The level may only be 0 or linear.\n"
|
" The level may only be 0, raid0, or linear.\n"
|
||||||
" All devices must be listed and the array will be started once complete.\n"
|
" 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"
|
||||||
|
" --level= -l : 0, raid0, or linear\n"
|
||||||
|
" --raid-disks= -n : number of active devices in array\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
char Help_assemble[] =
|
char Help_assemble[] =
|
||||||
|
@ -261,53 +294,140 @@ char Help_assemble[] =
|
||||||
"\n"
|
"\n"
|
||||||
"This usage assembles one or more raid arrays from pre-existing\n"
|
"This usage assembles one or more raid arrays from pre-existing\n"
|
||||||
"components.\n"
|
"components.\n"
|
||||||
"For each array, mdadm needs to know the md device, the identify of\n"
|
"For each array, mdadm needs to know the md device, the identity of\n"
|
||||||
"the array, and a number of sub devices. These can be found in a number\n"
|
"the array, and a number of sub devices. These can be found in a number\n"
|
||||||
"of ways.\n"
|
"of ways.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The md device is either given on the command line or is found listed\n"
|
"The md device is either given on the command line or is found listed\n"
|
||||||
"in the config file. The array identity is determined either from the\n"
|
"in the config file. The array identity is determined either from the\n"
|
||||||
"--uuid or --super-minor commandline arguments, or from the config file,\n"
|
"--uuid or --super-minor commandline arguments, from the config file,\n"
|
||||||
"or from the first component device on the command line.\n"
|
"or from the first component device on the command line.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The different combinations of these are as follows:\n"
|
"The different combinations of these are as follows:\n"
|
||||||
" If the --scan option is not given, then only devices and identities\n"
|
" If the --scan option is not given, then only devices and identities\n"
|
||||||
" listed on the command line are considered.\n"
|
" listed on the command line are considered.\n"
|
||||||
" The first device will be the array devices, and the remainder will\n"
|
" The first device will be the array device, and the remainder will be\n"
|
||||||
" examined when looking for components.\n"
|
" examined when looking for components.\n"
|
||||||
" If an explicit identity is given with --uuid or --super-minor, then\n"
|
" If an explicit identity is given with --uuid or --super-minor, then\n"
|
||||||
" Each device with a superblock which matches that identity is considered,\n"
|
" only devices with a superblock which matches that identity is considered,\n"
|
||||||
" otherwise every device listed is considered.\n"
|
" otherwise every device listed is considered.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" If the --scan option is given, and no devices are listed, then\n"
|
" If the --scan option is given, and no devices are listed, then\n"
|
||||||
" every array listed in the config file is considered for assembly.\n"
|
" every array listed in the config file is considered for assembly.\n"
|
||||||
" The identity can candidate devices are determined from the config file.\n"
|
" The identity of candidate devices are determined from the config file.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" If the --scan option is given as well as one or more devices, then\n"
|
" If the --scan option is given as well as one or more devices, then\n"
|
||||||
" Those devices are md devices that are to be assembled. Their identity\n"
|
" Those devices are md devices that are to be assembled. Their identity\n"
|
||||||
" and components are determined from the config file.\n"
|
" and components are determined from the config file.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The config file contains, apart from blank lines and comment lines that\n"
|
"Options that are valid with --assemble (-A) are:\n"
|
||||||
"start with a has, two sorts of configuration lines, array lines and\n"
|
" --uuid= -u : uuid of array to assemble. Devices which don't\n"
|
||||||
"device lines.\n"
|
" have this uuid are excluded\n"
|
||||||
"Each configuration line is constructed of a number of space separated\n"
|
" --super-minor= -m : minor number to look for in super-block when\n"
|
||||||
"words, and can be continued on subsequent physical lines by indenting\n"
|
" choosing devices to use.\n"
|
||||||
"those lines.\n"
|
" --config= -c : config file\n"
|
||||||
|
" --scan -s : scan config file for missing information\n"
|
||||||
|
" --run -R : Try to start the array even if not enough devices\n"
|
||||||
|
" 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"
|
||||||
|
;
|
||||||
|
|
||||||
|
char Help_manage[] =
|
||||||
|
"Usage: mdadm arraydevice options component devices...\n"
|
||||||
"\n"
|
"\n"
|
||||||
"A device line starts with the word 'device' and then has a number of words\n"
|
"This usage is for managing the component devices within an array.\n"
|
||||||
"which identify devices. These words should be names of devices in the filesystem,\n"
|
"The --manage option is not needed and is assumed if the first argument\n"
|
||||||
"and can contain wildcards. There can be multiple words or each device line,\n"
|
"is a device name or a management option.\n"
|
||||||
"and multiple device lines. All devices so listed are checked for relevant\n"
|
"The first device listed will be taken to be an md array device, and\n"
|
||||||
"super blocks when assembling arrays.\n"
|
"subsequent devices are (potential) components of that array.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"An array line start with the word 'array'. This is followed by the name of\n"
|
"Options that are valid with management mode are:\n"
|
||||||
"the array device in the filesystem, e.g. '/dev/md2'. Subsequent words\n"
|
" --add -a : hotadd subsequent devices to the array\n"
|
||||||
"describe the identity of the array, used to recognise devices to include in the\n"
|
" --remove -r : remove subsequent devices, which must not be active\n"
|
||||||
"array. The identity can be given as a UUID with a word starting 'uuid=', or\n"
|
" --fail -f : mark subsequent devices a faulty\n"
|
||||||
"as a minor-number stored in the superblock using 'super-minor=', or as a list\n"
|
" --set-faulty : same as --fail\n"
|
||||||
"of devices. This is given as a comma separated list of names, possibly containing\n"
|
" --run -R : start a partially built array\n"
|
||||||
"wildcards, preceeded by 'devices='. If multiple critea are given, than a device\n"
|
" --stop -S : deactive array, releasing all resources\n"
|
||||||
"must match all of them to be considered.\n"
|
" --readonly -o : mark array as readonly\n"
|
||||||
|
" --readwrite -w : mark array as readwrite\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
char Help_misc[] =
|
||||||
|
"Usage: mdadm misc_option devices...\n"
|
||||||
|
"\n"
|
||||||
|
"This usage is for performing some task on one or more devices, which\n"
|
||||||
|
"may be arrays or components, depending on the task.\n"
|
||||||
|
"The --misc option is not needed (though it is allowed) and is assumed\n"
|
||||||
|
"if the first argument in a misc option.\n"
|
||||||
|
"\n"
|
||||||
|
"Options that are valid with the miscellaneous mode are:\n"
|
||||||
|
" --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"
|
||||||
|
" --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"
|
||||||
|
" --readonly -o : mark array as readonly\n"
|
||||||
|
" --readwrite -w : mark array as readwrite\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
char Help_monitor[] =
|
||||||
|
"Usage: mdadm --monitor options devices\n"
|
||||||
|
"\n"
|
||||||
|
"This usage causes mdadm to monitor a number of md arrays by periodically\n"
|
||||||
|
"polling their status and acting on any changes.\n"
|
||||||
|
"If any devices are listed then those devices are monitored, otherwise\n"
|
||||||
|
"all devices listed in the config file are monitored.\n"
|
||||||
|
"The address for mailing advisories to, and the program to handle\n"
|
||||||
|
"each change can be specified in the config file or on the command line.\n"
|
||||||
|
"If no mail address or program are specified, then mdadm reports all\n"
|
||||||
|
"state changes to stdout.\n"
|
||||||
|
"\n"
|
||||||
|
"Options that are valid with the monitor (--F --follow) mode are:\n"
|
||||||
|
" --mail= -m : Address to mail alerts of failure to\n"
|
||||||
|
" --program= -p : Program to run when an event is detected\n"
|
||||||
|
" --alert= : same as --program\n"
|
||||||
|
" --delay= -d : seconds of delay between polling state. default=60\n"
|
||||||
|
" --config= -c : specify a different config file\n"
|
||||||
|
" --scan -s : find mail-address/program in config file\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
char Help_config[] =
|
||||||
|
"The /etc/mdadm.conf config file:\n\n"
|
||||||
|
" The config file contains, apart from blank lines and comment lines that\n"
|
||||||
|
" start with a hash(#), four sorts of configuration lines: array lines, \n"
|
||||||
|
" device lines, mailaddr lines and program lines.\n"
|
||||||
|
" Each configuration line is constructed of a number of space separated\n"
|
||||||
|
" words, and can be continued on subsequent physical lines by indenting\n"
|
||||||
|
" those lines.\n"
|
||||||
|
"\n"
|
||||||
|
" A device line starts with the word 'device' and then has a number of words\n"
|
||||||
|
" which identify devices. These words should be names of devices in the\n"
|
||||||
|
" filesystem, and can contain wildcards. There can be multiple words or each\n"
|
||||||
|
" device line, and multiple device lines. All devices so listed are checked\n"
|
||||||
|
" for relevant super blocks when assembling arrays.\n"
|
||||||
|
"\n"
|
||||||
|
" An array line start with the word 'array'. This is followed by the name of\n"
|
||||||
|
" the array device in the filesystem, e.g. '/dev/md2'. Subsequent words\n"
|
||||||
|
" describe the identity of the array, used to recognise devices to include in the\n"
|
||||||
|
" 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"
|
||||||
|
" 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"
|
||||||
|
" one Email address. 'mdadm --monitor --scan' will send alerts of failed drives\n"
|
||||||
|
" to this Email address."
|
||||||
|
"\n"
|
||||||
|
" A program line starts with the word 'program' and should contain exactly\n"
|
||||||
|
" one program name. 'mdadm --monitor --scan' will run this program when any\n"
|
||||||
|
" event is detected.\n"
|
||||||
"\n"
|
"\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -340,5 +460,17 @@ mapping_t pers[] = {
|
||||||
{ "4", 4},
|
{ "4", 4},
|
||||||
{ "raid5", 5},
|
{ "raid5", 5},
|
||||||
{ "5", 5},
|
{ "5", 5},
|
||||||
|
{ "multipath", -4},
|
||||||
|
{ "mp", -4},
|
||||||
{ NULL, 0}
|
{ NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
mapping_t modes[] = {
|
||||||
|
{ "assemble", ASSEMBLE},
|
||||||
|
{ "build", BUILD},
|
||||||
|
{ "create", CREATE},
|
||||||
|
{ "manage", MANAGE},
|
||||||
|
{ "misc", MISC},
|
||||||
|
{ "monitor", MONITOR},
|
||||||
|
};
|
||||||
|
|
15
TODO
15
TODO
|
@ -1,20 +1,27 @@
|
||||||
|
|
||||||
|
|
||||||
?? Allow -S /dev/md? - current complains subsequent not a/d/r
|
?? Allow -S /dev/md? - current complains subsequent not a/d/r - DONE
|
||||||
|
|
||||||
* new "Query" mode to subsume --detail and --examine.
|
* new "Query" mode to subsume --detail and --examine.
|
||||||
--query or -Q, takes a device and tells if it is an MD device,
|
--query or -Q, takes a device and tells if it is an MD device,
|
||||||
and also tells in a raid superblock is found.
|
and also tells in a raid superblock is found.
|
||||||
|
DONE
|
||||||
|
|
||||||
* write proc.c to parse /proc/mdstat file, and maybe /proc/partitions too.
|
* write mdstat.c to parse /proc/mdstat file
|
||||||
Build list of arrays: name, rebuild-percent
|
Build list of arrays: name, rebuild-percent
|
||||||
|
DONE
|
||||||
|
|
||||||
* --detail --scan to read mdadm.conf, and then iterate over these,
|
* parse /proc/partitions and map major/minor into /dev/* names,
|
||||||
|
and use that for default DEVICE list ????
|
||||||
|
|
||||||
|
* --detail --scan to read /proc/mdstat, and then iterate over these,
|
||||||
but assume --brief. --verbose can override
|
but assume --brief. --verbose can override
|
||||||
check each subdevice to see if it is in conf_get_devs.
|
check each subdevice to see if it is in conf_get_devs.
|
||||||
Warn if not.
|
Warn if not.
|
||||||
|
DONE, but don't warn yet...
|
||||||
|
|
||||||
* Support multipath ... maybe...
|
* Support multipath ... maybe...
|
||||||
|
maybe DONE
|
||||||
|
|
||||||
* --follow to syslog
|
* --follow to syslog
|
||||||
|
|
||||||
|
|
73
config.c
73
config.c
|
@ -70,7 +70,7 @@
|
||||||
#endif
|
#endif
|
||||||
char DefaultConfFile[] = CONFFILE;
|
char DefaultConfFile[] = CONFFILE;
|
||||||
|
|
||||||
char *keywords[] = { "device", "array", NULL };
|
char *keywords[] = { "device", "array", "mailaddr", "program", NULL };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* match_keyword returns an index into the keywords array, or -1 for no match
|
* match_keyword returns an index into the keywords array, or -1 for no match
|
||||||
|
@ -202,7 +202,7 @@ struct conf_dev {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int devline(char *line)
|
void devline(char *line)
|
||||||
{
|
{
|
||||||
char *w;
|
char *w;
|
||||||
struct conf_dev *cd;
|
struct conf_dev *cd;
|
||||||
|
@ -236,6 +236,7 @@ void arrayline(char *line)
|
||||||
mis.raid_disks = -1;
|
mis.raid_disks = -1;
|
||||||
mis.devices = NULL;
|
mis.devices = NULL;
|
||||||
mis.devname = NULL;
|
mis.devname = NULL;
|
||||||
|
mis.spare_group = NULL;
|
||||||
|
|
||||||
for (w=dl_next(line); w!=line; w=dl_next(w)) {
|
for (w=dl_next(line); w!=line; w=dl_next(w)) {
|
||||||
if (w[0] == '/') {
|
if (w[0] == '/') {
|
||||||
|
@ -302,7 +303,37 @@ void arrayline(char *line)
|
||||||
mddevlp = &mi->next;
|
mddevlp = &mi->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *alert_email = NULL;
|
||||||
|
void mailline(char *line)
|
||||||
|
{
|
||||||
|
char *w;
|
||||||
|
|
||||||
|
for (w=dl_next(line); w != line ; w=dl_next(w)) {
|
||||||
|
if (alert_email == NULL)
|
||||||
|
alert_email = strdup(w);
|
||||||
|
else
|
||||||
|
fprintf(stderr, Name ": excess address on MAIL line: %s - ignored\n",
|
||||||
|
w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *alert_program = NULL;
|
||||||
|
void programline(char *line)
|
||||||
|
{
|
||||||
|
char *w;
|
||||||
|
|
||||||
|
for (w=dl_next(line); w != line ; w=dl_next(w)) {
|
||||||
|
if (alert_program == NULL)
|
||||||
|
alert_program = strdup(w);
|
||||||
|
else
|
||||||
|
fprintf(stderr, Name ": excess program on PROGRAM line: %s - ignored\n",
|
||||||
|
w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int loaded = 0;
|
int loaded = 0;
|
||||||
|
|
||||||
void load_conffile(char *conffile)
|
void load_conffile(char *conffile)
|
||||||
|
@ -324,9 +355,15 @@ void load_conffile(char *conffile)
|
||||||
case 0: /* DEVICE */
|
case 0: /* DEVICE */
|
||||||
devline(line);
|
devline(line);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1: /* ARRAY */
|
||||||
arrayline(line);
|
arrayline(line);
|
||||||
break;
|
break;
|
||||||
|
case 2: /* MAIL */
|
||||||
|
mailline(line);
|
||||||
|
break;
|
||||||
|
case 3: /* PROGRAM */
|
||||||
|
programline(line);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, Name ": Unknown keyword %s\n", line);
|
fprintf(stderr, Name ": Unknown keyword %s\n", line);
|
||||||
}
|
}
|
||||||
|
@ -337,6 +374,18 @@ void load_conffile(char *conffile)
|
||||||
/* printf("got file\n"); */
|
/* printf("got file\n"); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *conf_get_mailaddr(char *conffile)
|
||||||
|
{
|
||||||
|
load_conffile(conffile);
|
||||||
|
return alert_email;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *conf_get_program(char *conffile)
|
||||||
|
{
|
||||||
|
load_conffile(conffile);
|
||||||
|
return alert_program;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mddev_ident_t conf_get_ident(char *conffile, char *dev)
|
mddev_ident_t conf_get_ident(char *conffile, char *dev)
|
||||||
{
|
{
|
||||||
|
@ -369,16 +418,16 @@ mddev_dev_t conf_get_devs(char *conffile)
|
||||||
glob(cd->name, flags, NULL, &globbuf);
|
glob(cd->name, flags, NULL, &globbuf);
|
||||||
flags |= GLOB_APPEND;
|
flags |= GLOB_APPEND;
|
||||||
}
|
}
|
||||||
|
if (flags & GLOB_APPEND) {
|
||||||
for (i=0; i<globbuf.gl_pathc; i++) {
|
for (i=0; i<globbuf.gl_pathc; i++) {
|
||||||
mddev_dev_t t = malloc(sizeof(*t));
|
mddev_dev_t t = malloc(sizeof(*t));
|
||||||
t->devname = strdup(globbuf.gl_pathv[i]);
|
t->devname = strdup(globbuf.gl_pathv[i]);
|
||||||
t->next = dlist;
|
t->next = dlist;
|
||||||
dlist = t;
|
dlist = t;
|
||||||
/* printf("one dev is %s\n", t->devname);*/
|
/* printf("one dev is %s\n", t->devname);*/
|
||||||
|
}
|
||||||
|
globfree(&globbuf);
|
||||||
}
|
}
|
||||||
globfree(&globbuf);
|
|
||||||
|
|
||||||
|
|
||||||
return dlist;
|
return dlist;
|
||||||
}
|
}
|
||||||
|
|
2
dlink.h
2
dlink.h
|
@ -15,7 +15,7 @@ struct __dl_head
|
||||||
#define dl_next(p) *((void**)&(((struct __dl_head*)(p))[-1].dh_next))
|
#define dl_next(p) *((void**)&(((struct __dl_head*)(p))[-1].dh_next))
|
||||||
#define dl_prev(p) *((void**)&(((struct __dl_head*)(p))[-1].dh_prev))
|
#define dl_prev(p) *((void**)&(((struct __dl_head*)(p))[-1].dh_prev))
|
||||||
|
|
||||||
void *dl_head();
|
void *dl_head(void);
|
||||||
char *dl_strdup(char *);
|
char *dl_strdup(char *);
|
||||||
char *dl_strndup(char *, int);
|
char *dl_strndup(char *, int);
|
||||||
void dl_insert(void*, void*);
|
void dl_insert(void*, void*);
|
||||||
|
|
130
md.4
130
md.4
|
@ -9,9 +9,9 @@ md \- Multiple Device driver aka Linux Software Raid
|
||||||
The
|
The
|
||||||
.B md
|
.B md
|
||||||
driver provides virtual devices that are created from one or more
|
driver provides virtual devices that are created from one or more
|
||||||
independant underlying devices. This array of devices often contains
|
independent underlying devices. This array of devices often contains
|
||||||
redundancy, and hence the acronym RAID which stands for a Redundant
|
redundancy, and hence the acronym RAID which stands for a Redundant
|
||||||
Array of Independant Devices.
|
Array of Independent Devices.
|
||||||
.PP
|
.PP
|
||||||
.B md
|
.B md
|
||||||
support RAID levels 1 (mirroring) 4 (striped array with parity device) and 5
|
support RAID levels 1 (mirroring) 4 (striped array with parity device) and 5
|
||||||
|
@ -20,13 +20,13 @@ device fails while using one of these level, the array will continue
|
||||||
to function.
|
to function.
|
||||||
.PP
|
.PP
|
||||||
.B md
|
.B md
|
||||||
also supports a number of pseudo RAID (non-redundant) configuations
|
also supports a number of pseudo RAID (non-redundant) configurations
|
||||||
including RAID0 (striped array), LINEAR (catenated array) and
|
including RAID0 (striped array), LINEAR (catenated array) and
|
||||||
MULTIPATH (a set of different interfaces to the same device).
|
MULTIPATH (a set of different interfaces to the same device).
|
||||||
|
|
||||||
.SS MD SUPER BLOCK
|
.SS MD SUPER BLOCK
|
||||||
With the exception of Legacy Arrays described below, each device that
|
With the exception of Legacy Arrays described below, each device that
|
||||||
is incorportated into an MD array has a
|
is incorporated into an MD array has a
|
||||||
.I super block
|
.I super block
|
||||||
written towards the end of the device. This superblock records
|
written towards the end of the device. This superblock records
|
||||||
information about the structure and state of the array so that the
|
information about the structure and state of the array so that the
|
||||||
|
@ -74,16 +74,134 @@ data that is on the array. However this cannot be done on a live
|
||||||
array.
|
array.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.SS RAID0
|
.SS RAID0
|
||||||
|
|
||||||
A RAID0 array (which has zero redundancy) is also known as a
|
A RAID0 array (which has zero redundancy) is also known as a
|
||||||
striped array.
|
striped array.
|
||||||
|
A RAID0 array is configured at creation with a
|
||||||
|
.B "Chunk Size"
|
||||||
|
which must be a multiple of 4 kibibytes.
|
||||||
|
|
||||||
|
The RAID0 driver places the first chunk of the array to the first
|
||||||
|
device, the second chunk to the second device, and so on until all
|
||||||
|
drives have been assigned one chuck. This collection of chunks forms
|
||||||
|
a
|
||||||
|
.BR stripe .
|
||||||
|
Further chunks are gathered into stripes in the same way which are
|
||||||
|
assigned to the remaining space in the drives.
|
||||||
|
|
||||||
|
If device in the array are not all the same size, then once the
|
||||||
|
smallest devices has been exhausted, the RAID0 driver starts
|
||||||
|
collecting chunks into smaller stripes that only span the drives which
|
||||||
|
still have remaining space.
|
||||||
|
|
||||||
|
|
||||||
.SS RAID1
|
.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.
|
||||||
|
|
||||||
|
Once initialised, each device in a RAID1 array contains exactly the
|
||||||
|
same data. Changes are written to all devices in parallel. Data is
|
||||||
|
read from any one device. The driver attempts to distribute read
|
||||||
|
requests across all devices to maximise performance.
|
||||||
|
|
||||||
|
All devices in a RAID1 array should be the same size. If they are
|
||||||
|
not, then only the amount of space available on the smallest device is
|
||||||
|
used. Any extra space on other devices is wasted.
|
||||||
|
|
||||||
.SS RAID4
|
.SS RAID4
|
||||||
|
|
||||||
|
A RAID4 array is like a RAID0 array with an extra device for storing
|
||||||
|
parity. Unlike RAID0, RAID4 also requires that all stripes span all
|
||||||
|
drives, so extra space on devices that are larger than the smallest is
|
||||||
|
wasted.
|
||||||
|
|
||||||
|
When any block in a RAID4 array is modified the parity block for that
|
||||||
|
stripe (i.e. the block in the parity device at the same device offset
|
||||||
|
as the stripe) is also modified so that the parity block always
|
||||||
|
contains the "parity" for the whole stripe. i.e. its contents is
|
||||||
|
equivalent to the result of performing an exclusive-or operation
|
||||||
|
between all the data blocks in the stripe.
|
||||||
|
|
||||||
|
This allows the array to continue to function if one device fails.
|
||||||
|
The data that was on that device can be calculated as needed from the
|
||||||
|
parity block and the other data blocks.
|
||||||
|
|
||||||
.SS RAID5
|
.SS RAID5
|
||||||
|
|
||||||
|
RAID5 is very similar to RAID4. The difference is that the parity
|
||||||
|
blocks for each stripe, instead of being on a single device, are
|
||||||
|
distributed across all devices. This allows more parallelism when
|
||||||
|
writing as two different block updates will quite possibly affect
|
||||||
|
parity blocks on different devices so there is less contention.
|
||||||
|
|
||||||
|
This also allows more parallelism when reading as read requests are
|
||||||
|
distributed over all the devices in the array instead of all but one.
|
||||||
|
|
||||||
.SS MUTIPATH
|
.SS MUTIPATH
|
||||||
.SS REBUILD/RESYNC
|
|
||||||
|
MULTIPATH is not really a RAID at all as there is only one real device
|
||||||
|
in a MULTIPATH md array. However there are multiple access points
|
||||||
|
(paths) to this device, and one of these paths might fail, so there
|
||||||
|
are some similarities.
|
||||||
|
|
||||||
|
A MULTIPATH array is composed of a number of different devices, often
|
||||||
|
fibre channel interfaces, that all refer the the same 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 UNCLEAN SHUTDOWN
|
||||||
|
|
||||||
|
When changes are made to an RAID1, RAID4, or RAID5 array there is a
|
||||||
|
possibility of inconsistency for short periods of time as each update
|
||||||
|
requires are least two block to be written to different devices, and
|
||||||
|
these writes probably wont happen at exactly the same time.
|
||||||
|
This is a system with one of these arrays is shutdown in the middle of
|
||||||
|
a write operation (e.g. due to power failure), the array may not be
|
||||||
|
consistent.
|
||||||
|
|
||||||
|
The handle this situation, the md driver marks an array as "dirty"
|
||||||
|
before writing any data to it, and marks it as "clean" when the array
|
||||||
|
is being disabled, e.g. at shutdown.
|
||||||
|
If the md driver finds an array to be dirty at startup, it proceeds to
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
.B does not
|
||||||
|
alert the operator to this condition. It should probably fail to
|
||||||
|
start an array in this condition without manual intervention.
|
||||||
|
|
||||||
|
.SS RECOVERY
|
||||||
|
|
||||||
|
If the md driver detects any error on a device in a RAID1, RAID4, or
|
||||||
|
RAID5 array, it immediately disables that device (marking it as faulty)
|
||||||
|
and continues operation on the remaining devices. If there is a spare
|
||||||
|
drive, the driver will start recreating on one of the spare drives the
|
||||||
|
data what was on that failed drive, either by copying a working drive
|
||||||
|
in a RAID1 configuration, or by doing calculations with the parity
|
||||||
|
block on RAID4 and RAID5.
|
||||||
|
|
||||||
|
Why this recovery process is happening, the md driver will monitor
|
||||||
|
accesses to the array and will slow down the rate of recovery if other
|
||||||
|
activity is happening, so that normal access to the array will not be
|
||||||
|
unduly affected. When no other activity is happening, the recovery
|
||||||
|
process proceeds at full speed. The actual speed targets for the two
|
||||||
|
different situations can be controlled by the
|
||||||
|
.B speed_limit_min
|
||||||
|
and
|
||||||
|
.B speed_limit_max
|
||||||
|
control files mentioned below.
|
||||||
|
|
||||||
|
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.TP
|
.TP
|
||||||
.B /proc/mdstat
|
.B /proc/mdstat
|
||||||
|
|
137
md.man
137
md.man
|
@ -11,10 +11,10 @@ SSYYNNOOPPSSIISS
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
DDEESSCCRRIIPPTTIIOONN
|
||||||
The mmdd driver provides virtual devices that are created
|
The mmdd driver provides virtual devices that are created
|
||||||
from one or more independant underlying devices. This
|
from one or more independent underlying devices. This
|
||||||
array of devices often contains redundancy, and hence the
|
array of devices often contains redundancy, and hence the
|
||||||
acronym RAID which stands for a Redundant Array of Inde-
|
acronym RAID which stands for a Redundant Array of Inde-
|
||||||
pendant Devices.
|
pendent Devices.
|
||||||
|
|
||||||
mmdd support RAID levels 1 (mirroring) 4 (striped array with
|
mmdd support RAID levels 1 (mirroring) 4 (striped array with
|
||||||
parity device) and 5 (striped array with distributed par-
|
parity device) and 5 (striped array with distributed par-
|
||||||
|
@ -23,14 +23,14 @@ DDEESSCCRRIIPPTTIIOONN
|
||||||
function.
|
function.
|
||||||
|
|
||||||
mmdd also supports a number of pseudo RAID (non-redundant)
|
mmdd also supports a number of pseudo RAID (non-redundant)
|
||||||
configuations including RAID0 (striped array), LINEAR
|
configurations including RAID0 (striped array), LINEAR
|
||||||
(catenated array) and MULTIPATH (a set of different inter-
|
(catenated array) and MULTIPATH (a set of different inter-
|
||||||
faces to the same device).
|
faces to the same device).
|
||||||
|
|
||||||
|
|
||||||
MMDD SSUUPPEERR BBLLOOCCKK
|
MMDD SSUUPPEERR BBLLOOCCKK
|
||||||
With the exception of Legacy Arrays described below, each
|
With the exception of Legacy Arrays described below, each
|
||||||
device that is incorportated into an MD array has a _s_u_p_e_r
|
device that is incorporated into an MD array has a _s_u_p_e_r
|
||||||
_b_l_o_c_k written towards the end of the device. This
|
_b_l_o_c_k written towards the end of the device. This
|
||||||
superblock records information about the structure and
|
superblock records information about the structure and
|
||||||
state of the array so that the array can be reliably re-
|
state of the array so that the array can be reliably re-
|
||||||
|
@ -77,16 +77,139 @@ DDEESSCCRRIIPPTTIIOONN
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RRAAIIDD00
|
RRAAIIDD00
|
||||||
A RAID0 array (which has zero redundancy) is also known as
|
A RAID0 array (which has zero redundancy) is also known as
|
||||||
a striped array.
|
a striped array. A RAID0 array is configured at creation
|
||||||
|
with a CChhuunnkk SSiizzee which must be a multiple of 4 kibibytes.
|
||||||
|
|
||||||
|
The RAID0 driver places the first chunk of the array to
|
||||||
|
the first device, the second chunk to the second device,
|
||||||
|
and so on until all drives have been assigned one chuck.
|
||||||
|
This collection of chunks forms a ssttrriippee. Further chunks
|
||||||
|
are gathered into stripes in the same way which are
|
||||||
|
assigned to the remaining space in the drives.
|
||||||
|
|
||||||
|
If device in the array are not all the same size, then
|
||||||
|
once the smallest devices has been exhausted, the RAID0
|
||||||
|
driver starts collecting chunks into smaller stripes that
|
||||||
|
only span the drives which still have remaining space.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RRAAIIDD11
|
RRAAIIDD11
|
||||||
|
A RAID1 array is also known as a mirrored set (though mir-
|
||||||
|
rors tend to provide reflect 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 read from any one device. The
|
||||||
|
driver attempts to distribute read requests across all
|
||||||
|
devices to maximise performance.
|
||||||
|
|
||||||
|
All devices in a RAID1 array should be the same size. If
|
||||||
|
they are not, then only the amount of space available on
|
||||||
|
the smallest device is used. Any extra space on other
|
||||||
|
devices is wasted.
|
||||||
|
|
||||||
|
|
||||||
RRAAIIDD44
|
RRAAIIDD44
|
||||||
|
A RAID4 array is like a RAID0 array with an extra device
|
||||||
|
for storing parity. Unlike RAID0, RAID4 also requires
|
||||||
|
that all stripes span all drives, so extra space on
|
||||||
|
devices that are larger than the smallest is wasted.
|
||||||
|
|
||||||
|
When any block in a RAID4 array is modified the parity
|
||||||
|
block for that stripe (i.e. the block in the parity device
|
||||||
|
at the same device offset as the stripe) is also modified
|
||||||
|
so that the parity block always contains the "parity" for
|
||||||
|
the whole stripe. i.e. its contents is equivalent to the
|
||||||
|
result of performing an exclusive-or operation between all
|
||||||
|
the data blocks in the stripe.
|
||||||
|
|
||||||
|
This allows the array to continue to function if one
|
||||||
|
device fails. The data that was on that device can be
|
||||||
|
calculated as needed from the parity block and the other
|
||||||
|
data blocks.
|
||||||
|
|
||||||
|
|
||||||
RRAAIIDD55
|
RRAAIIDD55
|
||||||
|
RAID5 is very similar to RAID4. The difference is that
|
||||||
|
the parity blocks for each stripe, instead of being on a
|
||||||
|
single device, are distributed across all devices. This
|
||||||
|
allows more parallelism when writing as two different
|
||||||
|
block updates will quite possibly affect parity blocks on
|
||||||
|
different devices so there is less contention.
|
||||||
|
|
||||||
|
This also allows more parallelism when reading as read
|
||||||
|
requests are distributed over all the devices in the array
|
||||||
|
instead of all but one.
|
||||||
|
|
||||||
|
|
||||||
MMUUTTIIPPAATTHH
|
MMUUTTIIPPAATTHH
|
||||||
RREEBBUUIILLDD//RREESSYYNNCC
|
MULTIPATH is not really a RAID at all as there is only one
|
||||||
|
real device in a MULTIPATH md array. However there are
|
||||||
|
multiple access points (paths) to this device, and one of
|
||||||
|
these paths might fail, so there are some similarities.
|
||||||
|
|
||||||
|
A MULTIPATH array is composed of a number of different
|
||||||
|
devices, often fibre channel interfaces, that all refer
|
||||||
|
the the same 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UUNNCCLLEEAANN SSHHUUTTDDOOWWNN
|
||||||
|
When changes are made to an RAID1, RAID4, or RAID5 array
|
||||||
|
there is a possibility of inconsistency for short periods
|
||||||
|
of time as each update requires are least two block to be
|
||||||
|
written to different devices, and these writes probably
|
||||||
|
wont happen at exactly the same time. This is a system
|
||||||
|
with one of these arrays is shutdown in the middle of a
|
||||||
|
write operation (e.g. due to power failure), the array may
|
||||||
|
not be consistent.
|
||||||
|
|
||||||
|
The handle this situation, the md driver marks an array as
|
||||||
|
"dirty" before writing any data to it, and marks it as
|
||||||
|
"clean" when the array is being disabled, e.g. at shut-
|
||||||
|
down. If the md driver finds an array to be dirty at
|
||||||
|
startup, it proceeds to correct any possibly inconsis-
|
||||||
|
tency. 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.
|
||||||
|
|
||||||
|
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 ddooeess
|
||||||
|
nnoott alert the operator to this condition. It should prob-
|
||||||
|
ably fail to start an array in this condition without man-
|
||||||
|
ual intervention.
|
||||||
|
|
||||||
|
|
||||||
|
RREECCOOVVEERRYY
|
||||||
|
If the md driver detects any error on a device in a RAID1,
|
||||||
|
RAID4, or RAID5 array, it immediately disables that device
|
||||||
|
(marking it as faulty) and continues operation on the
|
||||||
|
remaining devices. If there is a spare drive, the driver
|
||||||
|
will start recreating on one of the spare drives the data
|
||||||
|
what was on that failed drive, either by copying a working
|
||||||
|
drive in a RAID1 configuration, or by doing calculations
|
||||||
|
with the parity block on RAID4 and RAID5.
|
||||||
|
|
||||||
|
Why this recovery process is happening, the md driver will
|
||||||
|
monitor accesses to the array and will slow down the rate
|
||||||
|
of recovery if other activity is happening, so that normal
|
||||||
|
access to the array will not be unduly affected. When no
|
||||||
|
other activity is happening, the recovery process proceeds
|
||||||
|
at full speed. The actual speed targets for the two dif-
|
||||||
|
ferent situations can be controlled by the ssppeeeedd__lliimmiitt__mmiinn
|
||||||
|
and ssppeeeedd__lliimmiitt__mmaaxx control files mentioned below.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FFIILLEESS
|
FFIILLEESS
|
||||||
//pprroocc//mmddssttaatt
|
//pprroocc//mmddssttaatt
|
||||||
Contains information about the status of currently
|
Contains information about the status of currently
|
||||||
|
|
366
mdadm.8
366
mdadm.8
|
@ -1,5 +1,5 @@
|
||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.TH mdadm 8
|
.TH MDADM 8
|
||||||
.SH NAME
|
.SH NAME
|
||||||
mdadm \- manage MD devices
|
mdadm \- manage MD devices
|
||||||
.I aka
|
.I aka
|
||||||
|
@ -7,7 +7,7 @@ Linux Software Raid.
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
||||||
.BI mdadm " [mode] <raiddevice> [options] <subdevices>"
|
.BI mdadm " [mode] <raiddevice> [options] <component-devices>"
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
RAID devices are virtual devices created from two or more
|
RAID devices are virtual devices created from two or more
|
||||||
|
@ -33,7 +33,7 @@ and
|
||||||
Recent kernels (2002) also support a mode known as
|
Recent kernels (2002) also support a mode known as
|
||||||
.BR MULTIPATH .
|
.BR MULTIPATH .
|
||||||
.B mdadm
|
.B mdadm
|
||||||
does not support MULTIPATH as yet.
|
only provides limited support for MULTIPATH as yet.
|
||||||
|
|
||||||
.B mdadm
|
.B mdadm
|
||||||
is a program that can be used to create, manage, and monitor
|
is a program that can be used to create, manage, and monitor
|
||||||
|
@ -56,18 +56,13 @@ configuration file. Also mdadm helps with management of the configuration
|
||||||
file.
|
file.
|
||||||
.IP \(bu 4
|
.IP \(bu 4
|
||||||
.B mdadm
|
.B mdadm
|
||||||
can provide information about your arrays (through Detail and Examine)
|
can provide information about your arrays (through Query, Detail, and Examine)
|
||||||
that
|
that
|
||||||
.B raidtools
|
.B raidtools
|
||||||
cannot.
|
cannot.
|
||||||
.IP \(bu 4
|
|
||||||
.B raidtools
|
|
||||||
can manage MULTIPATH devices which
|
|
||||||
.B mdadm
|
|
||||||
cannot yet manage.
|
|
||||||
|
|
||||||
.SH MODES
|
.SH MODES
|
||||||
mdadm has 7 major modes of operation:
|
mdadm has 6 major modes of operation:
|
||||||
.TP
|
.TP
|
||||||
.B Assemble
|
.B Assemble
|
||||||
Assemble the parts of a previously created
|
Assemble the parts of a previously created
|
||||||
|
@ -89,32 +84,19 @@ Create a new array with per-device superblocks.
|
||||||
'''in several step create-add-add-run or it can all happen with one command.
|
'''in several step create-add-add-run or it can all happen with one command.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B Detail
|
.B Manage
|
||||||
Display the details of a given md device. Details include the RAID
|
This is for doing things to specific components of an array such as
|
||||||
level, the number of devices, which ones are faulty (if any), and the
|
adding new spares and removing faulty devices.
|
||||||
array UUID.
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B Examine
|
.B Misc
|
||||||
Examine a device to see if it is part of an md array, and print out
|
This mode allows operations on independent devices such as examine MD
|
||||||
the details of that array.
|
superblocks, erasing old superblocks and stopping active arrays.
|
||||||
This mode can also be used to examine a large number of devices and to
|
|
||||||
print out a summary of the arrays found in a format suitable for the
|
|
||||||
.B mdadm.conf
|
|
||||||
configuration file.
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B "Follow or Monitor"
|
.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.
|
||||||
|
|
||||||
.TP
|
|
||||||
.B Manage
|
|
||||||
This is for odd bits an pieces like hotadd, hotremove, setfaulty, stop,
|
|
||||||
readonly, readwrite.
|
|
||||||
'''If an array is only partially setup by the
|
|
||||||
'''Create or Assemble commands, subsequent Manage commands can finish the
|
|
||||||
'''job.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
||||||
Available options are:
|
Available options are:
|
||||||
|
@ -131,6 +113,13 @@ Build a legacy array without superblocks.
|
||||||
.BR -C ", " --create
|
.BR -C ", " --create
|
||||||
Create a new array.
|
Create a new array.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR -Q ", " --query
|
||||||
|
Examine a device to see
|
||||||
|
(1) if it is an md device and (2) if it is a component of an md
|
||||||
|
array.
|
||||||
|
Information about what is discovered is presented.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR -D ", " --detail
|
.BR -D ", " --detail
|
||||||
Print detail of one or more md devices.
|
Print detail of one or more md devices.
|
||||||
|
@ -164,6 +153,36 @@ Be less verbose. This is used with
|
||||||
and
|
and
|
||||||
.BR --examine .
|
.BR --examine .
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR -f ", " --force
|
||||||
|
Be more forceful about certain operations. See the various modes of
|
||||||
|
the exact meaning of this option in different contexts.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR -c ", " --config=
|
||||||
|
Specify the config file. Default is
|
||||||
|
.BR /etc/mdadm.conf .
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR -s ", " --scan
|
||||||
|
scan config file or
|
||||||
|
.B /proc/mdstat
|
||||||
|
for missing information.
|
||||||
|
In general, this option gives
|
||||||
|
.B mdadm
|
||||||
|
permission to get any missing information, like component devices,
|
||||||
|
array devices, array identities, and alert destination from the
|
||||||
|
configuration file:
|
||||||
|
.BR /etc/mdadm.conf .
|
||||||
|
One exception is MISC mode when using
|
||||||
|
.B --detail
|
||||||
|
or
|
||||||
|
.B --stop
|
||||||
|
in which case
|
||||||
|
.B --scan
|
||||||
|
says to get a list of array devices from
|
||||||
|
.BR /proc/mdstat .
|
||||||
|
|
||||||
.SH For create or build:
|
.SH For create or build:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
@ -222,15 +241,6 @@ don't have this minor number are excluded. If you create an array as
|
||||||
/dev/md1, then all superblock will contain the minor number 1, even if
|
/dev/md1, then all superblock will contain the minor number 1, even if
|
||||||
the array is later assembled as /dev/md2.
|
the array is later assembled as /dev/md2.
|
||||||
|
|
||||||
.TP
|
|
||||||
.BR -c ", " --config=
|
|
||||||
config file. Default is
|
|
||||||
.BR /etc/mdadm.conf .
|
|
||||||
|
|
||||||
.TP
|
|
||||||
.BR -s ", " --scan
|
|
||||||
scan config file for missing information
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR -f ", " --force
|
.BR -f ", " --force
|
||||||
Assemble the array even if some superblocks appear out-of-date
|
Assemble the array even if some superblocks appear out-of-date
|
||||||
|
@ -245,7 +255,7 @@ With
|
||||||
.B --run
|
.B --run
|
||||||
an attempt will be made to start it anyway.
|
an attempt will be made to start it anyway.
|
||||||
|
|
||||||
.SH General management
|
.SH For Manage mode:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR -a ", " --add
|
.BR -a ", " --add
|
||||||
|
@ -265,6 +275,8 @@ mark listed devices as faulty.
|
||||||
.BR --set-faulty
|
.BR --set-faulty
|
||||||
same as --fail.
|
same as --fail.
|
||||||
|
|
||||||
|
.SH For Misc mode:
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR -R ", " --run
|
.BR -R ", " --run
|
||||||
start a partially built array.
|
start a partially built array.
|
||||||
|
@ -281,8 +293,31 @@ mark array as readonly.
|
||||||
.BR -w ", " --readwrite
|
.BR -w ", " --readwrite
|
||||||
mark array as readwrite.
|
mark array as readwrite.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B --zero-superblock
|
||||||
|
If the device contains a valid md superblock, the block is
|
||||||
|
over-written with zeros. With
|
||||||
|
--force
|
||||||
|
the block where the superblock would be is over-written even if it
|
||||||
|
doesn't appear to be valid.
|
||||||
|
|
||||||
.SH ASSEMBLY MODE
|
.SH For Monitor mode:
|
||||||
|
.TP
|
||||||
|
.BR -m ", " --mail
|
||||||
|
Give a mail address to send alerts to.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR -p ", " --program ", " --alert
|
||||||
|
Give a program to be run whenever an event is detected.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR -d ", " --delay
|
||||||
|
Give a delay in seconds.
|
||||||
|
.B mdadm
|
||||||
|
polls the md arrays and then waits this many seconds before polling
|
||||||
|
again. The default is 60 seconds.
|
||||||
|
|
||||||
|
.SH ASSEMBLE MODE
|
||||||
|
|
||||||
.HP 12
|
.HP 12
|
||||||
Usage:
|
Usage:
|
||||||
|
@ -296,7 +331,7 @@ Usage:
|
||||||
.PP
|
.PP
|
||||||
This usage assembles one or more raid arrays from pre-existing components.
|
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
|
For each array, mdadm needs to know the md device, the identity of the
|
||||||
array, and a number of sub devices. These can be found in a number of ways.
|
array, and a number of component-devices. These can be found in a number of ways.
|
||||||
|
|
||||||
The md device is either given before
|
The md device is either given before
|
||||||
.B --scan
|
.B --scan
|
||||||
|
@ -308,7 +343,7 @@ The identity can be given with the
|
||||||
option, with the
|
option, with the
|
||||||
.B --super-minor
|
.B --super-minor
|
||||||
option, can be found in in the config file, or will be taken from the
|
option, can be found in in the config file, or will be taken from the
|
||||||
super block on the first subdevice listed on the command line.
|
super block on the first component-device listed on the command line.
|
||||||
|
|
||||||
Devices can be given on the
|
Devices can be given on the
|
||||||
.B --assemble
|
.B --assemble
|
||||||
|
@ -387,7 +422,7 @@ can override this caution.
|
||||||
|
|
||||||
'''If the
|
'''If the
|
||||||
'''.B --size
|
'''.B --size
|
||||||
'''option is given, it is not necessary to list any subdevices in this command.
|
'''option is given, it is not necessary to list any component-devices in this command.
|
||||||
'''They can be added later, before a
|
'''They can be added later, before a
|
||||||
'''.B --run.
|
'''.B --run.
|
||||||
'''If no
|
'''If no
|
||||||
|
@ -404,64 +439,223 @@ be in use.
|
||||||
.B --readonly
|
.B --readonly
|
||||||
start the array readonly - not supported yet.
|
start the array readonly - not supported yet.
|
||||||
|
|
||||||
.SH DETAIL MODE
|
.SH MANAGE MODE
|
||||||
.HP 12
|
.HP 12
|
||||||
Usage:
|
Usage:
|
||||||
.B mdadm --detail
|
.B mdadm
|
||||||
.RB [ --brief ]
|
.I device
|
||||||
.I device ...
|
.I options... devices...
|
||||||
.PP
|
.PP
|
||||||
|
|
||||||
This usage sill print out the details of the given array including a
|
This usage will allow individual devices in an array to be failed,
|
||||||
list of component devices. To determine names for the devices,
|
removed or added. It is possible to perform multiple operations with
|
||||||
.B mdadm
|
on command. For example:
|
||||||
searches
|
.br
|
||||||
.B /dev
|
mdadm /dev/md0 -f /dev/hda1 -r /dev/hda1 /a /dev/hda1
|
||||||
for device files with the right major and minor numbers.
|
.br
|
||||||
|
will firstly mark
|
||||||
|
.B /dev/hda1
|
||||||
|
as faulty in
|
||||||
|
.B /dev/md0
|
||||||
|
and will then remove it from the array and finally add it back
|
||||||
|
in as a spare. However only one md array can be affect by a single
|
||||||
|
command.
|
||||||
|
|
||||||
With
|
.SH MISC MODE
|
||||||
.B --brief
|
.HP 12
|
||||||
|
Usage:
|
||||||
.B mdadm
|
.B mdadm
|
||||||
prints a single line that identifies the level, number of disks, and
|
.I options ...
|
||||||
UUID of the array. This line is suitable for inclusion in
|
.I devices ...
|
||||||
|
.PP
|
||||||
|
|
||||||
|
MISC mode includes a number if distinct operations that
|
||||||
|
operate on distinct devices. The operations are:
|
||||||
|
.TP
|
||||||
|
--query
|
||||||
|
The device is examined to see if it is
|
||||||
|
(1) an active md array, or
|
||||||
|
(2) a component of an md array.
|
||||||
|
The information discovered is reported.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
--detail
|
||||||
|
The device should be an active md device. mdadm will display
|
||||||
|
a detailed description of the array.
|
||||||
|
.B --brief
|
||||||
|
will cause the output to be less detailed and format to be
|
||||||
|
suitable for inclusion in
|
||||||
.BR /etc/mdadm.conf .
|
.BR /etc/mdadm.conf .
|
||||||
|
|
||||||
.SH EXAMINE MODE
|
.TP
|
||||||
|
--examine
|
||||||
|
The device should be a component of an md array. mdadm will
|
||||||
|
read the md superblock of the device and display the contents.
|
||||||
|
If
|
||||||
|
.B --brief
|
||||||
|
is given, or
|
||||||
|
.B --scan
|
||||||
|
then multiple devices that are components of the one array
|
||||||
|
are grouped together and reported in a single entry suitable
|
||||||
|
for inclusion in
|
||||||
|
.BR /etc/mdadm.conf .
|
||||||
|
|
||||||
|
Have
|
||||||
|
.B --scan
|
||||||
|
without listing any devices will cause all devices listed in the
|
||||||
|
config file to be examined.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
--stop
|
||||||
|
This devices should active md arrays which will be deactivated, if
|
||||||
|
they are not currently in use.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
--run
|
||||||
|
This will fully activate a partially assembled md array.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
--readonly
|
||||||
|
This will mark an active array as read-only, providing that it is
|
||||||
|
not currently being used.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
--readwrite
|
||||||
|
This will change a
|
||||||
|
.B readonly
|
||||||
|
array back to being read/write.
|
||||||
|
|
||||||
|
.SH MONITOR MODE
|
||||||
|
|
||||||
.HP 12
|
.HP 12
|
||||||
Usage:
|
Usage:
|
||||||
.B mdadm --examine
|
.B mdadm --monitor
|
||||||
.RB [ --scan ]
|
.I options... devices...
|
||||||
.RB [ --brief ]
|
|
||||||
.I device ...
|
|
||||||
.PP
|
.PP
|
||||||
This usage will examine some block devices to see if that have a valid
|
This usage causes
|
||||||
RAID superblock on them. The information in each valid raid
|
.B mdadm
|
||||||
superblock will be printed.
|
to periodically poll a number of md arrays and to report on any events
|
||||||
|
noticed.
|
||||||
|
.B mdadm
|
||||||
|
will never exit once it decides that there are arrays to be checked,
|
||||||
|
so it should normally be run in the background.
|
||||||
|
|
||||||
|
If any devices are listed on the command line,
|
||||||
|
.B mdadm
|
||||||
|
will only monitor those devices. Otherwise all arrays listed in the
|
||||||
|
configuration file will be monitored. Further, if
|
||||||
|
.B --scan
|
||||||
|
is given, then any other md devices that appear in
|
||||||
|
.B /proc/mdstat
|
||||||
|
will also be monitored.
|
||||||
|
|
||||||
|
The result of monitoring the arrays is the generation of events.
|
||||||
|
These events are passed to a separate program (is specified) and may
|
||||||
|
be mail to a given E-mail address.
|
||||||
|
|
||||||
|
|
||||||
If
|
If
|
||||||
.B --scan
|
.B --scan
|
||||||
is used, the no devices should be listed, and the complete set of
|
is given, then a program or an E-mail address must be specified on the
|
||||||
devices identified in the configuration file are checked.
|
command line or in the config file. If neither are available, then
|
||||||
.B --scan
|
|
||||||
implies
|
|
||||||
.B --brief
|
|
||||||
but this implication can be countered by specifying
|
|
||||||
.BR --verbose .
|
|
||||||
|
|
||||||
With
|
|
||||||
.B --brief
|
|
||||||
.B mdadm
|
.B mdadm
|
||||||
will output an config file entry of each distinct array that was
|
will not monitor anything.
|
||||||
found. This entry will list the UUID, the raid level, and a list of
|
Without
|
||||||
the individual devices on which a superblock for that array was found.
|
.B --scan
|
||||||
This output will by syntactically suitable for inclusion in the
|
.B mdadm
|
||||||
configuration file, but should
|
will continue monitoring along as something was found to monitor. If
|
||||||
.B NOT
|
no program or email is given, then each event is reported to
|
||||||
be used blindly. Often the array description that you want in the
|
.BR stdout .
|
||||||
configuration file is much less specific than that given by
|
|
||||||
.BR "mdadm -Bs" .
|
The different events are:
|
||||||
For example, you normally do not want to list the devices,
|
|
||||||
particularly if they are SCSI devices.
|
.RS 4
|
||||||
|
.TP
|
||||||
|
.B DeviceDisappeared
|
||||||
|
An md array which previously was configured appear to no longer be
|
||||||
|
configured.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B RebuildStarted
|
||||||
|
An md array started reconstruction.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI Rebuild NN
|
||||||
|
Where
|
||||||
|
.I NN
|
||||||
|
is 20, 40, 60, or 80, this indicates that rebuild has passed that many
|
||||||
|
percentage of the total.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B Fail
|
||||||
|
An active component device of an array has been marked as faulty.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B FailSpare
|
||||||
|
A spare component device which was being rebuilt to replace a faulty
|
||||||
|
device has failed.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B SpareActive
|
||||||
|
A spare component device which was being rebuilt to replace a faulty
|
||||||
|
device as been successfully rebuild and has been made active.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B NewArray
|
||||||
|
A new md array has been detected in the
|
||||||
|
.B /proc/mdstat
|
||||||
|
file.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B MoveSpare
|
||||||
|
A spare drive has been moved from one array in a
|
||||||
|
.B spare-group
|
||||||
|
to another to allow a failed drive to be replaced.
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
Only
|
||||||
|
.B Fail
|
||||||
|
and
|
||||||
|
.B FailSpare
|
||||||
|
cause Email to be sent. All events cause the program to be run.
|
||||||
|
The program is run with two or three arguments, they being the event
|
||||||
|
name, the array device and possibly a second device.
|
||||||
|
|
||||||
|
Each event has an associated array device (e.g.
|
||||||
|
.BR /dev/md1 )
|
||||||
|
and possibly a second device. For
|
||||||
|
.BR Fail ,
|
||||||
|
.BR FailSpare ,
|
||||||
|
and
|
||||||
|
.B SpareActive
|
||||||
|
the second device is the relevant component device.
|
||||||
|
For
|
||||||
|
.B MoveSpare
|
||||||
|
the second device is the array that the spare was moved from.
|
||||||
|
|
||||||
|
For
|
||||||
|
.B mdadm
|
||||||
|
to move spares from one array to another, the different arrays need to
|
||||||
|
be labelled with the same
|
||||||
|
.B spare-group
|
||||||
|
in the configuration file. The
|
||||||
|
.B spare-group
|
||||||
|
name can be any string. It is only necessary that different spare
|
||||||
|
groups use different name.
|
||||||
|
|
||||||
|
When
|
||||||
|
.B mdadm
|
||||||
|
detects that an array which is in a spare group has fewer active
|
||||||
|
devices than necessary for the complete array, and has no spare
|
||||||
|
devices, it will look for another array in the same spare group that
|
||||||
|
has a full complement of working drive and a spare. It will then
|
||||||
|
attempt to remove the spare from the second drive and add it to the
|
||||||
|
first.
|
||||||
|
If the removal succeeds but the adding fails, then it is added back to
|
||||||
|
the original array.
|
||||||
|
|
||||||
|
|
||||||
'''.SH BUGS
|
'''.SH BUGS
|
||||||
'''no known bugs.
|
'''no known bugs.
|
||||||
|
|
338
mdadm.c
338
mdadm.c
|
@ -34,7 +34,7 @@ int open_mddev(char *dev)
|
||||||
{
|
{
|
||||||
int mdfd = open(dev, O_RDWR, 0);
|
int mdfd = open(dev, O_RDWR, 0);
|
||||||
if (mdfd < 0)
|
if (mdfd < 0)
|
||||||
fprintf(stderr,Name ": error opening %s: %s\n",
|
fprintf(stderr, Name ": error opening %s: %s\n",
|
||||||
dev, strerror(errno));
|
dev, strerror(errno));
|
||||||
else if (md_get_version(mdfd) <= 0) {
|
else if (md_get_version(mdfd) <= 0) {
|
||||||
fprintf(stderr, Name ": %s does not appear to be an md device\n",
|
fprintf(stderr, Name ": %s does not appear to be an md device\n",
|
||||||
|
@ -49,12 +49,12 @@ int open_mddev(char *dev)
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char mode = '\0';
|
int mode = 0;
|
||||||
int opt;
|
int opt;
|
||||||
|
int option_index;
|
||||||
char *help_text;
|
char *help_text;
|
||||||
char *c;
|
char *c;
|
||||||
int rv;
|
int rv;
|
||||||
int i;
|
|
||||||
|
|
||||||
int chunk = 0;
|
int chunk = 0;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
@ -89,36 +89,22 @@ int main(int argc, char *argv[])
|
||||||
ident.super_minor= -1;
|
ident.super_minor= -1;
|
||||||
ident.devices=0;
|
ident.devices=0;
|
||||||
|
|
||||||
while ((opt=getopt_long(argc, argv,
|
while ((option_index = -1) ,
|
||||||
|
(opt=getopt_long(argc, argv,
|
||||||
short_options, long_options,
|
short_options, long_options,
|
||||||
NULL)) != -1) {
|
&option_index)) != -1) {
|
||||||
|
int newmode = mode;
|
||||||
|
/* firstly, so mode-independant options */
|
||||||
switch(opt) {
|
switch(opt) {
|
||||||
case '@': /* just incase they say --manage */
|
|
||||||
case 'A':
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
case 'D':
|
|
||||||
case 'E':
|
|
||||||
case 'F':
|
|
||||||
case 'H':
|
|
||||||
/* setting mode - only once */
|
|
||||||
if (mode) {
|
|
||||||
fprintf(stderr, Name ": --%s/-%c not allowed, mode already set to %s\n",
|
|
||||||
long_options[opt-'A'+1].name,
|
|
||||||
long_options[opt-'A'+1].val,
|
|
||||||
long_options[mode-'A'+1].name);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
mode = opt;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
help_text = Help;
|
help_text = Help;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'C': help_text = Help_create; break;
|
case ASSEMBLE : help_text = Help_assemble; break;
|
||||||
case 'B': help_text = Help_build; break;
|
case BUILD : help_text = Help_build; break;
|
||||||
case 'A': help_text = Help_assemble; break;
|
case CREATE : help_text = Help_create; break;
|
||||||
|
case MANAGE : help_text = Help_manage; break;
|
||||||
|
case MISC : help_text = Help_misc; break;
|
||||||
|
case MONITOR : help_text = Help_monitor; break;
|
||||||
}
|
}
|
||||||
fputs(help_text,stderr);
|
fputs(help_text,stderr);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -133,18 +119,83 @@ int main(int argc, char *argv[])
|
||||||
case 'b': brief = 1;
|
case 'b': brief = 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 1: /* an undecorated option - must be a device name.
|
case ':':
|
||||||
* Depending on mode, it could be that:
|
case '?':
|
||||||
* All devices listed are "md" devices : --Detail, -As
|
fputs(Usage, stderr);
|
||||||
* No devices are "md" devices : --Examine
|
exit(2);
|
||||||
* First device is "md", others are component: -A,-B,-C
|
}
|
||||||
* Only accept on device before mode is determined.
|
/* second, figure out the mode.
|
||||||
* If mode is @, then require devmode for other devices.
|
* Some options force the mode. Others
|
||||||
*/
|
* set the mode if it isn't already
|
||||||
if (devs_found > 0 && !mode ) {
|
*/
|
||||||
fprintf(stderr, Name ": Must give mode flag before second device name at %s\n", optarg);
|
|
||||||
exit(2);
|
switch(opt) {
|
||||||
|
case '@': /* just incase they say --manage */
|
||||||
|
newmode = MANAGE; break;
|
||||||
|
case 'a':
|
||||||
|
case 'r':
|
||||||
|
case 'f':
|
||||||
|
case 1 : if (!mode) newmode = MANAGE; break;
|
||||||
|
|
||||||
|
case 'A': newmode = ASSEMBLE; break;
|
||||||
|
case 'B': newmode = BUILD; break;
|
||||||
|
case 'C': newmode = CREATE; break;
|
||||||
|
case 'F': newmode = MONITOR;break;
|
||||||
|
|
||||||
|
case '#':
|
||||||
|
case 'D':
|
||||||
|
case 'E':
|
||||||
|
case 'Q': newmode = MISC; break;
|
||||||
|
case 'R':
|
||||||
|
case 'S':
|
||||||
|
case 'o':
|
||||||
|
case 'w':
|
||||||
|
case 'K': if (!mode) newmode = MISC; break;
|
||||||
|
}
|
||||||
|
if (mode && newmode == mode) {
|
||||||
|
/* everybody happy ! */
|
||||||
|
} else if (mode && newmode != mode) {
|
||||||
|
/* not allowed.. */
|
||||||
|
fprintf(stderr, Name ": ");
|
||||||
|
if (option_index >= 0)
|
||||||
|
fprintf(stderr, "--%s", long_options[option_index].name);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "-%c", opt);
|
||||||
|
fprintf(stderr, " would set mode to %s, but it is already %s.\n",
|
||||||
|
map_num(modes, newmode),
|
||||||
|
map_num(modes, mode));
|
||||||
|
exit(2);
|
||||||
|
} else if (!mode && newmode) {
|
||||||
|
mode = newmode;
|
||||||
|
} else {
|
||||||
|
/* special case of -c --help */
|
||||||
|
if (opt == 'c' &&
|
||||||
|
( strncmp(optarg, "--h", 3)==0 ||
|
||||||
|
strncmp(optarg, "-h", 2)==0)) {
|
||||||
|
fputs(Help_config, stderr);
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
if (option_index >= 0)
|
||||||
|
fprintf(stderr, "--%s", long_options[option_index].name);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "-%c", opt);
|
||||||
|
fprintf(stderr, " does not set the mode, and so cannot be first.\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we just set the mode, then done */
|
||||||
|
switch(opt) {
|
||||||
|
case '@':
|
||||||
|
case '#':
|
||||||
|
case 'A':
|
||||||
|
case 'B':
|
||||||
|
case 'C':
|
||||||
|
case 'F':
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (opt == 1) {
|
||||||
|
/* an undecorated option - must be a device name.
|
||||||
|
*/
|
||||||
if (devs_found > 0 && mode == '@' && !devmode) {
|
if (devs_found > 0 && mode == '@' && !devmode) {
|
||||||
fprintf(stderr, Name ": Must give on of -a/-r/-f for subsequent devices at %s\n", optarg);
|
fprintf(stderr, Name ": Must give on of -a/-r/-f for subsequent devices at %s\n", optarg);
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -162,22 +213,14 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
devs_found++;
|
devs_found++;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case ':':
|
|
||||||
case '?':
|
|
||||||
fputs(Usage, stderr);
|
|
||||||
exit(2);
|
|
||||||
default:
|
|
||||||
/* force mode setting - @==manage if nothing else */
|
|
||||||
if (!mode) mode = '@';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We've got a mode, and opt is now something else which
|
/* We've got a mode, and opt is now something else which
|
||||||
* could depend on the mode */
|
* could depend on the mode */
|
||||||
#define O(a,b) ((a<<8)|b)
|
#define O(a,b) ((a<<8)|b)
|
||||||
switch (O(mode,opt)) {
|
switch (O(mode,opt)) {
|
||||||
case O('C','c'):
|
case O(CREATE,'c'):
|
||||||
case O('B','c'): /* chunk or rounding */
|
case O(BUILD,'c'): /* chunk or rounding */
|
||||||
if (chunk) {
|
if (chunk) {
|
||||||
fprintf(stderr, Name ": chunk/rounding may only be specified once. "
|
fprintf(stderr, Name ": chunk/rounding may only be specified once. "
|
||||||
"Second value is %s.\n", optarg);
|
"Second value is %s.\n", optarg);
|
||||||
|
@ -191,7 +234,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('C','z'): /* size */
|
case O(CREATE,'z'): /* size */
|
||||||
if (size) {
|
if (size) {
|
||||||
fprintf(stderr, Name ": size may only be specified once. "
|
fprintf(stderr, Name ": size may only be specified once. "
|
||||||
"Second value is %s.\n", optarg);
|
"Second value is %s.\n", optarg);
|
||||||
|
@ -205,8 +248,8 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('C','l'):
|
case O(CREATE,'l'):
|
||||||
case O('B','l'): /* set raid level*/
|
case O(BUILD,'l'): /* set raid level*/
|
||||||
if (level != -10) {
|
if (level != -10) {
|
||||||
fprintf(stderr, Name ": raid level may only be set once. "
|
fprintf(stderr, Name ": raid level may only be set once. "
|
||||||
"Second value is %s.\n", optarg);
|
"Second value is %s.\n", optarg);
|
||||||
|
@ -218,12 +261,12 @@ int main(int argc, char *argv[])
|
||||||
optarg);
|
optarg);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
if (level > 0 && mode == 'B') {
|
if (level != 0 && level != -1 && mode == BUILD) {
|
||||||
fprintf(stderr, Name ": Raid level %s not permitted with --build.\n",
|
fprintf(stderr, Name ": Raid level %s not permitted with --build.\n",
|
||||||
optarg);
|
optarg);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
if (sparedisks > 0 && level < 1) {
|
if (sparedisks > 0 && level < 1 && level >= -1) {
|
||||||
fprintf(stderr, Name ": raid level %s is incompatible with spare-disks setting.\n",
|
fprintf(stderr, Name ": raid level %s is incompatible with spare-disks setting.\n",
|
||||||
optarg);
|
optarg);
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -231,7 +274,7 @@ int main(int argc, char *argv[])
|
||||||
ident.level = level;
|
ident.level = level;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('C','p'): /* raid5 layout */
|
case O(CREATE,'p'): /* raid5 layout */
|
||||||
if (layout >= 0) {
|
if (layout >= 0) {
|
||||||
fprintf(stderr,Name ": layout may only be sent once. "
|
fprintf(stderr,Name ": layout may only be sent once. "
|
||||||
"Second value was %s\n", optarg);
|
"Second value was %s\n", optarg);
|
||||||
|
@ -257,8 +300,8 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('C','n'):
|
case O(CREATE,'n'):
|
||||||
case O('B','n'): /* number of raid disks */
|
case O(BUILD,'n'): /* number of raid disks */
|
||||||
if (raiddisks) {
|
if (raiddisks) {
|
||||||
fprintf(stderr, Name ": raid-disks set twice: %d and %s\n",
|
fprintf(stderr, Name ": raid-disks set twice: %d and %s\n",
|
||||||
raiddisks, optarg);
|
raiddisks, optarg);
|
||||||
|
@ -273,13 +316,13 @@ int main(int argc, char *argv[])
|
||||||
ident.raid_disks = raiddisks;
|
ident.raid_disks = raiddisks;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('C','x'): /* number of spare (eXtra) discs */
|
case O(CREATE,'x'): /* number of spare (eXtra) discs */
|
||||||
if (sparedisks) {
|
if (sparedisks) {
|
||||||
fprintf(stderr,Name ": spare-disks set twice: %d and %s\n",
|
fprintf(stderr,Name ": spare-disks set twice: %d and %s\n",
|
||||||
sparedisks, optarg);
|
sparedisks, optarg);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
if (level > -10 && level < 1) {
|
if (level > -10 && level <= 0 && level >= -1) {
|
||||||
fprintf(stderr, Name ": spare-disks setting is incompatible with raid level %d\n",
|
fprintf(stderr, Name ": spare-disks setting is incompatible with raid level %d\n",
|
||||||
level);
|
level);
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -291,14 +334,14 @@ int main(int argc, char *argv[])
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case O('C','f'): /* force honouring of device list */
|
case O(CREATE,'f'): /* force honouring of device list */
|
||||||
case O('A','f'): /* force assembly */
|
case O(ASSEMBLE,'f'): /* force assembly */
|
||||||
case O('H','f'): /* force zero */
|
case O(MISC,'f'): /* force zero */
|
||||||
force=1;
|
force=1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* now for the Assemble options */
|
/* now for the Assemble options */
|
||||||
case O('A','u'): /* uuid of array */
|
case O(ASSEMBLE,'u'): /* uuid of array */
|
||||||
if (ident.uuid_set) {
|
if (ident.uuid_set) {
|
||||||
fprintf(stderr, Name ": uuid cannot be set twice. "
|
fprintf(stderr, Name ": uuid cannot be set twice. "
|
||||||
"Second value %s.\n", optarg);
|
"Second value %s.\n", optarg);
|
||||||
|
@ -312,7 +355,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('A','m'): /* super-minor for array */
|
case O(ASSEMBLE,'m'): /* super-minor for array */
|
||||||
if (ident.super_minor >= 0) {
|
if (ident.super_minor >= 0) {
|
||||||
fprintf(stderr, Name ": super-minor cannot be set twice. "
|
fprintf(stderr, Name ": super-minor cannot be set twice. "
|
||||||
"Second value: %s.\n", optarg);
|
"Second value: %s.\n", optarg);
|
||||||
|
@ -325,8 +368,8 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('A','c'): /* config file */
|
case O(ASSEMBLE,'c'): /* config file */
|
||||||
case O('F','c'):
|
case O(MONITOR,'c'):
|
||||||
if (configfile) {
|
if (configfile) {
|
||||||
fprintf(stderr, Name ": configfile cannot be set twice. "
|
fprintf(stderr, Name ": configfile cannot be set twice. "
|
||||||
"Second value is %s.\n", optarg);
|
"Second value is %s.\n", optarg);
|
||||||
|
@ -335,12 +378,13 @@ int main(int argc, char *argv[])
|
||||||
configfile = optarg;
|
configfile = optarg;
|
||||||
/* FIXME possibly check that config file exists. Even parse it */
|
/* FIXME possibly check that config file exists. Even parse it */
|
||||||
continue;
|
continue;
|
||||||
case O('A','s'): /* scan */
|
case O(ASSEMBLE,'s'): /* scan */
|
||||||
case O('E','s'):
|
case O(MISC,'s'):
|
||||||
|
case O(MONITOR,'s'):
|
||||||
scan = 1;
|
scan = 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('F','m'): /* mail address */
|
case O(MONITOR,'m'): /* mail address */
|
||||||
if (mailaddr)
|
if (mailaddr)
|
||||||
fprintf(stderr, Name ": only specify one mailaddress. %s ignored.\n",
|
fprintf(stderr, Name ": only specify one mailaddress. %s ignored.\n",
|
||||||
optarg);
|
optarg);
|
||||||
|
@ -348,7 +392,7 @@ int main(int argc, char *argv[])
|
||||||
mailaddr = optarg;
|
mailaddr = optarg;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('F','p'): /* alert program */
|
case O(MONITOR,'p'): /* alert program */
|
||||||
if (program)
|
if (program)
|
||||||
fprintf(stderr, Name ": only specify one alter program. %s ignored.\n",
|
fprintf(stderr, Name ": only specify one alter program. %s ignored.\n",
|
||||||
optarg);
|
optarg);
|
||||||
|
@ -356,7 +400,7 @@ int main(int argc, char *argv[])
|
||||||
program = optarg;
|
program = optarg;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('F','d'): /* delay in seconds */
|
case O(MONITOR,'d'): /* delay in seconds */
|
||||||
if (delay)
|
if (delay)
|
||||||
fprintf(stderr, Name ": only specify delay once. %s ignored.\n",
|
fprintf(stderr, Name ": only specify delay once. %s ignored.\n",
|
||||||
optarg);
|
optarg);
|
||||||
|
@ -374,29 +418,29 @@ int main(int argc, char *argv[])
|
||||||
/* now the general management options. Some are applicable
|
/* now the general management options. Some are applicable
|
||||||
* to other modes. None have arguments.
|
* to other modes. None have arguments.
|
||||||
*/
|
*/
|
||||||
case O('@','a'):
|
case O(MANAGE,'a'):
|
||||||
case O('C','a'):
|
case O(CREATE,'a'):
|
||||||
case O('B','a'):
|
case O(BUILD,'a'):
|
||||||
case O('A','a'): /* add a drive */
|
case O(ASSEMBLE,'a'): /* add a drive */
|
||||||
devmode = 'a';
|
devmode = 'a';
|
||||||
continue;
|
continue;
|
||||||
case O('@','r'): /* remove a drive */
|
case O(MANAGE,'r'): /* remove a drive */
|
||||||
devmode = 'r';
|
devmode = 'r';
|
||||||
continue;
|
continue;
|
||||||
case O('@','f'): /* set faulty */
|
case O(MANAGE,'f'): /* set faulty */
|
||||||
devmode = 'f';
|
devmode = 'f';
|
||||||
continue;
|
continue;
|
||||||
case O('@','R'):
|
case O(MANAGE,'R'):
|
||||||
case O('A','R'):
|
case O(ASSEMBLE,'R'):
|
||||||
case O('B','R'):
|
case O(BUILD,'R'):
|
||||||
case O('C','R'): /* Run the array */
|
case O(CREATE,'R'): /* Run the array */
|
||||||
if (runstop < 0) {
|
if (runstop < 0) {
|
||||||
fprintf(stderr, Name ": Cannot both Stop and Run an array\n");
|
fprintf(stderr, Name ": Cannot both Stop and Run an array\n");
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
runstop = 1;
|
runstop = 1;
|
||||||
continue;
|
continue;
|
||||||
case O('@','S'):
|
case O(MANAGE,'S'):
|
||||||
if (runstop > 0) {
|
if (runstop > 0) {
|
||||||
fprintf(stderr, Name ": Cannot both Run and Stop an array\n");
|
fprintf(stderr, Name ": Cannot both Run and Stop an array\n");
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -404,26 +448,44 @@ int main(int argc, char *argv[])
|
||||||
runstop = -1;
|
runstop = -1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O('@','o'):
|
case O(MANAGE,'o'):
|
||||||
if (readonly < 0) {
|
if (readonly < 0) {
|
||||||
fprintf(stderr, Name ": Cannot have both readonly and readwrite\n");
|
fprintf(stderr, Name ": Cannot have both readonly and readwrite\n");
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
readonly = 1;
|
readonly = 1;
|
||||||
continue;
|
continue;
|
||||||
case O('@','w'):
|
case O(MANAGE,'w'):
|
||||||
if (readonly > 0) {
|
if (readonly > 0) {
|
||||||
fprintf(stderr, "mkdctl: Cannot have both readwrite and readonly.\n");
|
fprintf(stderr, Name ": Cannot have both readwrite and readonly.\n");
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
readonly = -1;
|
readonly = -1;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
case O(MISC,'Q'):
|
||||||
|
case O(MISC,'D'):
|
||||||
|
case O(MISC,'E'):
|
||||||
|
case O(MISC,'K'):
|
||||||
|
case O(MISC,'R'):
|
||||||
|
case O(MISC,'S'):
|
||||||
|
case O(MISC,'o'):
|
||||||
|
case O(MISC,'w'):
|
||||||
|
if (devmode && devmode != opt &&
|
||||||
|
(devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
|
||||||
|
fprintf(stderr, Name ": --examine/-E cannot be given with -%c\n",
|
||||||
|
devmode =='E'?opt:devmode);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
devmode = opt;
|
||||||
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
/* We have now processed all the valid options. Anything else is
|
/* We have now processed all the valid options. Anything else is
|
||||||
* an error
|
* an error
|
||||||
*/
|
*/
|
||||||
fprintf(stderr, Name ": option %c not valid in mode %c\n",
|
fprintf(stderr, Name ": option %c not valid in %s mode\n",
|
||||||
opt, mode);
|
opt, map_num(modes, mode));
|
||||||
exit(2);
|
exit(2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -436,13 +498,13 @@ int main(int argc, char *argv[])
|
||||||
* hopefully it's mostly right but there might be some stuff
|
* hopefully it's mostly right but there might be some stuff
|
||||||
* missing
|
* missing
|
||||||
*
|
*
|
||||||
* That is mosty checked in ther per-mode stuff but...
|
* That is mosty checked in the per-mode stuff but...
|
||||||
*
|
*
|
||||||
* For @,B,C and A without -s, the first device listed must be an md device
|
* For @,B,C and A without -s, the first device listed must be an md device
|
||||||
* we check that here and open it.
|
* we check that here and open it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (mode=='@' || mode == 'B' || mode == 'C' || (mode == 'A' && ! scan)) {
|
if (mode==MANAGE || mode == BUILD || mode == CREATE || (mode == ASSEMBLE && ! scan)) {
|
||||||
if (devs_found < 1) {
|
if (devs_found < 1) {
|
||||||
fprintf(stderr, Name ": an md device must be given in this mode\n");
|
fprintf(stderr, Name ": an md device must be given in this mode\n");
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -452,10 +514,9 @@ int main(int argc, char *argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rv = 0;
|
rv = 0;
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case '@':/* Management */
|
case MANAGE:
|
||||||
/* readonly, add/remove, readwrite, runstop */
|
/* readonly, add/remove, readwrite, runstop */
|
||||||
if (readonly>0)
|
if (readonly>0)
|
||||||
rv = Manage_ro(devlist->devname, mdfd, readonly);
|
rv = Manage_ro(devlist->devname, mdfd, readonly);
|
||||||
|
@ -467,7 +528,7 @@ int main(int argc, char *argv[])
|
||||||
if (!rv && runstop)
|
if (!rv && runstop)
|
||||||
rv = Manage_runstop(devlist->devname, mdfd, runstop);
|
rv = Manage_runstop(devlist->devname, mdfd, runstop);
|
||||||
break;
|
break;
|
||||||
case 'A': /* Assemble */
|
case ASSEMBLE:
|
||||||
if (!scan)
|
if (!scan)
|
||||||
rv = Assemble(devlist->devname, mdfd, &ident, configfile,
|
rv = Assemble(devlist->devname, mdfd, &ident, configfile,
|
||||||
devlist->next,
|
devlist->next,
|
||||||
|
@ -513,32 +574,89 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'B': /* Build */
|
case BUILD:
|
||||||
rv = Build(devlist->devname, mdfd, chunk, level, raiddisks, devlist->next);
|
rv = Build(devlist->devname, mdfd, chunk, level, raiddisks, devlist->next);
|
||||||
break;
|
break;
|
||||||
case 'C': /* Create */
|
case CREATE:
|
||||||
rv = Create(devlist->devname, mdfd, chunk, level, layout, size,
|
rv = Create(devlist->devname, mdfd, chunk, level, layout, size,
|
||||||
raiddisks, sparedisks,
|
raiddisks, sparedisks,
|
||||||
devs_found-1, devlist->next, runstop, verbose, force);
|
devs_found-1, devlist->next, runstop, verbose, force);
|
||||||
break;
|
break;
|
||||||
case 'D': /* Detail */
|
case MISC:
|
||||||
for (dv=devlist ; dv; dv=dv->next)
|
|
||||||
rv |= Detail(dv->devname, brief);
|
if (devmode == 'E') {
|
||||||
break;
|
if (devlist == NULL && !scan) {
|
||||||
case 'E': /* Examine */
|
fprintf(stderr, Name ": No devices to examine\n");
|
||||||
if (devlist == NULL && scan==0) {
|
exit(2);
|
||||||
fprintf(stderr, Name ": No devices to examine\n");
|
}
|
||||||
exit(2);
|
if (devlist == NULL)
|
||||||
|
devlist = conf_get_devs(configfile);
|
||||||
|
if (devlist == NULL) {
|
||||||
|
fprintf(stderr, Name ": No devices listed in %s\n", configfile);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
rv = Examine(devlist, devlist?brief:!verbose, scan);
|
||||||
|
} else {
|
||||||
|
if (devlist == NULL) {
|
||||||
|
if ((devmode == 'S' ||devmode=='D') && scan) {
|
||||||
|
/* apply to all devices in /proc/mdstat */
|
||||||
|
struct mdstat_ent *ms = mdstat_read();
|
||||||
|
struct mdstat_ent *e;
|
||||||
|
for (e=ms ; e ; e=e->next) {
|
||||||
|
char *name = get_md_name(e->devnum);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
fprintf(stderr, Name ": cannot find device file for %s\n",
|
||||||
|
e->dev);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (devmode == 'D')
|
||||||
|
rv |= Detail(name, !verbose);
|
||||||
|
else if (devmode=='S') {
|
||||||
|
mdfd = open_mddev(name);
|
||||||
|
if (mdfd >= 0)
|
||||||
|
rv |= Manage_runstop(name, mdfd, -1);
|
||||||
|
}
|
||||||
|
put_md_name(name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, Name ": No devices given.\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (dv=devlist ; dv; dv=dv->next) {
|
||||||
|
switch(dv->disposition) {
|
||||||
|
case 'D':
|
||||||
|
rv |= Detail(dv->devname, brief); continue;
|
||||||
|
case 'K': /* Zero superblock */
|
||||||
|
rv |= Kill(dv->devname, force); continue;
|
||||||
|
case 'Q':
|
||||||
|
rv |= Query(dv->devname); continue;
|
||||||
|
}
|
||||||
|
mdfd = open_mddev(dv->devname);
|
||||||
|
if (mdfd>=0)
|
||||||
|
switch(dv->disposition) {
|
||||||
|
case 'R':
|
||||||
|
rv |= Manage_runstop(dv->devname, mdfd, 1); break;
|
||||||
|
case 'S':
|
||||||
|
rv |= Manage_runstop(dv->devname, mdfd, -1); break;
|
||||||
|
case 'o':
|
||||||
|
rv |= Manage_ro(dv->devname, mdfd, 1); break;
|
||||||
|
case 'w':
|
||||||
|
rv |= Manage_ro(dv->devname, mdfd, -1); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rv = Examine(devlist, devlist?brief:!verbose, configfile);
|
|
||||||
break;
|
break;
|
||||||
case 'F': /* Follow */
|
case MONITOR:
|
||||||
rv= Monitor(devlist, mailaddr, program,
|
/*
|
||||||
delay?delay:60, configfile);
|
if (!devlist && !scan) {
|
||||||
break;
|
fprintf(stderr, Name ": Cannot monitor: need --scan or at least one device\n");
|
||||||
case 'H': /* Zero superblock */
|
rv = 1;
|
||||||
for (dv=devlist ; dv; dv=dv->next)
|
break;
|
||||||
rv |= Kill(dv->devname, force);
|
}
|
||||||
|
*/ rv= Monitor(devlist, mailaddr, program,
|
||||||
|
delay?delay:60, scan, configfile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
exit(rv);
|
exit(rv);
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#DEVICE /dev/sd[bcdjkl]1
|
#DEVICE /dev/sd[bcdjkl]1
|
||||||
#DEVICE /dev/hda1 /dev/hdb1
|
#DEVICE /dev/hda1 /dev/hdb1
|
||||||
#
|
#
|
||||||
|
# If you mount devfs on /dev, then a suitable way to list all devices is:
|
||||||
|
#DEVICE /dev/discs/*/*
|
||||||
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# ARRAY lines specify an array to assemble and a method of identification.
|
# ARRAY lines specify an array to assemble and a method of identification.
|
||||||
|
@ -38,3 +41,17 @@
|
||||||
#ARRAY /dev/md0 UUID=3aaa0122:29827cfa:5331ad66:ca767371
|
#ARRAY /dev/md0 UUID=3aaa0122:29827cfa:5331ad66:ca767371
|
||||||
#ARRAY /dev/md1 superminor=1
|
#ARRAY /dev/md1 superminor=1
|
||||||
#ARRAY /dev/md2 devices=/dev/hda1,/dev/hda2
|
#ARRAY /dev/md2 devices=/dev/hda1,/dev/hda2
|
||||||
|
#
|
||||||
|
# ARRAY lines can also specify a "spare-group" for each array. mdadm --monitor
|
||||||
|
# will then move a spare between arrays in a spare-group if one array has a failed
|
||||||
|
# drive but no spare
|
||||||
|
#ARRAY /dev/md4 uuid=b23f3c6d:aec43a9f:fd65db85:369432df spare-group=group1
|
||||||
|
#ARRAY /dev/md5 uuid=19464854:03f71b1b:e0df2edd:246cc977 spare-group=group1
|
||||||
|
#
|
||||||
|
# When used in --follow (aka --monitor) mode, mdadm needs a
|
||||||
|
# mail address and/or a program. This can be given with "mailaddr"
|
||||||
|
# and "program" lines to that monitoring can be started using
|
||||||
|
# mdadm --follow --scan & echo $! > /var/run/mdadm
|
||||||
|
# If the lines are not found, mdadm will exit quietly
|
||||||
|
#MAILADDR root@mydomain.tld
|
||||||
|
#PROGRAM /usr/sbin/handle-mdadm-events
|
||||||
|
|
52
mdadm.conf.5
52
mdadm.conf.5
|
@ -11,7 +11,7 @@ is a tool for creating, managing, and monitoring RAID devices using the
|
||||||
driver in Linux.
|
driver in Linux.
|
||||||
.PP
|
.PP
|
||||||
Some common tasks, such as assembling all arrays, can be simplified
|
Some common tasks, such as assembling all arrays, can be simplified
|
||||||
by describing the devices and array in this configuation file.
|
by describing the devices and array in this configuration file.
|
||||||
|
|
||||||
.SS SYNTAX
|
.SS SYNTAX
|
||||||
The file should be seen as a collection of words separated by white
|
The file should be seen as a collection of words separated by white
|
||||||
|
@ -24,7 +24,7 @@ though it were a continuation of the previous line.
|
||||||
|
|
||||||
Empty lines are ignored, but otherwise each (non continuation) line
|
Empty lines are ignored, but otherwise each (non continuation) line
|
||||||
must start with a keyword as listed below. The key words are case
|
must start with a keyword as listed below. The key words are case
|
||||||
insensitve and can be abbreviated to 3 characters.
|
insensitive and can be abbreviated to 3 characters.
|
||||||
|
|
||||||
The keywords are:
|
The keywords are:
|
||||||
.TP
|
.TP
|
||||||
|
@ -59,7 +59,8 @@ The ARRAY lines identify actual arrays. The second word on the line
|
||||||
should be the name of the device where the array is normally
|
should be the name of the device where the array is normally
|
||||||
assembled, such as
|
assembled, such as
|
||||||
.BR /dev/md1 .
|
.BR /dev/md1 .
|
||||||
Subsequent words identify the array. If multiple identities are given,
|
Subsequent words identify the array, or identify the array as a member
|
||||||
|
of a group. If multiple identities are given,
|
||||||
then the array must match ALL identities to be considered a match.
|
then the array must match ALL identities to be considered a match.
|
||||||
Each identity word has a tag, and equals sign, and some value.
|
Each identity word has a tag, and equals sign, and some value.
|
||||||
The options are:
|
The options are:
|
||||||
|
@ -95,7 +96,52 @@ The value is the number of disks in a complete active array. As with
|
||||||
this is mainly for compatibility with the output of
|
this is mainly for compatibility with the output of
|
||||||
|
|
||||||
.BR "mdadm --examine --scan" .
|
.BR "mdadm --examine --scan" .
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B spare-group=
|
||||||
|
The value is a textual name for a group of arrays. All arrays with
|
||||||
|
the same
|
||||||
|
.B spare-group
|
||||||
|
name are considered to be part of the same group. The significance of
|
||||||
|
a group of arrays is that
|
||||||
|
.B mdadm
|
||||||
|
will, when monitoring the arrays, move a spare drive from one array in
|
||||||
|
a group to another array in that group if the first array had a failed
|
||||||
|
or missing drive but no spare.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B MAILADDR
|
||||||
|
The
|
||||||
|
.B mailaddr
|
||||||
|
line gives an E-mail address that alerts should be
|
||||||
|
sent to when
|
||||||
|
.M mdadm
|
||||||
|
is running in
|
||||||
|
.B --monitor
|
||||||
|
mode (and was given the
|
||||||
|
.B --scan
|
||||||
|
option). There should only be one
|
||||||
|
.B MAILADDR
|
||||||
|
line and it should have only one address.
|
||||||
|
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B PROGRAM
|
||||||
|
The
|
||||||
|
.B program
|
||||||
|
line gives the name of a program to be run when
|
||||||
|
.B "mdadm --monitor"
|
||||||
|
detects potentially interesting events on any of the arrays that it
|
||||||
|
is monitoring. This program gets run with two or three arguments, they
|
||||||
|
being the Event, the md device, and possibly the related component
|
||||||
|
device.
|
||||||
|
|
||||||
|
There should only be one
|
||||||
|
.B program
|
||||||
|
line and it should be give only one program.
|
||||||
|
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR mdadm (8),
|
.BR mdadm (8),
|
||||||
.BR md (4).
|
.BR md (4).
|
||||||
|
|
|
@ -15,7 +15,7 @@ DDEESSCCRRIIPPTTIIOONN
|
||||||
|
|
||||||
Some common tasks, such as assembling all arrays, can be
|
Some common tasks, such as assembling all arrays, can be
|
||||||
simplified by describing the devices and array in this
|
simplified by describing the devices and array in this
|
||||||
configuation file.
|
configuration file.
|
||||||
|
|
||||||
|
|
||||||
SSYYNNTTAAXX
|
SSYYNNTTAAXX
|
||||||
|
@ -30,7 +30,7 @@ DDEESSCCRRIIPPTTIIOONN
|
||||||
|
|
||||||
Empty lines are ignored, but otherwise each (non continua-
|
Empty lines are ignored, but otherwise each (non continua-
|
||||||
tion) line must start with a keyword as listed below. The
|
tion) line must start with a keyword as listed below. The
|
||||||
key words are case insensitve and can be abbreviated to 3
|
key words are case insensitive and can be abbreviated to 3
|
||||||
characters.
|
characters.
|
||||||
|
|
||||||
The keywords are:
|
The keywords are:
|
||||||
|
@ -57,46 +57,81 @@ DDEESSCCRRIIPPTTIIOONN
|
||||||
AARRRRAAYY The ARRAY lines identify actual arrays. The second
|
AARRRRAAYY The ARRAY lines identify actual arrays. The second
|
||||||
word on the line should be the name of the device
|
word on the line should be the name of the device
|
||||||
where the array is normally assembled, such as
|
where the array is normally assembled, such as
|
||||||
//ddeevv//mmdd11. Subsequent words identify the array. If
|
//ddeevv//mmdd11. Subsequent words identify the array, or
|
||||||
multiple identities are given, then the array must
|
identify the array as a member of a group. If mul-
|
||||||
match ALL identities to be considered a match.
|
tiple identities are given, then the array must
|
||||||
Each identity word has a tag, and equals sign, and
|
match ALL identities to be considered a match.
|
||||||
|
Each identity word has a tag, and equals sign, and
|
||||||
some value. The options are:
|
some value. The options are:
|
||||||
|
|
||||||
|
|
||||||
uuuuiidd== The value should be a 128 bit uuid in hexadeci-
|
uuuuiidd== The value should be a 128 bit uuid in hexadeci-
|
||||||
mal, with punctuation interspersed if desired.
|
mal, with punctuation interspersed if desired.
|
||||||
This must match the uuid stored in the
|
This must match the uuid stored in the
|
||||||
superblock.
|
superblock.
|
||||||
|
|
||||||
ssuuppeerr--mmiinnoorr==
|
ssuuppeerr--mmiinnoorr==
|
||||||
The value is an integer which indicates the
|
The value is an integer which indicates the
|
||||||
minor number that was stored in the superblock
|
minor number that was stored in the superblock
|
||||||
when the array was created. When an array is
|
when the array was created. When an array is
|
||||||
created as /dev/mdX, then the minor number X is
|
created as /dev/mdX, then the minor number X is
|
||||||
stored.
|
stored.
|
||||||
|
|
||||||
ddeevviicceess==
|
ddeevviicceess==
|
||||||
The value is a comma separated list of device
|
The value is a comma separated list of device
|
||||||
names. Precisely these devices will be used to
|
names. Precisely these devices will be used to
|
||||||
assemble the array. Note that the devices
|
assemble the array. Note that the devices
|
||||||
listed there must also be listed on a DEVICE
|
listed there must also be listed on a DEVICE
|
||||||
line.
|
line.
|
||||||
|
|
||||||
lleevveell== The value is a raid level. This is not nor-
|
lleevveell== The value is a raid level. This is not nor-
|
||||||
mally used to identify an array, but is sup-
|
mally used to identify an array, but is sup-
|
||||||
ported so that the output of
|
ported so that the output of
|
||||||
|
|
||||||
mmddaaddmm ----eexxaammiinnee ----ssccaann
|
mmddaaddmm ----eexxaammiinnee ----ssccaann
|
||||||
|
|
||||||
can be use directly in the configuration file.
|
can be use directly in the configuration file.
|
||||||
|
|
||||||
ddiisskkss== The value is the number of disks in a complete
|
ddiisskkss== The value is the number of disks in a complete
|
||||||
active array. As with lleevveell== this is mainly
|
active array. As with lleevveell== this is mainly
|
||||||
for compatibility with the output of
|
for compatibility with the output of
|
||||||
|
|
||||||
mmddaaddmm ----eexxaammiinnee ----ssccaann.
|
mmddaaddmm ----eexxaammiinnee ----ssccaann.
|
||||||
|
|
||||||
|
|
||||||
|
ssppaarree--ggrroouupp==
|
||||||
|
The value is a textual name for a group of
|
||||||
|
arrays. All arrays with the same ssppaarree--ggrroouupp
|
||||||
|
name are considered to be part of the same
|
||||||
|
group. The significance of a group of arrays
|
||||||
|
is that mmddaaddmm will, when monitoring the arrays,
|
||||||
|
move a spare drive from one array in a group to
|
||||||
|
another array in that group if the first array
|
||||||
|
had a failed or missing drive but no spare.
|
||||||
|
|
||||||
|
|
||||||
|
MMAAIILLAADDDDRR
|
||||||
|
The mmaaiillaaddddrr line gives an E-mail address that
|
||||||
|
alerts should be sent to when is running in ----mmoonnii--
|
||||||
|
ttoorr mode (and was given the ----ssccaann option). There
|
||||||
|
should only be one MMAAIILLAADDDDRR line and it should have
|
||||||
|
only one address.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PPRROOGGRRAAMM
|
||||||
|
The pprrooggrraamm line gives the name of a program to be
|
||||||
|
run when mmddaaddmm ----mmoonniittoorr detects potentially inter-
|
||||||
|
esting events on any of the arrays that it is moni-
|
||||||
|
toring. This program gets run with two or three
|
||||||
|
arguments, they being the Event, the md device, and
|
||||||
|
possibly the related component device.
|
||||||
|
|
||||||
|
There should only be one pprrooggrraamm line and it should
|
||||||
|
be give only one program.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
SSEEEE AALLSSOO
|
||||||
mmddaaddmm(8), mmdd(4).
|
mmddaaddmm(8), mmdd(4).
|
||||||
|
|
||||||
|
|
73
mdadm.h
73
mdadm.h
|
@ -42,21 +42,36 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <linux/kdev_t.h>
|
#include <linux/kdev_t.h>
|
||||||
#include <linux/fs.h>
|
/*#include <linux/fs.h> */
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <asm/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#define MD_MAJOR 9
|
#define MD_MAJOR 9
|
||||||
|
|
||||||
/* I seem to need this to make BLKGETSIZE64 to work... */
|
#ifndef BLKGETSIZE64
|
||||||
#define u64 __u64
|
#define BLKGETSIZE64 _IOR(0x12,114,sizeof(__u64)) /* return device size in bytes (u64 *arg) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "md_u.h"
|
#include "md_u.h"
|
||||||
|
#include "md_p.h"
|
||||||
|
|
||||||
#define Name "mdadm"
|
#define Name "mdadm"
|
||||||
|
|
||||||
|
enum mode {
|
||||||
|
ASSEMBLE=1,
|
||||||
|
BUILD,
|
||||||
|
CREATE,
|
||||||
|
MANAGE,
|
||||||
|
MISC,
|
||||||
|
MONITOR,
|
||||||
|
};
|
||||||
|
|
||||||
extern char short_options[];
|
extern char short_options[];
|
||||||
extern struct option long_options[];
|
extern struct option long_options[];
|
||||||
extern char Version[], Usage[], Help[], Help_create[], Help_build[], Help_assemble[];
|
extern char Version[], Usage[], Help[],
|
||||||
|
Help_create[], Help_build[], Help_assemble[],
|
||||||
|
Help_manage[], Help_misc[], Help_monitor[], Help_config[];
|
||||||
|
|
||||||
/* structures read from config file */
|
/* structures read from config file */
|
||||||
/* List of mddevice names and identifiers
|
/* List of mddevice names and identifiers
|
||||||
|
@ -99,13 +114,27 @@ typedef struct mapping {
|
||||||
int num;
|
int num;
|
||||||
} mapping_t;
|
} mapping_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct mdstat_ent {
|
||||||
|
char *dev;
|
||||||
|
int devnum;
|
||||||
|
int active;
|
||||||
|
char *level;
|
||||||
|
char *pattern; /* U or up, _ for down */
|
||||||
|
int percent; /* -1 if no resync */
|
||||||
|
struct mdstat_ent *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct mdstat_ent *mdstat_read(void);
|
||||||
|
extern void free_mdstat(struct mdstat_ent *ms);
|
||||||
|
|
||||||
#ifndef Sendmail
|
#ifndef Sendmail
|
||||||
#define Sendmail "/usr/lib/sendmail -t"
|
#define Sendmail "/usr/lib/sendmail -t"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char *map_num(mapping_t *map, int num);
|
extern char *map_num(mapping_t *map, int num);
|
||||||
extern int map_name(mapping_t *map, char *name);
|
extern int map_name(mapping_t *map, char *name);
|
||||||
extern mapping_t r5layout[], pers[];
|
extern mapping_t r5layout[], pers[], modes[];
|
||||||
|
|
||||||
extern char *map_dev(int major, int minor);
|
extern char *map_dev(int major, int minor);
|
||||||
|
|
||||||
|
@ -134,22 +163,42 @@ extern int Create(char *mddev, int mdfd,
|
||||||
int runstop, int verbose, int force);
|
int runstop, int verbose, int force);
|
||||||
|
|
||||||
extern int Detail(char *dev, int brief);
|
extern int Detail(char *dev, int brief);
|
||||||
extern int Examine(mddev_dev_t devlist, int brief, char *conffile);
|
extern int Query(char *dev);
|
||||||
|
extern int Examine(mddev_dev_t devlist, int brief, int scan);
|
||||||
extern int Monitor(mddev_dev_t devlist,
|
extern int Monitor(mddev_dev_t devlist,
|
||||||
char *mailaddr, char *alert_cmd,
|
char *mailaddr, char *alert_cmd,
|
||||||
int period,
|
int period, int scan,
|
||||||
char *config);
|
char *config);
|
||||||
|
|
||||||
extern int Kill(char *dev, int force);
|
extern int Kill(char *dev, int force);
|
||||||
|
|
||||||
extern int md_get_version(int fd);
|
extern int md_get_version(int fd);
|
||||||
extern int get_linux_version();
|
extern int get_linux_version(void);
|
||||||
extern int parse_uuid(char *str, int uuid[4]);
|
extern int parse_uuid(char *str, int uuid[4]);
|
||||||
extern int check_ext2(int fd, char *name);
|
extern int check_ext2(int fd, char *name);
|
||||||
extern int check_reiser(int fd, char *name);
|
extern int check_reiser(int fd, char *name);
|
||||||
extern int check_raid(int fd, char *name);
|
extern int check_raid(int fd, char *name);
|
||||||
|
|
||||||
extern mddev_ident_t conf_get_ident(char *, char*);
|
extern mddev_ident_t conf_get_ident(char *conffile, char *dev);
|
||||||
extern mddev_dev_t conf_get_devs(char *);
|
extern mddev_dev_t conf_get_devs(char *conffile);
|
||||||
|
extern char *conf_get_mailaddr(char *conffile);
|
||||||
|
extern char *conf_get_program(char *conffile);
|
||||||
|
extern char *conf_line(FILE *file);
|
||||||
|
extern void free_line(char *line);
|
||||||
|
extern int match_oneof(char *devices, char *devname);
|
||||||
|
extern int load_super(int fd, mdp_super_t *super);
|
||||||
|
extern void uuid_from_super(int uuid[4], mdp_super_t *super);
|
||||||
|
extern int same_uuid(int a[4], int b[4]);
|
||||||
|
extern int compare_super(mdp_super_t *first, mdp_super_t *second);
|
||||||
|
extern int calc_sb_csum(mdp_super_t *super);
|
||||||
|
extern int store_super(int fd, mdp_super_t *super);
|
||||||
|
extern int enough(int level, int raid_disks, int avail_disks);
|
||||||
|
extern int ask(char *mesg);
|
||||||
|
|
||||||
|
|
||||||
extern char *human_size(long long bytes);
|
extern char *human_size(long long bytes);
|
||||||
|
char *human_size_brief(long long bytes);
|
||||||
|
|
||||||
|
extern void put_md_name(char *name);
|
||||||
|
extern char *get_md_name(int dev);
|
||||||
|
|
||||||
|
|
423
mdadm.man
423
mdadm.man
|
@ -1,423 +0,0 @@
|
||||||
mdadm(8) mdadm(8)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NNAAMMEE
|
|
||||||
mdadm - manage MD devices _a_k_a Linux Software Raid.
|
|
||||||
|
|
||||||
|
|
||||||
SSYYNNOOPPSSIISS
|
|
||||||
mmddaaddmm _[_m_o_d_e_] _<_r_a_i_d_d_e_v_i_c_e_> _[_o_p_t_i_o_n_s_] _<_s_u_b_d_e_v_i_c_e_s_>
|
|
||||||
|
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
|
||||||
RAID devices are virtual devices created from two or more
|
|
||||||
real block devices. This allows multiple devices (typi-
|
|
||||||
cally disk drives or partitions there-of) to be combined
|
|
||||||
into a single device to hold (for example) a single
|
|
||||||
filesystem. Some RAID levels included redundancy and so
|
|
||||||
can survive some degree of device failure.
|
|
||||||
|
|
||||||
Linux Software RAID devices are implemented through the md
|
|
||||||
(Multiple Devices) device driver.
|
|
||||||
|
|
||||||
Currently, Linux supports LLIINNEEAARR md devices, RRAAIIDD00 (strip-
|
|
||||||
ing), RRAAIIDD11 (mirroring), RRAAIIDD44 and RRAAIIDD55..
|
|
||||||
|
|
||||||
Recent kernels (2002) also support a mode known as MMUULLTTII--
|
|
||||||
PPAATTHH. mmddaaddmm does not support MULTIPATH as yet.
|
|
||||||
|
|
||||||
mmddaaddmm is a program that can be used to create, manage, and
|
|
||||||
monitor MD devices. As such it provides a similar set of
|
|
||||||
functionality to the rraaiiddttoooollss packages. The key differ-
|
|
||||||
ences between mmddaaddmm and rraaiiddttoooollss are:
|
|
||||||
|
|
||||||
+o mmddaaddmm is a single program and not a collection of pro-
|
|
||||||
grams.
|
|
||||||
|
|
||||||
+o mmddaaddmm can perform (almost) all of its functions with-
|
|
||||||
out having a configuration file. Also mdadm helps
|
|
||||||
with management of the configuration file.
|
|
||||||
|
|
||||||
+o mmddaaddmm can provide information about your arrays
|
|
||||||
(through Detail and Examine) that rraaiiddttoooollss cannot.
|
|
||||||
|
|
||||||
+o rraaiiddttoooollss can manage MULTIPATH devices which mmddaaddmm
|
|
||||||
cannot yet manage.
|
|
||||||
|
|
||||||
|
|
||||||
MMOODDEESS
|
|
||||||
mdadm has 7 major modes of operation:
|
|
||||||
|
|
||||||
AAsssseemmbbllee
|
|
||||||
Assemble the parts of a previously created array
|
|
||||||
into an active array. Components can be explicitly
|
|
||||||
given or can be searched for. mmddaaddmm checks that
|
|
||||||
the components do form a bona fide array, and can,
|
|
||||||
on request, fiddle superblock information so as to
|
|
||||||
assemble a faulty array.
|
|
||||||
|
|
||||||
|
|
||||||
BBuuiilldd Build a legacy array without per-device
|
|
||||||
superblocks.
|
|
||||||
|
|
||||||
|
|
||||||
CCrreeaattee Create a new array with per-device superblocks.
|
|
||||||
|
|
||||||
|
|
||||||
DDeettaaiill Display the details of a given md device. Details
|
|
||||||
include the RAID level, the number of devices,
|
|
||||||
which ones are faulty (if any), and the array UUID.
|
|
||||||
|
|
||||||
|
|
||||||
EExxaammiinnee
|
|
||||||
Examine a device to see if it is part of an md
|
|
||||||
array, and print out the details of that array.
|
|
||||||
This mode can also be used to examine a large num-
|
|
||||||
ber of devices and to print out a summary of the
|
|
||||||
arrays found in a format suitable for the
|
|
||||||
mmddaaddmm..ccoonnff configuration file.
|
|
||||||
|
|
||||||
|
|
||||||
FFoollllooww oorr MMoonniittoorr
|
|
||||||
Monitor one or more md devices and act on any state
|
|
||||||
changes.
|
|
||||||
|
|
||||||
|
|
||||||
MMaannaaggee This is for odd bits an pieces like hotadd,
|
|
||||||
hotremove, setfaulty, stop, readonly, readwrite.
|
|
||||||
|
|
||||||
|
|
||||||
OOPPTTIIOONNSS
|
|
||||||
Available options are:
|
|
||||||
|
|
||||||
|
|
||||||
--AA, ----aasssseemmbbllee
|
|
||||||
Assemble an existing array.
|
|
||||||
|
|
||||||
|
|
||||||
--BB, ----bbuuiilldd
|
|
||||||
Build a legacy array without superblocks.
|
|
||||||
|
|
||||||
|
|
||||||
--CC, ----ccrreeaattee
|
|
||||||
Create a new array.
|
|
||||||
|
|
||||||
|
|
||||||
--DD, ----ddeettaaiill
|
|
||||||
Print detail of one or more md devices.
|
|
||||||
|
|
||||||
|
|
||||||
--EE, ----eexxaammiinnee
|
|
||||||
Print content of md superblock on device(s).
|
|
||||||
|
|
||||||
|
|
||||||
--FF, ----ffoollllooww, ----mmoonniittoorr
|
|
||||||
Select MMoonniittoorr mode.
|
|
||||||
|
|
||||||
|
|
||||||
--hh, ----hheellpp
|
|
||||||
Display help message or, after above option, mode
|
|
||||||
specific help message.
|
|
||||||
|
|
||||||
|
|
||||||
--VV, ----vveerrssiioonn
|
|
||||||
Print version information for mdadm.
|
|
||||||
|
|
||||||
|
|
||||||
--vv, ----vveerrbboossee
|
|
||||||
Be more verbose about what is happening.
|
|
||||||
|
|
||||||
|
|
||||||
--bb, ----bbrriieeff
|
|
||||||
Be less verbose. This is used with ----ddeettaaiill and
|
|
||||||
----eexxaammiinnee.
|
|
||||||
|
|
||||||
|
|
||||||
FFoorr ccrreeaattee oorr bbuuiilldd::
|
|
||||||
--cc, ----cchhuunnkk==
|
|
||||||
Specify chunk size of kibibytes. The default is
|
|
||||||
64.
|
|
||||||
|
|
||||||
|
|
||||||
----rroouunnddiinngg==
|
|
||||||
Specify rounding factor for linear array (==chunk
|
|
||||||
size)
|
|
||||||
|
|
||||||
|
|
||||||
--ll, ----lleevveell==
|
|
||||||
Set raid level. Options are: linear, raid0, 0,
|
|
||||||
stripe, raid1, 1, mirror, raid5, 4, raid5, 5.
|
|
||||||
Obviously some of these are synonymous. Only the
|
|
||||||
first 4 are valid when Building.
|
|
||||||
|
|
||||||
|
|
||||||
--pp, ----ppaarriittyy==
|
|
||||||
Set raid5 parity algorithm. Options are:
|
|
||||||
{left,right}-{,a}symmetric, la, ra, ls, rs. The
|
|
||||||
default is left-symmetric.
|
|
||||||
|
|
||||||
|
|
||||||
----llaayyoouutt==
|
|
||||||
same as --parity
|
|
||||||
|
|
||||||
|
|
||||||
--nn, ----rraaiidd--ddiisskkss==
|
|
||||||
number of active devices in array.
|
|
||||||
|
|
||||||
|
|
||||||
--xx, ----ssppaarree--ddiisskkss==
|
|
||||||
number of spare (eXtra) disks in initial array.
|
|
||||||
Spares can be added and removed later.
|
|
||||||
|
|
||||||
|
|
||||||
--zz, ----ssiizzee==
|
|
||||||
Amount (in Kibibytes) of space to use from each
|
|
||||||
drive in RAID1/4/5. This must be a multiple of the
|
|
||||||
chunk size, and must leave about 128Kb of space at
|
|
||||||
the end of the drive for the RAID superblock. If
|
|
||||||
this is not specified (as it normally is not) the
|
|
||||||
smallest drive (or partition) sets the size, though
|
|
||||||
if there is a variance among the drives of greater
|
|
||||||
than 1%, a warning is issued.
|
|
||||||
|
|
||||||
|
|
||||||
FFoorr aasssseemmbbllee::
|
|
||||||
--uu, ----uuuuiidd==
|
|
||||||
uuid of array to assemble. Devices which don't have
|
|
||||||
this uuid are excluded
|
|
||||||
|
|
||||||
|
|
||||||
--mm, ----ssuuppeerr--mmiinnoorr==
|
|
||||||
Minor number of device that array was created for.
|
|
||||||
Devices which don't have this minor number are
|
|
||||||
excluded. If you create an array as /dev/md1, then
|
|
||||||
all superblock will contain the minor number 1,
|
|
||||||
even if the array is later assembled as /dev/md2.
|
|
||||||
|
|
||||||
|
|
||||||
--cc, ----ccoonnffiigg==
|
|
||||||
config file. Default is //eettcc//mmddaaddmm..ccoonnff.
|
|
||||||
|
|
||||||
|
|
||||||
--ss, ----ssccaann
|
|
||||||
scan config file for missing information
|
|
||||||
|
|
||||||
|
|
||||||
--ff, ----ffoorrccee
|
|
||||||
Assemble the array even if some superblocks appear
|
|
||||||
out-of-date
|
|
||||||
|
|
||||||
|
|
||||||
--RR, ----rruunn
|
|
||||||
Attempt to start the array even if fewer drives
|
|
||||||
were given than are needed for a full array. Nor-
|
|
||||||
mally if not all drives are found and ----ssccaann is not
|
|
||||||
used, then the array will be assembled but not
|
|
||||||
started. With ----rruunn an attempt will be made to
|
|
||||||
start it anyway.
|
|
||||||
|
|
||||||
|
|
||||||
GGeenneerraall mmaannaaggeemmeenntt
|
|
||||||
--aa, ----aadddd
|
|
||||||
hotadd listed devices.
|
|
||||||
|
|
||||||
|
|
||||||
--rr, ----rreemmoovvee
|
|
||||||
remove listed devices. The must not be active.
|
|
||||||
i.e. they should be failed or spare devices.
|
|
||||||
|
|
||||||
|
|
||||||
--ff, ----ffaaiill
|
|
||||||
mark listed devices as faulty.
|
|
||||||
|
|
||||||
|
|
||||||
----sseett--ffaauullttyy
|
|
||||||
same as --fail.
|
|
||||||
|
|
||||||
|
|
||||||
--RR, ----rruunn
|
|
||||||
start a partially built array.
|
|
||||||
|
|
||||||
|
|
||||||
--SS, ----ssttoopp
|
|
||||||
deactivate array, releasing all resources.
|
|
||||||
|
|
||||||
|
|
||||||
--oo, ----rreeaaddoonnllyy
|
|
||||||
mark array as readonly.
|
|
||||||
|
|
||||||
|
|
||||||
--ww, ----rreeaaddwwrriittee
|
|
||||||
mark array as readwrite.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AASSSSEEMMBBLLYY MMOODDEE
|
|
||||||
Usage: mmddaaddmm ----aasssseemmbbllee _d_e_v_i_c_e _o_p_t_i_o_n_s_._._.
|
|
||||||
|
|
||||||
Usage: mmddaaddmm ----aasssseemmbbllee ----ssccaann _o_p_t_i_o_n_s_._._.
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
sub devices. These can be found in a number of ways.
|
|
||||||
|
|
||||||
The md device is either given before ----ssccaann or is found
|
|
||||||
from the config file. In the latter case, multiple md
|
|
||||||
devices can be started with a single mdadm command.
|
|
||||||
|
|
||||||
The identity can be given with the ----uuuuiidd option, with the
|
|
||||||
----ssuuppeerr--mmiinnoorr option, can be found in in the config file,
|
|
||||||
or will be taken from the super block on the first subde-
|
|
||||||
vice listed on the command line.
|
|
||||||
|
|
||||||
Devices can be given on the ----aasssseemmbbllee command line or
|
|
||||||
from the config file. Only devices which have an md
|
|
||||||
superblock which contains the right identity will be con-
|
|
||||||
sidered for any device.
|
|
||||||
|
|
||||||
The config file is only used if explicitly named with
|
|
||||||
----ccoonnffiigg or requested with ----ssccaann.. In the later case,
|
|
||||||
//eettcc//mmddaaddmm..ccoonnff is used.
|
|
||||||
|
|
||||||
If ----ssccaann is not given, then the config file will only be
|
|
||||||
used to find the identity of md arrays.
|
|
||||||
|
|
||||||
Normally the array will be started after it is assembled.
|
|
||||||
However is ----ssccaann is not given and insufficient drives
|
|
||||||
were lists to start a complete (non-degraded) array, then
|
|
||||||
the array is not started (to guard against usage errors).
|
|
||||||
To insist that the array be started in this case (as may
|
|
||||||
work for RAID1 or RAID5), give the ----rruunn flag.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BBUUIILLDD MMOODDEE
|
|
||||||
Usage: mmddaaddmm ----bbuuiilldd _d_e_v_i_c_e ----cchhuunnkk==_X ----lleevveell==_Y ----rraaiidd--
|
|
||||||
ddiisskkss==_Z _d_e_v_i_c_e_s
|
|
||||||
|
|
||||||
|
|
||||||
This usage is similar to ----ccrreeaattee. The difference is that
|
|
||||||
it creates a legacy array without a superblock. With these
|
|
||||||
arrays there is no difference between initially creating
|
|
||||||
the array and subsequently assembling the array, except
|
|
||||||
that hopefully there is useful data there in the second
|
|
||||||
case.
|
|
||||||
|
|
||||||
The level may only be 0, raid0, or linear. All devices
|
|
||||||
must be listed and the array will be started once com-
|
|
||||||
plete.
|
|
||||||
|
|
||||||
|
|
||||||
CCRREEAATTEE MMOODDEE
|
|
||||||
Usage: mmddaaddmm ----ccrreeaattee _d_e_v_i_c_e ----cchhuunnkk==_X ----lleevveell==_Y
|
|
||||||
----rraaiidd--ddiisskkss==_Z _d_e_v_i_c_e_s
|
|
||||||
|
|
||||||
|
|
||||||
This usage will initialise a new md array, associate some
|
|
||||||
devices with it, and activate the array.
|
|
||||||
|
|
||||||
As devices are added, they are checked to see if they con-
|
|
||||||
tain raid superblocks or filesystems. They are also check
|
|
||||||
to see if the variance in device size exceeds 1%.
|
|
||||||
|
|
||||||
If any discrepancy is found, the array will not automati-
|
|
||||||
cally be run, though the presence of a ----rruunn can override
|
|
||||||
this caution.
|
|
||||||
|
|
||||||
|
|
||||||
The General Management options that are valid with --cre-
|
|
||||||
ate are:
|
|
||||||
|
|
||||||
----rruunn insist of running the array even if some devices
|
|
||||||
look like they might be in use.
|
|
||||||
|
|
||||||
|
|
||||||
----rreeaaddoonnllyy
|
|
||||||
start the array readonly - not supported yet.
|
|
||||||
|
|
||||||
|
|
||||||
DDEETTAAIILL MMOODDEE
|
|
||||||
Usage: mmddaaddmm ----ddeettaaiill [----bbrriieeff] _d_e_v_i_c_e _._._.
|
|
||||||
|
|
||||||
|
|
||||||
This usage sill print out the details of the given array
|
|
||||||
including a list of component devices. To determine names
|
|
||||||
for the devices, mmddaaddmm searches //ddeevv for device files with
|
|
||||||
the right major and minor numbers.
|
|
||||||
|
|
||||||
With ----bbrriieeff mmddaaddmm prints a single line that identifies
|
|
||||||
the level, number of disks, and UUID of the array. This
|
|
||||||
line is suitable for inclusion in //eettcc//mmddaaddmm..ccoonnff.
|
|
||||||
|
|
||||||
|
|
||||||
EEXXAAMMIINNEE MMOODDEE
|
|
||||||
Usage: mmddaaddmm ----eexxaammiinnee [----ssccaann] [----bbrriieeff] _d_e_v_i_c_e _._._.
|
|
||||||
|
|
||||||
This usage will examine some block devices to see if that
|
|
||||||
have a valid RAID superblock on them. The information in
|
|
||||||
each valid raid superblock will be printed.
|
|
||||||
|
|
||||||
If ----ssccaann is used, the no devices should be listed, and
|
|
||||||
the complete set of devices identified in the configura-
|
|
||||||
tion file are checked. ----ssccaann implies ----bbrriieeff but this
|
|
||||||
implication can be countered by specifying ----vveerrbboossee.
|
|
||||||
|
|
||||||
With ----bbrriieeff mmddaaddmm will output an config file entry of
|
|
||||||
each distinct array that was found. This entry will list
|
|
||||||
the UUID, the raid level, and a list of the individual
|
|
||||||
devices on which a superblock for that array was found.
|
|
||||||
This output will by syntactically suitable for inclusion
|
|
||||||
in the configuration file, but should NNOOTT be used blindly.
|
|
||||||
Often the array description that you want in the configu-
|
|
||||||
ration file is much less specific than that given by mmddaaddmm
|
|
||||||
--BBss. For example, you normally do not want to list the
|
|
||||||
devices, particularly if they are SCSI devices.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FFIILLEESS
|
|
||||||
//pprroocc//mmddssttaatt
|
|
||||||
If you're using the //pprroocc filesystem, //pprroocc//mmddssttaatt gives
|
|
||||||
you informations about md devices status. This file is
|
|
||||||
not currently used by mmddaaddmm.
|
|
||||||
|
|
||||||
|
|
||||||
//eettcc//mmddaaddmm..ccoonnff
|
|
||||||
The config file lists which devices may be scanned to see
|
|
||||||
if they contain MD super block, and gives identifying
|
|
||||||
information (e.g. UUID) about known MD arrays. See
|
|
||||||
mmddaaddmm..ccoonnff(5) for more details.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TTOODDOO
|
|
||||||
Finish and document Follow mode.
|
|
||||||
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
|
||||||
For information on the various levels of RAID, check out:
|
|
||||||
|
|
||||||
|
|
||||||
http://ostenfeld.dk/~jakob/Software-RAID.HOWTO/
|
|
||||||
|
|
||||||
for new releases of the RAID driver check out:
|
|
||||||
|
|
||||||
|
|
||||||
ftp://ftp.kernel.org/pub/linux/kernel/peo-
|
|
||||||
ple/mingo/raid-patches
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
http://www.cse.unsw.edu.au/~neilb/patches/linux-
|
|
||||||
stable/
|
|
||||||
|
|
||||||
mmddaaddmm..ccoonnff(5), mmdd(4).
|
|
||||||
|
|
||||||
_r_a_i_d_t_a_b(5), _r_a_i_d_0_r_u_n(8), _r_a_i_d_s_t_o_p(8), _m_k_r_a_i_d(8)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mdadm(8)
|
|
|
@ -1,13 +1,12 @@
|
||||||
Summary: mdadm is used for controlling Linux md devices (aka RAID arrays)
|
Summary: mdadm is used for controlling Linux md devices (aka RAID arrays)
|
||||||
Name: mdadm
|
Name: mdadm
|
||||||
Version: 0.7.2
|
Version: 0.8
|
||||||
Release: 1
|
Release: 1
|
||||||
Source: http://www.cse.unsw.edu.au/~neilb/source/mdadm/mdadm-%{version}.tgz
|
Source: http://www.cse.unsw.edu.au/~neilb/source/mdadm/mdadm-%{version}.tgz
|
||||||
URL: http://www.cse.unsw.edu.au/~neilb/source/mdadm/
|
URL: http://www.cse.unsw.edu.au/~neilb/source/mdadm/
|
||||||
License: GPL
|
License: GPL
|
||||||
Group: Utilities/System
|
Group: Utilities/System
|
||||||
BuildRoot: ${_tmppath}/%{name}-root
|
BuildRoot: %{_tmppath}/%{name}-root
|
||||||
Packager: Danilo Godec <danci@agenda.si> (et.al.)
|
|
||||||
Obsoletes: mdctl
|
Obsoletes: mdctl
|
||||||
|
|
||||||
%description
|
%description
|
||||||
|
@ -33,7 +32,7 @@ make CFLAGS="$RPM_OPT_FLAGS" SYSCONFDIR="%{_sysconfdir}"
|
||||||
#rm -rf $RPM_BUILD_ROOT
|
#rm -rf $RPM_BUILD_ROOT
|
||||||
mkdir -p $RPM_BUILD_ROOT/%{_sbindir}
|
mkdir -p $RPM_BUILD_ROOT/%{_sbindir}
|
||||||
install -m755 mdadm $RPM_BUILD_ROOT/%{_sbindir}
|
install -m755 mdadm $RPM_BUILD_ROOT/%{_sbindir}
|
||||||
mkdir -p $RPM_BUILD_ROOT/${_sysconfdir}
|
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}
|
||||||
install -m644 mdadm.conf-example $RPM_BUILD_ROOT/%{_sysconfdir}/mdadm.conf
|
install -m644 mdadm.conf-example $RPM_BUILD_ROOT/%{_sysconfdir}/mdadm.conf
|
||||||
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man4
|
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man4
|
||||||
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man5
|
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||||
|
|
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* mdstat - parse /proc/mdstat file. Part of:
|
||||||
|
* mdadm - manage Linux "md" devices aka RAID arrays.
|
||||||
|
*
|
||||||
|
* Copyright (C) 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The /proc/mdstat file comes in at least 3 flavours:
|
||||||
|
* In an unpatched 2.2 kernel (md 0.36.6):
|
||||||
|
* Personalities : [n raidx] ...
|
||||||
|
* read_ahead {not set|%d sectors}
|
||||||
|
* md0 : {in}active{ raidX /dev/hda... %d blocks{ maxfault=%d}}
|
||||||
|
* md1 : .....
|
||||||
|
*
|
||||||
|
* Normally only 4 md lines, but all are listed.
|
||||||
|
*
|
||||||
|
* In a patched 2.2 kernel (md 0.90.0)
|
||||||
|
* Personalities : [raidx] ...
|
||||||
|
* read_ahead {not set|%d sectors}
|
||||||
|
* mdN : {in}active {(readonly)} raidX dev[%d]{(F)} ... %d blocks STATUS RESYNC
|
||||||
|
* ... Only initialised arrays listed
|
||||||
|
* unused: dev dev dev | <none>
|
||||||
|
*
|
||||||
|
* STATUS is personality dependant:
|
||||||
|
* linear: %dk rounding
|
||||||
|
* raid0: %dk chunks
|
||||||
|
* raid1: [%d/%d] [U_U] ( raid/working. operational or not)
|
||||||
|
* raid5: level 4/5, %dk chunk, algorithm %d [%d/%d] [U_U]
|
||||||
|
*
|
||||||
|
* RESYNC is empty or:
|
||||||
|
* {resync|recovery}=%u%% finish=%u.%umin
|
||||||
|
* or
|
||||||
|
* resync=DELAYED
|
||||||
|
*
|
||||||
|
* In a 2.4 kernel (md 0.90.0/2.4)
|
||||||
|
* Personalities : [raidX] ...
|
||||||
|
* read_ahead {not set|%d sectors}
|
||||||
|
* mdN : {in}active {(read-only)} raidX dev[%d]{(F)} ...
|
||||||
|
* %d blocks STATUS
|
||||||
|
* RESYNC
|
||||||
|
* unused: dev dev .. | <none>
|
||||||
|
*
|
||||||
|
* STATUS matches 0.90.0/2.2
|
||||||
|
* RESYNC includes [===>....],
|
||||||
|
* adds a space after {resync|recovery} and before and after '='
|
||||||
|
* adds a decimal to the recovery percent.
|
||||||
|
* adds (%d/%d) resync amount and max_blocks, before finish.
|
||||||
|
* adds speed=%dK/sec after finish
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Out of this we want to extract:
|
||||||
|
* list of devices, active or not
|
||||||
|
* pattern of failed drives (so need number of drives)
|
||||||
|
* percent resync complete
|
||||||
|
*
|
||||||
|
* As continuation is indicated by leading space, we use
|
||||||
|
* conf_line from config.c to read logical lines
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mdadm.h"
|
||||||
|
#include "dlink.h"
|
||||||
|
|
||||||
|
void free_mdstat(struct mdstat_ent *ms)
|
||||||
|
{
|
||||||
|
while (ms) {
|
||||||
|
struct mdstat_ent *t;
|
||||||
|
if (ms->dev) free(ms->dev);
|
||||||
|
if (ms->level) free(ms->level);
|
||||||
|
if (ms->pattern) free(ms->pattern);
|
||||||
|
t = ms;
|
||||||
|
ms = ms->next;
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mdstat_ent *mdstat_read()
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
struct mdstat_ent *all, **end;
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
f = fopen("/proc/mdstat", "r");
|
||||||
|
if (f == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
all = NULL;
|
||||||
|
end = &all;
|
||||||
|
for (; (line = conf_line(f)) ; free_line(line)) {
|
||||||
|
struct mdstat_ent *ent;
|
||||||
|
char *w;
|
||||||
|
|
||||||
|
if (strcmp(line, "Personalities")==0)
|
||||||
|
continue;
|
||||||
|
if (strcmp(line, "read_ahead")==0)
|
||||||
|
continue;
|
||||||
|
if (strcmp(line, "unused")==0)
|
||||||
|
continue;
|
||||||
|
/* Better be an md line.. */
|
||||||
|
if (strncmp(line, "md", 2)!= 0
|
||||||
|
|| atoi(line+2)<0) {
|
||||||
|
fprintf(stderr, Name ": bad /proc/mdstat line starts: %s\n", line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent = malloc(sizeof(*ent));
|
||||||
|
if (!ent) {
|
||||||
|
fprintf(stderr, Name ": malloc failed reading /proc/mdstat.\n");
|
||||||
|
free_line(line);
|
||||||
|
fclose(f);
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
ent->dev = ent->level = ent->pattern= NULL;
|
||||||
|
ent->next = NULL;
|
||||||
|
ent->percent = -1;
|
||||||
|
ent->active = -1;
|
||||||
|
|
||||||
|
ent->dev = strdup(line);
|
||||||
|
ent->devnum = atoi(line+2);
|
||||||
|
|
||||||
|
for (w=dl_next(line); w!= line ; w=dl_next(w)) {
|
||||||
|
int l = strlen(w);
|
||||||
|
char *eq;
|
||||||
|
if (strcmp(w, "active")==0)
|
||||||
|
ent->active = 1;
|
||||||
|
else if (strcmp(w, "inactive")==0)
|
||||||
|
ent->active = 0;
|
||||||
|
else if (ent->active >=0 &&
|
||||||
|
ent->level == NULL &&
|
||||||
|
w[0] != '(' /*readonly*/)
|
||||||
|
ent->level = strdup(w);
|
||||||
|
else if (!ent->pattern &&
|
||||||
|
w[0] == '[' &&
|
||||||
|
(w[1] == 'U' || w[1] == '_')) {
|
||||||
|
ent->pattern = strdup(w+1);
|
||||||
|
if (ent->pattern[l-2]==']')
|
||||||
|
ent->pattern[l-2] = '\0';
|
||||||
|
} else if (ent->percent == -1 &&
|
||||||
|
strncmp(w, "re", 2)== 0 &&
|
||||||
|
w[l-1] == '%' &&
|
||||||
|
(eq=strchr(w, '=')) != NULL ) {
|
||||||
|
ent->percent = atoi(eq+1);
|
||||||
|
} else if (ent->percent == -1 &&
|
||||||
|
w[0] >= '0' &&
|
||||||
|
w[0] <= '9' &&
|
||||||
|
w[l-1] == '%') {
|
||||||
|
ent->percent = atoi(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*end = ent;
|
||||||
|
end = &ent->next;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return all;
|
||||||
|
}
|
71
util.c
71
util.c
|
@ -113,6 +113,8 @@ int get_linux_version()
|
||||||
int enough(int level, int raid_disks, int avail_disks)
|
int enough(int level, int raid_disks, int avail_disks)
|
||||||
{
|
{
|
||||||
switch (level) {
|
switch (level) {
|
||||||
|
case -4:
|
||||||
|
return avail_disks>= 1;
|
||||||
case -1:
|
case -1:
|
||||||
case 0:
|
case 0:
|
||||||
return avail_disks == raid_disks;
|
return avail_disks == raid_disks;
|
||||||
|
@ -197,8 +199,8 @@ int load_super(int fd, mdp_super_t *super)
|
||||||
* 5 - no magic
|
* 5 - no magic
|
||||||
* 6 - wrong major version
|
* 6 - wrong major version
|
||||||
*/
|
*/
|
||||||
long size;
|
unsigned long size;
|
||||||
long long offset;
|
unsigned long long offset;
|
||||||
|
|
||||||
if (ioctl(fd, BLKGETSIZE, &size))
|
if (ioctl(fd, BLKGETSIZE, &size))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -433,14 +435,14 @@ char *human_size(long long bytes)
|
||||||
if (bytes < 5000*1024)
|
if (bytes < 5000*1024)
|
||||||
buf[0]=0;
|
buf[0]=0;
|
||||||
else if (bytes < 2*1024LL*1024LL*1024LL)
|
else if (bytes < 2*1024LL*1024LL*1024LL)
|
||||||
sprintf(buf, " (%d.%02d MiB %d.%02d MB)",
|
sprintf(buf, " (%ld.%02ld MiB %ld.%02ld MB)",
|
||||||
(long)(bytes>>20),
|
(long)(bytes>>20),
|
||||||
(long)(bytes&0xfffff)/(0x100000/100),
|
(long)(bytes&0xfffff)/(0x100000/100),
|
||||||
(long)(bytes/1000/1000),
|
(long)(bytes/1000/1000),
|
||||||
(long)((bytes%1000000)/10000)
|
(long)((bytes%1000000)/10000)
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
sprintf(buf, " (%d.%02d GiB %d.%02d GB)",
|
sprintf(buf, " (%ld.%02ld GiB %ld.%02ld GB)",
|
||||||
(long)(bytes>>30),
|
(long)(bytes>>30),
|
||||||
(long)((bytes>>10)&0xfffff)/(0x100000/100),
|
(long)((bytes>>10)&0xfffff)/(0x100000/100),
|
||||||
(long)(bytes/1000LL/1000LL/1000LL),
|
(long)(bytes/1000LL/1000LL/1000LL),
|
||||||
|
@ -448,3 +450,64 @@ char *human_size(long long bytes)
|
||||||
);
|
);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *human_size_brief(long long bytes)
|
||||||
|
{
|
||||||
|
static char buf[30];
|
||||||
|
|
||||||
|
|
||||||
|
if (bytes < 5000*1024)
|
||||||
|
sprintf(buf, "%ld.%02ldKiB",
|
||||||
|
(long)(bytes>>10), (long)((bytes&1023)*100/1024)
|
||||||
|
);
|
||||||
|
else if (bytes < 2*1024LL*1024LL*1024LL)
|
||||||
|
sprintf(buf, "%ld.%02ldMiB",
|
||||||
|
(long)(bytes>>20),
|
||||||
|
(long)(bytes&0xfffff)/(0x100000/100)
|
||||||
|
);
|
||||||
|
else
|
||||||
|
sprintf(buf, "%ld.%02ldGiB",
|
||||||
|
(long)(bytes>>30),
|
||||||
|
(long)((bytes>>10)&0xfffff)/(0x100000/100)
|
||||||
|
);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MD_MAJOR 9
|
||||||
|
char *get_md_name(int dev)
|
||||||
|
{
|
||||||
|
/* find /dev/md%d or /dev/md/%d or make a device /dev/.tmp.md%d */
|
||||||
|
static char devname[50];
|
||||||
|
struct stat stb;
|
||||||
|
dev_t rdev = MKDEV(MD_MAJOR, dev);
|
||||||
|
|
||||||
|
sprintf(devname, "/dev/md%d", dev);
|
||||||
|
if (stat(devname, &stb) == 0
|
||||||
|
&& (S_IFMT&stb.st_mode) == S_IFBLK
|
||||||
|
&& (stb.st_rdev == rdev))
|
||||||
|
return devname;
|
||||||
|
|
||||||
|
sprintf(devname, "/dev/md/%d", dev);
|
||||||
|
if (stat(devname, &stb) == 0
|
||||||
|
&& (S_IFMT&stb.st_mode) == S_IFBLK
|
||||||
|
&& (stb.st_rdev == rdev))
|
||||||
|
return devname;
|
||||||
|
|
||||||
|
sprintf(devname, "/dev/.tmp.md%d", dev);
|
||||||
|
if (mknod(devname, S_IFBLK | 0600, rdev) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (stat(devname, &stb) == 0
|
||||||
|
&& (S_IFMT&stb.st_mode) == S_IFBLK
|
||||||
|
&& (stb.st_rdev == rdev))
|
||||||
|
return devname;
|
||||||
|
unlink(devname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put_md_name(char *name)
|
||||||
|
{
|
||||||
|
if (strncmp(name, "/dev/.tmp.md", 12)==0)
|
||||||
|
unlink(name);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue