struct intel_hba *hba; /* device path of the raid controller for this metadata */
const struct imsm_orom *orom; /* platform firmware support */
struct intel_super *next; /* (temp) list for disambiguating family_num */
+ struct md_bb bb; /* memory for get_bad_blocks call */
};
struct intel_disk {
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;
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));
}
struct imsm_super *mpb = super->anchor;
struct imsm_disk *disk;
int i;
+ __u32 bbm_log_size = __le32_to_cpu(mpb->bbm_log_size);
for (i = 0; i < mpb->num_disks ; i++) {
disk = __get_imsm_disk(mpb, i);
set_pba_of_lba0(map, pba_of_lba0(map)/IMSM_4K_DIV);
}
}
+ if (bbm_log_size) {
+ struct bbm_log *log = (void *)mpb +
+ __le32_to_cpu(mpb->mpb_size) - bbm_log_size;
+ __u32 i;
+
+ for (i = 0; i < log->entry_count; i++) {
+ struct bbm_log_entry *entry =
+ &log->marked_block_entries[i];
+
+ __u8 count = entry->marked_count + 1;
+ unsigned long long sector =
+ __le48_to_cpu(&entry->defective_block_start);
+
+ entry->defective_block_start =
+ __cpu_to_le48(sector/IMSM_4K_DIV);
+ entry->marked_count = max(count/IMSM_4K_DIV, 1) - 1;
+ }
+ }
mpb->check_sum = __gen_imsm_checksum(mpb);
}
struct imsm_super *mpb = super->anchor;
struct imsm_disk *disk;
int i;
+ __u32 bbm_log_size = __le32_to_cpu(mpb->bbm_log_size);
for (i = 0; i < mpb->num_disks ; i++) {
disk = __get_imsm_disk(mpb, i);
set_pba_of_lba0(map, pba_of_lba0(map)*IMSM_4K_DIV);
}
}
+ if (bbm_log_size) {
+ struct bbm_log *log = (void *)mpb +
+ __le32_to_cpu(mpb->mpb_size) - bbm_log_size;
+ __u32 i;
+
+ for (i = 0; i < log->entry_count; i++) {
+ struct bbm_log_entry *entry =
+ &log->marked_block_entries[i];
+
+ __u8 count = entry->marked_count + 1;
+ unsigned long long sector =
+ __le48_to_cpu(&entry->defective_block_start);
+
+ entry->defective_block_start =
+ __cpu_to_le48(sector*IMSM_4K_DIV);
+ entry->marked_count = count*IMSM_4K_DIV - 1;
+ }
+ }
mpb->check_sum = __gen_imsm_checksum(mpb);
}
__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));
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;
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);
}
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)
continue;
sprintf(path, "/sys/bus/pci/drivers/nvme/%s", ent->d_name);
- /* if not a intel NVMe - skip it*/
- if (devpath_to_vendor(path) != 0x8086)
- continue;
rp = realpath(path, NULL);
if (!rp)
for (entry = orom_entries; entry; entry = entry->next) {
if (entry->type == SYS_DEV_VMD) {
print_imsm_capability(&entry->orom);
+ printf(" 3rd party NVMe :%s supported\n",
+ imsm_orom_has_tpv_support(&entry->orom)?"":" not");
for (hba = list; hba; hba = hba->next) {
if (hba->type == SYS_DEV_VMD) {
char buf[PATH_MAX];
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",
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",
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;
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);
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));
static void free_imsm(struct intel_super *super)
{
__free_imsm(super, 1);
+ free(super->bb.entries);
free(super);
}
super->current_vol = -1;
super->create_offset = ~((unsigned long long) 0);
+
+ super->bb.entries = xmalloc(BBM_LOG_MAX_ENTRIES *
+ sizeof(struct md_bb_entry));
+ if (!super->bb.entries) {
+ free(super);
+ return NULL;
+ }
+
return super;
}
}
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)
{
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 {
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;
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)
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);
}
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)
{
}
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)
"\tRAID 0 is the only supported configuration for this type of x8 device.\n");
break;
}
+ } else if (super->hba->type == SYS_DEV_VMD && super->orom &&
+ !imsm_orom_has_tpv_support(super->orom)) {
+ pr_err("\tPlatform configuration does not support non-Intel NVMe drives.\n"
+ "\tPlease refer to Intel(R) RSTe user guide.\n");
+ free(dd->devname);
+ free(dd);
+ return 1;
}
}
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");
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");
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)
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 {
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;
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.
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;
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);
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,
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;
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;
return ret;
}
+/*******************************************************************************
+* Function: imsm_get_badblocks
+* Description: This routine get list of bad blocks for an array
+*
+* Parameters:
+* a : array
+* slot : disk number
+* Returns:
+* bb : structure containing bad blocks
+* NULL : error
+******************************************************************************/
+static struct md_bb *imsm_get_badblocks(struct active_array *a, int slot)
+{
+ int inst = a->info.container_member;
+ struct intel_super *super = a->container->sb;
+ struct imsm_dev *dev = get_imsm_dev(super, inst);
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
+ int ord;
+
+ ord = imsm_disk_slot_to_ord(a, slot);
+ if (ord < 0)
+ return NULL;
+
+ get_volume_badblocks(super->bbm_log, ord_to_idx(ord), pba_of_lba0(map),
+ blocks_per_member(map), &super->bb);
+
+ return &super->bb;
+}
+/*******************************************************************************
+* Function: examine_badblocks_imsm
+* Description: Prints list of bad blocks on a disk to the standard output
+*
+* Parameters:
+* st : metadata handler
+* fd : open file descriptor for device
+* devname : device name
+* Returns:
+* 0 : Success
+* 1 : Error
+******************************************************************************/
+static int examine_badblocks_imsm(struct supertype *st, int fd, char *devname)
+{
+ struct intel_super *super = st->sb;
+ struct bbm_log *log = super->bbm_log;
+ struct dl *d = NULL;
+ int any = 0;
+
+ for (d = super->disks; d ; d = d->next) {
+ if (strcmp(d->devname, devname) == 0)
+ break;
+ }
+
+ if ((d == NULL) || (d->index < 0)) { /* serial mismatch probably */
+ pr_err("%s doesn't appear to be part of a raid array\n",
+ devname);
+ return 1;
+ }
+
+ if (log != NULL) {
+ unsigned int i;
+ struct bbm_log_entry *entry = &log->marked_block_entries[0];
+
+ for (i = 0; i < log->entry_count; i++) {
+ if (entry[i].disk_ordinal == d->index) {
+ unsigned long long sector = __le48_to_cpu(
+ &entry[i].defective_block_start);
+ int cnt = entry[i].marked_count + 1;
+
+ if (!any) {
+ printf("Bad-blocks on %s:\n", devname);
+ any = 1;
+ }
+
+ printf("%20llu for %d sectors\n", sector, cnt);
+ }
+ }
+ }
+
+ if (!any)
+ printf("No bad-blocks list configured on %s\n", devname);
+
+ return 0;
+}
/*******************************************************************************
* Function: init_migr_record_imsm
* Description: Function inits imsm migration record
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);
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 {
geo->raid_disks + devNumChange,
&chunk,
geo->size, INVALID_SECTORS,
- 0, 0, 1))
+ 0, 0, info.consistency_policy, 1))
change = -1;
if (check_devs) {
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");
.manage_reshape = imsm_manage_reshape,
.recover_backup = recover_backup_imsm,
.copy_metadata = copy_metadata_imsm,
+ .examine_badblocks = examine_badblocks_imsm,
#endif
.match_home = match_home_imsm,
.uuid_from_super= uuid_from_super_imsm,
.prepare_update = imsm_prepare_update,
.record_bad_block = imsm_record_badblock,
.clear_bad_block = imsm_clear_badblock,
+ .get_bad_blocks = imsm_get_badblocks,
#endif /* MDASSEMBLE */
};