]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
imsm: FIX: Sometimes reshape cannot be finished
authorAdam Kwolek <adam.kwolek@intel.com>
Tue, 14 Jun 2011 23:13:49 +0000 (09:13 +1000)
committerNeilBrown <neilb@suse.de>
Tue, 14 Jun 2011 23:13:49 +0000 (09:13 +1000)
When array size is not aligned to copy area, number of migration unit
is increased in init_migr_record_imsm():7665 to reshape whole array.
During calculation of last migration unit, this should be in mind also,
otherwise checkpoint (max-1) is always written and reshape
is never finished in mdadm.

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

index 5dc8ca8adb6a1b6575fdb9c5e34341fd490ffdea..bb76f74938c0c046fa5f5388f27e2e216dcf8b5f 100644 (file)
@@ -7788,24 +7788,34 @@ abort:
 int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state)
 {
        struct intel_super *super = st->sb;
+       unsigned long long blocks_per_unit;
+       unsigned long long curr_migr_unit;
+
        if (load_imsm_migr_rec(super, info) != 0) {
                dprintf("imsm: ERROR: Cannot read migration record "
                        "for checkpoint save.\n");
                return 1;
        }
 
-       if (__le32_to_cpu(super->migr_rec->blocks_per_unit) == 0) {
+       blocks_per_unit = __le32_to_cpu(super->migr_rec->blocks_per_unit);
+       if (blocks_per_unit == 0) {
                dprintf("imsm: no migration in progress.\n");
                return 2;
        }
+       curr_migr_unit = info->reshape_progress / blocks_per_unit;
+       /* check if array is alligned to copy area
+        * if it is not alligned, add one to current migration unit value
+        * this can happend on array reshape finish only
+        */
+       if (info->reshape_progress % blocks_per_unit)
+               curr_migr_unit++;
 
        super->migr_rec->curr_migr_unit =
-         __cpu_to_le32(info->reshape_progress /
-                       __le32_to_cpu(super->migr_rec->blocks_per_unit));
+               __cpu_to_le32(curr_migr_unit);
        super->migr_rec->rec_status = __cpu_to_le32(state);
        super->migr_rec->dest_1st_member_lba =
-         __cpu_to_le32((__le32_to_cpu(super->migr_rec->curr_migr_unit))
-                       * __le32_to_cpu(super->migr_rec->dest_depth_per_unit));
+               __cpu_to_le32(curr_migr_unit *
+                             __le32_to_cpu(super->migr_rec->dest_depth_per_unit));
        if (write_imsm_migr_rec(st) < 0) {
                dprintf("imsm: Cannot write migration record "
                        "outside backup area\n");