return _sys_dev_type[type];
}
-#ifndef MDASSEMBLE
static struct intel_hba * alloc_intel_hba(struct sys_dev *device)
{
struct intel_hba *result = malloc(sizeof(*result));
return result;
}
-
static int attach_hba_to_super(struct intel_super *super, struct sys_dev *device)
{
struct intel_hba *hba;
return NULL;
}
-#endif /* MDASSEMBLE */
+static int find_intel_hba_capability(int fd, struct intel_super *super,
+ char *devname);
+
static struct supertype *match_metadata_desc_imsm(char *arg)
{
struct supertype *st;
migr_chunk = migr_strip_blocks_resync(dev);
disks = imsm_num_data_members(dev, 0);
blocks_per_unit = stripes_per_unit * migr_chunk * disks;
- if (migr_type(dev) == MIGR_GEN_MIGR)
- return blocks_per_unit;
stripe = __le32_to_cpu(map->blocks_per_strip) * disks;
segment = blocks_per_unit / stripe;
block_rel = blocks_per_unit - segment * stripe;
struct imsm_map *map_to_analyse = map;
struct dl *dl;
char *devname;
+ unsigned int component_size_alligment;
int map_disks = info->array.raid_disks;
if (prev_map)
info->data_offset = __le32_to_cpu(map_to_analyse->pba_of_lba0);
info->component_size =
__le32_to_cpu(map_to_analyse->blocks_per_member);
+
+ /* check component size aligment
+ */
+ component_size_alligment =
+ info->component_size % (info->array.chunk_size/512);
+
+ if (component_size_alligment &&
+ (info->array.level != 1) && (info->array.level != UnSet)) {
+ dprintf("imsm: reported component size alligned from %llu ",
+ info->component_size);
+ info->component_size -= component_size_alligment;
+ dprintf("to %llu (%i).\n",
+ info->component_size, component_size_alligment);
+ }
+
memset(info->uuid, 0, sizeof(info->uuid));
info->recovery_start = MaxSector;
int used_disks;
info->reshape_progress = blocks_per_unit * units;
+
+ /* checkpoint is written per disks unit
+ * recalculate it to reshape position
+ */
+ used_disks = imsm_num_data_members(dev, 0);
+ info->reshape_progress *= used_disks;
dprintf("IMSM: General Migration checkpoint : %llu "
"(%llu) -> read reshape progress : %llu\n",
units, blocks_per_unit, info->reshape_progress);
tst->sb = NULL;
return 0;
}
+ /* in platform dependent environment test if the disks
+ * use the same Intel hba
+ */
+ if (!check_env("IMSM_NO_PLATFORM")) {
+ if (!first->hba || !sec->hba ||
+ (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);
+ return 3;
+ }
+ }
/* if an anchor does not have num_raid_devs set then it is a free
* floating spare
static void __free_imsm(struct intel_super *super, int free_disks);
/* load_imsm_mpb - read matrix metadata
- * allocates super->mpb to be freed by free_super
+ * allocates super->mpb to be freed by free_imsm
*/
static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
{
}
__free_imsm(super, 0);
+ /* reload capability and hba */
+
+ /* capability and hba must be updated with new super allocation */
+ find_intel_hba_capability(fd, super, devname);
super->len = ROUND_UP(anchor->mpb_size, 512);
if (posix_memalign(&super->buf, 512, super->len) != 0) {
if (devname)
free(super->buf);
super->buf = NULL;
}
+ /* unlink capability description */
+ super->orom = NULL;
if (free_disks)
free_imsm_disks(super);
free_devlist(super);
memset(super, 0, sizeof(*super));
super->current_vol = -1;
super->create_offset = ~((__u32 ) 0);
- if (!check_env("IMSM_NO_PLATFORM"))
- super->orom = find_imsm_orom();
}
-
return super;
}
+/*
+ * find and allocate hba and OROM/EFI based on valid fd of RAID component device
+ */
+static int find_intel_hba_capability(int fd, struct intel_super *super, char *devname)
+{
+ struct sys_dev *hba_name;
+ int rv = 0;
+
+ if ((fd < 0) || check_env("IMSM_NO_PLATFORM")) {
+ super->orom = NULL;
+ super->hba = NULL;
+ return 0;
+ }
+ hba_name = find_disk_attached_hba(fd, NULL);
+ if (!hba_name) {
+ if (devname)
+ fprintf(stderr,
+ Name ": %s is not attached to Intel(R) RAID controller.\n",
+ devname);
+ return 1;
+ }
+ rv = attach_hba_to_super(super, hba_name);
+ if (rv == 2) {
+ if (devname) {
+ struct intel_hba *hba = super->hba;
+
+ fprintf(stderr, Name ": %s is attached to Intel(R) %s RAID "
+ "controller (%s),\n"
+ " but the container is assigned to Intel(R) "
+ "%s RAID controller (",
+ devname,
+ hba_name->path,
+ hba_name->pci_id ? : "Err!",
+ get_sys_dev_type(hba_name->type));
+
+ while (hba) {
+ fprintf(stderr, "%s", hba->pci_id ? : "Err!");
+ if (hba->next)
+ fprintf(stderr, ", ");
+ hba = hba->next;
+ }
+
+ fprintf(stderr, ").\n"
+ " Mixing devices attached to different 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;
+}
+
#ifndef MDASSEMBLE
/* find_missing - helper routine for load_super_imsm_all that identifies
* disks that have disappeared from the system. This routine relies on
struct intel_super *s = alloc_super();
char nm[32];
int dfd;
+ int rv;
err = 1;
if (!s)
if (dfd < 0)
goto error;
+ rv = find_intel_hba_capability(dfd, s, devname);
+ /* no orom/efi or non-intel hba of the disk */
+ if (rv != 0)
+ goto error;
+
err = load_and_parse_mpb(dfd, s, NULL, 1);
/* retry the load if we might have raced against mdmon */
sizeof(*super));
return 1;
}
-
+ /* Load hba and capabilities if they exist.
+ * But do not preclude loading metadata in case capabilities or hba are
+ * non-compliant and ignore_hw_compat is set.
+ */
+ rv = find_intel_hba_capability(fd, super, devname);
+ /* no orom/efi or non-intel hba of the disk */
+ if ((rv != 0) && (st->ignore_hw_compat == 0)) {
+ if (devname)
+ fprintf(stderr,
+ Name ": No OROM/EFI properties for %s\n", devname);
+ free_imsm(super);
+ return 2;
+ }
rv = load_and_parse_mpb(fd, super, devname, 0);
if (rv) {
* We do not need to test disks attachment for container based additions,
* they shall be already tested when container was created/assembled.
*/
- if ((fd != -1) && !check_env("IMSM_NO_PLATFORM")) {
- struct sys_dev *hba_name;
- struct intel_hba *hba;
-
- hba_name = find_disk_attached_hba(fd, NULL);
- if (!hba_name) {
- fprintf(stderr,
- Name ": %s is not attached to Intel(R) RAID controller.\n",
- devname ? : "disk");
- return 1;
- }
- rv = attach_hba_to_super(super, hba_name);
- switch (rv) {
- case 2:
- fprintf(stderr, Name ": %s is attached to Intel(R) %s RAID "
- "controller (%s),\n but the container is assigned to Intel(R) "
- "%s RAID controller (",
- devname,
- get_sys_dev_type(hba_name->type),
- hba_name->pci_id ? : "Err!",
- get_sys_dev_type(hba_name->type));
-
- hba = super->hba;
- while (hba) {
- fprintf(stderr, "%s", hba->pci_id ? : "Err!");
- if (hba->next)
- fprintf(stderr, ", ");
- hba = hba->next;
- }
-
- fprintf(stderr, ").\n"
- " Mixing devices attached to different controllers "
- "is not allowed.\n");
- free_sys_dev(&hba_name);
- return 1;
- }
- free_sys_dev(&hba_name);
+ rv = find_intel_hba_capability(fd, super, devname);
+ /* no orom/efi or non-intel hba of the disk */
+ if (rv != 0) {
+ dprintf("capability: %p fd: %d ret: %d\n",
+ super->orom, fd, rv);
+ return 1;
}
if (super->current_vol >= 0)
} else {
dd->next = super->disks;
super->disks = dd;
+ super->updates_pending++;
}
return 0;
{
int fd;
unsigned long long ldsize;
- const struct imsm_orom *orom;
+ struct intel_super *super=NULL;
+ int rv = 0;
if (level != LEVEL_CONTAINER)
return 0;
if (!dev)
return 1;
- if (check_env("IMSM_NO_PLATFORM"))
- orom = NULL;
- else
- orom = find_imsm_orom();
- if (orom && raiddisks > orom->tds) {
- if (verbose)
- fprintf(stderr, Name ": %d exceeds maximum number of"
- " platform supported disks: %d\n",
- raiddisks, orom->tds);
- return 0;
- }
-
fd = open(dev, O_RDONLY|O_EXCL, 0);
if (fd < 0) {
if (verbose)
close(fd);
return 0;
}
+
+ /* capabilities retrieve could be possible
+ * note that there is no fd for the disks in array.
+ */
+ super = alloc_super();
+ if (!super) {
+ fprintf(stderr,
+ Name ": malloc of %zu failed.\n",
+ sizeof(*super));
+ close(fd);
+ return 0;
+ }
+
+ rv = find_intel_hba_capability(fd, super, verbose ? dev : NULL);
+ if (rv != 0) {
+#if DEBUG
+ char str[256];
+ fd2devname(fd, str);
+ dprintf("validate_geometry_imsm_container: 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 */
+ close(fd);
+ free_imsm(super);
+ return 0;
+ }
close(fd);
+ if (super->orom && raiddisks > super->orom->tds) {
+ if (verbose)
+ fprintf(stderr, Name ": %d exceeds maximum number of"
+ " platform supported disks: %d\n",
+ raiddisks, super->orom->tds);
+
+ free_imsm(super);
+ return 0;
+ }
*freesize = avail_size_imsm(st, ldsize >> 9);
+ free_imsm(super);
return 1;
}
*/
chunk = __le16_to_cpu(map->blocks_per_strip) >> 1;
+#ifndef MDASSEMBLE
if (!validate_geometry_imsm_orom(super,
get_imsm_raid_level(map), /* RAID level */
imsm_level_to_layout(get_imsm_raid_level(map)),
"Cannot proceed with the action(s).\n");
continue;
}
+#endif /* MDASSEMBLE */
this = malloc(sizeof(*this));
if (!this) {
fprintf(stderr, Name ": failed to allocate %zu bytes\n",
__u32 ord;
int slot;
struct imsm_map *map;
- char buf[MAX_RAID_SERIAL_LEN+3];
- unsigned int len, shift = 0;
/* new failures are always set in map[0] */
map = get_imsm_map(dev, 0);
if (is_failed(disk) && (ord & IMSM_ORD_REBUILD))
return 0;
- sprintf(buf, "%s:0", disk->serial);
- if ((len = strlen(buf)) >= MAX_RAID_SERIAL_LEN)
- shift = len - MAX_RAID_SERIAL_LEN + 1;
- strncpy((char *)disk->serial, &buf[shift], MAX_RAID_SERIAL_LEN);
-
disk->status |= FAILED_DISK;
set_imsm_ord_tbl_ent(map, slot, idx | IMSM_ORD_REBUILD);
if (map->failed_disk_num == 0xff)
geo->raid_disks > 1 ? "s" : "");
break;
}
+ /* check if component size is aligned to chunk size
+ */
+ if (info->component_size %
+ (info->array.chunk_size/512)) {
+ dprintf("Component size is not aligned to "
+ "chunk size\n");
+ break;
+ }
}
if (*old_raid_disks &&
return 0;
}
+static int warn_user_about_risk(void)
+{
+ int rv = 0;
+
+ fprintf(stderr,
+ "\nThis is an experimental feature. Data on the RAID volume(s) "
+ "can be lost!!!\n\n"
+ "To continue command execution please make sure that\n"
+ "the grow process will not be interrupted. Use safe power\n"
+ "supply to avoid unexpected system reboot. Make sure that\n"
+ "reshaped container is not assembled automatically during\n"
+ "system boot.\n"
+ "If reshape is interrupted, assemble array manually\n"
+ "using e.g. '-Ac' option and up to date mdadm.conf file.\n"
+ "Assembly in scan mode is not possible in such case.\n"
+ "Growing container with boot array is not possible.\n"
+ "If boot array reshape is interrupted, whole file system\n"
+ "can be lost.\n\n");
+ rv = ask("Do you want to continue? ");
+ fprintf(stderr, "\n");
+
+ return rv;
+}
+
static int imsm_reshape_super(struct supertype *st, long long size, int level,
int layout, int chunksize, int raid_disks,
int delta_disks, char *backup, char *dev,
/* On container level we can only increase number of devices. */
dprintf("imsm: info: Container operation\n");
int old_raid_disks = 0;
+
+ /* this warning will be removed when imsm checkpointing
+ * will be implemented, and restoring from check-point
+ * operation will be transparent for reboot process
+ */
+ if (warn_user_about_risk() == 0)
+ return ret_val;
+
if (imsm_reshape_is_allowed_on_container(
st, &geo, &old_raid_disks)) {
struct imsm_update_reshape *u = NULL;