X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=super-intel.c;h=e28ac7d30ccd5653999cfccdc1992067da89df73;hp=10fbcd6fee3dbc94f4da51115a9a02c9402c005e;hb=c60495c8b6db4026bc0b45f4d7ac53f30170281b;hpb=ba728be72f4b3f0b5cf56d19670a5cf117b0e373 diff --git a/super-intel.c b/super-intel.c index 10fbcd6f..e28ac7d3 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,9 +429,9 @@ struct imsm_update_activate_spare { }; struct geo_params { - int dev_id; + char devnm[32]; char *dev_name; - long long size; + unsigned long long size; int level; int layout; int chunksize; @@ -508,7 +506,6 @@ 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", @@ -558,25 +555,16 @@ static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device if (super->hba == NULL) { super->hba = alloc_intel_hba(device); return 1; - } - - hba = super->hba; - /* Intel metadata allows for all disks attached to the same type HBA. - * Do not sypport odf HBA types mixing - */ - if (device->type != hba->type) + } else + /* IMSM metadata disallows to attach disks to multiple + * controllers. + */ return 2; - - while (hba->next) - hba = hba->next; - - hba->next = alloc_intel_hba(device); - return 1; } 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 +575,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 +601,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 +659,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 +950,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 +1294,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) { @@ -1532,6 +1506,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; @@ -1798,7 +1825,42 @@ static void print_imsm_capability(const struct imsm_orom *orom) 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"); + 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 @@ -1815,7 +1877,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only) 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")) @@ -1829,8 +1891,9 @@ static int detail_platform_imsm(int verbose, int enumerate_only) result = 2; break; } + else + result = 0; } - free_sys_dev(&list); return result; } @@ -1839,38 +1902,72 @@ static int detail_platform_imsm(int verbose, int enumerate_only) if (verbose > 0) pr_err("no active Intel(R) RAID " "controller found.\n"); - free_sys_dev(&list); return 2; } else if (verbose > 0) print_found_intel_controllers(list); for (hba = list; hba; hba = hba->next) { + if (controller_path && (compare_paths(hba->path,controller_path) != 0)) + continue; orom = find_imsm_capability(hba->type); if (!orom) pr_err("imsm capabilities not found for controller: %s (type %s)\n", hba->path, get_sys_dev_type(hba->type)); - else + else { + result = 0; print_imsm_capability(orom); + 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.\n", hba->pci_id); + result |= 2; + } + } + } + } + + if (controller_path && result == 1) + pr_err("no active Intel(R) RAID " + "controller found under %s\n",controller_path); + + return result; +} + +static int export_detail_platform_imsm(int verbose, char *controller_path) +{ + const struct imsm_orom *orom; + 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; + orom = find_imsm_capability(hba->type); + if (!orom) { + if (verbose > 0) + pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",hba->path); + } + else { + print_imsm_capability_export(orom); + result = 0; } } - free_sys_dev(&list); return result; } + #endif static int match_home_imsm(struct supertype *st, char *homehost) @@ -1897,7 +1994,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. @@ -2326,7 +2423,6 @@ static int imsm_create_metadata_checkpoint_update( return update_memory_size; } - static void imsm_update_metadata_locally(struct supertype *st, void *buf, int len); @@ -2483,7 +2579,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)); @@ -2645,11 +2740,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 +2765,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 +2815,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; @@ -2950,7 +3040,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 +3078,22 @@ 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 (first->hba && sec->hba && + strcmp(first->hba->path, sec->hba->path) != 0) { 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); + first->hba ? first->hba->path : NULL, + sec->hba ? sec->hba->path : NULL); return 3; } } @@ -3032,7 +3124,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 +3147,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 +3495,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; } @@ -3742,15 +3833,13 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de hba = hba->next; } - fprintf(stderr, ").\n" - " Mixing devices attached to different controllers " - "is not allowed.\n"); + fprintf(stderr, ").\n"); + cont_err("Mixing devices attached to multiple controllers " + "is not allowed.\n"); } - free_sys_dev(&hba_name); return 2; } super->orom = find_imsm_capability(hba_name->type); - free_sys_dev(&hba_name); if (!super->orom) return 3; return 0; @@ -3947,7 +4036,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); } } @@ -4033,7 +4122,7 @@ imsm_thunderdome(struct intel_super **super_list, int len) champion = s; if (conflict) - fprintf(stderr, "Chose family %#x on '%s', " + 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); @@ -4106,16 +4195,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 +4265,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 +4281,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 +4314,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 +4330,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; char nm[32]; int dfd = -1; - int rv; int err = 0; int retry; @@ -4268,17 +4352,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 +4383,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 +4398,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 +4422,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,6 +4445,22 @@ 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 = mdstat_by_component(fd2devnm(fd)); + + 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 " @@ -4486,7 +4581,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. @@ -4597,7 +4693,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; @@ -4644,7 +4741,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 +4757,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); @@ -4854,7 +4958,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; @@ -4920,7 +5025,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; @@ -4945,7 +5049,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; } @@ -4992,7 +5095,7 @@ 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", + pr_err("%s: failed for device %d:%d %s\n", __func__, d->major, d->minor, strerror(errno)); return 1; } @@ -5102,7 +5205,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 +5227,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,7 +5308,9 @@ 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) { @@ -5266,7 +5372,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,7 +5505,6 @@ 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) @@ -5523,7 +5628,6 @@ get_devices(const char *hba_path) continue; } - dv = xcalloc(1, sizeof(*dv)); dv->devname = xstrdup(buf); dv->next = devlist; @@ -5705,7 +5809,6 @@ count_volumes_list(struct md_list *devlist, char *homehost, return count; } - static int count_volumes(char *hba, int dpa, int verbose) { @@ -5763,17 +5866,17 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, 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", 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)) { + 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; @@ -5790,7 +5893,7 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, 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"); return 0; @@ -5798,12 +5901,14 @@ validate_geometry_imsm_orom(struct intel_super *super, int level, int layout, 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) { @@ -6086,6 +6191,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 +6207,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); } @@ -6136,7 +6243,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, } if (freesize) return reserve_space(st, raiddisks, size, - chunk?*chunk:0, freesize); + *chunk, freesize); } return 1; } @@ -6144,6 +6251,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 +6279,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 +6292,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 +6350,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 +6406,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; } @@ -6457,7 +6565,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra sb_errors = 1; } - /* count spare devices, not used in maps */ for (d = super->disks; d; d = d->next) @@ -6549,7 +6656,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra if (ord & IMSM_ORD_REBUILD) recovery_start = 0; - /* + /* * if we skip some disks the array will be assmebled degraded; * reset resync start to avoid a dirty-degraded * situation when performing the intial sync @@ -6603,7 +6710,6 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra return rest; } - static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, int failed, int look_in_map) { @@ -6612,7 +6718,7 @@ static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev, map = get_imsm_map(dev, look_in_map); if (!failed) - return map->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 +6748,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,7 +6841,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", + pr_err("%s: subarry index %d, out of range\n", __func__, atoi(inst)); return -ENODEV; } @@ -6833,6 +6939,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 +6955,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 +7221,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) @@ -7412,7 +7525,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; @@ -7556,7 +7668,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 +7709,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,7 +7752,6 @@ 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; @@ -7718,7 +7829,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) @@ -7878,7 +7988,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,7 +8017,7 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u, break; if (!dl) { - fprintf(stderr, "error: imsm_activate_spare passed " + pr_err("error: imsm_activate_spare passed " "an unknown disk (index: %d)\n", u->dl->index); return 0; @@ -8214,9 +8323,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 @@ -8293,7 +8402,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; @@ -8478,7 +8587,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 +8600,15 @@ static void imsm_process_update(struct supertype *st, break; } default: - fprintf(stderr, "error: unsuported process update 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 +8617,28 @@ 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: + if (update->len < (int)sizeof(struct imsm_update_general_migration_checkpoint)) + return 0; dprintf("imsm: prepare_update() " "for update_general_migration_checkpoint called\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,6 +8679,9 @@ static void imsm_prepare_update(struct supertype *st, struct intel_dev *dl; void **space_tail = (void**)&update->space_list; + if (update->len < (int)sizeof(*u)) + return 0; + dprintf("imsm: imsm_prepare_update() for update_reshape\n"); for (dl = super->devlist; dl; dl = dl->next) { @@ -8593,6 +8714,9 @@ static void imsm_prepare_update(struct supertype *st, void *s; int current_level = -1; + if (update->len < (int)sizeof(*u)) + return 0; + dprintf("imsm: imsm_prepare_update() for update_reshape\n"); /* add space for bigger array in update @@ -8660,6 +8784,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 +8803,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 +8827,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 +8866,7 @@ static void imsm_prepare_update(struct supertype *st, else super->next_buf = NULL; } + return 1; } /* must be called while manager is quiesced */ @@ -8842,7 +8990,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 +9030,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 +9041,54 @@ 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")) { + struct sys_dev *idev; + struct mdinfo *dev; + char *hba_path = NULL; + char *dev_path = devt_to_devpath(makedev(info->disk.major, + info->disk.minor)); + + for (idev = find_intel_devices(); idev; idev = idev->next) { + if (strstr(dev_path, idev->path)) { + hba_path = idev->path; + break; + } + } + free(dev_path); + + if (hba_path) { + for (dev = info->next; dev; dev = dev->next) { + if (!devt_attached_to_hba(makedev(dev->disk.major, + dev->disk.minor), hba_path)) { + 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; + } + } + } + } + return 0; +} #ifndef MDASSEMBLE /******************************************************************************* * Function: init_migr_record_imsm @@ -8954,7 +9142,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); @@ -9250,7 +9437,7 @@ 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; @@ -9264,30 +9451,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, @@ -9304,10 +9490,9 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, int devices_that_can_grow = 0; dprintf("imsm: imsm_reshape_is_allowed_on_container(ENTER): " - "st->devnum = (%i)\n", - st->devnum); + "st->devnm = (%s)\n", st->devnm); - if (geo->size != -1 || + if (geo->size > 0 || geo->level != UnSet || geo->layout != UnSet || geo->chunksize != 0 || @@ -9325,8 +9510,7 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, 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); @@ -9383,10 +9567,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; } @@ -9406,10 +9589,10 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st, /* 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) { @@ -9502,7 +9685,6 @@ abort: return 0; } - /****************************************************************************** * function: imsm_create_metadata_update_for_size_change() * Creates update for IMSM array for array size change. @@ -9614,8 +9796,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 +9809,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 @@ -9647,9 +9829,9 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, int data_disks; struct imsm_dev *dev; struct intel_super *super; - long long current_size; + unsigned long long current_size; unsigned long long free_size; - long long max_size; + unsigned long long max_size; int rv; getinfo_super_imsm_volume(st, &info, NULL); @@ -9737,16 +9919,23 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, */ current_size = info.custom_array_size / data_disks; - if (geo->size > 0) { + if ((geo->size > 0) && (geo->size != MAX_SIZE)) { /* align component size */ geo->size = imsm_component_size_aligment_check( 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 ((current_size != geo->size) && (geo->size > 0)) { if (change != -1) { pr_err("Error. Size change should be the only " "one at a time.\n"); @@ -9755,8 +9944,8 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, } 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); + "can be expanded only (%i/%s).\n", + super->current_vol, st->devnm); goto analyse_change_exit; } /* check the maximum available size @@ -9776,7 +9965,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, chunk * 1024, max_size); } - if (geo->size == 0) { + if (geo->size == MAX_SIZE) { /* requested size change to the maximum available size */ if (max_size == 0) { @@ -9823,7 +10012,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; @@ -9881,7 +10070,8 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo) return 0; } -static int imsm_reshape_super(struct supertype *st, long long size, int level, +static int imsm_reshape_super(struct supertype *st, unsigned long long size, + int level, int layout, int chunksize, int raid_disks, int delta_disks, char *backup, char *dev, int direction, int verbose) @@ -9894,7 +10084,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, 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; @@ -9909,7 +10099,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, 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; @@ -9948,19 +10138,20 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, */ 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; @@ -10033,7 +10224,7 @@ 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"); unsigned long long completed; /* to_complete : new sync_max position */ unsigned long long to_complete = sra->reshape_progress; @@ -10052,10 +10243,10 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) return 0; } - if (completed > to_complete) { + if (completed > position_to_set) { dprintf("imsm: wait_for_reshape_imsm() " "wrong next position to set %llu (%llu)\n", - to_complete, completed); + to_complete, position_to_set); close(fd); return -1; } @@ -10071,10 +10262,7 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) do { char action[20]; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - select(fd+1, &rfds, NULL, NULL, NULL); + sysfs_wait(fd, NULL); if (sysfs_get_str(sra, NULL, "sync_action", action, 20) > 0 && strncmp(action, "reshape", 7) != 0) @@ -10085,7 +10273,7 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) close(fd); return 1; } - } while (completed < to_complete); + } while (completed < position_to_set); close(fd); return 0; @@ -10355,6 +10543,8 @@ static int imsm_manage_reshape( 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 @@ -10374,6 +10564,7 @@ abort: return ret_val; } + #endif /* MDASSEMBLE */ struct superswitch super_imsm = { @@ -10389,6 +10580,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, @@ -10397,6 +10589,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, @@ -10415,7 +10608,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",