]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Assemble: add support for replacement devices.
authorNeilBrown <neilb@suse.de>
Tue, 23 Oct 2012 22:48:18 +0000 (09:48 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 23 Oct 2012 22:48:18 +0000 (09:48 +1100)
Need to possibly collect 2 devices for each slot, and
original and a replacement.

Signed-off-by: NeilBrown <neilb@suse.de>
Assemble.c
md_p.h
super1.c

index cbc591c7c4cbd76a4a8bb2cda42d9a326de6f732..94e314b78040190faec3d6c1fd9d20546123f1d3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
  *
  *
  *    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<<MD_DISK_REPLACEMENT)) ? " replacement":"");
                devices[devcnt].devname = devname;
                devices[devcnt].uptodate = 0;
                devices[devcnt].included = (tmpdev->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<<MD_DISK_REPLACEMENT))
+                               i++;
+                       if (i >= 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<<MD_DISK_REPLACEMENT))?" replacement":"");
                } else if (j >= 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<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
-               else
+               if (i >= content->array.raid_disks * 2)
                        desired_state = 0;
+               else if (i & 1)
+                       desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_REPLACEMENT);
+               else
+                       desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
 
                if (j<0)
                        continue;
diff --git a/md_p.h b/md_p.h
index 517b20411e29bc7c46229c1ea5e1e625d40a6174..c7c4388b5d7376121d698df11bc58af893e1a36c 100644 (file)
--- a/md_p.h
+++ b/md_p.h
@@ -84,6 +84,8 @@
                                   * dire need
                                   */
 
+#define MD_DISK_REPLACEMENT    17
+
 typedef struct mdp_device_descriptor_s {
        __u32 number;           /* 0 Device number in the entire set          */
        __u32 major;            /* 1 Device major number                      */
index dd6b9be1e0e82a65d1d14abad10a8ebe6b13c092..54e935a4752bc02dfc8bd96b59796f15aac168f6 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -766,6 +766,11 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
        strncpy(info->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<<MD_DISK_ACTIVE))
                        want = info->disk.raid_disk;
                else
                        want = 0xFFFF;