]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
mdadm: drop get_required_spare_criteria()
[thirdparty/mdadm.git] / super-intel.c
index 6a664a2e58d3232581225178030fc87d1a783600..7ad391ac92904bccd3ab6c3c5be3519705e67646 100644 (file)
@@ -1736,48 +1736,6 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
        return  (remainder < rv) ? remainder : rv;
 }
 
-/*
- * Return minimum size of a spare and sector size
- * that can be used in this array
- */
-int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
-{
-       struct intel_super *super = st->sb;
-       struct dl *dl;
-       struct extent *e;
-       int i;
-       unsigned long long size = 0;
-
-       c->min_size = 0;
-       c->sector_size = 0;
-
-       if (!super)
-               return -EINVAL;
-       /* find first active disk in array */
-       dl = super->disks;
-       while (dl && (is_failed(&dl->disk) || dl->index == -1))
-               dl = dl->next;
-       if (!dl)
-               return -EINVAL;
-       /* find last lba used by subarrays */
-       e = get_extents(super, dl, 0);
-       if (!e)
-               return -EINVAL;
-       for (i = 0; e[i].size; i++)
-               continue;
-       if (i > 0)
-               size = e[i-1].start + e[i-1].size;
-       free(e);
-
-       /* add the amount of space needed for metadata */
-       size += imsm_min_reserved_sectors(super);
-
-       c->min_size = size * 512;
-       c->sector_size = super->sector_size;
-
-       return 0;
-}
-
 static bool is_gen_migration(struct imsm_dev *dev);
 
 #define IMSM_4K_DIV 8
@@ -3778,6 +3736,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
        struct intel_super *super = st->sb;
        struct imsm_disk *disk;
        int map_disks = info->array.raid_disks;
+       int max_enough = -1;
        int i;
        struct imsm_super *mpb;
 
@@ -3819,9 +3778,12 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
 
        for (i = 0; i < mpb->num_raid_devs; i++) {
                struct imsm_dev *dev = get_imsm_dev(super, i);
-               int j = 0;
+               int failed, enough, j, missing = 0;
                struct imsm_map *map;
+               __u8 state;
 
+               failed = imsm_count_failed(super, dev, MAP_0);
+               state = imsm_check_degraded(super, dev, failed, MAP_0);
                map = get_imsm_map(dev, MAP_0);
 
                /* any newly missing disks?
@@ -3836,11 +3798,37 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
 
                        if (!(ord & IMSM_ORD_REBUILD) &&
                            get_imsm_missing(super, idx)) {
+                               missing = 1;
                                break;
                        }
                }
+
+               if (state == IMSM_T_STATE_FAILED)
+                       enough = -1;
+               else if (state == IMSM_T_STATE_DEGRADED &&
+                        (state != map->map_state || missing))
+                       enough = 0;
+               else /* we're normal, or already degraded */
+                       enough = 1;
+               if (is_gen_migration(dev) && missing) {
+                       /* during general migration we need all disks
+                        * that process is running on.
+                        * No new missing disk is allowed.
+                        */
+                       max_enough = -1;
+                       enough = -1;
+                       /* no more checks necessary
+                        */
+                       break;
+               }
+               /* in the missing/failed disk case check to see
+                * if at least one array is runnable
+                */
+               max_enough = max(max_enough, enough);
        }
 
+       info->container_enough = max_enough;
+
        if (super->disks) {
                __u32 reserved = imsm_reserved_sectors(super, super->disks);
 
@@ -4144,17 +4132,17 @@ static int imsm_read_serial(int fd, char *devname,
 
        memset(buf, 0, sizeof(buf));
 
+       if (check_env("IMSM_DEVNAME_AS_SERIAL")) {
+               memset(serial, 0, serial_buf_len);
+               fd2devname(fd, (char *) serial);
+               return 0;
+       }
+
        rv = nvme_get_serial(fd, buf, sizeof(buf));
 
        if (rv)
                rv = scsi_get_serial(fd, buf, sizeof(buf));
 
-       if (rv && check_env("IMSM_DEVNAME_AS_SERIAL")) {
-               memset(serial, 0, MAX_RAID_SERIAL_LEN);
-               fd2devname(fd, (char *) serial);
-               return 0;
-       }
-
        if (rv != 0) {
                if (devname)
                        pr_err("Failed to retrieve serial for %s\n",
@@ -8741,6 +8729,9 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
                super->updates_pending++;
        }
 
+       if (a->prev_action == idle)
+               goto skip_mark_checkpoint;
+
 mark_checkpoint:
        /* skip checkpointing for general migration,
         * it is controlled in mdadm
@@ -11264,6 +11255,84 @@ static const char *imsm_get_disk_controller_domain(const char *path)
        return drv;
 }
 
+/**
+ * get_spare_criteria_imsm() - set spare criteria.
+ * @st: supertype.
+ * @mddev_path: path to md device devnode, it must be container.
+ * @c: spare_criteria struct to fill, not NULL.
+ *
+ * If superblock is not loaded, use mddev_path to load_container. It must be given in this case.
+ * Filles size and sector size accordingly to superblock.
+ */
+mdadm_status_t get_spare_criteria_imsm(struct supertype *st, char *mddev_path,
+                                      struct spare_criteria *c)
+{
+       mdadm_status_t ret = MDADM_STATUS_ERROR;
+       bool free_superblock = false;
+       unsigned long long size = 0;
+       struct intel_super *super;
+       struct extent *e;
+       struct dl *dl;
+       int i;
+
+       /* If no superblock and no mddev_path, we cannot load superblock. */
+       assert(st->sb || mddev_path);
+
+       if (mddev_path) {
+               int fd = open(mddev_path, O_RDONLY);
+
+               if (!is_fd_valid(fd))
+                       return MDADM_STATUS_ERROR;
+
+               if (!st->sb) {
+                       if (load_container_imsm(st, fd, st->devnm)) {
+                               close(fd);
+                               return MDADM_STATUS_ERROR;
+                       }
+                       free_superblock = true;
+               }
+               close(fd);
+       }
+
+       super = st->sb;
+
+       /* find first active disk in array */
+       dl = super->disks;
+       while (dl && (is_failed(&dl->disk) || dl->index == -1))
+               dl = dl->next;
+
+       if (!dl)
+               goto out;
+
+       /* find last lba used by subarrays */
+       e = get_extents(super, dl, 0);
+       if (!e)
+               goto out;
+
+       for (i = 0; e[i].size; i++)
+               continue;
+       if (i > 0)
+               size = e[i - 1].start + e[i - 1].size;
+       free(e);
+
+       /* add the amount of space needed for metadata */
+       size += imsm_min_reserved_sectors(super);
+
+       c->min_size = size * 512;
+       c->sector_size = super->sector_size;
+       c->criteria_set = true;
+       ret = MDADM_STATUS_SUCCESS;
+
+out:
+       if (free_superblock)
+               free_super_imsm(st);
+
+       if (ret != MDADM_STATUS_SUCCESS)
+               c->criteria_set = false;
+
+       return ret;
+}
+
 static char *imsm_find_array_devnm_by_subdev(int subdev, char *container)
 {
        static char devnm[32];
@@ -11394,7 +11463,7 @@ static struct mdinfo *get_spares_for_grow(struct supertype *st)
 {
        struct spare_criteria sc;
 
-       get_spare_criteria_imsm(st, &sc);
+       get_spare_criteria_imsm(st, NULL, &sc);
        return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
 }