summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2006-12-14 17:31:13 +1100
committerNeil Brown <neilb@suse.de>2006-12-14 17:31:13 +1100
commit583315d9c522c310c89d5640ae884ef7984b9c30 (patch)
treee3a1f9d2e617fc90460b7786fc01e8c255cbe211
parent757234466509aae6221c2cb96e8366f41ba7e532 (diff)
downloadmdadm-583315d9c522c310c89d5640ae884ef7984b9c30.tar.gz
mdadm-583315d9c522c310c89d5640ae884ef7984b9c30.tar.xz
mdadm-583315d9c522c310c89d5640ae884ef7984b9c30.zip
Give useful message if raid4/5/6 cannot be started because it is not clean and is also degraded.
-rw-r--r--Assemble.c31
-rw-r--r--ChangeLog2
-rw-r--r--mdadm.h2
-rw-r--r--super0.c1
-rw-r--r--super1.c1
-rw-r--r--util.c12
6 files changed, 42 insertions, 7 deletions
diff --git a/Assemble.c b/Assemble.c
index 23e3583..59f4239 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 46af0ee..756ed92 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 f6e7b5e..1976dd1 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 fbb7eb9..d2338a9 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 140f637..1890949 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 8d06848..6148ff8 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;
}