]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
mdadm: Fixup more broken logical operator formatting
[thirdparty/mdadm.git] / super-intel.c
index fbff215c0ec12521ea6fec407a4217a7c2eaf2df..3d0a37c6a906ef2a31345eefbc20394d0aae4891 100644 (file)
@@ -232,8 +232,13 @@ struct imsm_super {
        __u32 orig_family_num;          /* 0x40 - 0x43 original family num */
        __u32 pwr_cycle_count;          /* 0x44 - 0x47 simulated power cycle count for array */
        __u32 bbm_log_size;             /* 0x48 - 0x4B - size of bad Block Mgmt Log in bytes */
-#define IMSM_FILLERS 35
-       __u32 filler[IMSM_FILLERS];     /* 0x4C - 0xD7 RAID_MPB_FILLERS */
+       __u16 num_raid_devs_created;    /* 0x4C - 0x4D Used for generating unique
+                                        * volume IDs for raid_dev created in this array
+                                        * (starts at 1)
+                                        */
+       __u16 filler1;                  /* 0x4E - 0x4F */
+#define IMSM_FILLERS 34
+       __u32 filler[IMSM_FILLERS];     /* 0x50 - 0xD7 RAID_MPB_FILLERS */
        struct imsm_disk disk[1];       /* 0xD8 diskTbl[numDisks] */
        /* here comes imsm_dev[num_raid_devs] */
        /* here comes BBM logs */
@@ -1378,37 +1383,46 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
        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)
+/*
+ * 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 rv = 0;
+       unsigned long long size = 0;
+
+       c->min_size = 0;
+       c->sector_size = 0;
 
        if (!super)
-               return rv;
+               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 rv;
+               return -EINVAL;
        /* find last lba used by subarrays */
        e = get_extents(super, dl);
        if (!e)
-               return rv;
+               return -EINVAL;
        for (i = 0; e[i].size; i++)
                continue;
        if (i > 0)
-               rv = e[i-1].start + e[i-1].size;
+               size = e[i-1].start + e[i-1].size;
        free(e);
 
        /* add the amount of space needed for metadata */
-       rv = rv + imsm_min_reserved_sectors(super);
+       size += imsm_min_reserved_sectors(super);
 
-       return rv * 512;
+       c->min_size = size * 512;
+       c->sector_size = super->sector_size;
+
+       return 0;
 }
 
 static int is_gen_migration(struct imsm_dev *dev);
@@ -1468,13 +1482,16 @@ static void print_imsm_dev(struct intel_super *super,
                       ord & IMSM_ORD_REBUILD ? " (out-of-sync)" : "");
        } else
                printf("      This Slot : ?\n");
+       printf("    Sector Size : %u\n", super->sector_size);
        sz = __le32_to_cpu(dev->size_high);
        sz <<= 32;
        sz += __le32_to_cpu(dev->size_low);
-       printf("     Array Size : %llu%s\n", (unsigned long long)sz,
+       printf("     Array Size : %llu%s\n",
+                  (unsigned long long)sz * 512 / super->sector_size,
               human_size(sz * 512));
        sz = blocks_per_member(map);
-       printf("   Per Dev Size : %llu%s\n", (unsigned long long)sz,
+       printf("   Per Dev Size : %llu%s\n",
+                  (unsigned long long)sz * 512 / super->sector_size,
               human_size(sz * 512));
        printf("  Sector Offset : %llu\n",
                pba_of_lba0(map));
@@ -4148,8 +4165,8 @@ int check_mpb_migr_compatibility(struct intel_super *super)
                        if (pba_of_lba0(map0) != pba_of_lba0(map1))
                                /* migration optimization area was used */
                                return -1;
-                       if (migr_rec->ascending_migr == 0
-                               && migr_rec->dest_depth_per_unit > 0)
+                       if (migr_rec->ascending_migr == 0 &&
+                           migr_rec->dest_depth_per_unit > 0)
                                /* descending reshape not supported yet */
                                return -1;
                }
@@ -4224,8 +4241,8 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
        sectors = mpb_sectors(anchor, sector_size) - 1;
        free(anchor);
 
-       if (posix_memalign(&super->migr_rec_buf, sector_size,
-           MIGR_REC_BUF_SECTORS*sector_size) != 0) {
+       if (posix_memalign(&super->migr_rec_buf, MAX_SECTOR_SIZE,
+           MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE) != 0) {
                pr_err("could not allocate migr_rec buffer\n");
                free(super->buf);
                return 2;
@@ -5253,8 +5270,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                        pr_err("could not allocate new mpb\n");
                        return 0;
                }
-               if (posix_memalign(&super->migr_rec_buf, sector_size,
-                                  MIGR_REC_BUF_SECTORS*sector_size) != 0) {
+               if (posix_memalign(&super->migr_rec_buf, MAX_SECTOR_SIZE,
+                                  MIGR_REC_BUF_SECTORS*
+                                  MAX_SECTOR_SIZE) != 0) {
                        pr_err("could not allocate migr_rec buffer\n");
                        free(super->buf);
                        free(super);
@@ -5368,6 +5386,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                set_imsm_ord_tbl_ent(map, i, IMSM_ORD_REBUILD);
        }
        mpb->num_raid_devs++;
+       mpb->num_raid_devs_created++;
+       dev->my_vol_raid_dev_num = mpb->num_raid_devs_created;
 
        if (s->consistency_policy <= CONSISTENCY_POLICY_RESYNC) {
                dev->rwh_policy = RWH_OFF;
@@ -5460,6 +5480,22 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
        return 1;
 }
 
+static int drive_validate_sector_size(struct intel_super *super, struct dl *dl)
+{
+       unsigned int member_sector_size;
+
+       if (dl->fd < 0) {
+               pr_err("Invalid file descriptor for %s\n", dl->devname);
+               return 0;
+       }
+
+       if (!get_dev_sector_size(dl->fd, dl->devname, &member_sector_size))
+               return 0;
+       if (member_sector_size != super->sector_size)
+               return 0;
+       return 1;
+}
+
 static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
                                     int fd, char *devname)
 {
@@ -5499,6 +5535,11 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
                return 1;
        }
 
+       if (!drive_validate_sector_size(super, dl)) {
+               pr_err("Combining drives of different sector size in one volume is not allowed\n");
+               return 1;
+       }
+
        /* add a pristine spare to the metadata */
        if (dl->index < 0) {
                dl->index = super->anchor->num_disks;
@@ -5709,21 +5750,15 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
        if (super->sector_size == 0) {
                /* this a first device, so sector_size is not set yet */
                super->sector_size = member_sector_size;
-       } else if (member_sector_size != super->sector_size) {
-               pr_err("Mixing between different sector size is forbidden, aborting...\n");
-               if (dd->devname)
-                       free(dd->devname);
-               free(dd);
-               return 1;
        }
 
        /* clear migr_rec when adding disk to container */
-       memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*super->sector_size);
-       if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*super->sector_size,
+       memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE);
+       if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*member_sector_size,
            SEEK_SET) >= 0) {
                if ((unsigned int)write(fd, super->migr_rec_buf,
-                   MIGR_REC_BUF_SECTORS*super->sector_size) !=
-                   MIGR_REC_BUF_SECTORS*super->sector_size)
+                   MIGR_REC_BUF_SECTORS*member_sector_size) !=
+                   MIGR_REC_BUF_SECTORS*member_sector_size)
                        perror("Write migr_rec failed");
        }
 
@@ -5915,7 +5950,7 @@ static int write_super_imsm(struct supertype *st, int doclose)
        }
        if (clear_migration_record)
                memset(super->migr_rec_buf, 0,
-                   MIGR_REC_BUF_SECTORS*sector_size);
+                   MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE);
 
        if (sector_size == 4096)
                convert_to_4k(super);
@@ -6407,7 +6442,7 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
 
        for (memb = mdstat ; memb ; memb = memb->next) {
                if (memb->metadata_version &&
-                   (strncmp(memb->metadata_version, "external:", 9) == 0)  &&
+                   (strncmp(memb->metadata_version, "external:", 9) == 0) &&
                    (strcmp(&memb->metadata_version[9], name) == 0) &&
                    !is_subarray(memb->metadata_version+9) &&
                    memb->members) {
@@ -6555,7 +6590,7 @@ count_volumes_list(struct md_list *devlist, char *homehost,
 
        for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) {
                char *devname = tmpdev->devname;
-               struct stat stb;
+               dev_t rdev;
                struct supertype *tst;
                int dfd;
                if (tmpdev->used > 1)
@@ -6571,14 +6606,7 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                        dprintf("cannot open device %s: %s\n",
                                devname, strerror(errno));
                        tmpdev->used = 2;
-               } else if (fstat(dfd, &stb)< 0) {
-                       /* Impossible! */
-                       dprintf("fstat failed for %s: %s\n",
-                               devname, strerror(errno));
-                       tmpdev->used = 2;
-               } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
-                       dprintf("%s is not a block device.\n",
-                               devname);
+               } else if (!fstat_is_blkdev(dfd, devname, &rdev)) {
                        tmpdev->used = 2;
                } else if (must_be_container(dfd)) {
                        struct supertype *cst;
@@ -6600,7 +6628,7 @@ count_volumes_list(struct md_list *devlist, char *homehost,
                        if (cst)
                                cst->ss->free_super(cst);
                } else {
-                       tmpdev->st_rdev = stb.st_rdev;
+                       tmpdev->st_rdev = rdev;
                        if (tst->ss->load_super(tst,dfd, NULL)) {
                                dprintf("no RAID superblock on %s\n",
                                        devname);
@@ -6855,7 +6883,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
                                         unsigned long long *freesize,
                                         int verbose)
 {
-       struct stat stb;
+       dev_t rdev;
        struct intel_super *super = st->sb;
        struct imsm_super *mpb;
        struct dl *dl;
@@ -6920,13 +6948,11 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
        }
 
        /* This device must be a member of the set */
-       if (stat(dev, &stb) < 0)
-               return 0;
-       if ((S_IFMT & stb.st_mode) != S_IFBLK)
+       if (!stat_is_blkdev(dev, &rdev))
                return 0;
        for (dl = super->disks ; dl ; dl = dl->next) {
-               if (dl->major == (int)major(stb.st_rdev) &&
-                   dl->minor == (int)minor(stb.st_rdev))
+               if (dl->major == (int)major(rdev) &&
+                   dl->minor == (int)minor(rdev))
                        break;
        }
        if (!dl) {
@@ -8447,6 +8473,9 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot,
                if (dl->index == -1 && !activate_new)
                        continue;
 
+               if (!drive_validate_sector_size(super, dl))
+                       continue;
+
                /* Does this unused device have the requisite free space?
                 * It needs to be able to cover all member volumes
                 */
@@ -10800,8 +10829,10 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
  */
 static struct mdinfo *get_spares_for_grow(struct supertype *st)
 {
-       unsigned long long min_size = min_acceptable_spare_size_imsm(st);
-       return container_choose_spares(st, min_size, NULL, NULL, NULL, 0);
+       struct spare_criteria sc;
+
+       get_spare_criteria_imsm(st, &sc);
+       return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
 }
 
 /******************************************************************************
@@ -10843,8 +10874,7 @@ static int imsm_create_metadata_update_for_reshape(
         */
        spares = get_spares_for_grow(st);
 
-       if (spares == NULL
-           || delta_disks > spares->array.spare_disks) {
+       if (spares == NULL || delta_disks > spares->array.spare_disks) {
                pr_err("imsm: ERROR: Cannot get spare devices for %s.\n", geo->dev_name);
                i = -1;
                goto abort;
@@ -11609,8 +11639,8 @@ static int imsm_manage_reshape(
 
        /* Find volume during the reshape */
        for (dv = super->devlist; dv; dv = dv->next) {
-               if (dv->dev->vol.migr_type == MIGR_GEN_MIGR
-                   && dv->dev->vol.migr_state == 1) {
+               if (dv->dev->vol.migr_type == MIGR_GEN_MIGR &&
+                   dv->dev->vol.migr_state == 1) {
                        dev = dv->dev;
                        migr_vol_qan++;
                }
@@ -11778,7 +11808,7 @@ static int imsm_manage_reshape(
        /* clear migr_rec on disks after successful migration */
        struct dl *d;
 
-       memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*sector_size);
+       memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE);
        for (d = super->disks; d; d = d->next) {
                if (d->index < 0 || is_failed(&d->disk))
                        continue;
@@ -11836,7 +11866,7 @@ struct superswitch super_imsm = {
        .update_super   = update_super_imsm,
 
        .avail_size     = avail_size_imsm,
-       .min_acceptable_spare_size = min_acceptable_spare_size_imsm,
+       .get_spare_criteria = get_spare_criteria_imsm,
 
        .compare_super  = compare_super_imsm,