]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
Replace snprintf with strncpy at some places to avoid truncation
[thirdparty/mdadm.git] / super-intel.c
index cee6951fa8ed9aaf25d0534ca59b034dd89e3de8..343f20d50215996890fb84032eb870d4cfbd6a16 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,10 +3383,11 @@ 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;
+       info->events = __le32_to_cpu(mpb->generation_num);
 
        for (i = 0; i < mpb->num_raid_devs; i++) {
                struct imsm_dev *dev = get_imsm_dev(super, i);
@@ -4121,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));
@@ -5636,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");
@@ -5846,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");
@@ -6481,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)
@@ -6508,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  {
@@ -6535,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;
@@ -6547,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.
@@ -7110,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);
@@ -7379,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,
@@ -8089,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;
@@ -8409,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;
@@ -10686,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);
@@ -10814,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 {
@@ -11495,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");