Fix assembling of raid10 in the face of missing devices.
We now check if enough devices are present properly, so --force can be used to good effect. Signed-off-by: Neil Brown <neilb@suse.de>
This commit is contained in:
parent
63f8c4c76b
commit
265e0f1731
17
Assemble.c
17
Assemble.c
|
@ -118,6 +118,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
|
|||
mddev_dev_t tmpdev;
|
||||
struct mdinfo info;
|
||||
struct mddev_ident_s ident2;
|
||||
char *avail;
|
||||
|
||||
vers = md_get_version(mdfd);
|
||||
if (vers <= 0) {
|
||||
|
@ -359,6 +360,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
|
|||
/* now we have some devices that might be suitable.
|
||||
* I wonder how many
|
||||
*/
|
||||
avail = malloc(info.array.raid_disks);
|
||||
memset(avail, 0, info.array.raid_disks);
|
||||
okcnt = 0;
|
||||
sparecnt=0;
|
||||
for (i=0; i< bestcnt ;i++) {
|
||||
|
@ -377,13 +380,16 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
|
|||
if (devices[j].events+event_margin >=
|
||||
devices[most_recent].events) {
|
||||
devices[j].uptodate = 1;
|
||||
if (i < info.array.raid_disks)
|
||||
if (i < info.array.raid_disks) {
|
||||
okcnt++;
|
||||
else
|
||||
avail[i]=1;
|
||||
} else
|
||||
sparecnt++;
|
||||
}
|
||||
}
|
||||
while (force && !enough(info.array.level, info.array.raid_disks, okcnt)) {
|
||||
while (force && !enough(info.array.level, info.array.raid_disks,
|
||||
info.array.layout,
|
||||
avail, okcnt)) {
|
||||
/* Choose the newest best drive which is
|
||||
* not up-to-date, update the superblock
|
||||
* and add it.
|
||||
|
@ -434,6 +440,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
|
|||
close(fd);
|
||||
devices[chosen_drive].events = devices[most_recent].events;
|
||||
devices[chosen_drive].uptodate = 1;
|
||||
avail[chosen_drive] = 1;
|
||||
okcnt++;
|
||||
free(super);
|
||||
}
|
||||
|
@ -599,7 +606,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
|
|||
|
||||
if (runstop == 1 ||
|
||||
(runstop == 0 &&
|
||||
( enough(info.array.level, info.array.raid_disks, okcnt) &&
|
||||
( enough(info.array.level, info.array.raid_disks, info.array.layout, avail, okcnt) &&
|
||||
(okcnt >= req_cnt || start_partial_ok)
|
||||
))) {
|
||||
if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
|
||||
|
@ -627,7 +634,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
|
|||
fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
|
||||
if (sparecnt)
|
||||
fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
|
||||
if (!enough(info.array.level, info.array.raid_disks, okcnt))
|
||||
if (!enough(info.array.level, info.array.raid_disks, info.array.layout, avail, okcnt))
|
||||
fprintf(stderr, " - not enough to start the array.\n");
|
||||
else {
|
||||
if (req_cnt == info.array.raid_disks)
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
Changes Prior to this release
|
||||
- Fix assembling of raid10 array when devices are missing.
|
||||
mdadm now correctly detects if a array is workable or not
|
||||
depending on which devices are present, and so will correctly
|
||||
handle "--assemble --force" if multiple devices have failed.
|
||||
- Report raid10 layout in --examine output.
|
||||
|
||||
Changes Prior to 2.0
|
||||
- Support assembling from byte-swapped superblocks
|
||||
metadata type "0.swap" and --update=byteorder
|
||||
- write-mostly and write-behind support for raid1.
|
||||
|
|
3
mdadm.h
3
mdadm.h
|
@ -291,7 +291,8 @@ extern void uuid_from_super(int uuid[4], mdp_super_t *super);
|
|||
extern int same_uuid(int a[4], int b[4], int swapuuid);
|
||||
/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
|
||||
extern unsigned long calc_csum(void *super, int bytes);
|
||||
extern int enough(int level, int raid_disks, int avail_disks);
|
||||
extern int enough(int level, int raid_disks, int layout,
|
||||
char *avail, int avail_disks);
|
||||
extern int ask(char *mesg);
|
||||
|
||||
|
||||
|
|
5
super0.c
5
super0.c
|
@ -131,6 +131,10 @@ static void examine_super0(void *sbv)
|
|||
c = map_num(r5layout, sb->layout);
|
||||
printf(" Layout : %s\n", c?c:"-unknown-");
|
||||
}
|
||||
if (sb->level == 10) {
|
||||
printf(" Layout : near=%d, far=%d\n",
|
||||
sb->layout&255, (sb->layout>>8)&255);
|
||||
}
|
||||
switch(sb->level) {
|
||||
case 0:
|
||||
case 4:
|
||||
|
@ -234,6 +238,7 @@ static void getinfo_super0(struct mdinfo *info, mddev_ident_t ident, void *sbv)
|
|||
info->array.patch_version = sb->patch_version;
|
||||
info->array.raid_disks = sb->raid_disks;
|
||||
info->array.level = sb->level;
|
||||
info->array.layout = sb->layout;
|
||||
info->array.md_minor = sb->md_minor;
|
||||
info->array.ctime = sb->ctime;
|
||||
|
||||
|
|
6
super1.c
6
super1.c
|
@ -180,6 +180,11 @@ static void examine_super1(void *sbv)
|
|||
c = map_num(r5layout, __le32_to_cpu(sb->layout));
|
||||
printf(" Layout : %s\n", c?c:"-unknown-");
|
||||
}
|
||||
if (__le32_to_cpu(sb->level) == 10) {
|
||||
int lo = __le32_to_cpu(sb->layout);
|
||||
printf(" Layout : near=%d, far=%d\n",
|
||||
lo&255, (lo>>8)&255);
|
||||
}
|
||||
switch(__le32_to_cpu(sb->level)) {
|
||||
case 0:
|
||||
case 4:
|
||||
|
@ -290,6 +295,7 @@ static void getinfo_super1(struct mdinfo *info, mddev_ident_t ident, void *sbv)
|
|||
info->array.patch_version = 0;
|
||||
info->array.raid_disks = __le32_to_cpu(sb->raid_disks);
|
||||
info->array.level = __le32_to_cpu(sb->level);
|
||||
info->array.layout = __le32_to_cpu(sb->layout);
|
||||
info->array.md_minor = -1;
|
||||
info->array.ctime = __le64_to_cpu(sb->ctime);
|
||||
|
||||
|
|
25
util.c
25
util.c
|
@ -118,10 +118,31 @@ int get_linux_version()
|
|||
return (a*1000000)+(b*1000)+c;
|
||||
}
|
||||
|
||||
int enough(int level, int raid_disks, int avail_disks)
|
||||
int enough(int level, int raid_disks, int layout,
|
||||
char *avail, int avail_disks)
|
||||
{
|
||||
int copies, first;
|
||||
switch (level) {
|
||||
case 10: return 1; /* a lie, but it is hard to tell */
|
||||
case 10:
|
||||
/* This is the tricky one - we need to check
|
||||
* which actual disks are present.
|
||||
*/
|
||||
copies = (layout&255)* (layout>>8);
|
||||
first=0;
|
||||
do {
|
||||
/* there must be one of the 'copies' form 'first' */
|
||||
int n = copies;
|
||||
int cnt=0;
|
||||
while (n--) {
|
||||
if (avail[first])
|
||||
cnt++;
|
||||
first = (first+1) % raid_disks;
|
||||
}
|
||||
if (cnt == 0)
|
||||
return 0;
|
||||
|
||||
} while (first != 0);
|
||||
return 1;
|
||||
|
||||
case -4:
|
||||
return avail_disks>= 1;
|
||||
|
|
Loading…
Reference in New Issue