mdadm-1.7.0

This commit is contained in:
Neil Brown 2004-08-11 02:16:01 +00:00
parent dd0781e505
commit e5329c3747
23 changed files with 539 additions and 76 deletions

46
ANNOUNCE-1.7.0 Normal file
View File

@ -0,0 +1,46 @@
Subject: ANNOUNCE: mdadm 1.7.0 - A tool for managing Soft RAID under Linux
I am pleased to announce the availability of
mdadm version 1.7.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.7.0 adds:
- Support "--grow --add" to add a device to a linear array, if the
kernel supports it. Not documented yet.
- Restore support for uclibc which was broken recently.
- Several improvements to the output of --detail, including
reporting "resyncing" or "recovering" in the state.
- Close filedescriptor at end of --detail (exit would have closed it
anyway, so this isn't abig deal).
- Report "Sync checkpoint" in --examine output if appropriate.
- Add --update=resync for --assemble mode to for a resync when the
array is assembled.
- Add support for "raid10", which is under development in 2.6.
Not documented yet.
- --monitor now reads spare-group and spares info from config file
even when names of arrays to scan are given on the command line
It is expected 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.
Prior to that, some point releases (1.7.1, 1.7.2 ...) may be released
so that the changes can be tested by interrested parties.
Development of mdadm is sponsored by CSE@UNSW:
The School of Computer Science and Engineering
at
The University of New South Wales
NeilBrown 11 August 2004

View File

@ -320,6 +320,11 @@ int Assemble(char *mddev, int mdfd,
} else if (i >= super.raid_disks && super.disks[i].number == 0)
super.disks[i].state = 0;
}
if (strcmp(update, "resync") == 0) {
/* make sure resync happens */
super.state &= ~(1<<MD_SB_CLEAN);
super.recovery_cp = 0;
}
super.sb_csum = calc_sb_csum(&super);
dfd = open(devname, O_RDWR, 0);
if (dfd < 0)

View File

@ -1,3 +1,19 @@
Changes Prior to this release
- Support "--grow --add" to add a device to a linear array, if the
kernel supports it. Not documented yet.
- Restore support for uclibc which was broken recently.
- Several improvements to the output of --detail, including
reporting "resyncing" or "recovering" in the state.
- Close filedescriptor at end of --detail (exit would have closed it
anyway, so this isn't abig deal).
- Report "Sync checkpoint" in --examine output if appropriate.
- Add --update=resync for --assemble mode to for a resync when the
array is assembled.
- Add support for "raid10", which is under development in 2.6.
Not documented yet.
- --monitor now reads spare-group and spares info from config file
even when names of arrays to scan are given on the command line
Changes Prior to 1.6.0 release
- Device name given in -Eb is determined by examining /dev rather
than assuming /dev/md%d

View File

@ -117,6 +117,12 @@ int Create(char *mddev, int mdfd,
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");
@ -126,9 +132,18 @@ int Create(char *mddev, int mdfd,
break;
}
if (level == 10)
/* check layout fits in array*/
if ((layout&255) * ((layout>>8)&255) > raiddisks) {
fprintf(stderr, Name ": that layout requires at least %d devices\n",
(layout&255) * ((layout>>8)&255));
return 1;
}
switch(level) {
case 4:
case 5:
case 10:
case 6:
case 0:
case -1: /* linear */

113
Detail.c
View File

@ -47,6 +47,9 @@ int Detail(char *dev, int brief, int test)
char *devices = NULL;
int spares = 0;
struct stat stb;
int is_26 = get_linux_version() >= 2006000;
int is_rebuilding = 0;
int failed = 0;
mdp_super_t super;
int have_super = 0;
@ -83,6 +86,34 @@ int Detail(char *dev, int brief, int test)
if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode))
stb.st_rdev = 0;
rv = 0;
/* try to load a superblock */
for (d= 0; d<MD_SB_DISKS; d++) {
mdu_disk_info_t disk;
char *dv;
disk.number = d;
if (ioctl(fd, GET_DISK_INFO, &disk) < 0)
continue;
if (d >= array.raid_disks &&
disk.major == 0 &&
disk.minor == 0)
continue;
if ((dv=map_dev(disk.major, disk.minor))) {
if (!have_super && (disk.state & (1<<MD_DISK_ACTIVE))) {
/* try to read the superblock from this device
* to get more info
*/
int fd2 = open(dv, O_RDONLY);
if (fd2 >=0 &&
load_super(fd2, &super) ==0 &&
(unsigned long)super.ctime == (unsigned long)array.ctime &&
(unsigned int)super.level == (unsigned int)array.level)
have_super = 1;
if (fd2 >= 0) close(fd2);
}
}
}
/* Ok, we have some info to print... */
c = map_num(pers, array.level);
if (brief)
@ -132,7 +163,8 @@ int Detail(char *dev, int brief, int test)
printf(" State : %s%s%s\n",
(array.state&(1<<MD_SB_CLEAN))?"clean":"dirty",
array.active_disks < array.raid_disks? ", degraded":"",
(e && e->percent >= 0) ? ", recovering": "");
(!e || e->percent < 0) ? "" :
(e->resync) ? ", resyncing": ", recovering");
printf(" Active Devices : %d\n", array.active_disks);
printf("Working Devices : %d\n", array.working_disks);
printf(" Failed Devices : %d\n", array.failed_disks);
@ -142,24 +174,40 @@ int Detail(char *dev, int brief, int test)
c = map_num(r5layout, array.layout);
printf(" Layout : %s\n", c?c:"-unknown-");
}
if (array.level == 10) {
printf(" Layout : near=%d, far=%d\n",
array.layout&255, (array.layout>>8)&255);
}
switch (array.level) {
case 0:
case 4:
case 5:
printf(" Chunk Size : %dK\n", array.chunk_size/1024);
case 10:
case 6:
printf(" Chunk Size : %dK\n\n", array.chunk_size/1024);
break;
case -1:
printf(" Rounding : %dK\n", array.chunk_size/1024);
printf(" Rounding : %dK\n\n", array.chunk_size/1024);
break;
default: break;
}
printf("\n");
if (e && e->percent >= 0)
if (e && e->percent >= 0) {
printf(" Rebuild Status : %d%% complete\n\n", e->percent);
is_rebuilding = 1;
}
free_mdstat(ms);
if (have_super) {
printf(" UUID : ");
if (super.minor_version >= 90)
printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
super.set_uuid2, super.set_uuid3);
else
printf("%08x", super.set_uuid0);
printf("\n Events : %d.%d\n\n", super.events_hi, super.events_lo);
}
printf(" Number Major Minor RaidDevice State\n");
}
for (d= 0; d<MD_SB_DISKS; d++) {
@ -177,14 +225,40 @@ int Detail(char *dev, int brief, int test)
disk.minor == 0)
continue;
if (!brief) {
printf(" %5d %5d %5d %5d ",
disk.number, disk.major, disk.minor, disk.raid_disk);
if (disk.state & (1<<MD_DISK_FAULTY)) printf(" faulty");
if (disk.number == array.raid_disks) printf("\n");
if (disk.raid_disk < 0)
printf(" %5d %5d %5d - ",
disk.number, disk.major, disk.minor);
else
printf(" %5d %5d %5d %5d ",
disk.number, disk.major, disk.minor, disk.raid_disk);
if (disk.state & (1<<MD_DISK_FAULTY)) {
printf(" faulty");
if (disk.raid_disk < array.raid_disks &&
disk.raid_disk >= 0)
failed++;
}
if (disk.state & (1<<MD_DISK_ACTIVE)) printf(" active");
if (disk.state & (1<<MD_DISK_SYNC)) printf(" sync");
if (disk.state & (1<<MD_DISK_REMOVED)) printf(" removed");
if (disk.state == 0) { printf(" spare"); spares++; }
if (disk.state == 0) printf(" spare");
if (disk.state == 0) {
if (is_26) {
if (disk.raid_disk < array.raid_disks && disk.raid_disk >= 0)
printf(" rebuilding");
} else if (is_rebuilding && failed) {
/* Taking a bit of a risk here, we remove the
* device from the array, and then put it back.
* If this fails, we are rebuilding
*/
int err = ioctl(fd, HOT_REMOVE_DISK, MKDEV(disk.major, disk.minor));
if (err == 0) ioctl(fd, HOT_ADD_DISK, MKDEV(disk.major, disk.minor));
if (err && errno == EBUSY)
printf(" rebuilding");
}
}
}
if (disk.state == 0) spares++;
if (test && d < array.raid_disks && disk.state & (1<<MD_DISK_FAULTY)) {
if ((rv & 1) && (array.level ==4 || array.level == 5))
rv |= 2;
@ -200,34 +274,21 @@ int Detail(char *dev, int brief, int test)
devices = strdup(dv);
} else
printf(" %s", dv);
if (!have_super && (disk.state & (1<<MD_DISK_ACTIVE))) {
/* try to read the superblock from this device
* to get more info
*/
int fd = open(dv, O_RDONLY);
if (fd >=0 &&
load_super(fd, &super) ==0 &&
(unsigned long)super.ctime == (unsigned long)array.ctime &&
(unsigned int)super.level == (unsigned int)array.level)
have_super = 1;
}
}
if (!brief) printf("\n");
}
if (spares && brief) printf(" spares=%d", spares);
if (have_super) {
if (brief) printf(" UUID=");
else printf(" UUID : ");
if (have_super && brief) {
printf(" UUID=");
if (super.minor_version >= 90)
printf("%08x:%08x:%08x:%08x", super.set_uuid0, super.set_uuid1,
super.set_uuid2, super.set_uuid3);
else
printf("%08x", super.set_uuid0);
if (!brief)
printf("\n Events : %d.%d\n", super.events_hi, super.events_lo);
}
if (brief && devices) printf("\n devices=%s", devices);
if (brief) printf("\n");
if (test && (rv&2)) rv &= ~1;
close(fd);
return rv;
}

View File

@ -174,11 +174,20 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
printf (" --- adjusting superblock for 2.2/sparc compatability ---\n");
}
printf(" Events : %d.%d\n", super.events_hi, super.events_lo);
if (super.events_hi == super.cp_events_hi &&
super.events_lo == super.cp_events_lo &&
super.recovery_cp > 0 &&
(super.state & (1<<MD_SB_CLEAN)) == 0 )
printf("Sync checkpoint : %d KB (%d%%)\n", super.recovery_cp/2, super.recovery_cp/(super.size/100*2));
printf("\n");
if (super.level == 5) {
c = map_num(r5layout, super.layout);
printf(" Layout : %s\n", c?c:"-unknown-");
}
if (super.level == 10)
printf(" Layout : near=%d, far=%d\n",
super.layout&255, (super.layout>>8) & 255);
switch(super.level) {
case 0:
case 4:
@ -209,6 +218,7 @@ int Examine(mddev_dev_t devlist, int brief, int scan, int SparcAdjust)
if ((dv=map_dev(dp->major, dp->minor)))
printf(" %s", dv);
printf("\n");
if (d == -1) printf("\n");
}
}
if (SparcAdjust == 2) {

192
Grow.c Normal file
View File

@ -0,0 +1,192 @@
/*
* mdadm - manage Linux "md" devices aka RAID arrays.
*
* Copyright (C) 2001-2004 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 "dlink.h"
#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
#error no endian defined
#endif
#include "md_u.h"
#include "md_p.h"
int Grow_Add_device(char *devname, int fd, char *newdev)
{
/* Add a device to an active array.
* Currently, just extend a linear array.
* This requires writing a new superblock on the
* new device, calling the kernel to add the device,
* and if that succeeds, update the superblock on
* all other devices.
* This means that we need to *find* all other devices.
*/
mdu_array_info_t array;
mdu_disk_info_t disk;
mdp_super_t super;
struct stat stb;
int nfd, fd2;
int d, nd;
if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
fprintf(stderr, Name ": cannot get array info for %s\n", devname);
return 1;
}
if (array.level != -1) {
fprintf(stderr, Name ": can only add devices to linear arrays\n");
return 1;
}
nfd = open(newdev, O_RDWR|O_EXCL);
if (nfd < 0) {
fprintf(stderr, Name ": cannot open %s\n", newdev);
return 1;
}
fstat(nfd, &stb);
if ((stb.st_mode & S_IFMT) != S_IFBLK) {
fprintf(stderr, Name ": %s is not a block device!\n", newdev);
close(nfd);
return 1;
}
/* now check out all the devices and make sure we can read the superblock */
for (d=0 ; d < array.raid_disks ; d++) {
mdu_disk_info_t disk;
char *dv;
disk.number = d;
if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
fprintf(stderr, Name ": cannot get device detail for device %d\n",
d);
return 1;
}
dv = map_dev(disk.major, disk.minor);
if (!dv) {
fprintf(stderr, Name ": cannot find device file for device %d\n",
d);
return 1;
}
fd2 = open(dv, O_RDWR);
if (!fd2) {
fprintf(stderr, Name ": cannot open device file %s\n", dv);
return 1;
}
if (load_super(fd2, &super)) {
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
close(fd2);
return 1;
}
close(fd2);
}
/* Ok, looks good. Lets update the superblock and write it out to
* newdev.
*/
memset(&super.disks[d], 0, sizeof(super.disks[d]));
super.disks[d].number = d;
super.disks[d].major = MAJOR(stb.st_rdev);
super.disks[d].minor = MINOR(stb.st_rdev);
super.disks[d].raid_disk = d;
super.disks[d].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
super.this_disk = super.disks[d];
super.sb_csum = calc_sb_csum(&super);
if (store_super(nfd, &super)) {
fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
close(nfd);
return 1;
}
disk.number = d;
disk.major = MAJOR(stb.st_rdev);
disk.minor = MINOR(stb.st_rdev);
disk.raid_disk = d;
disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
close(nfd);
if (ioctl(fd, ADD_NEW_DISK, &disk) != 0) {
fprintf(stderr, Name ": Cannot add new disk to this array\n");
return 1;
}
/* Well, that seems to have worked.
* Now go through and update all superblocks
*/
if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
fprintf(stderr, Name ": cannot get array info for %s\n", devname);
return 1;
}
nd = d;
for (d=0 ; d < array.raid_disks ; d++) {
mdu_disk_info_t disk;
char *dv;
disk.number = d;
if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
fprintf(stderr, Name ": cannot get device detail for device %d\n",
d);
return 1;
}
dv = map_dev(disk.major, disk.minor);
if (!dv) {
fprintf(stderr, Name ": cannot find device file for device %d\n",
d);
return 1;
}
fd2 = open(dv, O_RDWR);
if (fd2 < 0) {
fprintf(stderr, Name ": cannot open device file %s\n", dv);
return 1;
}
if (load_super(fd2, &super)) {
fprintf(stderr, Name ": cannot find super block on %s\n", dv);
close(fd);
return 1;
}
super.raid_disks = nd+1;
super.nr_disks = nd+1;
super.active_disks = nd+1;
super.working_disks = nd+1;
memset(&super.disks[nd], 0, sizeof(super.disks[nd]));
super.disks[nd].number = nd;
super.disks[nd].major = MAJOR(stb.st_rdev);
super.disks[nd].minor = MINOR(stb.st_rdev);
super.disks[nd].raid_disk = nd;
super.disks[nd].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
super.this_disk = super.disks[d];
super.sb_csum = calc_sb_csum(&super);
if (store_super(fd2, &super)) {
fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
close(fd2);
return 1;
}
close(fd2);
}
return 0;
}

View File

@ -30,7 +30,7 @@
# define "CXFLAGS" to give extra flags to CC.
# e.g. make CXFLAGS=-O to optimise
TCC = tcc
UCLIBC_GCC = i386-uclibc-gcc
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 )
CC = gcc
CXFLAGS = -ggdb
@ -55,8 +55,8 @@ MAN8DIR = $(MANDIR)/man8
KLIBC=/home/src/klibc/klibc-0.77
OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o Create.o Detail.o Examine.o Monitor.o dlink.o Kill.o Query.o
SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c Create.c Detail.c Examine.c Monitor.c dlink.c Kill.c Query.c
OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o
SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c
all : mdadm mdadm.man md.man mdadm.conf.man

View File

@ -163,6 +163,7 @@ int Monitor(mddev_dev_t devlist,
} else {
mddev_dev_t dv;
for (dv=devlist ; dv; dv=dv->next) {
mddev_ident_t mdlist = conf_get_ident(config, dv->devname);
struct state *st = malloc(sizeof *st);
if (st == NULL)
continue;
@ -174,6 +175,11 @@ int Monitor(mddev_dev_t devlist,
st->percent = -2;
st->expected_spares = -1;
st->spare_group = NULL;
if (mdlist) {
st->expected_spares = mdlist->spare_disks;
if (mdlist->spare_group)
st->spare_group = strdup(mdlist->spare_group);
}
statelist = st;
}
}
@ -216,7 +222,8 @@ int Monitor(mddev_dev_t devlist,
close(fd);
continue;
}
if (array.level != 1 && array.level != 5 && array.level != -4) {
if (array.level != 1 && array.level != 5 && array.level != -4 &&
array.level != 6 && array.level != 10) {
if (!st->err)
alert("DeviceDisappeared", dev, "Wrong-Level",
mailaddr, alert_cmd);

View File

@ -29,7 +29,7 @@
#include "mdadm.h"
char Version[] = Name " - v1.6.0 - 4 June 2004\n";
char Version[] = Name " - v1.7.0 - 11 August 2004\n";
/*
* File: ReadMe.c
*
@ -216,7 +216,7 @@ char OptionHelp[] =
" --layout= : same as --parity\n"
" --raid-devices= -n : number of active devices in array\n"
" --spare-devices= -x: number of spares (eXtras) devices in initial array\n"
" --size= -z : Size (in K) of each drive in RAID1/4/5/6 - optional\n"
" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n"
" --force -f : Honour devices as listed on command line. Don't\n"
" : insert a missing drive for RAID5.\n"
" --auto(=p) -a : Automatically allocate new (partitioned) md array if needed.\n"
@ -284,7 +284,7 @@ char Help_create[] =
" --layout= : same as --parity\n"
" --raid-devices= -n : number of active devices in array\n"
" --spare-devices= -x: number of spares (eXtras) devices in initial array\n"
" --size= -z : Size (in K) of each drive in RAID1/4/5/6 - optional\n"
" --size= -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional\n"
" --force -f : Honour devices as listed on command line. Don't\n"
" : insert a missing drive for RAID5.\n"
" --run -R : insist of running the array even if not all\n"
@ -508,6 +508,8 @@ mapping_t pers[] = {
{ "mp", -4},
{ "raid6", 6},
{ "6", 6},
{ "raid10", 10},
{ "10", 10},
{ NULL, 0}
};

View File

@ -364,7 +364,7 @@ void arrayline(char *line)
}
if (mis.devname == NULL)
fprintf(stderr, Name ": ARRAY line with no device\n");
else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor < 0)
else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet)
fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname);
else {
mi = malloc(sizeof(*mi));

43
inventory Normal file
View File

@ -0,0 +1,43 @@
ANNOUNCE-1.0.0
ANNOUNCE-1.1.0
ANNOUNCE-1.2.0
ANNOUNCE-1.3.0
ANNOUNCE-1.4.0
ANNOUNCE-1.5.0
ANNOUNCE-1.6.0
ANNOUNCE-1.7.0
Assemble.c
Build.c
COPYING
ChangeLog
Create.c
Detail.c
Examine.c
Grow.c
INSTALL
Kill.c
Makefile
Manage.c
Monitor.c
Query.c
ReadMe.c
TODO
config.c
dlink.c
dlink.h
inventory
makedist
md.4
md_p.h
md_u.h
mdadm.8
mdadm.c
mdadm.conf-example
mdadm.conf.5
mdadm.h
mdadm.spec
mdassemble.c
mdstat.c
raid5extend.c
util.c

View File

@ -21,9 +21,13 @@ grep "^Version: *$version$" mdadm.spec > /dev/null 2>&1 ||
if [ -f ANNOUNCE-$version ]
then :
else
echo ANNONCE-$version does not exist
echo ANNOUNCE-$version does not exist
exit 1
fi
if grep "^ANNOUNCE-$version\$" inventory
then :
else { cat inventory ; echo ANNOUNCE-$version ; } | sort -o inventory
fi
echo version = $version
base=mdadm-$version.tgz
@ -38,6 +42,12 @@ then
( cd .. ; ln -s mdadm mdadm-$version ; tar chvf - --exclude="TAGS" --exclude='*~' --exclude=.patches --exclude='*,v' --exclude='*.o' --exclude mdadm --exclude=mdadm'.[^ch0-9]' --exclude=RCS mdadm-$version ; rm mdadm-$version ) | gzip --best > $target/$base
chmod a+r $target/$base
ls -l $target/$base
if tar tzf $target/$base | sed 's,[^/]*/,,' | sort | diff -u inventory -
then : correct files found
else echo "Extra files, or invertory is out-of-date"
rm $target/$base
exit 1
fi
rpm -ta $target/$base
find /home/neilb/src/RPM -name "*mdadm-$version-*" \

7
md_p.h
View File

@ -131,11 +131,16 @@ typedef struct mdp_superblock_s {
#if __BYTE_ORDER == __BIG_ENDIAN
__u32 events_hi; /* 7 high-order of superblock update count */
__u32 events_lo; /* 8 low-order of superblock update count */
__u32 cp_events_hi; /* 9 high-order of checkpoint update count */
__u32 cp_events_lo; /* 10 low-order of checkpoint update count */
#else
__u32 events_lo; /* 7 low-order of superblock update count */
__u32 events_hi; /* 8 high-order of superblock update count */
__u32 cp_events_lo; /* 9 low-order of checkpoint update count */
__u32 cp_events_hi; /* 10 high-order of checkpoint update count */
#endif
__u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 9];
__u32 recovery_cp; /* 11 recovery checkpoint sector count */
__u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12];
/*
* Personality information

12
mdadm.8
View File

@ -1,5 +1,5 @@
.\" -*- nroff -*-
.TH MDADM 8 "" v1.6.0
.TH MDADM 8 "" v1.7.0
.SH NAME
mdadm \- manage MD devices
.I aka
@ -407,6 +407,7 @@ Update the superblock on each device while assembling the array. The
argument given to this flag can be one of
.BR sparc2.2 ,
.BR summaries ,
.BR resync ,
or
.BR super-minor .
@ -428,6 +429,15 @@ field on each superblock to match the minor number of the array being
assembled. This is not needed on 2.6 and later kernels as they make
this adjustment automatically.
The
.B resync
option will cause the array to be marked
.I dirty
meaning that any redundancy in the array (e.g. parity for raid5,
copies for raid1) may be incorrect. This will cause the raid system
to perform a "resync" pass to make sure that all redundant information
is correct.
The
.B summaries
option will correct the summaries in the superblock. That is the

53
mdadm.c
View File

@ -235,6 +235,8 @@ int main(int argc, char *argv[])
int daemonise = 0;
int oneshot = 0;
int copies;
int mdfd = -1;
ident.uuid_set=0;
@ -361,6 +363,10 @@ int main(int argc, char *argv[])
fprintf(stderr, Name ": Must give one of -a/-r/-f for subsequent devices at %s\n", optarg);
exit(2);
}
if (devs_found > 0 && mode == 'G' && !devmode) {
fprintf(stderr, Name ": Must give one of -a for devices do add: %s\n", optarg);
exit(2);
}
dv = malloc(sizeof(*dv));
if (dv == NULL) {
fprintf(stderr, Name ": malloc failed\n");
@ -441,7 +447,7 @@ int main(int argc, char *argv[])
continue;
case O(CREATE,'p'): /* raid5 layout */
if (layout >= 0) {
if (layout != UnSet) {
fprintf(stderr,Name ": layout may only be sent once. "
"Second value was %s\n", optarg);
exit(2);
@ -464,6 +470,21 @@ int main(int argc, char *argv[])
exit(2);
}
break;
case 10:
/* 'f' or 'n' followed by a number <= raid_disks */
if ((optarg[0] != 'n' && optarg[0] != 'f') ||
(copies = strtoul(optarg+1, &cp, 10)) < 1 ||
copies > 200 ||
*cp) {
fprintf(stderr, Name ": layout for raid10 must be 'nNN' or 'fNN' where NN is a number, not %s\n", optarg);
exit(2);
}
if (optarg[0] == 'n')
layout = 256 + copies;
else
layout = 1 + (copies<<8);
break;
}
continue;
@ -596,12 +617,15 @@ int main(int argc, char *argv[])
exit(2);
}
update = optarg;
if (strcmp(update, "sparc2.2")==0) continue;
if (strcmp(update, "sparc2.2")==0)
continue;
if (strcmp(update, "super-minor") == 0)
continue;
if (strcmp(update, "summaries")==0)
continue;
fprintf(stderr, Name ": '--update %s' invalid. Only 'sparc2.2', 'super-minor' or 'summaries' supported\n",update);
if (strcmp(update, "resync")==0)
continue;
fprintf(stderr, Name ": '--update %s' invalid. Only 'sparc2.2', 'super-minor', 'resync' or 'summaries' supported\n",update);
exit(2);
case O(ASSEMBLE,'c'): /* config file */
@ -663,6 +687,7 @@ int main(int argc, char *argv[])
/* now the general management options. Some are applicable
* to other modes. None have arguments.
*/
case O(GROW,'a'):
case O(MANAGE,'a'): /* add a drive */
devmode = 'a';
continue;
@ -944,16 +969,24 @@ int main(int argc, char *argv[])
case GROW:
if (devs_found > 1) {
fprintf(stderr, Name ": Only one device may be given for --grow\n");
rv = 1;
break;
}
if (size >= 0 && raiddisks) {
/* must be '-a'. */
if (size >= 0 || raiddisks) {
fprintf(stderr, Name ": --size, --raiddisks, and --add are exclusing in --grow mode\n");
rv = 1;
break;
}
for (dv=devlist->next; dv ; dv=dv->next) {
rv = Grow_Add_device(devlist->devname, mdfd, dv->devname);
if (rv)
break;
}
} else if (size >= 0 && raiddisks) {
fprintf(stderr, Name ": can only grow size OR raiddisks, not both\n");
rv = 1;
break;
}
rv = Manage_resize(devlist->devname, mdfd, size, raiddisks);
} else
rv = Manage_resize(devlist->devname, mdfd, size, raiddisks);
break;
}
exit(rv);

View File

@ -136,6 +136,7 @@ struct mdstat_ent {
char *level;
char *pattern; /* U or up, _ for down */
int percent; /* -1 if no resync */
int resync; /* 1 if resync, 0 if recovery */
struct mdstat_ent *next;
};
@ -159,6 +160,7 @@ 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_subdevs(char *devname, int fd,
mddev_dev_t devlist);
extern int Grow_Add_device(char *devname, int fd, char *newdev);
extern int Assemble(char *mddev, int mdfd,

View File

@ -1,6 +1,6 @@
Summary: mdadm is used for controlling Linux md devices (aka RAID arrays)
Name: mdadm
Version: 1.6.0
Version: 1.7.0
Release: 1
Source: http://www.cse.unsw.edu.au/~neilb/source/mdadm/mdadm-%{version}.tgz
URL: http://www.cse.unsw.edu.au/~neilb/source/mdadm/

Binary file not shown.

View File

@ -153,6 +153,7 @@ struct mdstat_ent *mdstat_read(int hold)
ent->next = NULL;
ent->percent = -1;
ent->active = -1;
ent->resync = 0;
ent->dev = strdup(line);
ent->devnum = devnum;
@ -179,6 +180,11 @@ struct mdstat_ent *mdstat_read(int hold)
w[l-1] == '%' &&
(eq=strchr(w, '=')) != NULL ) {
ent->percent = atoi(eq+1);
if (strncmp(w,"resync", 4)==0)
ent->resync = 1;
} else if (ent->percent == -1 &&
strncmp(w, "resync", 4)==0) {
ent->resync = 1;
} else if (ent->percent == -1 &&
w[0] >= '0' &&
w[0] <= '9' &&

1
t
View File

@ -1 +0,0 @@
ARRAY /dev/fred auto=parti /dev/fred

2
test
View File

@ -1,2 +0,0 @@
dev partitions
array /dev/md0 super-minor=6

53
util.c
View File

@ -121,6 +121,8 @@ int get_linux_version()
int enough(int level, int raid_disks, int avail_disks)
{
switch (level) {
case 10: return 1; /* a lie, but it is hard to tell */
case -4:
return avail_disks>= 1;
case -1:
@ -375,6 +377,32 @@ int map_name(mapping_t *map, char *name)
return UnSet;
}
int is_standard(char *dev)
{
/* tests if dev is a "standard" md dev name.
* i.e if the last component is "/dNN" or "/mdNN",
* where NN is a string of digits
*/
dev = strrchr(dev, '/');
if (!dev)
return 0;
if (strncmp(dev, "/d",2)==0)
dev += 2;
else if (strncmp(dev, "/md", 3)==0)
dev += 3;
else
return 0;
if (!*dev)
return 0;
while (isdigit(*dev))
dev++;
if (*dev)
return 0;
return 1;
}
/*
* convert a major/minor pair for a block device into a name in /dev, if possible.
* On the first call, walk /dev collecting name.
@ -421,31 +449,6 @@ int add_dev(const char *name, const struct stat *stb, int flag)
return 0;
}
int is_standard(char *dev)
{
/* tests if dev is a "standard" md dev name.
* i.e if the last component is "/dNN" or "/mdNN",
* where NN is a string of digits
*/
dev = strrchr(dev, '/');
if (!dev)
return 0;
if (strncmp(dev, "/d",2)==0)
dev += 2;
else if (strncmp(dev, "/md", 3)==0)
dev += 3;
else
return 0;
if (!*dev)
return 0;
while (isdigit(*dev))
dev++;
if (*dev)
return 0;
return 1;
}
/*
* Find a block device with the right major/minor number.
* Avoid /dev/mdNN and /dev/md/dNN is possible