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