]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdadm: drop get_required_spare_criteria()
authorMariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Thu, 29 Feb 2024 11:52:06 +0000 (12:52 +0100)
committerMariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Mon, 11 Mar 2024 10:06:18 +0000 (11:06 +0100)
Only IMSM implements get_spare_criteria, so load_super() in
get_required_spare_criteria() is dead code. It is moved inside
metadata handler, because only IMSM implements it.

Give possibility to provide devnode to be opened. With that we can hide
load_container() used only to fill spare criteria inside handler
and simplify implementation in generic code.

Add helper function for testing spare criteria in Incremental and
error messages.

File descriptor in get_spare_criteria_imsm() is always opened on purpose.
New functionality added in next patches will require it. For the same
reason, function is moved to other place.

No functional changes.

Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Incremental.c
Monitor.c
mdadm.h
super-intel.c

index 2b5a5859ced7fd9b9d60f0d0f78d97075dec7f8a..66c2cc86dc5a6efbce8a8cc3de64f89211a4adaf 100644 (file)
@@ -833,6 +833,53 @@ container_members_max_degradation(struct map_ent *map, struct map_ent *me)
        return max_degraded;
 }
 
+/**
+ * incremental_external_test_spare_criteria() - helper to test spare criteria.
+ * @st: supertype, must be not NULL, it is duplicated here.
+ * @container_devnm: devnm of the container.
+ * @disk_fd: file descriptor of device to tested.
+ * @verbose: verbose flag.
+ *
+ * The function is used on new drive verification path to check if it can be added to external
+ * container. To test spare criteria, metadata must be loaded. It duplicates super to not mess in
+ * original one.
+ * Function is executed if superblock supports get_spare_criteria(), otherwise success is returned.
+ */
+mdadm_status_t incremental_external_test_spare_criteria(struct supertype *st, char *container_devnm,
+                                                       int disk_fd, int verbose)
+{
+       mdadm_status_t rv = MDADM_STATUS_ERROR;
+       char container_devname[PATH_MAX];
+       struct spare_criteria sc = {0};
+       struct supertype *dup;
+
+       if (!st->ss->get_spare_criteria)
+               return MDADM_STATUS_SUCCESS;
+
+       dup = dup_super(st);
+       snprintf(container_devname, PATH_MAX, "/dev/%s", container_devnm);
+
+       if (dup->ss->get_spare_criteria(dup, container_devname, &sc) != 0) {
+               if (verbose > 1)
+                       pr_err("Failed to get spare criteria for %s\n", container_devname);
+               goto out;
+       }
+
+       if (!disk_fd_matches_criteria(disk_fd, &sc)) {
+               if (verbose > 1)
+                       pr_err("Disk does not match spare criteria for %s\n", container_devname);
+               goto out;
+       }
+
+       rv = MDADM_STATUS_SUCCESS;
+
+out:
+       dup->ss->free_super(dup);
+       free(dup);
+
+       return rv;
+}
+
 static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                           struct map_ent *target, int bare,
                           struct supertype *st, int verbose)
@@ -873,8 +920,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                struct supertype *st2;
                struct domainlist *dl = NULL;
                struct mdinfo *sra;
-               unsigned long long devsize, freesize = 0;
-               struct spare_criteria sc = {0};
+               unsigned long long freesize = 0;
 
                if (is_subarray(mp->metadata))
                        continue;
@@ -925,34 +971,19 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
                if (sra->array.failed_disks == -1)
                        sra->array.failed_disks = container_members_max_degradation(map, mp);
 
-               get_dev_size(dfd, NULL, &devsize);
                if (sra->component_size == 0) {
-                       /* true for containers, here we must read superblock
-                        * to obtain minimum spare size */
-                       struct supertype *st3 = dup_super(st2);
-                       int mdfd = open_dev(mp->devnm);
-                       if (mdfd < 0) {
-                               free(st3);
+                       /* true for containers */
+                       if (incremental_external_test_spare_criteria(st2, mp->devnm, dfd, verbose))
                                goto next;
-                       }
-                       if (st3->ss->load_container &&
-                           !st3->ss->load_container(st3, mdfd, mp->path)) {
-                               if (st3->ss->get_spare_criteria)
-                                       st3->ss->get_spare_criteria(st3, &sc);
-                               st3->ss->free_super(st3);
-                       }
-                       free(st3);
-                       close(mdfd);
                }
-               if ((sra->component_size > 0 &&
-                    st2->ss->validate_geometry(st2, sra->array.level, sra->array.layout,
+
+               if (sra->component_size > 0 &&
+                   st2->ss->validate_geometry(st2, sra->array.level, sra->array.layout,
                                                sra->array.raid_disks, &sra->array.chunk_size,
                                                sra->component_size,
                                                sra->devs ? sra->devs->data_offset : INVALID_SECTORS,
                                                devname, &freesize, sra->consistency_policy,
-                                               0) &&
-                    freesize < sra->component_size) ||
-                   (sra->component_size == 0 && devsize < sc.min_size)) {
+                                               0) && freesize < sra->component_size) {
                        if (verbose > 1)
                                pr_err("not adding %s to %s as it is too small\n",
                                        devname, mp->path);
index 1ece8712b03261737050a32537e74afa154166f7..6b4560ae4f45b7115529082607beb629ad49f6c8 100644 (file)
--- a/Monitor.c
+++ b/Monitor.c
@@ -1008,34 +1008,6 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
        return new_found;
 }
 
-static int get_required_spare_criteria(struct state *st,
-                                      struct spare_criteria *sc)
-{
-       int fd;
-
-       if (!st->metadata || !st->metadata->ss->get_spare_criteria) {
-               sc->min_size = 0;
-               sc->sector_size = 0;
-               return 0;
-       }
-
-       fd = open(st->devname, O_RDONLY);
-       if (fd < 0)
-               return 1;
-       if (st->metadata->ss->external)
-               st->metadata->ss->load_container(st->metadata, fd, st->devname);
-       else
-               st->metadata->ss->load_super(st->metadata, fd, st->devname);
-       close(fd);
-       if (!st->metadata->sb)
-               return 1;
-
-       st->metadata->ss->get_spare_criteria(st->metadata, sc);
-       st->metadata->ss->free_super(st->metadata);
-
-       return 0;
-}
-
 static int check_donor(struct state *from, struct state *to)
 {
        struct state *sub;
@@ -1178,8 +1150,11 @@ static void try_spare_migration(struct state *statelist)
                                /* member of a container */
                                to = to->parent;
 
-                       if (get_required_spare_criteria(to, &sc))
-                               continue;
+                       if (to->metadata->ss->get_spare_criteria)
+                               if (to->metadata->ss->get_spare_criteria(to->metadata, to->devname,
+                                                                        &sc))
+                                       continue;
+
                        if (to->metadata->ss->external) {
                                /* We must make sure there is
                                 * no suitable spare in container already.
diff --git a/mdadm.h b/mdadm.h
index e8abd730941218d2529e50253ef178dbf9f9b11e..cbc586f5e3ef8e8ae199fb6bd14fc53583ee4d86 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -1116,10 +1116,9 @@ extern struct superswitch {
         * Return spare criteria for array:
         * - minimum disk size can be used in array;
         * - sector size can be used in array.
-        * Return values: 0 - for success and -EINVAL on error.
         */
-       int (*get_spare_criteria)(struct supertype *st,
-                                 struct spare_criteria *sc);
+       mdadm_status_t (*get_spare_criteria)(struct supertype *st, char *mddev_path,
+                                            struct spare_criteria *sc);
        /* Find somewhere to put a bitmap - possibly auto-size it - and
         * update the metadata to record this.  The array may be newly
         * created, in which case data_size may be updated, or it might
index 39ec4754cb12537a2fae2a406374bbedb87a4557..7ad391ac92904bccd3ab6c3c5be3519705e67646 100644 (file)
@@ -1736,46 +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;
-
-       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;
-       c->criteria_set = true;
-
-       return 0;
-}
-
 static bool is_gen_migration(struct imsm_dev *dev);
 
 #define IMSM_4K_DIV 8
@@ -11295,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];
@@ -11425,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);
 }