};
struct geo_params {
- int dev_id;
+ char devnm[32];
char *dev_name;
unsigned long long size;
int level;
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)
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;
}
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;
__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)
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;
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
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"))
result = 2;
break;
}
+ else
+ result = 0;
}
- free_sys_dev(&list);
return result;
}
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)
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));
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);
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;
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;
}
}
}
fprintf(stderr, ").\n"
- " Mixing devices attached to different controllers "
+ " 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;
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,
*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;
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);
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;
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);
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;
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;
struct intel_super *super;
int rv;
- if (test_partition(fd))
+ if (!st->ignore_hw_compat && test_partition(fd))
/* IMSM not allowed on partitions */
return 1;
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.
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;
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
size_t mpb_size;
char *version;
+ if (data_offset != INVALID_SECTORS) {
+ fprintf(stderr, Name ": 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);
}
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;
#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)
{
}
}
- *freesize = avail_size_imsm(st, ldsize >> 9);
+ *freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
free_imsm(super);
return 1;
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" : "");
*/
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)
{
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)
{
/* Must be a fresh device to add to a container */
return validate_geometry_imsm_container(st, level, layout,
raiddisks,
- chunk?*chunk:0, size,
+ chunk?*chunk:0,
+ size, data_offset,
dev, freesize,
verbose);
}
/* creating in a given container */
return validate_geometry_imsm_volume(st, level, layout,
raiddisks, chunk, size,
+ data_offset,
dev, freesize, verbose);
}
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;
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;
}
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);
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;
}
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
*/
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);
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,
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 > 0 ||
geo->level != UnSet ||
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);
* 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;
}
}
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
imsm_layout,
geo->raid_disks + devNumChange,
&chunk,
- geo->size,
+ geo->size, INVALID_SECTORS,
0, 0, 1))
change = -1;
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;
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;
*/
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;
.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,
.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,