]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Handle checkpointing during reshape
authorNeilBrown <neilb@suse.de>
Thu, 16 Dec 2010 04:48:05 +0000 (15:48 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 16 Dec 2010 04:48:05 +0000 (15:48 +1100)
We need to allow metadata to handle progress of reshape,
completion, and abort-before-start.

Include all those in ->set_array_state()

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

index 860e5785aaf7f4abd9fa8e3418e740b6fbcf5cfa..9cb8049971f4168828d3da202176f168a7705c74 100644 (file)
@@ -503,6 +503,7 @@ static void manage_member(struct mdstat_ent *mdstat,
                 * and look for new stuff.
                 */
                struct mdinfo *info, *d, *d2, *newd;
+               unsigned long long array_size;
                struct active_array *newa = NULL;
                a->check_reshape = 0;
                info = sysfs_read(-1, mdstat->devnum,
@@ -529,6 +530,11 @@ static void manage_member(struct mdstat_ent *mdstat,
                                continue;
                        disk_init_and_add(newd, d, newa);
                }
+               if (sysfs_get_ll(info, NULL, "array_size", &array_size) == 0
+                   && a->info.custom_array_size > array_size) {
+                       sysfs_set_num(info, NULL, "array_size",
+                                     a->info.custom_array_size);
+               }
        out2:
                sysfs_free(info);
                if (newa)
index f566890531b8f46c807acb36553ea019e5bce0f2..3962d9e90ed0279ba3cca39c6a409ba3adbf4cd2 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -339,8 +339,8 @@ static int read_and_act(struct active_array *a)
 
        /* Check for recovery checkpoint notifications.  We need to be a
         * minimum distance away from the last checkpoint to prevent
-        * over checkpointing.  Note reshape checkpointing is not
-        * handled here.
+        * over checkpointing.  Note reshape checkpointing is handled
+        * in the second branch.
         */
        if (sync_completed > a->last_checkpoint &&
            sync_completed - a->last_checkpoint > a->info.component_size >> 4 &&
@@ -350,7 +350,17 @@ static int read_and_act(struct active_array *a)
                 */
                a->last_checkpoint = sync_completed;
                a->container->ss->set_array_state(a, a->curr_state <= clean);
-       } else if (sync_completed > a->last_checkpoint)
+       } else if ((a->curr_action == idle && a->prev_action == reshape) ||
+                  (a->curr_action == reshape
+                   && sync_completed > a->last_checkpoint) ) {
+               /* Reshape has progressed or completed so we need to
+                * update the array state - and possibly the array size
+                */
+               a->last_checkpoint = sync_completed;
+               a->container->ss->set_array_state(a, a->curr_state <= clean);
+       }
+
+       if (sync_completed > a->last_checkpoint)
                a->last_checkpoint = sync_completed;
 
        a->container->ss->sync_metadata(a->container);
index 8fd49344db01d4a27481c5c8d4d3f5e949f7be26..3182d4741ebbb2dcac05b870f0a193ddc8ed3630 100644 (file)
@@ -1503,6 +1503,7 @@ static __u64 blocks_per_migr_unit(struct imsm_dev *dev)
                return migr_chunk * stripes_per_unit;
        }
        case MIGR_GEN_MIGR:
+               /* FIXME I need a number here */
        case MIGR_STATE_CHANGE:
        default:
                return 0;
@@ -4825,7 +4826,7 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
 
 static void imsm_set_disk(struct active_array *a, int n, int state);
 
-/* Handle dirty -> clean transititions and resync.  Degraded and rebuild
+/* Handle dirty -> clean transititions, resync and reshape.  Degraded and rebuild
  * states are handled in imsm_set_disk() with one exception, when a
  * resync is stopped due to a new failure this routine will set the
  * 'degraded' state for the array.
@@ -4843,12 +4844,55 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
        if (dev->vol.migr_state &&
            dev->vol.migr_type  == MIGR_GEN_MIGR) {
                /* array state change is blocked due to reshape action
-                *
-                * '1' is returned to indicate that array is clean
+                * We might need to
+                * - abort the reshape (if last_checkpoint is 0 and action!= reshape)
+                * - finish the reshape (if last_checkpoint is big and action != reshape)
+                * - update curr_migr_unit
                 */
-               dprintf("imsm: imsm_set_array_state() called "\
-                       "during reshape.\n");
-               return 1;
+               if (a->curr_action == reshape) {
+                       /* still reshaping, maybe update curr_migr_unit */
+                       long long blocks_per_unit = blocks_per_migr_unit(dev);
+                       long long unit = a->last_checkpoint;
+                       unit /= blocks_per_unit;
+                       if (unit > __le32_to_cpu(dev->vol.curr_migr_unit)) {
+                               dev->vol.curr_migr_unit = __cpu_to_le32(unit);
+                               super->updates_pending++;
+                       }
+               } else {
+                       if (a->last_checkpoint == 0 && a->prev_action == reshape) {
+                               /* for some reason we aborted the reshape.
+                                * Better clean up
+                                */
+                               struct imsm_map *map2 = get_imsm_map(dev, 1);
+                               dev->vol.migr_state = 0;
+                               dev->vol.migr_type = 0;
+                               dev->vol.curr_migr_unit = 0;
+                               memcpy(map, map2, sizeof_imsm_map(map2));
+                               super->updates_pending++;
+                       }
+                       if (a->last_checkpoint >= a->info.component_size) {
+                               unsigned long long array_blocks;
+                               int used_disks;
+                               /* it seems the reshape is all done */
+                               dev->vol.migr_state = 0;
+                               dev->vol.migr_type = 0;
+                               dev->vol.curr_migr_unit = 0;
+
+                               used_disks = imsm_num_data_members(dev);
+                               array_blocks = map->blocks_per_member * used_disks;
+                               /* round array size down to closest MB */
+                               array_blocks = (array_blocks >> SECT_PER_MB_SHIFT)
+                                       << SECT_PER_MB_SHIFT;
+                               dev->size_low = __cpu_to_le32((__u32) array_blocks);
+                               dev->size_high = __cpu_to_le32((__u32) (array_blocks >> 32));
+                               a->info.custom_array_size = array_blocks;
+                               a->check_reshape = 1; /* encourage manager to update
+                                                      * array size
+                                                      */
+                               super->updates_pending++;
+                       }                               
+               }
+               return 0;
        }
 
        /* before we activate this array handle any missing disks */