[SYS_DEV_UNKNOWN] = "Unknown",
[SYS_DEV_SAS] = "SAS",
[SYS_DEV_SATA] = "SATA",
- [SYS_DEV_NVME] = "NVMe"
+ [SYS_DEV_NVME] = "NVMe",
+ [SYS_DEV_VMD] = "VMD"
};
const char *get_sys_dev_type(enum sys_dev_type type)
if (device->type != hba->type)
return 2;
+ /* Always forbid spanning between VMD domains (seen as different controllers by mdadm) */
+ if (device->type == SYS_DEV_VMD && !path_attached_to_hba(device->path, hba->path))
+ return 2;
+
/* Multiple same type HBAs can be used if they share the same OROM */
const struct imsm_orom *device_orom = get_orom_by_device_id(device->dev_id);
break;
}
sprintf(device, "/sys/dev/block/%d:%d/device/type", major, minor);
- if (load_sys(device, buf) != 0) {
+ if (load_sys(device, buf, sizeof(buf)) != 0) {
if (verbose > 0)
pr_err("failed to read device type for %s\n",
path);
vendor[0] = '\0';
model[0] = '\0';
sprintf(device, "/sys/dev/block/%d:%d/device/vendor", major, minor);
- if (load_sys(device, buf) == 0) {
+ if (load_sys(device, buf, sizeof(buf)) == 0) {
strncpy(vendor, buf, sizeof(vendor));
vendor[sizeof(vendor) - 1] = '\0';
c = (char *) &vendor[sizeof(vendor) - 1];
}
sprintf(device, "/sys/dev/block/%d:%d/device/model", major, minor);
- if (load_sys(device, buf) == 0) {
+ if (load_sys(device, buf, sizeof(buf)) == 0) {
strncpy(model, buf, sizeof(model));
model[sizeof(model) - 1] = '\0';
c = (char *) &model[sizeof(model) - 1];
return err;
}
+static void print_vmd_attached_devs(struct sys_dev *hba)
+{
+ struct dirent *ent;
+ DIR *dir;
+ char path[292];
+ char link[256];
+ char *c, *rp;
+
+ if (hba->type != SYS_DEV_VMD)
+ return;
+
+ /* scroll through /sys/dev/block looking for devices attached to
+ * this hba
+ */
+ dir = opendir("/sys/bus/pci/drivers/nvme");
+ if (!dir)
+ return;
+
+ for (ent = readdir(dir); ent; ent = readdir(dir)) {
+ int n;
+
+ /* is 'ent' a device? check that the 'subsystem' link exists and
+ * that its target matches 'bus'
+ */
+ sprintf(path, "/sys/bus/pci/drivers/nvme/%s/subsystem",
+ ent->d_name);
+ n = readlink(path, link, sizeof(link));
+ if (n < 0 || n >= (int)sizeof(link))
+ continue;
+ link[n] = '\0';
+ c = strrchr(link, '/');
+ if (!c)
+ continue;
+ if (strncmp("pci", c+1, strlen("pci")) != 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)
+ continue;
+
+ if (path_attached_to_hba(rp, hba->path)) {
+ printf(" NVMe under VMD : %s\n", rp);
+ }
+ free(rp);
+ }
+
+ closedir(dir);
+}
+
static void print_found_intel_controllers(struct sys_dev *elem)
{
for (; elem; elem = elem->next) {
fprintf(stderr, "SAS ");
else if (elem->type == SYS_DEV_NVME)
fprintf(stderr, "NVMe ");
- fprintf(stderr, "RAID controller");
+
+ if (elem->type == SYS_DEV_VMD)
+ fprintf(stderr, "VMD domain");
+ else
+ fprintf(stderr, "RAID controller");
+
if (elem->pci_id)
fprintf(stderr, " at %s", elem->pci_id);
fprintf(stderr, ".\n");
if (controller_path && (compare_paths(hba->path, controller_path) != 0))
continue;
if (!find_imsm_capability(hba)) {
+ char buf[PATH_MAX];
pr_err("imsm capabilities not found for controller: %s (type %s)\n",
- hba->path, get_sys_dev_type(hba->type));
+ hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path,
+ get_sys_dev_type(hba->type));
continue;
}
result = 0;
const struct orom_entry *entry;
for (entry = orom_entries; entry; entry = entry->next) {
- print_imsm_capability(&entry->orom);
+ if (entry->type == SYS_DEV_VMD) {
+ for (hba = list; hba; hba = hba->next) {
+ if (hba->type == SYS_DEV_VMD) {
+ char buf[PATH_MAX];
+ print_imsm_capability(&entry->orom);
+ printf(" I/O Controller : %s (%s)\n",
+ vmd_domain_to_controller(hba, buf), get_sys_dev_type(hba->type));
+ print_vmd_attached_devs(hba);
+ printf("\n");
+ }
+ }
+ continue;
+ }
- if (imsm_orom_is_nvme(&entry->orom)) {
+ print_imsm_capability(&entry->orom);
+ if (entry->type == SYS_DEV_NVME) {
for (hba = list; hba; hba = hba->next) {
if (hba->type == SYS_DEV_NVME)
printf(" NVMe Device : %s\n", hba->path);
}
+ printf("\n");
continue;
}
for (hba = list; hba; hba = hba->next) {
if (controller_path && (compare_paths(hba->path,controller_path) != 0))
continue;
- if (!find_imsm_capability(hba) && verbose > 0)
- pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n", hba->path);
+ if (!find_imsm_capability(hba) && verbose > 0) {
+ char buf[PATH_MAX];
+ pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",
+ hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path);
+ }
else
result = 0;
}
const struct orom_entry *entry;
- for (entry = orom_entries; entry; entry = entry->next)
+ for (entry = orom_entries; entry; entry = entry->next) {
+ if (entry->type == SYS_DEV_VMD) {
+ for (hba = list; hba; hba = hba->next)
+ print_imsm_capability_export(&entry->orom);
+ continue;
+ }
print_imsm_capability_export(&entry->orom);
+ }
return result;
}
if (devname) {
struct intel_hba *hba = super->hba;
- pr_err("%s is attached to Intel(R) %s RAID controller (%s),\n"
- " but the container is assigned to Intel(R) %s RAID controller (",
+ pr_err("%s is attached to Intel(R) %s %s (%s),\n"
+ " but the container is assigned to Intel(R) %s %s (",
devname,
get_sys_dev_type(hba_name->type),
+ hba_name->type == SYS_DEV_VMD ? "domain" : "RAID controller",
hba_name->pci_id ? : "Err!",
- get_sys_dev_type(super->hba->type));
+ get_sys_dev_type(super->hba->type),
+ hba->type == SYS_DEV_VMD ? "domain" : "RAID controller");
while (hba) {
fprintf(stderr, "%s", hba->pci_id ? : "Err!");
hba = hba->next;
}
fprintf(stderr, ").\n"
- " Mixing devices attached to different controllers is not allowed.\n");
+ " Mixing devices attached to different %s is not allowed.\n",
+ hba_name->type == SYS_DEV_VMD ? "VMD domains" : "controllers");
}
return 2;
}
devid_list = entry->devid_list;
for (dv = devid_list; dv; dv = dv->next) {
-
struct md_list *devlist = NULL;
struct sys_dev *device = device_by_id(dv->devid);
char *hba_path;
else
return 0;
+ /* VMD has one orom entry for all domain, but spanning is not allowed.
+ * VMD arrays should be counted per domain (controller), so skip
+ * domains that are not the given one.
+ */
+ if ((hba->type == SYS_DEV_VMD) &&
+ (strncmp(device->path, hba->path, strlen(device->path)) != 0))
+ continue;
+
devlist = get_devices(hba_path);
/* if no intel devices return zero volumes */
if (devlist == NULL)
return 1;
}
- if (orom != orom2) {
+ if ((orom != orom2) || ((hba->type == SYS_DEV_VMD) && (hba != hba2))) {
pr_err("WARNING - IMSM container assembled with disks under different HBAs!\n"
" This operation is not supported and can lead to data loss.\n");
return 1;
if (sysfs_fd_get_ll(fd, &completed) < 0) {
dprintf("cannot read reshape_position (no reshape in progres)\n");
close(fd);
- return 0;
+ return 1;
}
if (completed > position_to_set) {
do {
char action[20];
- sysfs_wait(fd, NULL);
+ int timeout = 3000;
+ sysfs_wait(fd, &timeout);
if (sysfs_get_str(sra, NULL, "sync_action",
action, 20) > 0 &&
- strncmp(action, "reshape", 7) != 0)
- break;
+ strncmp(action, "reshape", 7) != 0) {
+ close(fd);
+ return -1;
+ }
if (sysfs_fd_get_ll(fd, &completed) < 0) {
dprintf("cannot read reshape_position (in loop)\n");
close(fd);
* Function: imsm_manage_reshape
* Description: Function finds array under reshape and it manages reshape
* process. It creates stripes backups (if required) and sets
- * checheckpoits.
+ * checkpoints.
* Parameters:
* afd : Backup handle (nattive) - not used
* sra : general array info
start = current_position * 512;
- /* allign reading start to old geometry */
+ /* align reading start to old geometry */
start_buf_shift = start % old_data_stripe_length;
start_src = start - start_buf_shift;
sra->reshape_progress = next_step;
/* wait until reshape finish */
- if (wait_for_reshape_imsm(sra, ndata) < 0) {
+ if (wait_for_reshape_imsm(sra, ndata)) {
dprintf("wait_for_reshape_imsm returned error!\n");
goto abort;
}
ret_val = 1;
abort:
free(buf);
+ /* See Grow.c: abort_reshape() for further explanation */
+ sysfs_set_num(sra, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL);
+ sysfs_set_num(sra, NULL, "suspend_hi", 0);
+ sysfs_set_num(sra, NULL, "suspend_lo", 0);
return ret_val;
}