]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdmon: when a reshape is detected, add any newly added devices to the array.
authorNeilBrown <neilb@suse.de>
Wed, 15 Dec 2010 22:07:52 +0000 (09:07 +1100)
committerNeilBrown <neilb@suse.de>
Wed, 15 Dec 2010 22:07:52 +0000 (09:07 +1100)
When mdadm starts a reshape, it might add some devices to the array
first.  mdmon needs to notice the reshape starting and check for any
new devices.  If there are any they need to be provided to be
monitored.

Signed-off-by: NeilBrown <neilb@suse.de>
managemon.c
mdmon.h
monitor.c

index 7e4924fe67977689afcebb6ae82c4ee571db173a..5cc50d8d3d9473be7003045bb82708d03de91d50 100644 (file)
@@ -420,12 +420,12 @@ static void manage_member(struct mdstat_ent *mdstat,
         * We do not need to look for device state changes here, that
         * is dealt with by the monitor.
         *
-        * We just look for changes which suggest that a reshape is
-        * being requested.
-        * Unfortunately decreases in raid_disks don't show up in
-        * mdstat until the reshape completes FIXME.
+        * If a reshape is being requested, monitor will have noticed
+        * that sync_action changed and will have set check_reshape.
+        * We just need to see if new devices have appeared.  All metadata
+        * updates will already have been processed.
         *
-        * Actually, we also want to handle degraded arrays here by
+        * We also want to handle degraded arrays here by
         * trying to find and assign a spare.
         * We do that whenever the monitor tells us too.
         */
@@ -488,6 +488,46 @@ static void manage_member(struct mdstat_ent *mdstat,
                }
                free_updates(&updates);
        }
+
+       if (a->check_reshape) {
+               /* mdadm might have added some devices to the array.
+                * We want to disk_init_and_add any such device to a
+                * duplicate_aa and replace a with that.
+                * mdstat doesn't have enough info so we sysfs_read
+                * and look for new stuff.
+                */
+               struct mdinfo *info, *d, *d2, *newd;
+               struct active_array *newa = NULL;
+               a->check_reshape = 0;
+               info = sysfs_read(-1, mdstat->devnum,
+                                 GET_DEVS|GET_OFFSET|GET_SIZE|GET_STATE);
+               if (!info)
+                       goto out2;
+               for (d = info->devs; d; d = d->next) {
+                       if (d->disk.raid_disk < 0)
+                               continue;
+                       for (d2 = a->info.devs; d2; d2 = d2->next)
+                               if (d2->disk.raid_disk ==
+                                   d->disk.raid_disk)
+                                       break;
+                       if (d2)
+                               /* already have this one */
+                               continue;
+                       if (!newa) {
+                               newa = duplicate_aa(a);
+                               if (!newa)
+                                       break;
+                       }
+                       newd = malloc(sizeof(*newd));
+                       if (!newd)
+                               continue;
+                       disk_init_and_add(newd, d, newa);
+               }
+       out2:
+               sysfs_free(info);
+               if (newa)
+                       replace_array(a->container, a, newa);
+       }
 }
 
 static int aa_ready(struct active_array *aa)
diff --git a/mdmon.h b/mdmon.h
index 5c515663f4a4225d1c23ec6c38c571537eca9cb2..6d1776f9281e5ab6e0a47ed29ed416ed2d483328 100644 (file)
--- a/mdmon.h
+++ b/mdmon.h
@@ -46,6 +46,7 @@ struct active_array {
        enum sync_action prev_action, curr_action, next_action;
 
        int check_degraded; /* flag set by mon, read by manage */
+       int check_reshape; /* flag set by mon, read by manage */
 
        int devnum;
 };
index f166bc8fd44b0b0140ed313e3720b4ffdd1b6764..f566890531b8f46c807acb36553ea019e5bce0f2 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -215,6 +215,7 @@ static int read_and_act(struct active_array *a)
 {
        unsigned long long sync_completed;
        int check_degraded = 0;
+       int check_reshape = 0;
        int deactivate = 0;
        struct mdinfo *mdi;
        int dirty = 0;
@@ -305,6 +306,15 @@ static int read_and_act(struct active_array *a)
                }
        }
 
+       if (!deactivate &&
+           a->curr_action == reshape &&
+           a->prev_action != reshape)
+               /* reshape was requested by mdadm.  Need to see if
+                * new devices have been added.  Manager does that
+                * when it sees check_reshape
+                */
+               check_reshape = 1;
+
        /* Check for failures and if found:
         * 1/ Record the failure in the metadata and unblock the device.
         *    FIXME update the kernel to stop notifying on failed drives when
@@ -393,9 +403,12 @@ static int read_and_act(struct active_array *a)
                mdi->next_state = 0;
        }
 
-       if (check_degraded) {
+       if (check_degraded || check_reshape) {
                /* manager will do the actual check */
-               a->check_degraded = 1;
+               if (check_degraded)
+                       a->check_degraded = 1;
+               if (check_reshape)
+                       a->check_reshape = 1;
                signal_manager();
        }