X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=super-intel.c;h=cfc8904e2d2cca5df92a54933a3d50ca6ccc5dff;hp=1d366131cf841be9692e598be19a91d8ed3ce34f;hb=676e87a806240b2bf32ad8738c59fe1c3b4b2b5b;hpb=d5d2c614739a2370e295d9e83594b9c52a11b887 diff --git a/super-intel.c b/super-intel.c index 1d366131..cfc8904e 100644 --- a/super-intel.c +++ b/super-intel.c @@ -101,7 +101,7 @@ struct imsm_disk { #define CONFIGURED_DISK __cpu_to_le32(0x02) /* Member of some RaidDev */ #define FAILED_DISK __cpu_to_le32(0x04) /* Permanent failure */ __u32 status; /* 0xF0 - 0xF3 */ - __u32 owner_cfg_num; /* which config 0,1,2... owns this disk */ + __u32 owner_cfg_num; /* which config 0,1,2... owns this disk */ __u32 total_blocks_hi; /* 0xF4 - 0xF5 total blocks hi */ #define IMSM_DISK_FILLERS 3 __u32 filler[IMSM_DISK_FILLERS]; /* 0xF5 - 0x107 MPB_DISK_FILLERS for future expansion */ @@ -235,7 +235,6 @@ struct bbm_log { struct bbm_log_entry mapped_block_entries[BBM_LOG_MAX_ENTRIES]; } __attribute__ ((__packed__)); - #ifndef MDASSEMBLE static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" }; #endif @@ -249,7 +248,6 @@ static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" * MIGR_REC_BUF_SIZE <= MIGR_REC_POSITION */ - #define UNIT_SRC_NORMAL 0 /* Source data for curr_migr_unit must * be recovered using srcMap */ #define UNIT_SRC_IN_CP_AREA 1 /* Source data for curr_migr_unit has @@ -431,7 +429,7 @@ struct imsm_update_activate_spare { }; struct geo_params { - int dev_id; + char devnm[32]; char *dev_name; unsigned long long size; int level; @@ -508,11 +506,12 @@ struct imsm_update_add_remove_disk { enum imsm_update_type type; }; - static const char *_sys_dev_type[] = { [SYS_DEV_UNKNOWN] = "Unknown", [SYS_DEV_SAS] = "SAS", - [SYS_DEV_SATA] = "SATA" + [SYS_DEV_SATA] = "SATA", + [SYS_DEV_NVME] = "NVMe", + [SYS_DEV_VMD] = "VMD" }; const char *get_sys_dev_type(enum sys_dev_type type) @@ -538,7 +537,8 @@ static struct intel_hba * alloc_intel_hba(struct sys_dev *device) static struct intel_hba * find_intel_hba(struct intel_hba *hba, struct sys_dev *device) { - struct intel_hba *result=NULL; + struct intel_hba *result; + for (result = hba; result; result = result->next) { if (result->type == device->type && strcmp(result->path, device->path) == 0) break; @@ -562,11 +562,21 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device hba = super->hba; /* Intel metadata allows for all disks attached to the same type HBA. - * Do not sypport odf HBA types mixing + * Do not support HBA types mixing */ 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); + + if (device_orom != super->orom) + return 2; + while (hba->next) hba = hba->next; @@ -576,7 +586,7 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device static struct sys_dev* find_disk_attached_hba(int fd, const char *devname) { - struct sys_dev *list, *elem, *prev; + struct sys_dev *list, *elem; char *disk_path; if ((list = find_intel_devices()) == NULL) @@ -587,32 +597,19 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname) else disk_path = diskfd_to_devpath(fd); - if (!disk_path) { - free_sys_dev(&list); + if (!disk_path) return 0; - } - for (prev = NULL, elem = list; elem; prev = elem, elem = elem->next) { - if (path_attached_to_hba(disk_path, elem->path)) { - if (prev == NULL) - list = list->next; - else - prev->next = elem->next; - elem->next = NULL; - if (disk_path != devname) - free(disk_path); - free_sys_dev(&list); + for (elem = list; elem; elem = elem->next) + if (path_attached_to_hba(disk_path, elem->path)) return elem; - } - } + if (disk_path != devname) free(disk_path); - free_sys_dev(&list); return NULL; } - static int find_intel_hba_capability(int fd, struct intel_super *super, char *devname); @@ -626,7 +623,6 @@ static struct supertype *match_metadata_desc_imsm(char *arg) return NULL; st = xcalloc(1, sizeof(*st)); - st->container_dev = NoMdDev; st->ss = &super_imsm; st->max_devs = IMSM_MAX_DEVICES; st->minor_version = 0; @@ -685,12 +681,12 @@ static __u32 __gen_imsm_checksum(struct imsm_super *mpb) __u32 *p = (__u32 *) mpb; __u32 sum = 0; - while (end--) { - sum += __le32_to_cpu(*p); + while (end--) { + sum += __le32_to_cpu(*p); p++; } - return sum - __le32_to_cpu(mpb->check_sum); + return sum - __le32_to_cpu(mpb->check_sum); } static size_t sizeof_imsm_map(struct imsm_map *map) @@ -976,7 +972,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl) } qsort(rv, memberships, sizeof(*rv), cmp_extent); - /* determine the start of the metadata + /* determine the start of the metadata * when no raid devices are defined use the default * ...otherwise allow the metadata to truncate the value * as is the case with older versions of imsm @@ -1320,12 +1316,12 @@ void examine_migr_rec_imsm(struct intel_super *super) /******************************************************************************* * function: imsm_check_attributes * Description: Function checks if features represented by attributes flags - * are supported by mdadm. + * are supported by mdadm. * Parameters: * attributes - Attributes read from metadata * Returns: - * 0 - passed attributes contains unsupported features flags - * 1 - all features are supported + * 0 - passed attributes contains unsupported features flags + * 1 - all features are supported ******************************************************************************/ static int imsm_check_attributes(__u32 attributes) { @@ -1396,7 +1392,7 @@ static int imsm_check_attributes(__u32 attributes) } if (not_supported) - dprintf(Name "(IMSM): Unknown attributes : %x\n", not_supported); + dprintf("(IMSM): Unknown attributes : %x\n", not_supported); ret_val = 0; } @@ -1532,6 +1528,59 @@ static void export_examine_super_imsm(struct supertype *st) printf("MD_DEVICES=%u\n", mpb->num_disks); } +static int copy_metadata_imsm(struct supertype *st, int from, int to) +{ + /* The second last 512byte sector of the device contains + * the "struct imsm_super" metadata. + * This contains mpb_size which is the size in bytes of the + * extended metadata. This is located immediately before + * the imsm_super. + * We want to read all that, plus the last sector which + * may contain a migration record, and write it all + * to the target. + */ + void *buf; + unsigned long long dsize, offset; + int sectors; + struct imsm_super *sb; + int written = 0; + + if (posix_memalign(&buf, 4096, 4096) != 0) + return 1; + + if (!get_dev_size(from, NULL, &dsize)) + goto err; + + if (lseek64(from, dsize-1024, 0) < 0) + goto err; + if (read(from, buf, 512) != 512) + goto err; + sb = buf; + if (strncmp((char*)sb->sig, MPB_SIGNATURE, MPB_SIG_LEN) != 0) + goto err; + + sectors = mpb_sectors(sb) + 2; + offset = dsize - sectors * 512; + if (lseek64(from, offset, 0) < 0 || + lseek64(to, offset, 0) < 0) + goto err; + while (written < sectors * 512) { + int n = sectors*512 - written; + if (n > 4096) + n = 4096; + if (read(from, buf, n) != n) + goto err; + if (write(to, buf, n) != n) + goto err; + written += n; + } + free(buf); + return 0; +err: + free(buf); + return 1; +} + static void detail_super_imsm(struct supertype *st, char *homehost) { struct mdinfo info; @@ -1576,7 +1625,10 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b * this hba */ dir = opendir("/sys/dev/block"); - for (ent = dir ? readdir(dir) : NULL; ent; ent = readdir(dir)) { + if (!dir) + return 1; + + for (ent = readdir(dir); ent; ent = readdir(dir)) { int fd; char model[64]; char vendor[64]; @@ -1606,7 +1658,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b 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); @@ -1621,7 +1673,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b 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]; @@ -1630,7 +1682,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b } 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]; @@ -1666,7 +1718,8 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b break; } *c = '\0'; - if (sscanf(&path[hba_len], "host%d", &port) == 1) + if ((sscanf(&path[hba_len], "ata%d", &port) == 1) || + ((sscanf(&path[hba_len], "host%d", &port) == 1))) port -= host_base; else { if (verbose > 0) { @@ -1717,6 +1770,61 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b return err; } +static int 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 1; + + /* scroll through /sys/dev/block looking for devices attached to + * this hba + */ + dir = opendir("/sys/bus/pci/drivers/nvme"); + if (!dir) + return 1; + + 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); + return 0; +} + static void print_found_intel_controllers(struct sys_dev *elem) { for (; elem; elem = elem->next) { @@ -1725,7 +1833,14 @@ static void print_found_intel_controllers(struct sys_dev *elem) fprintf(stderr, "SATA "); else if (elem->type == SYS_DEV_SAS) fprintf(stderr, "SAS "); - fprintf(stderr, "RAID controller"); + else if (elem->type == SYS_DEV_NVME) + fprintf(stderr, "NVMe "); + + 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"); @@ -1746,7 +1861,8 @@ static int ahci_get_port_count(const char *hba_path, int *port_count) for (ent = readdir(dir); ent; ent = readdir(dir)) { int host; - if (sscanf(ent->d_name, "host%d", &host) != 1) + if ((sscanf(ent->d_name, "ata%d", &host) != 1) && + ((sscanf(ent->d_name, "host%d", &host) != 1))) continue; if (*port_count == 0) host_base = host; @@ -1762,9 +1878,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count) static void print_imsm_capability(const struct imsm_orom *orom) { - printf(" Platform : Intel(R) Matrix Storage Manager\n"); - printf(" Version : %d.%d.%d.%d\n", orom->major_ver, orom->minor_ver, - orom->hotfix_ver, orom->build); + printf(" Platform : Intel(R) "); + if (orom->capabilities == 0 && orom->driver_features == 0) + printf("Matrix Storage Manager\n"); + else + printf("Rapid Storage Technology%s\n", + imsm_orom_is_enterprise(orom) ? " enterprise" : ""); + if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) + printf(" Version : %d.%d.%d.%d\n", orom->major_ver, + orom->minor_ver, orom->hotfix_ver, orom->build); printf(" RAID Levels :%s%s%s%s%s\n", imsm_orom_has_raid0(orom) ? " raid0" : "", imsm_orom_has_raid1(orom) ? " raid1" : "", @@ -1793,12 +1915,49 @@ static void print_imsm_capability(const struct imsm_orom *orom) printf(" 2TB disks :%s supported\n", (orom->attr & IMSM_OROM_ATTR_2TB_DISK)?"":" not"); printf(" Max Disks : %d\n", orom->tds); - printf(" Max Volumes : %d per array, %d per controller\n", - orom->vpa, orom->vphba); + printf(" Max Volumes : %d per array, %d per %s\n", + orom->vpa, orom->vphba, + imsm_orom_is_nvme(orom) ? "platform" : "controller"); return; } -static int detail_platform_imsm(int verbose, int enumerate_only) +static void print_imsm_capability_export(const struct imsm_orom *orom) +{ + printf("MD_FIRMWARE_TYPE=imsm\n"); + if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) + printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver, + orom->hotfix_ver, orom->build); + printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n", + imsm_orom_has_raid0(orom) ? "raid0 " : "", + imsm_orom_has_raid1(orom) ? "raid1 " : "", + imsm_orom_has_raid1e(orom) ? "raid1e " : "", + imsm_orom_has_raid5(orom) ? "raid10 " : "", + imsm_orom_has_raid10(orom) ? "raid5 " : ""); + printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + imsm_orom_has_chunk(orom, 2) ? "2k " : "", + imsm_orom_has_chunk(orom, 4) ? "4k " : "", + imsm_orom_has_chunk(orom, 8) ? "8k " : "", + imsm_orom_has_chunk(orom, 16) ? "16k " : "", + imsm_orom_has_chunk(orom, 32) ? "32k " : "", + imsm_orom_has_chunk(orom, 64) ? "64k " : "", + imsm_orom_has_chunk(orom, 128) ? "128k " : "", + imsm_orom_has_chunk(orom, 256) ? "256k " : "", + imsm_orom_has_chunk(orom, 512) ? "512k " : "", + imsm_orom_has_chunk(orom, 1024*1) ? "1M " : "", + imsm_orom_has_chunk(orom, 1024*2) ? "2M " : "", + imsm_orom_has_chunk(orom, 1024*4) ? "4M " : "", + imsm_orom_has_chunk(orom, 1024*8) ? "8M " : "", + imsm_orom_has_chunk(orom, 1024*16) ? "16M " : "", + imsm_orom_has_chunk(orom, 1024*32) ? "32M " : "", + imsm_orom_has_chunk(orom, 1024*64) ? "64M " : ""); + printf("IMSM_2TB_VOLUMES=%s\n",(orom->attr & IMSM_OROM_ATTR_2TB) ? "yes" : "no"); + printf("IMSM_2TB_DISKS=%s\n",(orom->attr & IMSM_OROM_ATTR_2TB_DISK) ? "yes" : "no"); + printf("IMSM_MAX_DISKS=%d\n",orom->tds); + printf("IMSM_MAX_VOLUMES_PER_ARRAY=%d\n",orom->vpa); + printf("IMSM_MAX_VOLUMES_PER_CONTROLLER=%d\n",orom->vphba); +} + +static int detail_platform_imsm(int verbose, int enumerate_only, char *controller_path) { /* There are two components to imsm platform support, the ahci SATA * controller and the option-rom. To find the SATA controller we @@ -1811,11 +1970,10 @@ static int detail_platform_imsm(int verbose, int enumerate_only) * platform capabilities. If raid support is disabled in the BIOS the * option-rom capability structure will not be available. */ - const struct imsm_orom *orom; struct sys_dev *list, *hba; int host_base = 0; int port_count = 0; - int result=0; + int result=1; if (enumerate_only) { if (check_env("IMSM_NO_PLATFORM")) @@ -1824,53 +1982,136 @@ static int detail_platform_imsm(int verbose, int enumerate_only) if (!list) return 2; for (hba = list; hba; hba = hba->next) { - orom = find_imsm_capability(hba->type); - if (!orom) { - result = 2; + if (find_imsm_capability(hba)) { + result = 0; break; } + else + result = 2; } - free_sys_dev(&list); return result; } list = find_intel_devices(); if (!list) { if (verbose > 0) - pr_err("no active Intel(R) RAID " - "controller found.\n"); - free_sys_dev(&list); + pr_err("no active Intel(R) RAID controller found.\n"); return 2; } else if (verbose > 0) print_found_intel_controllers(list); for (hba = list; hba; hba = hba->next) { - orom = find_imsm_capability(hba->type); - if (!orom) + 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->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path, + get_sys_dev_type(hba->type)); + continue; + } + result = 0; + } + + if (controller_path && result == 1) { + pr_err("no active Intel(R) RAID controller found under %s\n", + controller_path); + return result; + } + + const struct orom_entry *entry; + + for (entry = orom_entries; entry; entry = entry->next) { + 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)); + if (print_vmd_attached_devs(hba)) { + if (verbose > 0) + pr_err("failed to get devices attached to VMD domain.\n"); + result |= 2; + } + printf("\n"); + } + } + continue; + } + + 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; + } + + struct devid_list *devid; + for (devid = entry->devid_list; devid; devid = devid->next) { + hba = device_by_id(devid->devid); + if (!hba) + continue; + + printf(" I/O Controller : %s (%s)\n", hba->path, get_sys_dev_type(hba->type)); - else - print_imsm_capability(orom); + if (hba->type == SYS_DEV_SATA) { + host_base = ahci_get_port_count(hba->path, &port_count); + if (ahci_enumerate_ports(hba->path, port_count, host_base, verbose)) { + if (verbose > 0) + pr_err("failed to enumerate ports on SATA controller at %s.\n", hba->pci_id); + result |= 2; + } + } + } + printf("\n"); + } + + return result; +} + +static int export_detail_platform_imsm(int verbose, char *controller_path) +{ + struct sys_dev *list, *hba; + int result=1; + + list = find_intel_devices(); + if (!list) { + if (verbose > 0) + pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_INTEL_DEVICES\n"); + result = 2; + return result; } for (hba = list; hba; hba = hba->next) { - printf(" I/O Controller : %s (%s)\n", - hba->path, get_sys_dev_type(hba->type)); - - if (hba->type == SYS_DEV_SATA) { - host_base = ahci_get_port_count(hba->path, &port_count); - if (ahci_enumerate_ports(hba->path, port_count, host_base, verbose)) { - if (verbose > 0) - pr_err("failed to enumerate " - "ports on SATA controller at %s.", hba->pci_id); - result |= 2; - } + if (controller_path && (compare_paths(hba->path,controller_path) != 0)) + continue; + 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) { + 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); } - free_sys_dev(&list); return result; } + #endif static int match_home_imsm(struct supertype *st, char *homehost) @@ -1897,7 +2138,7 @@ static void uuid_from_super_imsm(struct supertype *st, int uuid[4]) * not the device-set. * uuid to recognise same set when adding a missing device back * to an array. This is a uuid for the device-set. - * + * * For each of these we can make do with a truncated * or hashed uuid rather than the original, as long as * everyone agrees. @@ -2045,7 +2286,7 @@ static __u8 imsm_num_data_members(struct imsm_dev *dev, int second_map) case 5: return map->num_members - 1; default: - dprintf("%s: unsupported raid level\n", __func__); + dprintf("unsupported raid level\n"); return 0; } } @@ -2222,12 +2463,12 @@ static struct imsm_dev *imsm_get_device_during_migration( static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info) { struct mdinfo *sd; - struct dl *dl = NULL; + struct dl *dl; char nm[30]; int retval = -1; int fd = -1; struct imsm_dev *dev; - struct imsm_map *map = NULL; + struct imsm_map *map; int slot = -1; /* find map under migration */ @@ -2302,7 +2543,7 @@ static int imsm_create_metadata_checkpoint_update( int update_memory_size = 0; - dprintf("imsm_create_metadata_checkpoint_update(enter)\n"); + dprintf("(enter)\n"); if (u == NULL) return 0; @@ -2314,19 +2555,16 @@ static int imsm_create_metadata_checkpoint_update( *u = xcalloc(1, update_memory_size); if (*u == NULL) { - dprintf("error: cannot get memory for " - "imsm_create_metadata_checkpoint_update update\n"); + dprintf("error: cannot get memory\n"); return 0; } (*u)->type = update_general_migration_checkpoint; (*u)->curr_migr_unit = __le32_to_cpu(super->migr_rec->curr_migr_unit); - dprintf("imsm_create_metadata_checkpoint_update: prepared for %u\n", - (*u)->curr_migr_unit); + dprintf("prepared for %u\n", (*u)->curr_migr_unit); return update_memory_size; } - static void imsm_update_metadata_locally(struct supertype *st, void *buf, int len); @@ -2351,7 +2589,7 @@ static int write_imsm_migr_rec(struct supertype *st) int len; struct imsm_update_general_migration_checkpoint *u; struct imsm_dev *dev; - struct imsm_map *map = NULL; + struct imsm_map *map; /* find map under migration */ dev = imsm_get_device_during_migration(super); @@ -2457,9 +2695,7 @@ static unsigned long long imsm_component_size_aligment_check(int level, */ component_size_alligment = component_size % (chunk_size/512); - dprintf("imsm_component_size_aligment_check(Level: %i, " - "chunk_size = %i, component_size = %llu), " - "component_size_alligment = %u\n", + dprintf("(Level: %i, chunk_size = %i, component_size = %llu), component_size_alligment = %u\n", level, chunk_size, component_size, component_size_alligment); @@ -2467,7 +2703,7 @@ static unsigned long long imsm_component_size_aligment_check(int level, dprintf("imsm: reported component size alligned from %llu ", component_size); component_size -= component_size_alligment; - dprintf("to %llu (%i).\n", + dprintf_cont("to %llu (%i).\n", component_size, component_size_alligment); } @@ -2483,7 +2719,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, struct imsm_map *prev_map = get_imsm_map(dev, MAP_1); struct imsm_map *map_to_analyse = map; struct dl *dl; - char *devname; int map_disks = info->array.raid_disks; memset(info, 0, sizeof(*info)); @@ -2608,8 +2843,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, info->reshape_progress = blocks_per_unit * units; - dprintf("IMSM: General Migration checkpoint : %llu " - "(%llu) -> read reshape progress : %llu\n", + dprintf("IMSM: General Migration checkpoint : %llu (%llu) -> read reshape progress : %llu\n", (unsigned long long)units, (unsigned long long)blocks_per_unit, info->reshape_progress); @@ -2645,11 +2879,7 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, info->array.major_version = -1; info->array.minor_version = -2; - devname = devnum2devname(st->container_dev); - *info->text_version = '\0'; - if (devname) - sprintf(info->text_version, "/%s/%d", devname, info->container_member); - free(devname); + sprintf(info->text_version, "/%s/%d", st->container_devnm, info->container_member); info->safe_mode_delay = 4000; /* 4 secs like the Matrix driver */ uuid_from_super_imsm(st, info->uuid); @@ -2674,7 +2904,6 @@ static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev, int look_in_map); - #ifndef MDASSEMBLE static void manage_second_map(struct intel_super *super, struct imsm_dev *dev) { @@ -2725,7 +2954,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * info->array.level = LEVEL_CONTAINER; info->array.layout = 0; info->array.md_minor = -1; - info->array.ctime = 0; /* N/A for imsm */ + info->array.ctime = 0; /* N/A for imsm */ info->array.utime = 0; info->array.chunk_size = 0; @@ -2793,7 +3022,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * */ max_enough = max(max_enough, enough); } - dprintf("%s: enough: %d\n", __func__, max_enough); + dprintf("enough: %d\n", max_enough); info->container_enough = max_enough; if (super->disks) { @@ -2832,7 +3061,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char * * for each disk in array */ struct mdinfo *getinfo_super_disks_imsm(struct supertype *st) { - struct mdinfo *mddev = NULL; + struct mdinfo *mddev; struct intel_super *super = st->sb; struct imsm_disk *disk; int count = 0; @@ -2950,7 +3179,8 @@ static size_t disks_to_mpb_size(int disks) return size; } -static __u64 avail_size_imsm(struct supertype *st, __u64 devsize) +static __u64 avail_size_imsm(struct supertype *st, __u64 devsize, + unsigned long long data_offset) { if (devsize < (MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS)) return 0; @@ -2987,21 +3217,27 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst) struct intel_super *first = st->sb; struct intel_super *sec = tst->sb; - if (!first) { - st->sb = tst->sb; - tst->sb = NULL; - return 0; - } + if (!first) { + st->sb = tst->sb; + tst->sb = NULL; + return 0; + } /* in platform dependent environment test if the disks * use the same Intel hba + * If not on Intel hba at all, allow anything. */ - if (!check_env("IMSM_NO_PLATFORM")) { - if (!first->hba || !sec->hba || - (first->hba->type != sec->hba->type)) { + if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) { + if (first->hba->type != sec->hba->type) { fprintf(stderr, - "HBAs of devices does not match %s != %s\n", - first->hba ? get_sys_dev_type(first->hba->type) : NULL, - sec->hba ? get_sys_dev_type(sec->hba->type) : NULL); + "HBAs of devices do not match %s != %s\n", + get_sys_dev_type(first->hba->type), + get_sys_dev_type(sec->hba->type)); + return 3; + } + if (first->orom != sec->orom) { + fprintf(stderr, + "HBAs of devices do not match %s != %s\n", + first->hba->pci_id, sec->hba->pci_id); return 3; } } @@ -3032,7 +3268,6 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst) } - /* if 'first' is a spare promote it to a populated mpb with sec's * family number */ @@ -3056,7 +3291,7 @@ static int compare_super_imsm(struct supertype *st, struct supertype *tst) if (i < sec->anchor->num_raid_devs) { /* allocation failure */ free_devlist(first); - fprintf(stderr, "imsm: failed to associate spare\n"); + pr_err("imsm: failed to associate spare\n"); return 3; } first->anchor->num_raid_devs = sec->anchor->num_raid_devs; @@ -3404,7 +3639,7 @@ struct bbm_log *__get_imsm_bbm_log(struct imsm_super *mpb) if (__le32_to_cpu(mpb->bbm_log_size)) { ptr = mpb; ptr += mpb->mpb_size - __le32_to_cpu(mpb->bbm_log_size); - } + } return ptr; } @@ -3477,8 +3712,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname) if (posix_memalign((void**)&anchor, 512, 512) != 0) { if (devname) - pr_err("Failed to allocate imsm anchor buffer" - " on %s\n", devname); + pr_err("Failed to allocate imsm anchor buffer on %s\n", devname); return 1; } if (read(fd, anchor, 512) != 512) { @@ -3515,7 +3749,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname) free(anchor); if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) { - pr_err("%s could not allocate migr_rec buffer\n", __func__); + pr_err("could not allocate migr_rec buffer\n"); free(super->buf); return 2; } @@ -3726,14 +3960,14 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de 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, - hba_name->path, + 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(hba_name->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!"); @@ -3741,18 +3975,16 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de fprintf(stderr, ", "); 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"); } - free_sys_dev(&hba_name); return 2; } - super->orom = find_imsm_capability(hba_name->type); - free_sys_dev(&hba_name); + super->orom = find_imsm_capability(hba_name); if (!super->orom) return 3; + return 0; } @@ -3817,8 +4049,8 @@ static int __prep_thunderdome(struct intel_super **table, int tbl_size, if (tbl_mpb->family_num == mpb->family_num) { if (tbl_mpb->check_sum == mpb->check_sum) { - dprintf("%s: mpb from %d:%d matches %d:%d\n", - __func__, super->disks->major, + dprintf("mpb from %d:%d matches %d:%d\n", + super->disks->major, super->disks->minor, table[i]->disks->major, table[i]->disks->minor); @@ -3835,8 +4067,8 @@ static int __prep_thunderdome(struct intel_super **table, int tbl_size, */ struct intel_disk *idisk; - dprintf("%s: mpb from %d:%d replaces %d:%d\n", - __func__, super->disks->major, + dprintf("mpb from %d:%d replaces %d:%d\n", + super->disks->major, super->disks->minor, table[i]->disks->major, table[i]->disks->minor); @@ -3864,8 +4096,8 @@ static int __prep_thunderdome(struct intel_super **table, int tbl_size, idisk->disk.status |= CONFIGURED_DISK; } - dprintf("%s: mpb from %d:%d prefer %d:%d\n", - __func__, super->disks->major, + dprintf("mpb from %d:%d prefer %d:%d\n", + super->disks->major, super->disks->minor, table[i]->disks->major, table[i]->disks->minor); @@ -3924,12 +4156,12 @@ validate_members(struct intel_super *super, struct intel_disk *disk_list, idisk->owner == IMSM_UNKNOWN_OWNER) ok_count++; else - dprintf("%s: '%.16s' owner %d != %d\n", - __func__, disk->serial, idisk->owner, + dprintf("'%.16s' owner %d != %d\n", + disk->serial, idisk->owner, owner); } else { - dprintf("%s: unknown disk %x [%d]: %.16s\n", - __func__, __le32_to_cpu(mpb->family_num), i, + dprintf("unknown disk %x [%d]: %.16s\n", + __le32_to_cpu(mpb->family_num), i, disk->serial); break; } @@ -3947,7 +4179,7 @@ static void show_conflicts(__u32 family_num, struct intel_super *super_list) for (s = super_list; s; s = s->next) { if (family_num != s->anchor->family_num) continue; - fprintf(stderr, "Conflict, offlining family %#x on '%s'\n", + pr_err("Conflict, offlining family %#x on '%s'\n", __le32_to_cpu(family_num), s->disks->devname); } } @@ -3985,8 +4217,8 @@ imsm_thunderdome(struct intel_super **super_list, int len) s = NULL; if (!s) - dprintf("%s: marking family: %#x from %d:%d offline\n", - __func__, mpb->family_num, + dprintf("marking family: %#x from %d:%d offline\n", + mpb->family_num, super_table[i]->disks->major, super_table[i]->disks->minor); super_table[i] = s; @@ -4033,8 +4265,7 @@ imsm_thunderdome(struct intel_super **super_list, int len) champion = s; if (conflict) - fprintf(stderr, "Chose family %#x on '%s', " - "assemble conflicts to new container with '--update=uuid'\n", + pr_err("Chose family %#x on '%s', assemble conflicts to new container with '--update=uuid'\n", __le32_to_cpu(s->anchor->family_num), s->disks->devname); /* collect all dl's onto 'champion', and update them to @@ -4106,16 +4337,14 @@ imsm_thunderdome(struct intel_super **super_list, int len) return champion; } - static int get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd); -static int get_super_block(struct intel_super **super_list, int devnum, char *devname, +static int get_super_block(struct intel_super **super_list, char *devnm, char *devname, int major, int minor, int keep_fd); static int get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list, int *max, int keep_fd); - static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, char *devname, struct md_list *devlist, int keep_fd) @@ -4178,15 +4407,14 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, free_imsm(s); } - if (err) return err; *sbp = super; if (fd >= 0) - st->container_dev = fd2devnum(fd); + strcpy(st->container_devnm, fd2devnm(fd)); else - st->container_dev = NoMdDev; + st->container_devnm[0] = 0; if (err == 0 && st->ss == NULL) { st->ss = &super_imsm; st->minor_version = 0; @@ -4195,7 +4423,6 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, return 0; } - static int get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list, int *max, int keep_fd) @@ -4229,7 +4456,7 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list int major = major(tmpdev->st_rdev); int minor = minor(tmpdev->st_rdev); err = get_super_block(super_list, - -1, + NULL, tmpdev->devname, major, minor, keep_fd); @@ -4245,13 +4472,12 @@ get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list return err; } -static int get_super_block(struct intel_super **super_list, int devnum, char *devname, +static int get_super_block(struct intel_super **super_list, char *devnm, char *devname, int major, int minor, int keep_fd) { - struct intel_super*s = NULL; + struct intel_super *s; char nm[32]; int dfd = -1; - int rv; int err = 0; int retry; @@ -4268,17 +4494,11 @@ static int get_super_block(struct intel_super **super_list, int devnum, char *de goto error; } - rv = find_intel_hba_capability(dfd, s, devname); - /* no orom/efi or non-intel hba of the disk */ - if (rv != 0) { - err = 4; - goto error; - } - + find_intel_hba_capability(dfd, s, devname); err = load_and_parse_mpb(dfd, s, NULL, keep_fd); /* retry the load if we might have raced against mdmon */ - if (err == 3 && (devnum != -1) && mdmon_running(devnum)) + if (err == 3 && devnm && mdmon_running(devnm)) for (retry = 0; retry < 3; retry++) { usleep(3000); err = load_and_parse_mpb(dfd, s, NULL, keep_fd); @@ -4305,11 +4525,11 @@ static int get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int *max, int keep_fd) { struct mdinfo *sra; - int devnum; + char *devnm; struct mdinfo *sd; int err = 0; int i = 0; - sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); + sra = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); if (!sra) return 1; @@ -4320,9 +4540,9 @@ get_sra_super_block(int fd, struct intel_super **super_list, char *devname, int goto error; } /* load all mpbs */ - devnum = fd2devnum(fd); + devnm = fd2devnm(fd); for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) { - if (get_super_block(super_list, devnum, devname, + if (get_super_block(super_list, devnm, devname, sd->disk.major, sd->disk.minor, keep_fd) != 0) { err = 7; goto error; @@ -4344,6 +4564,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname) { struct intel_super *super; int rv; + int retry; if (test_partition(fd)) /* IMSM not allowed on partitions */ @@ -4366,10 +4587,29 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname) } rv = load_and_parse_mpb(fd, super, devname, 0); + /* retry the load if we might have raced against mdmon */ + if (rv == 3) { + struct mdstat_ent *mdstat = NULL; + char *name = fd2kname(fd); + + if (name) + mdstat = mdstat_by_component(name); + + if (mdstat && mdmon_running(mdstat->devnm) && getpid() != mdmon_pid(mdstat->devnm)) { + for (retry = 0; retry < 3; retry++) { + usleep(3000); + rv = load_and_parse_mpb(fd, super, devname, 0); + if (rv != 3) + break; + } + } + + free_mdstat(mdstat); + } + if (rv) { if (devname) - pr_err("Failed to load all information " - "sections on %s\n", devname); + pr_err("Failed to load all information sections on %s\n", devname); free_imsm(super); return rv; } @@ -4486,7 +4726,8 @@ 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, - char *homehost, int *uuid) + char *homehost, int *uuid, + long long data_offset) { /* We are creating a volume inside a pre-existing container. * so st->sb is already set. @@ -4504,8 +4745,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, unsigned long long num_data_stripes; if (super->orom && mpb->num_raid_devs >= super->orom->vpa) { - pr_err("This imsm-container already has the " - "maximum of %d volumes\n", super->orom->vpa); + pr_err("This imsm-container already has the maximum of %d volumes\n", super->orom->vpa); return 0; } @@ -4522,8 +4762,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, } if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) { - pr_err("%s could not allocate migr_rec buffer\n", - __func__); + pr_err("could not allocate migr_rec buffer\n"); free(super->buf); free(super); free(mpb_new); @@ -4597,7 +4836,8 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info)); map->failed_disk_num = ~0; if (info->level > 0) - map->map_state = IMSM_T_STATE_UNINITIALIZED; + map->map_state = (info->state ? IMSM_T_STATE_NORMAL + : IMSM_T_STATE_UNINITIALIZED); else map->map_state = info->failed_disks ? IMSM_T_STATE_FAILED : IMSM_T_STATE_NORMAL; @@ -4606,8 +4846,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, if (info->level == 1 && info->raid_disks > 2) { free(dev); free(dv); - pr_err("imsm does not support more than 2 disks" - "in a raid1 volume\n"); + pr_err("imsm does not support more than 2 disksin a raid1 volume\n"); return 0; } @@ -4644,7 +4883,8 @@ 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, - char *homehost, int *uuid) + char *homehost, int *uuid, + unsigned long long data_offset) { /* This is primarily called by Create when creating a new array. * We will then get add_to_super called for each component, and then @@ -4659,8 +4899,14 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, size_t mpb_size; char *version; + if (data_offset != INVALID_SECTORS) { + pr_err("data-offset not supported by imsm\n"); + return 0; + } + if (st->sb) - return init_super_imsm_volume(st, info, size, name, homehost, uuid); + return init_super_imsm_volume(st, info, size, name, homehost, uuid, + data_offset); if (info) mpb_size = disks_to_mpb_size(info->nr_disks); @@ -4673,11 +4919,11 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info, super = NULL; } if (!super) { - pr_err("%s could not allocate superblock\n", __func__); + pr_err("could not allocate superblock\n"); return 0; } if (posix_memalign(&super->migr_rec_buf, 512, MIGR_REC_BUF_SIZE) != 0) { - pr_err("%s could not allocate migr_rec buffer\n", __func__); + pr_err("could not allocate migr_rec buffer\n"); free(super->buf); free(super); return 0; @@ -4854,7 +5100,8 @@ int mark_spare(struct dl *disk) } static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, - int fd, char *devname) + int fd, char *devname, + unsigned long long data_offset) { struct intel_super *super = st->sb; struct dl *dd; @@ -4895,6 +5142,14 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, } get_dev_size(fd, NULL, &size); + /* clear migr_rec when adding disk to container */ + memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE); + if (lseek64(fd, size - MIGR_REC_POSITION, SEEK_SET) >= 0) { + if (write(fd, super->migr_rec_buf, + MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE) + perror("Write migr_rec failed"); + } + size /= 512; serialcpy(dd->disk.serial, dd->serial); set_total_blocks(&dd->disk, size); @@ -4920,7 +5175,6 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, return 0; } - static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk) { struct intel_super *super = st->sb; @@ -4931,8 +5185,7 @@ static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk) * is prepared. */ if (!st->update_tail) { - pr_err("%s shall be used in mdmon context only" - "(line %d).\n", __func__, __LINE__); + pr_err("shall be used in mdmon context only\n"); return 1; } dd = xcalloc(1, sizeof(*dd)); @@ -4945,7 +5198,6 @@ static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk) dd->next = super->disk_mgmt_list; super->disk_mgmt_list = dd; - return 0; } @@ -4966,13 +5218,13 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose) __u32 sum; struct dl *d; - spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super)), - spare->generation_num = __cpu_to_le32(1UL), + spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super)); + spare->generation_num = __cpu_to_le32(1UL); spare->attributes = MPB_ATTRIB_CHECKSUM_VERIFY; - spare->num_disks = 1, - spare->num_raid_devs = 0, - spare->cache_size = mpb->cache_size, - spare->pwr_cycle_count = __cpu_to_le32(1), + spare->num_disks = 1; + spare->num_raid_devs = 0; + spare->cache_size = mpb->cache_size; + spare->pwr_cycle_count = __cpu_to_le32(1); snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH, MPB_SIGNATURE MPB_VERSION_RAID0); @@ -4992,8 +5244,8 @@ static int write_super_imsm_spares(struct intel_super *super, int doclose) spare->check_sum = __cpu_to_le32(sum); if (store_imsm_mpb(d->fd, spare)) { - fprintf(stderr, "%s: failed for device %d:%d %s\n", - __func__, d->major, d->minor, strerror(errno)); + pr_err("failed for device %d:%d %s\n", + d->major, d->minor, strerror(errno)); return 1; } if (doclose) { @@ -5086,8 +5338,8 @@ static int write_super_imsm(struct supertype *st, int doclose) if (store_imsm_mpb(d->fd, mpb)) fprintf(stderr, - "%s: failed for device %d:%d (fd: %d)%s\n", - __func__, d->major, d->minor, + "failed for device %d:%d (fd: %d)%s\n", + d->major, d->minor, d->fd, strerror(errno)); if (doclose) { @@ -5102,7 +5354,6 @@ static int write_super_imsm(struct supertype *st, int doclose) return 0; } - static int create_array(struct supertype *st, int dev_idx) { size_t len; @@ -5125,6 +5376,8 @@ static int create_array(struct supertype *st, int dev_idx) int idx = get_imsm_disk_idx(dev, i, MAP_X); disk = get_imsm_disk(super, idx); + if (!disk) + disk = get_imsm_missing(super, idx); serialcpy(inf[i].serial, disk->serial); } append_metadata_update(st, u, len); @@ -5204,13 +5457,15 @@ static int imsm_bbm_log_size(struct imsm_super *mpb) #ifndef MDASSEMBLE static int validate_geometry_imsm_container(struct supertype *st, int level, int layout, int raiddisks, int chunk, - unsigned long long size, char *dev, + unsigned long long size, + unsigned long long data_offset, + char *dev, unsigned long long *freesize, int verbose) { int fd; unsigned long long ldsize; - struct intel_super *super=NULL; + struct intel_super *super; int rv = 0; if (level != LEVEL_CONTAINER) @@ -5239,7 +5494,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, #if DEBUG char str[256]; fd2devname(fd, str); - dprintf("validate_geometry_imsm_container: fd: %d %s orom: %p rv: %d raiddisk: %d\n", + dprintf("fd: %d %s orom: %p rv: %d raiddisk: %d\n", fd, str, super->orom, rv, raiddisks); #endif /* no orom/efi or non-intel hba of the disk */ @@ -5251,8 +5506,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, if (super->orom) { if (raiddisks > super->orom->tds) { if (verbose) - pr_err("%d exceeds maximum number of" - " platform supported disks: %d\n", + pr_err("%d exceeds maximum number of platform supported disks: %d\n", raiddisks, super->orom->tds); free_imsm(super); return 0; @@ -5266,7 +5520,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, } } - *freesize = avail_size_imsm(st, ldsize >> 9); + *freesize = avail_size_imsm(st, ldsize >> 9, data_offset); free_imsm(super); return 1; @@ -5399,16 +5653,15 @@ static int is_raid_level_supported(const struct imsm_orom *orom, int level, int return 0; } - static int active_arrays_by_format(char *name, char* hba, struct md_list **devlist, int dpa, int verbose) { struct mdstat_ent *mdstat = mdstat_read(0, 0); - struct mdstat_ent *memb = NULL; + struct mdstat_ent *memb; int count = 0; int num = 0; - struct md_list *dv = NULL; + struct md_list *dv; int found; for (memb = mdstat ; memb ; memb = memb->next) { @@ -5425,7 +5678,7 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist, if (num > 0) fd = open(path, O_RDONLY, 0); if ((num <= 0) || (fd < 0)) { - pr_vrb(": Cannot open %s: %s\n", + pr_vrb("Cannot open %s: %s\n", dev->name, strerror(errno)); } free(path); @@ -5437,15 +5690,15 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist, for (vol = mdstat ; vol ; vol = vol->next) { if ((vol->active > 0) && vol->metadata_version && - is_container_member(vol, memb->dev)) { + is_container_member(vol, memb->devnm)) { found++; count++; } } if (*devlist && (found < dpa)) { dv = xcalloc(1, sizeof(*dv)); - dv->devname = xmalloc(strlen(memb->dev) + strlen("/dev/") + 1); - sprintf(dv->devname, "%s%s", "/dev/", memb->dev); + dv->devname = xmalloc(strlen(memb->devnm) + strlen("/dev/") + 1); + sprintf(dv->devname, "%s%s", "/dev/", memb->devnm); dv->found = found; dv->used = 0; dv->next = *devlist; @@ -5466,7 +5719,7 @@ get_loop_devices(void) { int i; struct md_list *devlist = NULL; - struct md_list *dv = NULL; + struct md_list *dv; for(i = 0; i < 12; i++) { dv = xcalloc(1, sizeof(*dv)); @@ -5483,7 +5736,7 @@ static struct md_list* get_devices(const char *hba_path) { struct md_list *devlist = NULL; - struct md_list *dv = NULL; + struct md_list *dv; struct dirent *ent; DIR *dir; int err = 0; @@ -5523,7 +5776,6 @@ get_devices(const char *hba_path) continue; } - dv = xcalloc(1, sizeof(*dv)); dv->devname = xstrdup(buf); dv->next = devlist; @@ -5547,7 +5799,7 @@ count_volumes_list(struct md_list *devlist, char *homehost, { struct md_list *tmpdev; int count = 0; - struct supertype *st = NULL; + struct supertype *st; /* first walk the list of devices to find a consistent set * that match the criterea, if that is possible. @@ -5556,7 +5808,7 @@ count_volumes_list(struct md_list *devlist, char *homehost, *found = 0; st = match_metadata_desc_imsm("imsm"); if (st == NULL) { - pr_vrb(": cannot allocate memory for imsm supertype\n"); + pr_vrb("cannot allocate memory for imsm supertype\n"); return 0; } @@ -5569,33 +5821,33 @@ count_volumes_list(struct md_list *devlist, char *homehost, continue; tst = dup_super(st); if (tst == NULL) { - pr_vrb(": cannot allocate memory for imsm supertype\n"); + pr_vrb("cannot allocate memory for imsm supertype\n"); goto err_1; } tmpdev->container = 0; dfd = dev_open(devname, O_RDONLY|O_EXCL); if (dfd < 0) { - dprintf(": cannot open device %s: %s\n", + 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", + 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", + dprintf("%s is not a block device.\n", devname); tmpdev->used = 2; } else if (must_be_container(dfd)) { struct supertype *cst; cst = super_by_fd(dfd, NULL); if (cst == NULL) { - dprintf(": cannot recognize container type %s\n", + dprintf("cannot recognize container type %s\n", devname); tmpdev->used = 2; } else if (tst->ss != st->ss) { - dprintf(": non-imsm container - ignore it: %s\n", + dprintf("non-imsm container - ignore it: %s\n", devname); tmpdev->used = 2; } else if (!tst->ss->load_container || @@ -5609,11 +5861,11 @@ count_volumes_list(struct md_list *devlist, char *homehost, } else { tmpdev->st_rdev = stb.st_rdev; if (tst->ss->load_super(tst,dfd, NULL)) { - dprintf(": no RAID superblock on %s\n", + dprintf("no RAID superblock on %s\n", devname); tmpdev->used = 2; } else if (tst->ss->compare_super == NULL) { - dprintf(": Cannot assemble %s metadata on %s\n", + dprintf("Cannot assemble %s metadata on %s\n", tst->ss->name, devname); tmpdev->used = 2; } @@ -5650,7 +5902,7 @@ count_volumes_list(struct md_list *devlist, char *homehost, * Or, if we are auto assembling, we just ignore the second * for now. */ - dprintf(": superblock on %s doesn't match others - assembly aborted\n", + dprintf("superblock on %s doesn't match others - assembly aborted\n", devname); goto loop; } @@ -5672,7 +5924,7 @@ count_volumes_list(struct md_list *devlist, char *homehost, if (iter->array.state & (1<text_version); } else count++; @@ -5680,11 +5932,11 @@ count_volumes_list(struct md_list *devlist, char *homehost, sysfs_free(head); } else { - dprintf(" no valid super block on device list: err: %d %p\n", + dprintf("No valid super block on device list: err: %d %p\n", err, st->sb); } } else { - dprintf(" no more devices to examin\n"); + dprintf("no more devices to examine\n"); } for (tmpdev = devlist; tmpdev; tmpdev = tmpdev->next) { @@ -5705,39 +5957,76 @@ count_volumes_list(struct md_list *devlist, char *homehost, return count; } - static int -count_volumes(char *hba, int dpa, int verbose) +count_volumes(struct intel_hba *hba, int dpa, int verbose) { - struct md_list *devlist = NULL; + struct sys_dev *idev, *intel_devices = find_intel_devices(); int count = 0; - int found = 0;; + const struct orom_entry *entry; + struct devid_list *dv, *devid_list; - devlist = get_devices(hba); - /* if no intel devices return zero volumes */ - if (devlist == NULL) + if (!hba || !hba->path) return 0; - count = active_arrays_by_format("imsm", hba, &devlist, dpa, verbose); - dprintf(" path: %s active arrays: %d\n", hba, count); - if (devlist == NULL) + for (idev = intel_devices; idev; idev = idev->next) { + if (strstr(idev->path, hba->path)) + break; + } + + if (!idev || !idev->dev_id) return 0; - do { - found = 0; - count += count_volumes_list(devlist, - NULL, - verbose, - &found); - dprintf("found %d count: %d\n", found, count); - } while (found); - - dprintf("path: %s total number of volumes: %d\n", hba, count); - - while(devlist) { - struct md_list *dv = devlist; - devlist = devlist->next; - free(dv->devname); - free(dv); + + entry = get_orom_entry_by_device_id(idev->dev_id); + + if (!entry || !entry->devid_list) + return 0; + + 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; + int found = 0; + + if (device) + hba_path = device->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 0; + + count += active_arrays_by_format("imsm", hba_path, &devlist, dpa, verbose); + dprintf("path: %s active arrays: %d\n", hba_path, count); + if (devlist == NULL) + return 0; + do { + found = 0; + count += count_volumes_list(devlist, + NULL, + verbose, + &found); + dprintf("found %d count: %d\n", found, count); + } while (found); + + dprintf("path: %s total number of volumes: %d\n", hba_path, count); + + while (devlist) { + struct md_list *dv = devlist; + devlist = devlist->next; + free(dv->devname); + free(dv); + } } return count; } @@ -5758,52 +6047,54 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, { /* check/set platform and metadata limits/defaults */ if (super->orom && raiddisks > super->orom->dpa) { - pr_vrb(": platform supports a maximum of %d disks per array\n", + pr_vrb("platform supports a maximum of %d disks per array\n", super->orom->dpa); return 0; } - /* capabilities of OROM tested - copied from validate_geometry_imsm_volume */ + /* capabilities of OROM tested - copied from validate_geometry_imsm_volume */ if (!is_raid_level_supported(super->orom, level, raiddisks)) { - pr_vrb(": platform does not support raid%d with %d disk%s\n", + pr_vrb("platform does not support raid%d with %d disk%s\n", level, raiddisks, raiddisks > 1 ? "s" : ""); return 0; } - if (chunk && (*chunk == 0 || *chunk == UnSet)) + if (*chunk == 0 || *chunk == UnSet) *chunk = imsm_default_chunk(super->orom); - if (super->orom && chunk && !imsm_orom_has_chunk(super->orom, *chunk)) { - pr_vrb(": platform does not support a chunk size of: " - "%d\n", *chunk); + if (super->orom && !imsm_orom_has_chunk(super->orom, *chunk)) { + pr_vrb("platform does not support a chunk size of: %d\n", *chunk); return 0; } if (layout != imsm_level_to_layout(level)) { if (level == 5) - pr_vrb(": imsm raid 5 only supports the left-asymmetric layout\n"); + pr_vrb("imsm raid 5 only supports the left-asymmetric layout\n"); else if (level == 10) - pr_vrb(": imsm raid 10 only supports the n2 layout\n"); + pr_vrb("imsm raid 10 only supports the n2 layout\n"); else - pr_vrb(": imsm unknown layout %#x for this raid level %d\n", + pr_vrb("imsm unknown layout %#x for this raid level %d\n", layout, level); return 0; } - if (super->orom && (super->orom->attr & IMSM_OROM_ATTR_2TB) == 0 && chunk && + if (super->orom && (super->orom->attr & IMSM_OROM_ATTR_2TB) == 0 && (calc_array_size(level, raiddisks, layout, *chunk, size) >> 32) > 0) { - pr_vrb(": platform does not support a volume size over 2TB\n"); + pr_vrb("platform does not support a volume size over 2TB\n"); return 0; } + return 1; } -/* validate_geometry_imsm_volume - lifted from validate_geometry_ddf_bvd +/* validate_geometry_imsm_volume - lifted from validate_geometry_ddf_bvd * FIX ME add ahci details */ static int validate_geometry_imsm_volume(struct supertype *st, int level, int layout, int raiddisks, int *chunk, - unsigned long long size, char *dev, + unsigned long long size, + unsigned long long data_offset, + char *dev, unsigned long long *freesize, int verbose) { @@ -5823,8 +6114,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, mpb = super->anchor; if (!validate_geometry_imsm_orom(super, level, layout, raiddisks, chunk, size, verbose)) { - pr_err("RAID gemetry validation failed. " - "Cannot proceed with the action(s).\n"); + pr_err("RAID gemetry validation failed. Cannot proceed with the action(s).\n"); return 0; } if (!dev) { @@ -5865,9 +6155,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, } if (dcnt < raiddisks) { if (verbose) - pr_err("imsm: Not enough " - "devices with space for this array " - "(%d < %d)\n", + pr_err("imsm: Not enough devices with space for this array (%d < %d)\n", dcnt, raiddisks); return 0; } @@ -5886,8 +6174,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, } if (!dl) { if (verbose) - pr_err("%s is not in the " - "same imsm set\n", dev); + pr_err("%s is not in the same imsm set\n", dev); return 0; } else if (super->orom && dl->index < 0 && mpb->num_raid_devs) { /* If a volume is present then the current creation attempt @@ -5895,15 +6182,12 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, * understand this configuration (all member disks must be * members of each array in the container). */ - pr_err("%s is a spare and a volume" - " is already defined for this container\n", dev); - pr_err("The option-rom requires all member" - " disks to be a member of all volumes\n"); + pr_err("%s is a spare and a volume is already defined for this container\n", dev); + pr_err("The option-rom requires all member disks to be a member of all volumes\n"); return 0; } else if (super->orom && mpb->num_raid_devs > 0 && mpb->num_disks != raiddisks) { - pr_err("The option-rom requires all member" - " disks to be a member of all volumes\n"); + pr_err("The option-rom requires all member disks to be a member of all volumes\n"); return 0; } @@ -5946,21 +6230,16 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, if (!check_env("IMSM_NO_PLATFORM") && mpb->num_raid_devs > 0 && size && size != maxsize) { - pr_err("attempting to create a second " - "volume with size less then remaining space. " - "Aborting...\n"); + pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n"); return 0; } if (maxsize < size || maxsize == 0) { if (verbose) { if (maxsize == 0) - pr_err("no free space" - " left on device. Aborting...\n"); + pr_err("no free space left on device. Aborting...\n"); else - pr_err("not enough space" - " to create volume of given size" - " (%llu < %llu). Aborting...\n", + pr_err("not enough space to create volume of given size (%llu < %llu). Aborting...\n", maxsize, size); } return 0; @@ -5969,10 +6248,10 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, *freesize = maxsize; if (super->orom) { - int count = count_volumes(super->hba->path, + int count = count_volumes(super->hba, super->orom->dpa, verbose); if (super->orom->vphba <= count) { - pr_vrb(": platform does not support more than %d raid volumes.\n", + pr_vrb("platform does not support more than %d raid volumes.\n", super->orom->vphba); return 0; } @@ -6046,9 +6325,7 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks, } if (!check_env("IMSM_NO_PLATFORM") && mpb->num_raid_devs > 0 && size && size != maxsize) { - pr_err("attempting to create a second " - "volume with size less then remaining space. " - "Aborting...\n"); + pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n"); return 0; } cnt = 0; @@ -6086,6 +6363,7 @@ static int reserve_space(struct supertype *st, int raiddisks, 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) { @@ -6101,7 +6379,8 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, /* Must be a fresh device to add to a container */ return validate_geometry_imsm_container(st, level, layout, raiddisks, - chunk?*chunk:0, size, + *chunk, + size, data_offset, dev, freesize, verbose); } @@ -6125,18 +6404,17 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, created */ if (super->orom && freesize) { int count; - count = count_volumes(super->hba->path, + count = count_volumes(super->hba, super->orom->dpa, verbose); if (super->orom->vphba <= count) { - pr_vrb(": platform does not support more" - " than %d raid volumes.\n", + pr_vrb("platform does not support more than %d raid volumes.\n", super->orom->vphba); return 0; } } if (freesize) return reserve_space(st, raiddisks, size, - chunk?*chunk:0, freesize); + *chunk, freesize); } return 1; } @@ -6144,6 +6422,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, /* creating in a given container */ return validate_geometry_imsm_volume(st, level, layout, raiddisks, chunk, size, + data_offset, dev, freesize, verbose); } @@ -6171,7 +6450,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, dev); return 0; } - sra = sysfs_read(cfd, 0, GET_VERSION); + sra = sysfs_read(cfd, NULL, GET_VERSION); if (sra && sra->array.major_version == -1 && strcmp(sra->text_version, "imsm") == 0) is_member = 1; @@ -6184,11 +6463,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, if (load_super_imsm_all(st, cfd, (void **) &super, NULL, NULL, 1) == 0) { st->sb = super; - st->container_dev = fd2devnum(cfd); + strcpy(st->container_devnm, fd2devnm(cfd)); close(cfd); return validate_geometry_imsm_volume(st, level, layout, raiddisks, chunk, - size, dev, + size, data_offset, dev, freesize, 1) ? 1 : -1; } @@ -6242,7 +6521,7 @@ static int kill_subarray_imsm(struct supertype *st) if (i < current_vol) continue; sprintf(subarray, "%u", i); - if (is_subarray_active(subarray, st->devname)) { + if (is_subarray_active(subarray, st->devnm)) { pr_err("deleting subarray-%d would change the UUID of active subarray-%d, aborting\n", current_vol, i); @@ -6298,7 +6577,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, char *ep; int vol; - if (is_subarray_active(subarray, st->devname)) { + if (is_subarray_active(subarray, st->devnm)) { pr_err("Unable to update name of active subarray\n"); return 2; } @@ -6412,7 +6691,7 @@ static void update_recovery_start(struct intel_super *super, * IMSM_ORD_REBUILD, so assume they are missing and the * disk_ord_tbl was not correctly updated */ - dprintf("%s: failed to locate out-of-sync disk\n", __func__); + dprintf("failed to locate out-of-sync disk\n"); return; } @@ -6446,18 +6725,15 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra /* do not assemble arrays when not all attributes are supported */ if (imsm_check_attributes(mpb->attributes) == 0) { sb_errors = 1; - pr_err("Unsupported attributes in IMSM metadata." - "Arrays activation is blocked.\n"); + pr_err("Unsupported attributes in IMSM metadata.Arrays activation is blocked.\n"); } /* check for bad blocks */ if (imsm_bbm_log_size(super->anchor)) { - pr_err("BBM log found in IMSM metadata." - "Arrays activation is blocked.\n"); + pr_err("BBM log found in IMSM metadata.Arrays activation is blocked.\n"); sb_errors = 1; } - /* count spare devices, not used in maps */ for (d = super->disks; d; d = d->next) @@ -6488,8 +6764,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra */ if (dev->vol.migr_state && (migr_type(dev) == MIGR_STATE_CHANGE)) { - pr_err("cannot assemble volume '%.16s':" - " unsupported migration in progress\n", + pr_err("cannot assemble volume '%.16s': unsupported migration in progress\n", dev->volume); continue; } @@ -6511,8 +6786,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra map->num_members, /* raid disks */ &chunk, join_u32(dev->size_low, dev->size_high), 1 /* verbose */)) { - pr_err("IMSM RAID geometry validation" - " failed. Array %s activation is blocked.\n", + pr_err("IMSM RAID geometry validation failed. Array %s activation is blocked.\n", dev->volume); this->array.state |= (1<map_state == IMSM_T_STATE_UNINITIALIZED ? + return map->map_state == IMSM_T_STATE_UNINITIALIZED ? IMSM_T_STATE_UNINITIALIZED : IMSM_T_STATE_NORMAL; switch (get_imsm_raid_level(map)) { @@ -6642,7 +6915,7 @@ static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, struct imsm_disk *disk; /* reset the potential in-sync count on even-numbered - * slots. num_copies is always 2 for imsm raid10 + * slots. num_copies is always 2 for imsm raid10 */ if ((i & 1) == 0) insync = 2; @@ -6735,8 +7008,7 @@ static int imsm_open_new(struct supertype *c, struct active_array *a, struct imsm_super *mpb = super->anchor; if (atoi(inst) >= mpb->num_raid_devs) { - fprintf(stderr, "%s: subarry index %d, out of range\n", - __func__, atoi(inst)); + pr_err("subarry index %d, out of range\n", atoi(inst)); return -ENODEV; } @@ -6833,6 +7105,12 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev) if (!super->missing) return; + /* When orom adds replacement for missing disk it does + * not remove entry of missing disk, but just updates map with + * new added disk. So it is not enough just to test if there is + * any missing disk, we have to look if there are any failed disks + * in map to stop migration */ + dprintf("imsm: mark missing\n"); /* end process for initialization and rebuild only */ @@ -6843,7 +7121,8 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev) failed = imsm_count_failed(super, dev, MAP_0); map_state = imsm_check_degraded(super, dev, failed, MAP_0); - end_migration(dev, super, map_state); + if (failed) + end_migration(dev, super, map_state); } for (dl = super->missing; dl; dl = dl->next) mark_missing(dev, &dl->disk, dl->index); @@ -7108,7 +7387,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state) __u8 map_state; if (n > map->num_members) - fprintf(stderr, "imsm: set_disk %d out of range 0..%d\n", + pr_err("imsm: set_disk %d out of range 0..%d\n", n, map->num_members - 1); if (n < 0) @@ -7142,7 +7421,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state) case IMSM_T_STATE_NORMAL: /* transition to normal state */ dprintf("normal: "); if (is_rebuilding(dev)) { - dprintf("while rebuilding"); + dprintf_cont("while rebuilding"); /* check if recovery is really finished */ for (mdi = a->info.devs; mdi ; mdi = mdi->next) if (mdi->recovery_start != MaxSector) { @@ -7150,8 +7429,8 @@ static void imsm_set_disk(struct active_array *a, int n, int state) break; } if (recovery_not_finished) { - dprintf("\nimsm: Rebuild has not finished yet, " - "state not changed"); + dprintf_cont("\n"); + dprintf("Rebuild has not finished yet, state not changed"); if (a->last_checkpoint < mdi->recovery_start) { a->last_checkpoint = mdi->recovery_start; super->updates_pending++; @@ -7166,7 +7445,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state) break; } if (is_gen_migration(dev)) { - dprintf("while general migration"); + dprintf_cont("while general migration"); if (a->last_checkpoint >= a->info.component_size) end_migration(dev, super, map_state); else @@ -7178,26 +7457,26 @@ static void imsm_set_disk(struct active_array *a, int n, int state) } break; case IMSM_T_STATE_DEGRADED: /* transition to degraded state */ - dprintf("degraded: "); + dprintf_cont("degraded: "); if ((map->map_state != map_state) && !dev->vol.migr_state) { - dprintf("mark degraded"); + dprintf_cont("mark degraded"); map->map_state = map_state; super->updates_pending++; a->last_checkpoint = 0; break; } if (is_rebuilding(dev)) { - dprintf("while rebuilding."); + dprintf_cont("while rebuilding."); if (map->map_state != map_state) { - dprintf(" Map state change"); + dprintf_cont(" Map state change"); end_migration(dev, super, map_state); super->updates_pending++; } break; } if (is_gen_migration(dev)) { - dprintf("while general migration"); + dprintf_cont("while general migration"); if (a->last_checkpoint >= a->info.component_size) end_migration(dev, super, map_state); else { @@ -7208,22 +7487,22 @@ static void imsm_set_disk(struct active_array *a, int n, int state) break; } if (is_initializing(dev)) { - dprintf("while initialization."); + dprintf_cont("while initialization."); map->map_state = map_state; super->updates_pending++; break; } break; case IMSM_T_STATE_FAILED: /* transition to failed state */ - dprintf("failed: "); + dprintf_cont("failed: "); if (is_gen_migration(dev)) { - dprintf("while general migration"); + dprintf_cont("while general migration"); map->map_state = map_state; super->updates_pending++; break; } if (map->map_state != map_state) { - dprintf("mark failed"); + dprintf_cont("mark failed"); end_migration(dev, super, map_state); super->updates_pending++; a->last_checkpoint = 0; @@ -7231,10 +7510,9 @@ static void imsm_set_disk(struct active_array *a, int n, int state) } break; default: - dprintf("state %i\n", map_state); + dprintf_cont("state %i\n", map_state); } - dprintf("\n"); - + dprintf_cont("\n"); } static int store_imsm_mpb(int fd, struct imsm_super *mpb) @@ -7296,7 +7574,7 @@ static struct dl *imsm_readd(struct intel_super *super, int idx, struct active_a dl = NULL; if (dl) - dprintf("%s: found %x:%x\n", __func__, dl->major, dl->minor); + dprintf("found %x:%x\n", dl->major, dl->minor); return dl; } @@ -7412,7 +7690,6 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot, return dl; } - static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed) { struct imsm_dev *dev2; @@ -7498,8 +7775,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, /* Cannot activate another spare if rebuild is in progress already */ if (is_rebuilding(dev)) { - dprintf("imsm: No spare activation allowed. " - "Rebuild in progress already.\n"); + dprintf("imsm: No spare activation allowed. Rebuild in progress already.\n"); return NULL; } @@ -7513,14 +7789,18 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, IMSM_T_STATE_DEGRADED) return NULL; + if (get_imsm_map(dev, MAP_0)->map_state == IMSM_T_STATE_UNINITIALIZED) { + dprintf("imsm: No spare activation allowed. Volume is not initialized.\n"); + return NULL; + } + /* * If there are any failed disks check state of the other volume. * Block rebuild if the another one is failed until failed disks * are removed from container. */ if (failed) { - dprintf("found failed disks in %.*s, check if there another" - "failed sub-array.\n", + dprintf("found failed disks in %.*s, check if there anotherfailed sub-array.\n", MAX_RAID_SERIAL_LEN, dev->volume); /* check if states of the other volumes allow for rebuild */ for (i = 0; i < super->anchor->num_raid_devs; i++) { @@ -7556,7 +7836,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, dl = imsm_add_spare(super, i, a, 1, rv); if (!dl) continue; - + /* found a usable disk with enough space */ di = xcalloc(1, sizeof(*di)); @@ -7597,7 +7877,7 @@ static struct mdinfo *imsm_activate_spare(struct active_array *a, * disk_ord_tbl for the array */ mu = xmalloc(sizeof(*mu)); - mu->buf = xcalloc(num_spares, + mu->buf = xcalloc(num_spares, sizeof(struct imsm_update_activate_spare)); mu->space = NULL; mu->space_list = NULL; @@ -7640,10 +7920,10 @@ static int disks_overlap(struct intel_super *super, int idx, struct imsm_update_ return 0; } - static struct dl *get_disk_super(struct intel_super *super, int major, int minor) { - struct dl *dl = NULL; + struct dl *dl; + for (dl = super->disks; dl; dl = dl->next) if ((dl->major == major) && (dl->minor == minor)) return dl; @@ -7652,7 +7932,7 @@ static struct dl *get_disk_super(struct intel_super *super, int major, int minor static int remove_disk_super(struct intel_super *super, int major, int minor) { - struct dl *prev = NULL; + struct dl *prev; struct dl *dl; prev = NULL; @@ -7665,8 +7945,7 @@ static int remove_disk_super(struct intel_super *super, int major, int minor) super->disks = dl->next; dl->next = NULL; __free_imsm_disk(dl); - dprintf("%s: removed %x:%x\n", - __func__, major, minor); + dprintf("removed %x:%x\n", major, minor); break; } prev = dl; @@ -7679,7 +7958,8 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind static int add_remove_disk_update(struct intel_super *super) { int check_degraded = 0; - struct dl *disk = NULL; + struct dl *disk; + /* add/remove some spares to/from the metadata/contrainer */ while (super->disk_mgmt_list) { struct dl *disk_cfg; @@ -7692,9 +7972,8 @@ static int add_remove_disk_update(struct intel_super *super) disk_cfg->next = super->disks; super->disks = disk_cfg; check_degraded = 1; - dprintf("%s: added %x:%x\n", - __func__, disk_cfg->major, - disk_cfg->minor); + dprintf("added %x:%x\n", + disk_cfg->major, disk_cfg->minor); } else if (disk_cfg->action == DISK_REMOVE) { dprintf("Disk remove action processed: %x.%x\n", disk_cfg->major, disk_cfg->minor); @@ -7718,7 +7997,6 @@ static int add_remove_disk_update(struct intel_super *super) return check_degraded; } - static int apply_reshape_migration_update(struct imsm_update_reshape_migration *u, struct intel_super *super, void ***space_list) @@ -7727,7 +8005,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * void **tofree = NULL; int ret_val = 0; - dprintf("apply_reshape_migration_update()\n"); + dprintf("(enter)\n"); if ((u->subdev < 0) || (u->subdev > 1)) { dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev); @@ -7805,8 +8083,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration * new_disk = get_disk_super(super, major(u->new_disks[0]), minor(u->new_disks[0])); - dprintf("imsm: new disk for reshape is: %i:%i " - "(%p, index = %i)\n", + dprintf("imsm: new disk for reshape is: %i:%i (%p, index = %i)\n", major(u->new_disks[0]), minor(u->new_disks[0]), new_disk, new_disk->index); @@ -7847,7 +8124,7 @@ static int apply_size_change_update(struct imsm_update_size_change *u, struct intel_dev *id; int ret_val = 0; - dprintf("apply_size_change_update()\n"); + dprintf("(enter)\n"); if ((u->subdev < 0) || (u->subdev > 1)) { dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev); @@ -7864,8 +8141,7 @@ static int apply_size_change_update(struct imsm_update_size_change *u, /* calculate new size */ blocks_per_member = u->new_size / used_disks; - dprintf("imsm: apply_size_change_update(size: %llu, " - "blocks per member: %llu)\n", + dprintf("(size: %llu, blocks per member: %llu)\n", u->new_size, blocks_per_member); set_blocks_per_member(map, blocks_per_member); imsm_set_array_size(dev, u->new_size); @@ -7878,7 +8154,6 @@ static int apply_size_change_update(struct imsm_update_size_change *u, return ret_val; } - static int apply_update_activate_spare(struct imsm_update_activate_spare *u, struct intel_super *super, struct active_array *active_array) @@ -7908,8 +8183,7 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u, break; if (!dl) { - fprintf(stderr, "error: imsm_activate_spare passed " - "an unknown disk (index: %d)\n", + pr_err("error: imsm_activate_spare passed an unknown disk (index: %d)\n", u->dl->index); return 0; } @@ -8009,15 +8283,14 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u, int ret_val = 0; unsigned int dev_id; - dprintf("imsm: apply_reshape_container_disks_update()\n"); + dprintf("(enter)\n"); /* enable spares to use in array */ for (i = 0; i < delta_disks; i++) { new_disk = get_disk_super(super, major(u->new_disks[i]), minor(u->new_disks[i])); - dprintf("imsm: new disk for reshape is: %i:%i " - "(%p, index = %i)\n", + dprintf("imsm: new disk for reshape is: %i:%i (%p, index = %i)\n", major(u->new_disks[i]), minor(u->new_disks[i]), new_disk, new_disk->index); if ((new_disk == NULL) || @@ -8214,9 +8487,9 @@ static void imsm_process_update(struct supertype *st, * the arrays for general migration and convert selected spares * into active devices. * update_activate_spare - a spare device has replaced a failed - * device in an array, update the disk_ord_tbl. If this disk is - * present in all member arrays then also clear the SPARE_DISK - * flag + * device in an array, update the disk_ord_tbl. If this disk is + * present in all member arrays then also clear the SPARE_DISK + * flag * update_create_array * update_kill_array * update_rename_array @@ -8250,8 +8523,7 @@ static void imsm_process_update(struct supertype *st, struct imsm_update_general_migration_checkpoint *u = (void *)update->buf; - dprintf("imsm: process_update() " - "for update_general_migration_checkpoint called\n"); + dprintf("called for update_general_migration_checkpoint\n"); /* find device under general migration */ for (id = super->devlist ; id; id = id->next) { @@ -8293,7 +8565,7 @@ static void imsm_process_update(struct supertype *st, break; } case update_activate_spare: { - struct imsm_update_activate_spare *u = (void *) update->buf; + struct imsm_update_activate_spare *u = (void *) update->buf; if (apply_update_activate_spare(u, super, st->arrays)) super->updates_pending++; break; @@ -8320,15 +8592,14 @@ static void imsm_process_update(struct supertype *st, /* handle racing creates: first come first serve */ if (u->dev_idx < mpb->num_raid_devs) { - dprintf("%s: subarray %d already defined\n", - __func__, u->dev_idx); + dprintf("subarray %d already defined\n", u->dev_idx); goto create_error; } /* check update is next in sequence */ if (u->dev_idx != mpb->num_raid_devs) { - dprintf("%s: can not create array %d expected index %d\n", - __func__, u->dev_idx, mpb->num_raid_devs); + dprintf("can not create array %d expected index %d\n", + u->dev_idx, mpb->num_raid_devs); goto create_error; } @@ -8353,14 +8624,14 @@ static void imsm_process_update(struct supertype *st, continue; if (disks_overlap(super, i, u)) { - dprintf("%s: arrays overlap\n", __func__); + dprintf("arrays overlap\n"); goto create_error; } } /* check that prepare update was successful */ if (!update->space) { - dprintf("%s: prepare update failed\n", __func__); + dprintf("prepare update failed\n"); goto create_error; } @@ -8372,7 +8643,7 @@ static void imsm_process_update(struct supertype *st, for (i = 0; i < new_map->num_members; i++) { dl = serial_to_dl(inf[i].serial, super); if (!dl) { - dprintf("%s: disk disappeared\n", __func__); + dprintf("disk disappeared\n"); goto create_error; } } @@ -8478,7 +8749,7 @@ static void imsm_process_update(struct supertype *st, } case update_add_remove_disk: { /* we may be able to repair some arrays if disks are - * being added, check teh status of add_remove_disk + * being added, check the status of add_remove_disk * if discs has been added. */ if (add_remove_disk_update(super)) { @@ -8491,15 +8762,14 @@ static void imsm_process_update(struct supertype *st, break; } default: - fprintf(stderr, "error: unsuported process update type:" - "(type: %d)\n", type); + pr_err("error: unsuported process update type:(type: %d)\n", type); } } static struct mdinfo *get_spares_for_grow(struct supertype *st); -static void imsm_prepare_update(struct supertype *st, - struct metadata_update *update) +static int imsm_prepare_update(struct supertype *st, + struct metadata_update *update) { /** * Allocate space to hold new disk entries, raid-device entries or a new @@ -8508,19 +8778,27 @@ static void imsm_prepare_update(struct supertype *st, * integrated by the monitor thread without worrying about live pointers * in the manager thread. */ - enum imsm_update_type type = *(enum imsm_update_type *) update->buf; + enum imsm_update_type type; struct intel_super *super = st->sb; struct imsm_super *mpb = super->anchor; size_t buf_len; size_t len = 0; + if (update->len < (int)sizeof(type)) + return 0; + + type = *(enum imsm_update_type *) update->buf; + switch (type) { case update_general_migration_checkpoint: - dprintf("imsm: prepare_update() " - "for update_general_migration_checkpoint called\n"); + if (update->len < (int)sizeof(struct imsm_update_general_migration_checkpoint)) + return 0; + dprintf("called for update_general_migration_checkpoint\n"); break; case update_takeover: { struct imsm_update_takeover *u = (void *)update->buf; + if (update->len < (int)sizeof(*u)) + return 0; if (u->direction == R0_TO_R10) { void **tail = (void **)&update->space_list; struct imsm_dev *dev = get_imsm_dev(super, u->subarray); @@ -8561,7 +8839,10 @@ static void imsm_prepare_update(struct supertype *st, struct intel_dev *dl; void **space_tail = (void**)&update->space_list; - dprintf("imsm: imsm_prepare_update() for update_reshape\n"); + if (update->len < (int)sizeof(*u)) + return 0; + + dprintf("for update_reshape\n"); for (dl = super->devlist; dl; dl = dl->next) { int size = sizeof_imsm_dev(dl->dev, 1); @@ -8593,7 +8874,10 @@ static void imsm_prepare_update(struct supertype *st, void *s; int current_level = -1; - dprintf("imsm: imsm_prepare_update() for update_reshape\n"); + if (update->len < (int)sizeof(*u)) + return 0; + + dprintf("for update_reshape\n"); /* add space for bigger array in update */ @@ -8660,6 +8944,13 @@ static void imsm_prepare_update(struct supertype *st, break; } case update_size_change: { + if (update->len < (int)sizeof(struct imsm_update_size_change)) + return 0; + break; + } + case update_activate_spare: { + if (update->len < (int)sizeof(struct imsm_update_activate_spare)) + return 0; break; } case update_create_array: { @@ -8672,6 +8963,9 @@ static void imsm_prepare_update(struct supertype *st, int i; int activate = 0; + if (update->len < (int)sizeof(*u)) + return 0; + inf = get_disk_info(u); len = sizeof_imsm_dev(dev, 1); /* allocate a new super->devlist entry */ @@ -8693,9 +8987,22 @@ static void imsm_prepare_update(struct supertype *st, } len += activate * sizeof(struct imsm_disk); break; - default: + } + case update_kill_array: { + if (update->len < (int)sizeof(struct imsm_update_kill_array)) + return 0; + break; + } + case update_rename_array: { + if (update->len < (int)sizeof(struct imsm_update_rename_array)) + return 0; break; } + case update_add_remove_disk: + /* no update->len needed */ + break; + default: + return 0; } /* check if we need a larger metadata buffer */ @@ -8719,6 +9026,7 @@ static void imsm_prepare_update(struct supertype *st, else super->next_buf = NULL; } + return 1; } /* must be called while manager is quiesced */ @@ -8731,8 +9039,7 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind int i, j, num_members; __u32 ord; - dprintf("%s: deleting device[%d] from imsm_super\n", - __func__, index); + dprintf("deleting device[%d] from imsm_super\n", index); /* shift all indexes down one */ for (iter = super->disks; iter; iter = iter->next) @@ -8842,7 +9149,6 @@ static int imsm_get_allowed_degradation(int level, int raid_disks, } } - /******************************************************************************* * Function: open_backup_targets * Description: Function opens file descriptors for all devices given in @@ -8883,7 +9189,7 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds, sd->disk.minor, 1); raid_fds[sd->disk.raid_disk] = dev_open(dn, O_RDWR); if (raid_fds[sd->disk.raid_disk] < 0) { - fprintf(stderr, "cannot open component\n"); + pr_err("cannot open component\n"); continue; } opened++; @@ -8894,13 +9200,90 @@ int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds, imsm_get_allowed_degradation(info->new_level, raid_disks, super, dev)) { - fprintf(stderr, "Not enough disks can be opened.\n"); + pr_err("Not enough disks can be opened.\n"); close_targets(raid_fds, raid_disks); return -2; } return 0; } +/******************************************************************************* + * Function: validate_container_imsm + * Description: This routine validates container after assemble, + * eg. if devices in container are under the same controller. + * + * Parameters: + * info : linked list with info about devices used in array + * Returns: + * 1 : HBA mismatch + * 0 : Success + ******************************************************************************/ +int validate_container_imsm(struct mdinfo *info) +{ + if (check_env("IMSM_NO_PLATFORM")) + return 0; + + struct sys_dev *idev; + struct sys_dev *hba = NULL; + struct sys_dev *intel_devices = find_intel_devices(); + char *dev_path = devt_to_devpath(makedev(info->disk.major, + info->disk.minor)); + + for (idev = intel_devices; idev; idev = idev->next) { + if (dev_path && strstr(dev_path, idev->path)) { + hba = idev; + break; + } + } + if (dev_path) + free(dev_path); + + if (!hba) { + pr_err("WARNING - Cannot detect HBA for device %s!\n", + devid2kname(makedev(info->disk.major, info->disk.minor))); + return 1; + } + + const struct imsm_orom *orom = get_orom_by_device_id(hba->dev_id); + struct mdinfo *dev; + + for (dev = info->next; dev; dev = dev->next) { + dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.minor)); + + struct sys_dev *hba2 = NULL; + for (idev = intel_devices; idev; idev = idev->next) { + if (dev_path && strstr(dev_path, idev->path)) { + hba2 = idev; + break; + } + } + if (dev_path) + free(dev_path); + + const struct imsm_orom *orom2 = hba2 == NULL ? NULL : + get_orom_by_device_id(hba2->dev_id); + + if (hba2 && hba->type != hba2->type) { + pr_err("WARNING - HBAs of devices do not match %s != %s\n", + get_sys_dev_type(hba->type), get_sys_dev_type(hba2->type)); + return 1; + } + + 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 (!orom) { + pr_err("WARNING - IMSM container assembled with disks under HBAs without IMSM platform support!\n" + " This operation is not supported and can lead to data loss.\n"); + return 1; + } + } + + return 0; +} #ifndef MDASSEMBLE /******************************************************************************* * Function: init_migr_record_imsm @@ -8954,7 +9337,6 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev, migr_rec->post_migr_vol_cap = dev->size_low; migr_rec->post_migr_vol_cap_hi = dev->size_high; - /* Find the smallest dev */ for (sd = info->devs ; sd ; sd = sd->next) { sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor); @@ -8999,8 +9381,8 @@ int save_backup_imsm(struct supertype *st, { int rv = -1; struct intel_super *super = st->sb; - unsigned long long *target_offsets = NULL; - int *targets = NULL; + unsigned long long *target_offsets; + int *targets; int i; struct imsm_map *map_dest = get_imsm_map(dev, MAP_0); int new_disks = map_dest->num_members; @@ -9081,8 +9463,7 @@ int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state) unsigned long long curr_migr_unit; if (load_imsm_migr_rec(super, info) != 0) { - dprintf("imsm: ERROR: Cannot read migration record " - "for checkpoint save.\n"); + dprintf("imsm: ERROR: Cannot read migration record for checkpoint save.\n"); return 1; } @@ -9106,8 +9487,7 @@ int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state) __cpu_to_le32(curr_migr_unit * __le32_to_cpu(super->migr_rec->dest_depth_per_unit)); if (write_imsm_migr_rec(st) < 0) { - dprintf("imsm: Cannot write migration record " - "outside backup area\n"); + dprintf("imsm: Cannot write migration record outside backup area\n"); return 1; } @@ -9129,7 +9509,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info) { struct intel_super *super = st->sb; struct migr_record *migr_rec = super->migr_rec; - struct imsm_map *map_dest = NULL; + struct imsm_map *map_dest; struct intel_dev *id = NULL; unsigned long long read_offset; unsigned long long write_offset; @@ -9218,16 +9598,14 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info) new_disks, super, id->dev)) { - pr_err("Cannot restore data from backup." - " Too many failed disks\n"); + pr_err("Cannot restore data from backup. Too many failed disks\n"); goto abort; } if (save_checkpoint_imsm(st, info, UNIT_SRC_NORMAL)) { /* ignore error == 2, this can mean end of reshape here */ - dprintf("imsm: Cannot write checkpoint to " - "migration record (UNIT_SRC_NORMAL) during restart\n"); + dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_NORMAL) during restart\n"); } else retval = 0; @@ -9250,11 +9628,11 @@ static const char *imsm_get_disk_controller_domain(const char *path) char *drv=NULL; struct stat st; - strncpy(disk_path, disk_by_path, PATH_MAX - 1); + strcpy(disk_path, disk_by_path); strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1); if (stat(disk_path, &st) == 0) { struct sys_dev* hba; - char *path=NULL; + char *path; path = devt_to_devpath(st.st_rdev); if (path == NULL) @@ -9264,30 +9642,29 @@ static const char *imsm_get_disk_controller_domain(const char *path) drv = "isci"; else if (hba && hba->type == SYS_DEV_SATA) drv = "ahci"; - else + else drv = "unknown"; dprintf("path: %s hba: %s attached: %s\n", path, (hba) ? hba->path : "NULL", drv); free(path); - if (hba) - free_sys_dev(&hba); } return drv; } -static int imsm_find_array_minor_by_subdev(int subdev, int container, int *minor) +static char *imsm_find_array_devnm_by_subdev(int subdev, char *container) { + static char devnm[32]; char subdev_name[20]; struct mdstat_ent *mdstat; sprintf(subdev_name, "%d", subdev); mdstat = mdstat_by_subdev(subdev_name, container); if (!mdstat) - return -1; + return NULL; - *minor = mdstat->devnum; + strcpy(devnm, mdstat->devnm); free_mdstat(mdstat); - return 0; + return devnm; } static int imsm_reshape_is_allowed_on_container(struct supertype *st, @@ -9303,30 +9680,25 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, struct mdinfo *info, *member; int devices_that_can_grow = 0; - dprintf("imsm: imsm_reshape_is_allowed_on_container(ENTER): " - "st->devnum = (%i)\n", - st->devnum); + dprintf("imsm: imsm_reshape_is_allowed_on_container(ENTER): st->devnm = (%s)\n", st->devnm); if (geo->size > 0 || geo->level != UnSet || geo->layout != UnSet || geo->chunksize != 0 || geo->raid_disks == UnSet) { - dprintf("imsm: Container operation is allowed for " - "raid disks number change only.\n"); + dprintf("imsm: Container operation is allowed for raid disks number change only.\n"); return ret_val; } if (direction == ROLLBACK_METADATA_CHANGES) { - dprintf("imsm: Metadata changes rollback is not supported for " - "container operation.\n"); + dprintf("imsm: Metadata changes rollback is not supported for container operation.\n"); return ret_val; } info = container_content_imsm(st, NULL); for (member = info; member; member = member->next) { - int result; - int minor; + char *result; dprintf("imsm: checking device_num: %i\n", member->container_member); @@ -9335,8 +9707,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, /* we work on container for Online Capacity Expansion * only so raid_disks has to grow */ - dprintf("imsm: for container operation raid disks " - "increase is required\n"); + dprintf("imsm: for container operation raid disks increase is required\n"); break; } @@ -9344,8 +9715,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, (info->array.level != 5)) { /* we cannot use this container with other raid level */ - dprintf("imsm: for container operation wrong" - " raid level (%i) detected\n", + dprintf("imsm: for container operation wrong raid level (%i) detected\n", info->array.level); break; } else { @@ -9356,8 +9726,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, if (!is_raid_level_supported(super->orom, member->array.level, geo->raid_disks)) { - dprintf("platform does not support raid%d with" - " %d disk%s\n", + dprintf("platform does not support raid%d with %d disk%s\n", info->array.level, geo->raid_disks, geo->raid_disks > 1 ? "s" : ""); @@ -9367,8 +9736,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, */ if (info->component_size % (info->array.chunk_size/512)) { - dprintf("Component size is not aligned to " - "chunk size\n"); + dprintf("Component size is not aligned to chunk size\n"); break; } } @@ -9383,10 +9751,9 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, * so they need to be assembled. We have already * checked that no recovery etc is happening. */ - result = imsm_find_array_minor_by_subdev(member->container_member, - st->container_dev, - &minor); - if (result < 0) { + result = imsm_find_array_devnm_by_subdev(member->container_member, + st->container_devnm); + if (result == NULL) { dprintf("imsm: cannot find array\n"); break; } @@ -9397,19 +9764,19 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, ret_val = 1; if (ret_val) - dprintf("\tContainer operation allowed\n"); + dprintf("Container operation allowed\n"); else - dprintf("\tError: %i\n", ret_val); + dprintf("Error: %i\n", ret_val); return ret_val; } /* Function: get_spares_for_grow * Description: Allocates memory and creates list of spare devices - * avaliable in container. Checks if spare drive size is acceptable. + * avaliable in container. Checks if spare drive size is acceptable. * Parameters: Pointer to the supertype structure * Returns: Pointer to the list of spare devices (mdinfo structure) on success, - * NULL if fail + * NULL if fail */ static struct mdinfo *get_spares_for_grow(struct supertype *st) { @@ -9430,15 +9797,14 @@ static int imsm_create_metadata_update_for_reshape( { struct intel_super *super = st->sb; struct imsm_super *mpb = super->anchor; - int update_memory_size = 0; - struct imsm_update_reshape *u = NULL; - struct mdinfo *spares = NULL; + int update_memory_size; + struct imsm_update_reshape *u; + struct mdinfo *spares; int i; - int delta_disks = 0; + int delta_disks; struct mdinfo *dev; - dprintf("imsm_update_metadata_for_reshape(enter) raid_disks = %i\n", - geo->raid_disks); + dprintf("(enter) raid_disks = %i\n", geo->raid_disks); delta_disks = geo->raid_disks - old_raid_disks; @@ -9459,8 +9825,7 @@ static int imsm_create_metadata_update_for_reshape( if (spares == NULL || delta_disks > spares->array.spare_disks) { - pr_err("imsm: ERROR: Cannot get spare devices " - "for %s.\n", geo->dev_name); + pr_err("imsm: ERROR: Cannot get spare devices for %s.\n", geo->dev_name); i = -1; goto abort; } @@ -9492,17 +9857,16 @@ abort: dprintf("imsm: reshape update preparation :"); if (i == delta_disks) { - dprintf(" OK\n"); + dprintf_cont(" OK\n"); *updatep = u; return update_memory_size; } free(u); - dprintf(" Error\n"); + dprintf_cont(" Error\n"); return 0; } - /****************************************************************************** * function: imsm_create_metadata_update_for_size_change() * Creates update for IMSM array for array size change. @@ -9514,11 +9878,10 @@ static int imsm_create_metadata_update_for_size_change( struct imsm_update_size_change **updatep) { struct intel_super *super = st->sb; - int update_memory_size = 0; - struct imsm_update_size_change *u = NULL; + int update_memory_size; + struct imsm_update_size_change *u; - dprintf("imsm_create_metadata_update_for_size_change(enter)" - " New size = %llu\n", geo->size); + dprintf("(enter) New size = %llu\n", geo->size); /* size of all update data without anchor */ update_memory_size = sizeof(struct imsm_update_size_change); @@ -9545,13 +9908,12 @@ static int imsm_create_metadata_update_for_migration( struct imsm_update_reshape_migration **updatep) { struct intel_super *super = st->sb; - int update_memory_size = 0; - struct imsm_update_reshape_migration *u = NULL; + int update_memory_size; + struct imsm_update_reshape_migration *u; struct imsm_dev *dev; int previous_level = -1; - dprintf("imsm_create_metadata_update_for_migration(enter)" - " New Level = %i\n", geo->level); + dprintf("(enter) New Level = %i\n", geo->level); /* size of all update data without anchor */ update_memory_size = sizeof(struct imsm_update_reshape_migration); @@ -9576,8 +9938,7 @@ static int imsm_create_metadata_update_for_migration( if (geo->chunksize != current_chunk_size) { u->new_chunksize = geo->chunksize / 1024; - dprintf("imsm: " - "chunk size change from %i to %i\n", + dprintf("imsm: chunk size change from %i to %i\n", current_chunk_size, u->new_chunksize); } previous_level = map->raid_level; @@ -9592,8 +9953,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"); + dprintf("error: cannot get spare device for requested migration"); return 0; } sysfs_free(spares); @@ -9614,8 +9974,8 @@ static void imsm_update_metadata_locally(struct supertype *st, mu.space = NULL; mu.space_list = NULL; mu.next = NULL; - imsm_prepare_update(st, &mu); - imsm_process_update(st, &mu); + if (imsm_prepare_update(st, &mu)) + imsm_process_update(st, &mu); while (mu.space_list) { void **space = mu.space_list; @@ -9627,7 +9987,7 @@ static void imsm_update_metadata_locally(struct supertype *st, /*************************************************************************** * Function: imsm_analyze_change * Description: Function analyze change for single volume -* and validate if transition is supported +* and validate if transition is supported * Parameters: Geometry parameters, supertype structure, * metadata change direction (apply/rollback) * Returns: Operation type code on success, -1 if fail @@ -9661,9 +10021,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, if (geo->level == 5) { change = CH_MIGRATION; if (geo->layout != ALGORITHM_LEFT_ASYMMETRIC) { - pr_err("Error. Requested Layout " - "not supported (left-asymmetric layout " - "is supported only)!\n"); + pr_err("Error. Requested Layout not supported (left-asymmetric layout is supported only)!\n"); change = -1; goto analyse_change_exit; } @@ -9688,8 +10046,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, break; } if (change == -1) { - pr_err("Error. Level Migration from %d to %d " - "not supported!\n", + pr_err("Error. Level Migration from %d to %d not supported!\n", info.array.level, geo->level); goto analyse_change_exit; } @@ -9710,8 +10067,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, geo->layout = 0; geo->level = 5; } else { - pr_err("Error. Layout Migration from %d to %d " - "not supported!\n", + pr_err("Error. Layout Migration from %d to %d not supported!\n", info.array.layout, geo->layout); change = -1; goto analyse_change_exit; @@ -9744,19 +10100,22 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, get_imsm_raid_level(dev->vol.map), chunk * 1024, geo->size * 2); + if (geo->size == 0) { + pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is 0).\n", + current_size); + goto analyse_change_exit; + } } if ((current_size != geo->size) && (geo->size > 0)) { if (change != -1) { - pr_err("Error. Size change should be the only " - "one at a time.\n"); + pr_err("Error. Size change should be the only one at a time.\n"); change = -1; goto analyse_change_exit; } if ((super->current_vol + 1) != super->anchor->num_raid_devs) { - pr_err("Error. The last volume in container " - "can be expanded only (%i/%i).\n", - super->current_vol, st->devnum); + pr_err("Error. The last volume in container can be expanded only (%i/%s).\n", + super->current_vol, st->devnm); goto analyse_change_exit; } /* check the maximum available size @@ -9780,8 +10139,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, /* requested size change to the maximum available size */ if (max_size == 0) { - pr_err("Error. Cannot find " - "maximum available space.\n"); + pr_err("Error. Cannot find maximum available space.\n"); change = -1; goto analyse_change_exit; } else @@ -9799,17 +10157,12 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, dprintf("Prepare update for size change to %llu\n", geo->size ); if (current_size >= geo->size) { - pr_err("Error. Size expansion is " - "supported only (current size is %llu, " - "requested size /rounded/ is %llu).\n", + pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is %llu).\n", current_size, geo->size); goto analyse_change_exit; } if (max_size && geo->size > max_size) { - pr_err("Error. Requested size is larger " - "than maximum available size (maximum " - "available size is %llu, " - "requested size /rounded/ is %llu).\n", + pr_err("Error. Requested size is larger than maximum available size (maximum available size is %llu, requested size /rounded/ is %llu).\n", max_size, geo->size); goto analyse_change_exit; } @@ -9823,7 +10176,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, imsm_layout, geo->raid_disks + devNumChange, &chunk, - geo->size, + geo->size, INVALID_SECTORS, 0, 0, 1)) change = -1; @@ -9832,9 +10185,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, struct imsm_super *mpb = super->anchor; if (mpb->num_raid_devs > 1) { - pr_err("Error. Cannot perform operation on %s" - "- for this operation it MUST be single " - "array in container\n", + pr_err("Error. Cannot perform operation on %s- for this operation it MUST be single array in container\n", geo->dev_name); change = -1; } @@ -9843,8 +10194,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, analyse_change_exit: if ((direction == ROLLBACK_METADATA_CHANGES) && ((change == CH_MIGRATION) || (change == CH_TAKEOVER))) { - dprintf("imsm: Metadata changes rollback is not supported for " - "migration and takeover operations.\n"); + dprintf("imsm: Metadata changes rollback is not supported for migration and takeover operations.\n"); change = -1; } return change; @@ -9890,12 +10240,12 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, int ret_val = 1; struct geo_params geo; - dprintf("imsm: reshape_super called.\n"); + dprintf("(enter)\n"); memset(&geo, 0, sizeof(struct geo_params)); geo.dev_name = dev; - geo.dev_id = st->devnum; + strcpy(geo.devnm, st->devnm); geo.size = size; geo.level = level; geo.layout = layout; @@ -9904,13 +10254,13 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, if (delta_disks != UnSet) geo.raid_disks += delta_disks; - dprintf("\tfor level : %i\n", geo.level); - dprintf("\tfor raid_disks : %i\n", geo.raid_disks); + dprintf("for level : %i\n", geo.level); + dprintf("for raid_disks : %i\n", geo.raid_disks); if (experimental() == 0) return ret_val; - if (st->container_dev == st->devnum) { + if (strcmp(st->container_devnm, st->devnm) == 0) { /* On container level we can only increase number of devices. */ dprintf("imsm: info: Container operation\n"); int old_raid_disks = 0; @@ -9938,8 +10288,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, free(u); } else { - pr_err("(imsm) Operation " - "is not allowed on this container\n"); + pr_err("(imsm) Operation is not allowed on this container\n"); } } else { /* On volume level we support following operations @@ -9949,19 +10298,20 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, */ struct intel_super *super = st->sb; struct intel_dev *dev = super->devlist; - int change, devnum; + int change; dprintf("imsm: info: Volume operation\n"); /* find requested device */ while (dev) { - if (imsm_find_array_minor_by_subdev( - dev->index, st->container_dev, &devnum) == 0 - && devnum == geo.dev_id) + char *devnm = + imsm_find_array_devnm_by_subdev( + dev->index, st->container_devnm); + if (devnm && strcmp(devnm, geo.devnm) == 0) break; dev = dev->next; } if (dev == NULL) { - pr_err("Cannot find %s (%i) subarray\n", - geo.dev_name, geo.dev_id); + pr_err("Cannot find %s (%s) subarray\n", + geo.dev_name, geo.devnm); goto exit_imsm_reshape_super; } super->current_vol = dev->index; @@ -9976,8 +10326,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, imsm_create_metadata_update_for_migration( st, &geo, &u); if (len < 1) { - dprintf("imsm: " - "Cannot prepare update\n"); + dprintf("imsm: Cannot prepare update\n"); break; } ret_val = 0; @@ -9996,8 +10345,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size, imsm_create_metadata_update_for_size_change( st, &geo, &u); if (len < 1) { - dprintf("imsm: " - "Cannot prepare update\n"); + dprintf("imsm: Cannot prepare update\n"); break; } ret_val = 0; @@ -10020,6 +10368,33 @@ exit_imsm_reshape_super: return ret_val; } +#define COMPLETED_OK 0 +#define COMPLETED_NONE 1 +#define COMPLETED_DELAYED 2 + +static int read_completed(int fd, unsigned long long *val) +{ + int ret; + char buf[50]; + + ret = sysfs_fd_get_str(fd, buf, 50); + if (ret < 0) + return ret; + + ret = COMPLETED_OK; + if (strncmp(buf, "none", 4) == 0) { + ret = COMPLETED_NONE; + } else if (strncmp(buf, "delayed", 7) == 0) { + ret = COMPLETED_DELAYED; + } else { + char *ep; + *val = strtoull(buf, &ep, 0); + if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' ')) + ret = -1; + } + return ret; +} + /******************************************************************************* * Function: wait_for_reshape_imsm * Description: Function writes new sync_max value and waits until @@ -10034,62 +10409,71 @@ exit_imsm_reshape_super: ******************************************************************************/ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) { - int fd = sysfs_get_fd(sra, NULL, "reshape_position"); + int fd = sysfs_get_fd(sra, NULL, "sync_completed"); + int retry = 3; unsigned long long completed; /* to_complete : new sync_max position */ unsigned long long to_complete = sra->reshape_progress; unsigned long long position_to_set = to_complete / ndata; if (fd < 0) { - dprintf("imsm: wait_for_reshape_imsm() " - "cannot open reshape_position\n"); + dprintf("cannot open reshape_position\n"); return 1; } - if (sysfs_fd_get_ll(fd, &completed) < 0) { - dprintf("imsm: wait_for_reshape_imsm() " - "cannot read reshape_position (no reshape in progres)\n"); - close(fd); - return 0; - } + do { + if (sysfs_fd_get_ll(fd, &completed) < 0) { + if (!retry) { + dprintf("cannot read reshape_position (no reshape in progres)\n"); + close(fd); + return 1; + } + usleep(30000); + } else + break; + } while (retry--); - if (completed > to_complete) { - dprintf("imsm: wait_for_reshape_imsm() " - "wrong next position to set %llu (%llu)\n", - to_complete, completed); + if (completed > position_to_set) { + dprintf("wrong next position to set %llu (%llu)\n", + to_complete, position_to_set); close(fd); return -1; } dprintf("Position set: %llu\n", position_to_set); if (sysfs_set_num(sra, NULL, "sync_max", position_to_set) != 0) { - dprintf("imsm: wait_for_reshape_imsm() " - "cannot set reshape position to %llu\n", + dprintf("cannot set reshape position to %llu\n", position_to_set); close(fd); return -1; } do { + int rc; char action[20]; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - select(fd+1, &rfds, NULL, NULL, 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; - if (sysfs_fd_get_ll(fd, &completed) < 0) { - dprintf("imsm: wait_for_reshape_imsm() " - "cannot read reshape_position (in loop)\n"); + strncmp(action, "reshape", 7) != 0) { + if (strncmp(action, "idle", 4) == 0) + break; close(fd); - return 1; + return -1; } - } while (completed < to_complete); + + rc = read_completed(fd, &completed); + if (rc < 0) { + dprintf("cannot read reshape_position (in loop)\n"); + close(fd); + return 1; + } else if (rc == COMPLETED_NONE) + break; + } while (completed < position_to_set); + close(fd); return 0; - } /******************************************************************************* @@ -10145,7 +10529,7 @@ int check_degradation_change(struct mdinfo *info, * 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 @@ -10169,7 +10553,7 @@ static int imsm_manage_reshape( { int ret_val = 0; struct intel_super *super = st->sb; - struct intel_dev *dv = NULL; + struct intel_dev *dv; struct imsm_dev *dev = NULL; struct imsm_map *map_src; int migr_vol_qan = 0; @@ -10187,7 +10571,10 @@ static int imsm_manage_reshape( int degraded = 0; int source_layout = 0; - if (!fds || !offsets || !sra) + if (!sra) + return ret_val; + + if (!fds || !offsets) goto abort; /* Find volume during the reshape */ @@ -10200,7 +10587,7 @@ static int imsm_manage_reshape( } /* Only one volume can migrate at the same time */ if (migr_vol_qan != 1) { - pr_err(": %s", migr_vol_qan ? + pr_err("%s", migr_vol_qan ? "Number of migrating volumes greater than 1\n" : "There is no volume during migrationg\n"); goto abort; @@ -10223,8 +10610,7 @@ static int imsm_manage_reshape( init_migr_record_imsm(st, dev, sra); else { if (__le32_to_cpu(migr_rec->rec_status) != UNIT_SRC_NORMAL) { - dprintf("imsm: cannot restart migration when data " - "are present in copy area.\n"); + dprintf("imsm: cannot restart migration when data are present in copy area.\n"); goto abort; } /* Save checkpoint to update migration record for current @@ -10234,9 +10620,7 @@ static int imsm_manage_reshape( if (save_checkpoint_imsm(st, sra, UNIT_SRC_NORMAL) == 1) { /* ignore error == 2, this can mean end of reshape here */ - dprintf("imsm: Cannot write checkpoint to " - "migration record (UNIT_SRC_NORMAL, " - "initial save)\n"); + dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_NORMAL, initial save)\n"); goto abort; } } @@ -10267,8 +10651,7 @@ static int imsm_manage_reshape( */ degraded = check_degradation_change(sra, fds, degraded); if (degraded > 1) { - dprintf("imsm: Abort reshape due to degradation" - " level (%i)\n", degraded); + dprintf("imsm: Abort reshape due to degradation level (%i)\n", degraded); goto abort; } @@ -10279,7 +10662,7 @@ static int imsm_manage_reshape( 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; @@ -10293,7 +10676,7 @@ static int imsm_manage_reshape( * to backup alligned to source array * [bytes] */ - unsigned long long next_step_filler = 0; + unsigned long long next_step_filler; unsigned long long copy_length = next_step * 512; /* allign copy area length to stripe in old geometry */ @@ -10302,10 +10685,7 @@ static int imsm_manage_reshape( if (next_step_filler) next_step_filler = (old_data_stripe_length - next_step_filler); - dprintf("save_stripes() parameters: start = %llu," - "\tstart_src = %llu,\tnext_step*512 = %llu," - "\tstart_in_buf_shift = %llu," - "\tnext_step_filler = %llu\n", + dprintf("save_stripes() parameters: start = %llu,\tstart_src = %llu,\tnext_step*512 = %llu,\tstart_in_buf_shift = %llu,\tnext_step_filler = %llu\n", start, start_src, copy_length, start_buf_shift, next_step_filler); @@ -10315,8 +10695,7 @@ static int imsm_manage_reshape( copy_length + next_step_filler + start_buf_shift, buf)) { - dprintf("imsm: Cannot save stripes" - " to buffer\n"); + dprintf("imsm: Cannot save stripes to buffer\n"); goto abort; } /* Convert data to destination format and store it @@ -10324,14 +10703,12 @@ static int imsm_manage_reshape( */ if (save_backup_imsm(st, dev, sra, buf + start_buf_shift, copy_length)) { - dprintf("imsm: Cannot save stripes to " - "target devices\n"); + dprintf("imsm: Cannot save stripes to target devices\n"); goto abort; } if (save_checkpoint_imsm(st, sra, UNIT_SRC_IN_CP_AREA)) { - dprintf("imsm: Cannot write checkpoint to " - "migration record (UNIT_SRC_IN_CP_AREA)\n"); + dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_IN_CP_AREA)\n"); goto abort; } } else { @@ -10352,29 +10729,52 @@ static int imsm_manage_reshape( 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; } + if (sigterm) + goto abort; if (save_checkpoint_imsm(st, sra, UNIT_SRC_NORMAL) == 1) { /* ignore error == 2, this can mean end of reshape here */ - dprintf("imsm: Cannot write checkpoint to " - "migration record (UNIT_SRC_NORMAL)\n"); + dprintf("imsm: Cannot write checkpoint to migration record (UNIT_SRC_NORMAL)\n"); goto abort; } } + /* clear migr_rec on disks after successful migration */ + struct dl *d; + + memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SIZE); + for (d = super->disks; d; d = d->next) { + if (d->index < 0 || is_failed(&d->disk)) + continue; + unsigned long long dsize; + + get_dev_size(d->fd, NULL, &dsize); + if (lseek64(d->fd, dsize - MIGR_REC_POSITION, + SEEK_SET) >= 0) { + if (write(d->fd, super->migr_rec_buf, + MIGR_REC_BUF_SIZE) != MIGR_REC_BUF_SIZE) + perror("Write migr_rec failed"); + } + } + /* return '1' if done */ ret_val = 1; abort: free(buf); - abort_reshape(sra); + /* 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; } + #endif /* MDASSEMBLE */ struct superswitch super_imsm = { @@ -10390,6 +10790,7 @@ struct superswitch super_imsm = { .add_to_super = add_to_super_imsm, .remove_from_super = remove_from_super_imsm, .detail_platform = detail_platform_imsm, + .export_detail_platform = export_detail_platform_imsm, .kill_subarray = kill_subarray_imsm, .update_subarray = update_subarray_imsm, .load_container = load_container_imsm, @@ -10398,6 +10799,7 @@ struct superswitch super_imsm = { .reshape_super = imsm_reshape_super, .manage_reshape = imsm_manage_reshape, .recover_backup = recover_backup_imsm, + .copy_metadata = copy_metadata_imsm, #endif .match_home = match_home_imsm, .uuid_from_super= uuid_from_super_imsm, @@ -10416,7 +10818,7 @@ struct superswitch super_imsm = { .free_super = free_super_imsm, .match_metadata_desc = match_metadata_desc_imsm, .container_content = container_content_imsm, - + .validate_container = validate_container_imsm, .external = 1, .name = "imsm",