]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
imsm: Update metadata for second array
authorAdam Kwolek <adam.kwolek@intel.com>
Thu, 6 Jan 2011 07:29:23 +0000 (18:29 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 6 Jan 2011 07:29:23 +0000 (18:29 +1100)
When second array reshape is about to start metadata should be updated
by mdmon in imsm_set_array_state().

Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
super-intel.c

index c52aea87d38ae7459d6710bbcc21e560445d4256..9ac4321dd80e3c7b78fcaea06b08ef65f07f890f 100644 (file)
@@ -4849,6 +4849,73 @@ 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);
 
+static void imsm_progress_container_reshape(struct intel_super *super)
+{
+       /* if no device has a migr_state, but some device has a
+        * different number of members than the previous device, start
+        * changing the number of devices in this device to match
+        * previous.
+        */
+       struct imsm_super *mpb = super->anchor;
+       int prev_disks = -1;
+       int i;
+
+       for (i = 0; i < mpb->num_raid_devs; i++) {
+               struct imsm_dev *dev = get_imsm_dev(super, i);
+               struct imsm_map *map = get_imsm_map(dev, 0);
+               struct imsm_map *map2;
+               int prev_num_members;
+               int used_disks;
+
+               if (dev->vol.migr_state)
+                       return;
+
+               if (prev_disks == -1)
+                       prev_disks = map->num_members;
+               if (prev_disks == map->num_members)
+                       continue;
+
+               /* OK, this array needs to enter reshape mode.
+                * i.e it needs a migr_state
+                */
+
+               prev_num_members = map->num_members;
+               map->num_members = prev_disks;
+               dev->vol.migr_state = 1;
+               dev->vol.curr_migr_unit = 0;
+               dev->vol.migr_type = MIGR_GEN_MIGR;
+               for (i = prev_num_members;
+                    i < map->num_members; i++)
+                       set_imsm_ord_tbl_ent(map, i, i);
+               map2 = get_imsm_map(dev, 1);
+               /* Copy the current map */
+               memcpy(map2, map, sizeof_imsm_map(map));
+               map2->num_members = prev_num_members;
+
+               /* calculate new size
+                */
+               used_disks = imsm_num_data_members(dev, 0);
+               if (used_disks) {
+                       unsigned long long array_blocks;
+
+                       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));
+               }
+               super->updates_pending++;
+       }
+}
+
 /* 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
@@ -4918,6 +4985,7 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
                                                       * array size
                                                       */
                                super->updates_pending++;
+                               imsm_progress_container_reshape(super);
                        }                               
                }
        }