From: Neil Brown Date: Thu, 14 Dec 2006 06:31:13 +0000 (+1100) Subject: Give useful message if raid4/5/6 cannot be started because it is not clean and is... X-Git-Tag: mdadm-2.6~14 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=commitdiff_plain;h=583315d9c522c310c89d5640ae884ef7984b9c30 Give useful message if raid4/5/6 cannot be started because it is not clean and is also degraded. --- diff --git a/Assemble.c b/Assemble.c index 23e35830..59f42390 100644 --- a/Assemble.c +++ b/Assemble.c @@ -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); diff --git a/ChangeLog b/ChangeLog index 46af0ee1..756ed92f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/mdadm.h b/mdadm.h index f6e7b5ee..1976dd10 100644 --- a/mdadm.h +++ b/mdadm.h @@ -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); diff --git a/super0.c b/super0.c index fbb7eb9e..d2338a9d 100644 --- a/super0.c +++ b/super0.c @@ -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; diff --git a/super1.c b/super1.c index 140f6371..18909497 100644 --- a/super1.c +++ b/super1.c @@ -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); diff --git a/util.c b/util.c index 8d06848e..6148ff8c 100644 --- a/util.c +++ b/util.c @@ -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; }