mddev_dev_t tmpdev;
struct mdinfo info;
struct mddev_ident_s ident2;
+ char *avail;
vers = md_get_version(mdfd);
if (vers <= 0) {
/* 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++) {
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.
close(fd);
devices[chosen_drive].events = devices[most_recent].events;
devices[chosen_drive].uptodate = 1;
+ avail[chosen_drive] = 1;
okcnt++;
free(super);
}
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) {
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)
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.
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);
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:
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;
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:
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);
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;