]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
mdadm: drop get_required_spare_criteria()
[thirdparty/mdadm.git] / super-intel.c
index 824c13564a379d4697268c18f692be4813b9873c..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
@@ -1825,7 +1783,7 @@ static void print_imsm_dev(struct intel_super *super,
        printf("\n");
        printf("    Failed disk : ");
        if (map->failed_disk_num == 0xff)
-               printf("none");
+               printf(STR_COMMON_NONE);
        else
                printf("%i", map->failed_disk_num);
        printf("\n");
@@ -2672,9 +2630,14 @@ static void print_imsm_capability(const struct imsm_orom *orom)
        else
                printf("Rapid Storage Technology%s\n",
                        imsm_orom_is_enterprise(orom) ? " enterprise" : "");
-       if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
-               printf("        Version : %d.%d.%d.%d\n", orom->major_ver,
-                               orom->minor_ver, orom->hotfix_ver, orom->build);
+       if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) {
+               if (imsm_orom_is_vmd_without_efi(orom))
+                       printf("        Version : %d.%d\n", orom->major_ver,
+                              orom->minor_ver);
+               else
+                       printf("        Version : %d.%d.%d.%d\n", orom->major_ver,
+                              orom->minor_ver, orom->hotfix_ver, orom->build);
+       }
        printf("    RAID Levels :%s%s%s%s%s\n",
               imsm_orom_has_raid0(orom) ? " raid0" : "",
               imsm_orom_has_raid1(orom) ? " raid1" : "",
@@ -2971,34 +2934,6 @@ static void uuid_from_super_imsm(struct supertype *st, int uuid[4])
        memcpy(uuid, buf, 4*4);
 }
 
-#if 0
-static void
-get_imsm_numerical_version(struct imsm_super *mpb, int *m, int *p)
-{
-       __u8 *v = get_imsm_version(mpb);
-       __u8 *end = mpb->sig + MAX_SIGNATURE_LENGTH;
-       char major[] = { 0, 0, 0 };
-       char minor[] = { 0 ,0, 0 };
-       char patch[] = { 0, 0, 0 };
-       char *ver_parse[] = { major, minor, patch };
-       int i, j;
-
-       i = j = 0;
-       while (*v != '\0' && v < end) {
-               if (*v != '.' && j < 2)
-                       ver_parse[i][j++] = *v;
-               else {
-                       i++;
-                       j = 0;
-               }
-               v++;
-       }
-
-       *m = strtol(minor, NULL, 0);
-       *p = strtol(patch, NULL, 0);
-}
-#endif
-
 static __u32 migr_strip_blocks_resync(struct imsm_dev *dev)
 {
        /* migr_strip_size when repairing or initializing parity */
@@ -3891,7 +3826,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
                 */
                max_enough = max(max_enough, enough);
        }
-       dprintf("enough: %d\n", max_enough);
+
        info->container_enough = max_enough;
 
        if (super->disks) {
@@ -4197,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",
@@ -5556,40 +5491,37 @@ static void imsm_update_version_info(struct intel_super *super)
        }
 }
 
-static int check_name(struct intel_super *super, char *name, int quiet)
+/**
+ * imsm_check_name() - check imsm naming criteria.
+ * @super: &intel_super pointer, not NULL.
+ * @name: name to check.
+ * @verbose: verbose level.
+ *
+ * Name must be no longer than &MAX_RAID_SERIAL_LEN and must be unique across volumes.
+ *
+ * Returns: &true if @name matches, &false otherwise.
+ */
+static bool imsm_is_name_allowed(struct intel_super *super, const char * const name,
+                                const int verbose)
 {
        struct imsm_super *mpb = super->anchor;
-       char *reason = NULL;
-       char *start = name;
-       size_t len = strlen(name);
        int i;
 
-       if (len > 0) {
-               while (isspace(start[len - 1]))
-                       start[--len] = 0;
-               while (*start && isspace(*start))
-                       ++start, --len;
-               memmove(name, start, len + 1);
+       if (is_string_lq(name, MAX_RAID_SERIAL_LEN + 1) == false) {
+               pr_vrb("imsm: Name \"%s\" is too long\n", name);
+               return false;
        }
 
-       if (len > MAX_RAID_SERIAL_LEN)
-               reason = "must be 16 characters or less";
-       else if (len == 0)
-               reason = "must be a non-empty string";
-
        for (i = 0; i < mpb->num_raid_devs; i++) {
                struct imsm_dev *dev = get_imsm_dev(super, i);
 
                if (strncmp((char *) dev->volume, name, MAX_RAID_SERIAL_LEN) == 0) {
-                       reason = "already exists";
-                       break;
+                       pr_vrb("imsm: Name \"%s\" already exists\n", name);
+                       return false;
                }
        }
 
-       if (reason && !quiet)
-               pr_err("imsm volume name %s\n", reason);
-
-       return !reason;
+       return true;
 }
 
 static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
@@ -5684,8 +5616,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                }
        }
 
-       if (!check_name(super, name, 0))
+       if (imsm_is_name_allowed(super, name, 1) == false)
                return 0;
+
        dv = xmalloc(sizeof(*dv));
        dev = xcalloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
        /*
@@ -7043,7 +6976,7 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
                        int fd = -1;
                        while (dev && !is_fd_valid(fd)) {
                                char *path = xmalloc(strlen(dev->name) + strlen("/dev/") + 1);
-                               num = sprintf(path, "%s%s", "/dev/", dev->name);
+                               num = snprintf(path, PATH_MAX, "%s%s", "/dev/", dev->name);
                                if (num > 0)
                                        fd = open(path, O_RDONLY, 0);
                                if (num <= 0 || !is_fd_valid(fd)) {
@@ -7935,7 +7868,7 @@ static int kill_subarray_imsm(struct supertype *st, char *subarray_id)
 
                if (i < current_vol)
                        continue;
-               sprintf(subarray, "%u", i);
+               snprintf(subarray, sizeof(subarray), "%u", i);
                if (is_subarray_active(subarray, st->devnm)) {
                        pr_err("deleting subarray-%d would change the UUID of active subarray-%d, aborting\n",
                               current_vol, i);
@@ -8013,7 +7946,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
                char *ep;
                int vol;
 
-               if (!check_name(super, name, 0))
+               if (imsm_is_name_allowed(super, name, 1) == false)
                        return 2;
 
                vol = strtoul(subarray, &ep, 10);
@@ -8733,23 +8666,6 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
                        /* still reshaping, maybe update vol_curr_migr_unit */
                        goto mark_checkpoint;
                } else {
-                       if (a->last_checkpoint == 0 && a->prev_action == reshape) {
-                               /* for some reason we aborted the reshape.
-                                *
-                                * disable automatic metadata rollback
-                                * user action is required to recover process
-                                */
-                               if (0) {
-                                       struct imsm_map *map2 =
-                                               get_imsm_map(dev, MAP_1);
-                                       dev->vol.migr_state = 0;
-                                       set_migr_type(dev, 0);
-                                       set_vol_curr_migr_unit(dev, 0);
-                                       memcpy(map, map2,
-                                              sizeof_imsm_map(map2));
-                                       super->updates_pending++;
-                               }
-                       }
                        if (a->last_checkpoint >= a->info.component_size) {
                                unsigned long long array_blocks;
                                int used_disks;
@@ -8813,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
@@ -10340,7 +10259,8 @@ static void imsm_process_update(struct supertype *st,
                        if (a->info.container_member == target)
                                break;
                dev = get_imsm_dev(super, u->dev_idx);
-               if (a || !check_name(super, name, 1)) {
+
+               if (a || !dev || imsm_is_name_allowed(super, name, 0) == false) {
                        dprintf("failed to rename subarray-%d\n", target);
                        break;
                }
@@ -11210,11 +11130,11 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
        unsigned int sector_size = super->sector_size;
        unsigned long long curr_migr_unit = current_migr_unit(migr_rec);
        unsigned long long num_migr_units = get_num_migr_units(migr_rec);
-       char buffer[20];
+       char buffer[SYSFS_MAX_BUF_SIZE];
        int skipped_disks = 0;
        struct dl *dl_disk;
 
-       err = sysfs_get_str(info, NULL, "array_state", (char *)buffer, 20);
+       err = sysfs_get_str(info, NULL, "array_state", (char *)buffer, sizeof(buffer));
        if (err < 1)
                return 1;
 
@@ -11308,7 +11228,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
        char *drv=NULL;
        struct stat st;
 
-       strcpy(disk_path, disk_by_path);
+       strncpy(disk_path, disk_by_path, PATH_MAX);
        strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1);
        if (stat(disk_path, &st) == 0) {
                struct sys_dev* hba;
@@ -11335,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];
@@ -11465,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);
 }
 
@@ -12133,14 +12131,14 @@ exit_imsm_reshape_super:
 static int read_completed(int fd, unsigned long long *val)
 {
        int ret;
-       char buf[50];
+       char buf[SYSFS_MAX_BUF_SIZE];
 
-       ret = sysfs_fd_get_str(fd, buf, 50);
+       ret = sysfs_fd_get_str(fd, buf, sizeof(buf));
        if (ret < 0)
                return ret;
 
        ret = COMPLETED_OK;
-       if (strncmp(buf, "none", 4) == 0) {
+       if (str_is_none(buf) == true) {
                ret = COMPLETED_NONE;
        } else if (strncmp(buf, "delayed", 7) == 0) {
                ret = COMPLETED_DELAYED;
@@ -12208,12 +12206,12 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
 
        do {
                int rc;
-               char action[20];
+               char action[SYSFS_MAX_BUF_SIZE];
                int timeout = 3000;
 
                sysfs_wait(fd, &timeout);
                if (sysfs_get_str(sra, NULL, "sync_action",
-                                 action, 20) > 0 &&
+                                 action, sizeof(action)) > 0 &&
                                strncmp(action, "reshape", 7) != 0) {
                        if (strncmp(action, "idle", 4) == 0)
                                break;
@@ -12260,7 +12258,7 @@ int check_degradation_change(struct mdinfo *info,
                        if (sd->disk.state & (1<<MD_DISK_FAULTY))
                                continue;
                        if (sd->disk.state & (1<<MD_DISK_SYNC)) {
-                               char sbuf[100];
+                               char sbuf[SYSFS_MAX_BUF_SIZE];
                                int raid_disk = sd->disk.raid_disk;
 
                                if (sysfs_get_str(info,