]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
imsm: Do not mark resync during reshape
[thirdparty/mdadm.git] / super-intel.c
index e9d9af80343a3b7d4fb3d31632c9839d021504a2..8e9e977450115ccceae777ae126c6b8f5b520529 100644 (file)
@@ -88,6 +88,7 @@
 
 #define MPB_SECTOR_CNT 2210
 #define IMSM_RESERVED_SECTORS 4096
+#define NUM_BLOCKS_DIRTY_STRIPE_REGION 2056
 #define SECT_PER_MB_SHIFT 11
 
 /* Disk configuration info. */
@@ -827,6 +828,8 @@ static int count_memberships(struct dl *dl, struct intel_super *super)
        return memberships;
 }
 
+static __u32 imsm_min_reserved_sectors(struct intel_super *super);
+
 static struct extent *get_extents(struct intel_super *super, struct dl *dl)
 {
        /* find a list of used extents on the given physical device */
@@ -840,7 +843,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl)
         * IMSM_RESERVED_SECTORS region
         */
        if (dl->index == -1)
-               reservation = MPB_SECTOR_CNT;
+               reservation = imsm_min_reserved_sectors(super);
        else
                reservation = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
 
@@ -933,6 +936,51 @@ static int is_failed(struct imsm_disk *disk)
        return (disk->status & FAILED_DISK) == FAILED_DISK;
 }
 
+/* try to determine how much space is reserved for metadata from
+ * the last get_extents() entry on the smallest active disk,
+ * otherwise fallback to the default
+ */
+static __u32 imsm_min_reserved_sectors(struct intel_super *super)
+{
+       struct extent *e;
+       int i;
+       __u32 min_active, remainder;
+       __u32 rv = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
+       struct dl *dl, *dl_min = NULL;
+
+       if (!super)
+               return rv;
+
+       min_active = 0;
+       for (dl = super->disks; dl; dl = dl->next) {
+               if (dl->index < 0)
+                       continue;
+               if (dl->disk.total_blocks < min_active || min_active == 0) {
+                       dl_min = dl;
+                       min_active = dl->disk.total_blocks;
+               }
+       }
+       if (!dl_min)
+               return rv;
+
+       /* find last lba used by subarrays on the smallest active disk */
+       e = get_extents(super, dl_min);
+       if (!e)
+               return rv;
+       for (i = 0; e[i].size; i++)
+               continue;
+
+       remainder = min_active - e[i].start;
+       free(e);
+
+       /* to give priority to recovery we should not require full
+          IMSM_RESERVED_SECTORS from the spare */
+       rv = MPB_SECTOR_CNT + NUM_BLOCKS_DIRTY_STRIPE_REGION;
+
+       /* if real reservation is smaller use that value */
+       return  (remainder < rv) ? remainder : rv;
+}
+
 /* Return minimum size of a spare that can be used in this array*/
 static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
 {
@@ -941,6 +989,7 @@ static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
        struct extent *e;
        int i;
        unsigned long long rv = 0;
+       __u32 reservation;
 
        if (!super)
                return rv;
@@ -958,9 +1007,12 @@ static unsigned long long min_acceptable_spare_size_imsm(struct supertype *st)
                continue;
        if (i > 0)
                rv = e[i-1].start + e[i-1].size;
+       reservation = __le32_to_cpu(dl->disk.total_blocks) - e[i].start;
        free(e);
+
        /* add the amount of space needed for metadata */
-       rv = rv + MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
+       rv = rv + imsm_min_reserved_sectors(super);
+
        return rv * 512;
 }
 
@@ -2185,6 +2237,31 @@ static int write_imsm_migr_rec(struct supertype *st)
 }
 #endif /* MDASSEMBLE */
 
+/* spare/missing disks activations are not allowe when
+ * array/container performs reshape operation, because
+ * all arrays in container works on the same disks set
+ */
+int imsm_reshape_blocks_arrays_changes(struct intel_super *super)
+{
+       int rv = 0;
+       struct intel_dev *i_dev;
+       struct imsm_dev *dev;
+
+       /* check whole container
+        */
+       for (i_dev = super->devlist; i_dev; i_dev = i_dev->next) {
+               dev = i_dev->dev;
+               if (dev->vol.migr_state &&
+                   dev->vol.migr_type == MIGR_GEN_MIGR) {
+                       /* No repair during any migration in container
+                        */
+                       rv = 1;
+                       break;
+               }
+       }
+       return rv;
+}
+
 static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap)
 {
        struct intel_super *super = st->sb;
@@ -2296,8 +2373,9 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
 
        info->reshape_progress = 0;
        info->resync_start = MaxSector;
-       if (map_to_analyse->map_state == IMSM_T_STATE_UNINITIALIZED ||
-           dev->vol.dirty) {
+       if ((map_to_analyse->map_state == IMSM_T_STATE_UNINITIALIZED ||
+           dev->vol.dirty) &&
+           imsm_reshape_blocks_arrays_changes(super) == 0) {
                info->resync_start = 0;
        }
        if (dev->vol.migr_state) {
@@ -6153,7 +6231,8 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
                        super->updates_pending++;
                        a->last_checkpoint = 0;
                }
-       } else if (!is_resyncing(dev) && !failed) {
+       } else if ((!is_resyncing(dev) && !failed) &&
+                  (imsm_reshape_blocks_arrays_changes(super) == 0)) {
                /* mark the start of the init process if nothing is failed */
                dprintf("imsm: mark resync start\n");
                if (map->map_state == IMSM_T_STATE_UNINITIALIZED)
@@ -6540,10 +6619,8 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
        dprintf("imsm: activate spare: inst=%d failed=%d (%d) level=%d\n",
                inst, failed, a->info.array.raid_disks, a->info.array.level);
 
-       if (dev->vol.migr_state &&
-           dev->vol.migr_type == MIGR_GEN_MIGR)
-               /* No repair during migration */
-               return NULL;
+       if (imsm_reshape_blocks_arrays_changes(super))
+                       return NULL;
 
        if (a->info.array.level == 4)
                /* No repair for takeovered array