Give useful message if raid4/5/6 cannot be started because it is not clean and is also degraded.

This commit is contained in:
Neil Brown 2006-12-14 17:31:13 +11:00
parent 7572344665
commit 583315d9c5
6 changed files with 42 additions and 7 deletions

View File

@ -111,6 +111,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
* START_ARRAY
*
*/
int clean = 0;
int must_close = 0;
int old_linux = 0;
int vers = 0; /* Keep gcc quite - it really is initialised */
@ -583,6 +584,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
}
st->ss->getinfo_super(&info, first_super);
clean = info.array.state & 1;
/* now we have some devices that might be suitable.
* I wonder how many
@ -617,7 +619,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
}
}
while (force && !enough(info.array.level, info.array.raid_disks,
info.array.layout,
info.array.layout, 1,
avail, okcnt)) {
/* Choose the newest best drive which is
* not up-to-date, update the superblock
@ -758,6 +760,7 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
change += st->ss->update_super(&info, super, "force-array",
devices[chosen_drive].devname, verbose,
0, NULL);
clean = 1;
}
if (change) {
@ -894,7 +897,8 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
if (runstop == 1 ||
(runstop <= 0 &&
( enough(info.array.level, info.array.raid_disks, info.array.layout, avail, okcnt) &&
( enough(info.array.level, info.array.raid_disks,
info.array.layout, clean, avail, okcnt) &&
(okcnt >= req_cnt || start_partial_ok)
))) {
if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
@ -937,6 +941,19 @@ int Assemble(struct supertype *st, char *mddev, int mdfd,
}
fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",
mddev, strerror(errno));
if (!enough(info.array.level, info.array.raid_disks,
info.array.layout, 1, avail, okcnt))
fprintf(stderr, Name ": Not enough devices to "
"start the array.\n");
else if (!enough(info.array.level,
info.array.raid_disks,
info.array.layout, clean,
avail, okcnt))
fprintf(stderr, Name ": Not enough devices to "
"start the array while not clean "
"- consider --force.\n");
if (must_close) close(mdfd);
return 1;
}
@ -953,8 +970,16 @@ 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, info.array.layout, avail, okcnt))
if (!enough(info.array.level, info.array.raid_disks,
info.array.layout, 1, avail, okcnt))
fprintf(stderr, " - not enough to start the array.\n");
else if (!enough(info.array.level,
info.array.raid_disks,
info.array.layout, clean,
avail, okcnt))
fprintf(stderr, " - not enough to start the "
"array while not clean - consider "
"--force.\n");
else {
if (req_cnt == info.array.raid_disks)
fprintf(stderr, " - need all %d to start it", req_cnt);

View File

@ -10,6 +10,8 @@ Changes Prior to this release
can change size.
- Default to --auto=yes so the array devices with 'standard' names
get created automatically, as this is almost always what is wanted.
- Give useful message if raid4/5/6 cannot be started because it is
not clean and is also degraded.
Changes Prior to 2.5.6 release
- Fix bug which meant "bitmap=xxx" in mdadm.conf was not handled

View File

@ -456,7 +456,7 @@ 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 layout,
extern int enough(int level, int raid_disks, int layout, int clean,
char *avail, int avail_disks);
extern int ask(char *mesg);
extern unsigned long long get_component_size(int fd);

View File

@ -320,6 +320,7 @@ static void getinfo_super0(struct mdinfo *info, void *sbv)
info->array.ctime = sb->ctime;
info->array.utime = sb->utime;
info->array.chunk_size = sb->chunk_size;
info->array.state = sb->state;
info->component_size = sb->size*2;
info->disk.state = sb->this_disk.state;

View File

@ -429,6 +429,7 @@ static void getinfo_super1(struct mdinfo *info, void *sbv)
info->array.ctime = __le64_to_cpu(sb->ctime);
info->array.utime = __le64_to_cpu(sb->utime);
info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512;
info->array.state = (__le64_to_cpu(sb->resync_offset)+1) ? 0 : 1;
info->data_offset = __le64_to_cpu(sb->data_offset);
info->component_size = __le64_to_cpu(sb->size);

12
util.c
View File

@ -170,7 +170,7 @@ void remove_partitions(int fd)
#endif
}
int enough(int level, int raid_disks, int layout,
int enough(int level, int raid_disks, int layout, int clean,
char *avail, int avail_disks)
{
int copies, first;
@ -205,9 +205,15 @@ int enough(int level, int raid_disks, int layout,
return avail_disks >= 1;
case 4:
case 5:
return avail_disks >= raid_disks-1;
if (clean)
return avail_disks >= raid_disks-1;
else
return avail_disks >= raid_disks;
case 6:
return avail_disks >= raid_disks-2;
if (clean)
return avail_disks >= raid_disks-2;
else
return avail_disks >= raid_disks;
default:
return 0;
}