From: NeilBrown Date: Tue, 23 Oct 2012 22:48:18 +0000 (+1100) Subject: Assemble: add support for replacement devices. X-Git-Tag: mdadm-3.3-rc1~163 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aacb2f816afbddf56c406039b8e2e6c0dbc8a8a0;p=thirdparty%2Fmdadm.git Assemble: add support for replacement devices. Need to possibly collect 2 devices for each slot, and original and a replacement. Signed-off-by: NeilBrown --- diff --git a/Assemble.c b/Assemble.c index cbc591c7..94e314b7 100644 --- a/Assemble.c +++ b/Assemble.c @@ -1,7 +1,7 @@ /* * mdadm - manage Linux "md" devices aka RAID arrays. * - * Copyright (C) 2001-2009 Neil Brown + * Copyright (C) 2001-2012 Neil Brown * * * This program is free software; you can redistribute it and/or modify @@ -135,7 +135,6 @@ static int select_devices(struct mddev_dev *devlist, struct mdinfo **contentp, struct context *c, int inargv, int auto_assem) - { struct mddev_dev *tmpdev; int num_devs; @@ -659,8 +658,9 @@ static int load_devices(struct devs *devices, char *devmap, stat(devname, &stb); if (c->verbose > 0) - pr_err("%s is identified as a member of %s, slot %d.\n", - devname, mddev, content->disk.raid_disk); + pr_err("%s is identified as a member of %s, slot %d%s.\n", + devname, mddev, content->disk.raid_disk, + (content->disk.state & (1<disposition == 'I'); @@ -678,11 +678,16 @@ static int load_devices(struct devs *devices, char *devmap, else i = devices[devcnt].i.disk.raid_disk; if (i+1 == 0) { - if (nextspare < content->array.raid_disks) - nextspare = content->array.raid_disks; + if (nextspare < content->array.raid_disks*2) + nextspare = content->array.raid_disks*2; i = nextspare++; } else { - if (i >= content->array.raid_disks && + /* i is raid_disk - double it so there is room for + * replacements */ + i *= 2; + if (devices[devcnt].i.disk.state & (1<= content->array.raid_disks*2 && i >= nextspare) nextspare = i+1; } @@ -913,23 +918,25 @@ static int start_array(int mdfd, devices[j].devname, mddev, strerror(errno)); - if (i < content->array.raid_disks + if (i < content->array.raid_disks * 2 || i == bestcnt) okcnt--; else sparecnt--; } else if (c->verbose > 0) - pr_err("added %s to %s as %d%s\n", + pr_err("added %s to %s as %d%s%s\n", devices[j].devname, mddev, devices[j].i.disk.raid_disk, devices[j].uptodate?"": - " (possibly out of date)"); + " (possibly out of date)", + (devices[j].i.disk.state & (1<= 0) { if (c->verbose > 0) pr_err("%s is already in %s as %d\n", devices[j].devname, mddev, devices[j].i.disk.raid_disk); - } else if (c->verbose > 0 && i < content->array.raid_disks) + } else if (c->verbose > 0 && i < content->array.raid_disks*2 + && (i&1) == 0) pr_err("no uptodate device for slot %d of %s\n", i, mddev); } @@ -1063,7 +1070,7 @@ static int start_array(int mdfd, if (c->verbose >= -1) { pr_err("%s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s"); if (rebuilding_cnt) - fprintf(stderr, "%s %d rebuilding", sparecnt?", ":" and ", rebuilding_cnt); + fprintf(stderr, "%s %d rebuilding", sparecnt?",":" and", rebuilding_cnt); if (sparecnt) fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s"); if (!enough(content->array.level, content->array.raid_disks, @@ -1080,7 +1087,7 @@ static int start_array(int mdfd, if (req_cnt == (unsigned)content->array.raid_disks) fprintf(stderr, " - need all %d to start it", req_cnt); else - fprintf(stderr, " - need %d of %d to start", req_cnt, content->array.raid_disks); + fprintf(stderr, " - need %d to start", req_cnt); fprintf(stderr, " (use --run to insist).\n"); } } @@ -1157,7 +1164,7 @@ int Assemble(struct supertype *st, char *mddev, int *best = NULL; /* indexed by raid_disk */ int bestcnt = 0; int devcnt; - unsigned int okcnt, sparecnt, rebuilding_cnt; + unsigned int okcnt, sparecnt, rebuilding_cnt, replcnt; int i; int most_recent = 0; int chosen_drive; @@ -1390,6 +1397,7 @@ try_again: */ avail = xcalloc(content->array.raid_disks, 1); okcnt = 0; + replcnt = 0; sparecnt=0; rebuilding_cnt=0; for (i=0; i< bestcnt; i++) { @@ -1426,14 +1434,17 @@ try_again: if (devices[j].i.events+event_margin >= devices[most_recent].i.events) { devices[j].uptodate = 1; - if (i < content->array.raid_disks) { + if (i < content->array.raid_disks * 2) { if (devices[j].i.recovery_start == MaxSector || (content->reshape_active && ((i >= content->array.raid_disks - content->delta_disks) || (i >= content->array.raid_disks - content->delta_disks - 1 && content->array.level == 4)))) { - okcnt++; - avail[i]=1; + if (!avail[i/2]) { + okcnt++; + avail[i/2]=1; + } else + replcnt++; } else rebuilding_cnt++; } else @@ -1497,10 +1508,12 @@ try_again: int j = best[i]; unsigned int desired_state; - if (i < content->array.raid_disks) - desired_state = (1<= content->array.raid_disks * 2) desired_state = 0; + else if (i & 1) + desired_state = (1<name, sb->set_name, 32); info->name[32] = 0; + if ((__le32_to_cpu(sb->feature_map)&MD_FEATURE_REPLACEMENT)) { + info->disk.state |= 1 << MD_DISK_REPLACEMENT; + } + + if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RECOVERY_OFFSET)) info->recovery_start = __le32_to_cpu(sb->recovery_offset); else @@ -847,7 +852,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, } else if (strcmp(update, "assemble")==0) { int d = info->disk.number; int want; - if (info->disk.state == 6) + if (info->disk.state & (1<disk.raid_disk; else want = 0xFFFF;