]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
Generic support for --consistency-policy and PPL
[thirdparty/mdadm.git] / super-intel.c
index b7a52031d11d61050797831aec97575633dd4255..5d0f131f6bc068930a7924fe2b0eff74ab017a96 100644 (file)
@@ -1480,8 +1480,10 @@ static void print_imsm_dev(struct intel_super *super,
        printf("    Dirty State : %s\n", dev->vol.dirty ? "dirty" : "clean");
 }
 
-static void print_imsm_disk(struct imsm_disk *disk, int index, __u32 reserved)
-{
+static void print_imsm_disk(struct imsm_disk *disk,
+                           int index,
+                           __u32 reserved,
+                           unsigned int sector_size) {
        char str[MAX_RAID_SERIAL_LEN + 1];
        __u64 sz;
 
@@ -1499,7 +1501,8 @@ static void print_imsm_disk(struct imsm_disk *disk, int index, __u32 reserved)
                                            is_failed(disk) ? " failed" : "");
        printf("             Id : %08x\n", __le32_to_cpu(disk->scsi_id));
        sz = total_blocks(disk) - reserved;
-       printf("    Usable Size : %llu%s\n", (unsigned long long)sz,
+       printf("    Usable Size : %llu%s\n",
+              (unsigned long long)sz * 512 / sector_size,
               human_size(sz * 512));
 }
 
@@ -1808,7 +1811,8 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
        __u32 reserved = imsm_reserved_sectors(super, super->disks);
        struct dl *dl;
 
-       snprintf(str, MPB_SIG_LEN, "%s", mpb->sig);
+       strncpy(str, (char *)mpb->sig, MPB_SIG_LEN);
+       str[MPB_SIG_LEN-1] = '\0';
        printf("          Magic : %s\n", str);
        snprintf(str, strlen(MPB_VERSION_RAID0), "%s", get_imsm_version(mpb));
        printf("        Version : %s\n", get_imsm_version(mpb));
@@ -1829,7 +1833,8 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
        printf("    MPB Sectors : %d\n", mpb_sectors(mpb, super->sector_size));
        printf("          Disks : %d\n", mpb->num_disks);
        printf("   RAID Devices : %d\n", mpb->num_raid_devs);
-       print_imsm_disk(__get_imsm_disk(mpb, super->disks->index), super->disks->index, reserved);
+       print_imsm_disk(__get_imsm_disk(mpb, super->disks->index),
+                       super->disks->index, reserved, super->sector_size);
        if (get_imsm_bbm_log_size(super->bbm_log)) {
                struct bbm_log *log = super->bbm_log;
 
@@ -1851,12 +1856,14 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
        for (i = 0; i < mpb->num_disks; i++) {
                if (i == super->disks->index)
                        continue;
-               print_imsm_disk(__get_imsm_disk(mpb, i), i, reserved);
+               print_imsm_disk(__get_imsm_disk(mpb, i), i, reserved,
+                               super->sector_size);
        }
 
        for (dl = super->disks; dl; dl = dl->next)
                if (dl->index == -1)
-                       print_imsm_disk(&dl->disk, -1, reserved);
+                       print_imsm_disk(&dl->disk, -1, reserved,
+                                       super->sector_size);
 
        examine_migr_rec_imsm(super);
 }
@@ -1945,7 +1952,7 @@ static int copy_metadata_imsm(struct supertype *st, int from, int to)
 
        if (lseek64(from, dsize-(2*sector_size), 0) < 0)
                goto err;
-       if (read(from, buf, sector_size) != sector_size)
+       if ((unsigned int)read(from, buf, sector_size) != sector_size)
                goto err;
        sb = buf;
        if (strncmp((char*)sb->sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0)
@@ -2816,7 +2823,7 @@ static int read_imsm_migr_rec(int fd, struct intel_super *super)
                       strerror(errno));
                goto out;
        }
-       if (read(fd, super->migr_rec_buf,
+       if ((unsigned int)read(fd, super->migr_rec_buf,
            MIGR_REC_BUF_SECTORS*sector_size) !=
            MIGR_REC_BUF_SECTORS*sector_size) {
                pr_err("Cannot read migr record block: %s\n",
@@ -3018,7 +3025,7 @@ static int write_imsm_migr_rec(struct supertype *st)
                               strerror(errno));
                        goto out;
                }
-               if (write(fd, super->migr_rec_buf,
+               if ((unsigned int)write(fd, super->migr_rec_buf,
                    MIGR_REC_BUF_SECTORS*sector_size) !=
                    MIGR_REC_BUF_SECTORS*sector_size) {
                        pr_err("Cannot write migr record block: %s\n",
@@ -3209,7 +3216,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
                                                        info->array.chunk_size,
                                                        super->sector_size,
                                                        info->component_size);
-       info->bb.supported = 0;
+       info->bb.supported = 1;
 
        memset(info->uuid, 0, sizeof(info->uuid));
        info->recovery_start = MaxSector;
@@ -3376,7 +3383,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
        info->name[0] = 0;
        info->recovery_start = MaxSector;
        info->recovery_blocked = imsm_reshape_blocks_arrays_changes(st->sb);
-       info->bb.supported = 0;
+       info->bb.supported = 1;
 
        /* do we have the all the insync disks that we expect? */
        mpb = super->anchor;
@@ -4122,7 +4129,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
                        pr_err("Failed to allocate imsm anchor buffer on %s\n", devname);
                return 1;
        }
-       if (read(fd, anchor, sector_size) != sector_size) {
+       if ((unsigned int)read(fd, anchor, sector_size) != sector_size) {
                if (devname)
                        pr_err("Cannot read anchor block on %s: %s\n",
                               devname, strerror(errno));
@@ -5148,7 +5155,7 @@ static int check_name(struct intel_super *super, char *name, int quiet)
 }
 
 static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
-                                 unsigned long long size, char *name,
+                                 struct shape *s, char *name,
                                  char *homehost, int *uuid,
                                  long long data_offset)
 {
@@ -5221,7 +5228,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                        disk->status = CONFIGURED_DISK | FAILED_DISK;
                        disk->scsi_id = __cpu_to_le32(~(__u32)0);
                        snprintf((char *) disk->serial, MAX_RAID_SERIAL_LEN,
-                                "missing:%d", i);
+                                "missing:%d", (__u8)i);
                }
                find_missing(super);
        } else {
@@ -5243,7 +5250,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
        array_blocks = calc_array_size(info->level, info->raid_disks,
                                               info->layout, info->chunk_size,
-                                              size * 2);
+                                              s->size * 2);
        /* round array size down to closest MB */
        array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
 
@@ -5257,7 +5264,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        vol->curr_migr_unit = 0;
        map = get_imsm_map(dev, MAP_0);
        set_pba_of_lba0(map, super->create_offset);
-       set_blocks_per_member(map, info_to_blocks_per_member(info, size));
+       set_blocks_per_member(map, info_to_blocks_per_member(info, s->size));
        map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
        map->failed_disk_num = ~0;
        if (info->level > 0)
@@ -5285,7 +5292,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
                map->num_domains = 1;
 
        /* info->size is only int so use the 'size' parameter instead */
-       num_data_stripes = (size * 2) / info_to_blocks_per_strip(info);
+       num_data_stripes = (s->size * 2) / info_to_blocks_per_strip(info);
        num_data_stripes /= map->num_domains;
        set_num_data_stripes(map, num_data_stripes);
 
@@ -5307,7 +5314,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
 }
 
 static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
-                          unsigned long long size, char *name,
+                          struct shape *s, char *name,
                           char *homehost, int *uuid,
                           unsigned long long data_offset)
 {
@@ -5330,7 +5337,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
        }
 
        if (st->sb)
-               return init_super_imsm_volume(st, info, size, name, homehost, uuid,
+               return init_super_imsm_volume(st, info, s, name, homehost, uuid,
                                              data_offset);
 
        if (info)
@@ -5637,7 +5644,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
        memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*super->sector_size);
        if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*super->sector_size,
            SEEK_SET) >= 0) {
-               if (write(fd, super->migr_rec_buf,
+               if ((unsigned int)write(fd, super->migr_rec_buf,
                    MIGR_REC_BUF_SECTORS*super->sector_size) !=
                    MIGR_REC_BUF_SECTORS*super->sector_size)
                        perror("Write migr_rec failed");
@@ -5847,7 +5854,8 @@ static int write_super_imsm(struct supertype *st, int doclose)
                        get_dev_size(d->fd, NULL, &dsize);
                        if (lseek64(d->fd, dsize - sector_size,
                            SEEK_SET) >= 0) {
-                               if (write(d->fd, super->migr_rec_buf,
+                               if ((unsigned int)write(d->fd,
+                                   super->migr_rec_buf,
                                    MIGR_REC_BUF_SECTORS*sector_size) !=
                                    MIGR_REC_BUF_SECTORS*sector_size)
                                        perror("Write migr_rec failed");
@@ -6482,20 +6490,20 @@ count_volumes_list(struct md_list *devlist, char *homehost,
        return count;
 }
 
-static int
-count_volumes(struct intel_hba *hba, int dpa, int verbose)
+static int __count_volumes(char *hba_path, int dpa, int verbose,
+                          int cmp_hba_path)
 {
        struct sys_dev *idev, *intel_devices = find_intel_devices();
        int count = 0;
        const struct orom_entry *entry;
        struct devid_list *dv, *devid_list;
 
-       if (!hba || !hba->path)
+       if (!hba_path)
                return 0;
 
        for (idev = intel_devices; idev; idev = idev->next) {
-               if (strstr(idev->path, hba->path))
-                               break;
+               if (strstr(idev->path, hba_path))
+                       break;
        }
 
        if (!idev || !idev->dev_id)
@@ -6509,22 +6517,28 @@ count_volumes(struct intel_hba *hba, int dpa, int verbose)
        devid_list = entry->devid_list;
        for (dv = devid_list; dv; dv = dv->next) {
                struct md_list *devlist;
-               struct sys_dev *device = device_by_id(dv->devid);
-               char *hba_path;
+               struct sys_dev *device = NULL;
+               char *hpath;
                int found = 0;
 
+               if (cmp_hba_path)
+                       device = device_by_id_and_path(dv->devid, hba_path);
+               else
+                       device = device_by_id(dv->devid);
+
                if (device)
-                       hba_path = device->path;
+                       hpath = device->path;
                else
                        return 0;
 
-               devlist = get_devices(hba_path);
+               devlist = get_devices(hpath);
                /* if no intel devices return zero volumes */
                if (devlist == NULL)
                        return 0;
 
-               count += active_arrays_by_format("imsm", hba_path, &devlist, dpa, verbose);
-               dprintf("path: %s active arrays: %d\n", hba_path, count);
+               count += active_arrays_by_format("imsm", hpath, &devlist, dpa,
+                                                verbose);
+               dprintf("path: %s active arrays: %d\n", hpath, count);
                if (devlist == NULL)
                        return 0;
                do  {
@@ -6536,7 +6550,7 @@ count_volumes(struct intel_hba *hba, int dpa, int verbose)
                        dprintf("found %d count: %d\n", found, count);
                } while (found);
 
-               dprintf("path: %s total number of volumes: %d\n", hba_path, count);
+               dprintf("path: %s total number of volumes: %d\n", hpath, count);
 
                while (devlist) {
                        struct md_list *dv = devlist;
@@ -6548,6 +6562,24 @@ count_volumes(struct intel_hba *hba, int dpa, int verbose)
        return count;
 }
 
+static int count_volumes(struct intel_hba *hba, int dpa, int verbose)
+{
+       if (!hba)
+               return 0;
+       if (hba->type == SYS_DEV_VMD) {
+               struct sys_dev *dev;
+               int count = 0;
+
+               for (dev = find_intel_devices(); dev; dev = dev->next) {
+                       if (dev->type == SYS_DEV_VMD)
+                               count += __count_volumes(dev->path, dpa,
+                                                        verbose, 1);
+               }
+               return count;
+       }
+       return __count_volumes(hba->path, dpa, verbose, 0);
+}
+
 static int imsm_default_chunk(const struct imsm_orom *orom)
 {
        /* up to 512 if the plaform supports it, otherwise the platform max.
@@ -6882,7 +6914,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                                  int raiddisks, int *chunk, unsigned long long size,
                                  unsigned long long data_offset,
                                  char *dev, unsigned long long *freesize,
-                                 int verbose)
+                                 int consistency_policy, int verbose)
 {
        int fd, cfd;
        struct mdinfo *sra;
@@ -7111,14 +7143,16 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
 
                        u->type = update_rename_array;
                        u->dev_idx = vol;
-                       snprintf((char *) u->name, MAX_RAID_SERIAL_LEN, "%s", name);
+                       strncpy((char *) u->name, name, MAX_RAID_SERIAL_LEN);
+                       u->name[MAX_RAID_SERIAL_LEN-1] = '\0';
                        append_metadata_update(st, u, sizeof(*u));
                } else {
                        struct imsm_dev *dev;
                        int i;
 
                        dev = get_imsm_dev(super, vol);
-                       snprintf((char *) dev->volume, MAX_RAID_SERIAL_LEN, "%s", name);
+                       strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
+                       dev->volume[MAX_RAID_SERIAL_LEN-1] = '\0';
                        for (i = 0; i < mpb->num_raid_devs; i++) {
                                dev = get_imsm_dev(super, i);
                                handle_missing(super, dev);
@@ -7380,7 +7414,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
                                info_d->component_size = blocks_per_member(map);
                        }
 
-                       info_d->bb.supported = 0;
+                       info_d->bb.supported = 1;
                        get_volume_badblocks(super->bbm_log, ord_to_idx(ord),
                                             info_d->data_offset,
                                             info_d->component_size,
@@ -8090,7 +8124,7 @@ static int store_imsm_mpb(int fd, struct imsm_super *mpb)
        if (lseek64(fd, dsize - (sector_size * 2), SEEK_SET) < 0)
                return 1;
 
-       if (write(fd, buf, sector_size) != sector_size)
+       if ((unsigned int)write(fd, buf, sector_size) != sector_size)
                return 1;
 
        return 0;
@@ -8410,7 +8444,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a,
                di->data_offset = pba_of_lba0(map);
                di->component_size = a->info.component_size;
                di->container_member = inst;
-               di->bb.supported = 0;
+               di->bb.supported = 1;
                super->random = random32();
                di->next = rv;
                rv = di;
@@ -10687,7 +10721,7 @@ static int imsm_create_metadata_update_for_migration(
                        free(u);
                        sysfs_free(spares);
                        update_memory_size = 0;
-                       dprintf("error: cannot get spare device for requested migration");
+                       pr_err("cannot get spare device for requested migration\n");
                        return 0;
                }
                sysfs_free(spares);
@@ -10815,6 +10849,11 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                        pr_err("Error. Chunk size change for RAID 10 is not supported.\n");
                        change = -1;
                        goto analyse_change_exit;
+               } else if (info.component_size % (geo->chunksize/512)) {
+                       pr_err("New chunk size (%dK) does not evenly divide device size (%lluk). Aborting...\n",
+                              geo->chunksize/1024, info.component_size/2);
+                       change = -1;
+                       goto analyse_change_exit;
                }
                change = CH_MIGRATION;
        } else {
@@ -10914,7 +10953,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
                                    geo->raid_disks + devNumChange,
                                    &chunk,
                                    geo->size, INVALID_SECTORS,
-                                   0, 0, 1))
+                                   0, 0, info.consistency_policy, 1))
                change = -1;
 
        if (check_devs) {
@@ -11496,7 +11535,7 @@ static int imsm_manage_reshape(
                get_dev_size(d->fd, NULL, &dsize);
                if (lseek64(d->fd, dsize - MIGR_REC_SECTOR_POSITION*sector_size,
                            SEEK_SET) >= 0) {
-                       if (write(d->fd, super->migr_rec_buf,
+                       if ((unsigned int)write(d->fd, super->migr_rec_buf,
                            MIGR_REC_BUF_SECTORS*sector_size) !=
                            MIGR_REC_BUF_SECTORS*sector_size)
                                perror("Write migr_rec failed");