#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 */
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
* 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
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"
};
const char *get_sys_dev_type(enum sys_dev_type type)
if (super->hba == NULL) {
super->hba = alloc_intel_hba(device);
return 1;
- } else
- /* IMSM metadata disallows to attach disks to multiple
- * controllers.
- */
+ }
+
+ hba = super->hba;
+ /* Intel metadata allows for all disks attached to the same type HBA.
+ * Do not support HBA types mixing
+ */
+ if (device->type != hba->type)
+ 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;
+
+ hba->next = alloc_intel_hba(device);
+ return 1;
}
static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
return NULL;
}
-
static int find_intel_hba_capability(int fd, struct intel_super *super,
char *devname);
}
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
/*******************************************************************************
* 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)
{
}
if (not_supported)
- dprintf(Name "(IMSM): Unknown attributes : %x\n", not_supported);
+ dprintf("(IMSM): Unknown attributes : %x\n", not_supported);
ret_val = 0;
}
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;
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) {
fprintf(stderr, "SATA ");
else if (elem->type == SYS_DEV_SAS)
fprintf(stderr, "SAS ");
+ else if (elem->type == SYS_DEV_NVME)
+ fprintf(stderr, "NVMe ");
fprintf(stderr, "RAID controller");
if (elem->pci_id)
fprintf(stderr, " at %s", elem->pci_id);
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;
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" : "",
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 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);
+ 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 " : "",
* 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;
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 = 0;
+ result = 2;
}
return result;
}
print_found_intel_controllers(list);
for (hba = list; hba; hba = hba->next) {
- if (controller_path && (compare_paths(hba->path,controller_path) != 0))
+ if (controller_path && (compare_paths(hba->path, controller_path) != 0))
continue;
- orom = find_imsm_capability(hba->type);
- if (!orom)
+ if (!find_imsm_capability(hba)) {
pr_err("imsm capabilities not found for controller: %s (type %s)\n",
hba->path, get_sys_dev_type(hba->type));
- else {
- result = 0;
- print_imsm_capability(orom);
+ 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 *oroms = get_oroms();
+ int i;
+
+ for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++) {
+ print_imsm_capability(&oroms[i].orom);
+
+ if (imsm_orom_is_nvme(&oroms[i].orom)) {
+ for (hba = list; hba; hba = hba->next) {
+ if (hba->type == SYS_DEV_NVME)
+ printf(" NVMe Device : %s\n", hba->path);
+ }
+ continue;
+ }
+
+ struct devid_list *devid;
+ for (devid = oroms[i].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));
if (hba->type == SYS_DEV_SATA) {
}
}
}
+ printf("\n");
}
- 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;
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) {
- if (verbose > 0)
- pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",hba->path);
- }
- else {
- print_imsm_capability_export(orom);
+ if (!find_imsm_capability(hba) && verbose > 0)
+ pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n", hba->path);
+ else
result = 0;
- }
}
+ const struct orom_entry *oroms = get_oroms();
+ int i;
+
+ for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++)
+ print_imsm_capability_export(&oroms[i].orom);
+
return result;
}
* 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.
case 5:
return map->num_members - 1;
default:
- dprintf("%s: unsupported raid level\n", __func__);
+ dprintf("unsupported raid level\n");
return 0;
}
}
int update_memory_size = 0;
- dprintf("imsm_create_metadata_checkpoint_update(enter)\n");
+ dprintf("(enter)\n");
if (u == NULL)
return 0;
*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);
*/
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);
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);
}
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)
{
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;
*/
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) {
* 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 &&
- strcmp(first->hba->path, sec->hba->path) != 0) {
+ 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 ? first->hba->path : NULL,
- sec->hba ? sec->hba->path : 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;
}
}
}
-
/* if 'first' is a spare promote it to a populated mpb with sec's
* family number
*/
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;
if (__le32_to_cpu(mpb->bbm_log_size)) {
ptr = mpb;
ptr += mpb->mpb_size - __le32_to_cpu(mpb->bbm_log_size);
- }
+ }
return ptr;
}
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;
}
" but the container is assigned to Intel(R) "
"%s RAID controller (",
devname,
- hba_name->path,
+ get_sys_dev_type(hba_name->type),
hba_name->pci_id ? : "Err!",
- get_sys_dev_type(hba_name->type));
+ get_sys_dev_type(super->hba->type));
while (hba) {
fprintf(stderr, "%s", hba->pci_id ? : "Err!");
fprintf(stderr, ", ");
hba = hba->next;
}
-
fprintf(stderr, ").\n"
- " Mixing devices attached to multiple controllers "
+ " Mixing devices attached to different controllers "
"is not allowed.\n");
}
return 2;
}
- super->orom = find_imsm_capability(hba_name->type);
+ super->orom = find_imsm_capability(hba_name);
if (!super->orom)
return 3;
+
return 0;
}
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);
*/
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);
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);
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;
}
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);
}
}
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;
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);
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, char *devnm, char *devname,
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)
free_imsm(s);
}
-
if (err)
return err;
return 0;
}
-
static int
get_devlist_super_block(struct md_list *devlist, struct intel_super **super_list,
int *max, int keep_fd)
{
struct intel_super *super;
int rv;
+ int retry;
if (test_partition(fd))
/* IMSM not allowed on partitions */
}
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 "
}
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);
char *version;
if (data_offset != INVALID_SECTORS) {
- fprintf(stderr, Name ": data-offset not supported by imsm\n");
+ pr_err("data-offset not supported by imsm\n");
return 0;
}
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;
}
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);
return 0;
}
-
static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk)
{
struct intel_super *super = st->sb;
* 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));
dd->next = super->disk_mgmt_list;
super->disk_mgmt_list = dd;
-
return 0;
}
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) {
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) {
return 0;
}
-
static int create_array(struct supertype *st, int dev_idx)
{
size_t len;
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);
#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 */
return 0;
}
-
static int
active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
int dpa, int verbose)
continue;
}
-
dv = xcalloc(1, sizeof(*dv));
dv->devname = xstrdup(buf);
dv->next = devlist;
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 ||
} 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;
}
* 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;
}
if (iter->array.state & (1<<MD_SB_BLOCK_VOLUME)) {
/* do not assemble arrays with unsupported
configurations */
- dprintf(": Cannot activate member %s.\n",
+ dprintf("Cannot activate member %s.\n",
iter->text_version);
} else
count++;
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) {
return count;
}
-
static int
count_volumes(char *hba, int dpa, int verbose)
{
return 0;
count = active_arrays_by_format("imsm", hba, &devlist, dpa, verbose);
- dprintf(" path: %s active arrays: %d\n", hba, count);
+ dprintf("path: %s active arrays: %d\n", hba, count);
if (devlist == NULL)
return 0;
do {
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;
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;
}
+
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,
/* Must be a fresh device to add to a container */
return validate_geometry_imsm_container(st, level, layout,
raiddisks,
- chunk?*chunk:0,
+ *chunk,
size, data_offset,
dev, freesize,
verbose);
}
if (freesize)
return reserve_space(st, raiddisks, size,
- chunk?*chunk:0, freesize);
+ *chunk, freesize);
}
return 1;
}
* 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;
}
sb_errors = 1;
}
-
/* count spare devices, not used in maps
*/
for (d = super->disks; d; d = d->next)
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
return rest;
}
-
static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
int failed, int look_in_map)
{
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)) {
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;
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;
}
__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)
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) {
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++;
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
}
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 {
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;
}
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)
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;
}
return dl;
}
-
static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
{
struct imsm_dev *dev2;
dl = imsm_add_spare(super, i, a, 1, rv);
if (!dl)
continue;
-
+
/* found a usable disk with enough space */
di = xcalloc(1, sizeof(*di));
* 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;
return 0;
}
-
static struct dl *get_disk_super(struct intel_super *super, int major, int minor)
{
struct dl *dl = NULL;
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;
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);
return check_degraded;
}
-
static int apply_reshape_migration_update(struct imsm_update_reshape_migration *u,
struct intel_super *super,
void ***space_list)
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);
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);
/* 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);
return ret_val;
}
-
static int apply_update_activate_spare(struct imsm_update_activate_spare *u,
struct intel_super *super,
struct active_array *active_array)
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;
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++) {
* 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
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) {
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;
/* 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;
}
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;
}
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;
}
}
}
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)) {
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
* 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);
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);
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
*/
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: {
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 */
}
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 */
else
super->next_buf = NULL;
}
+ return 1;
}
/* must be called while manager is quiesced */
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)
}
}
-
/*******************************************************************************
* Function: open_backup_targets
* Description: Function opens file descriptors for all devices given in
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++;
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) {
+ 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
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);
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;
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);
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)
{
int delta_disks = 0;
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;
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.
int update_memory_size = 0;
struct imsm_update_size_change *u = NULL;
- 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);
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);
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;
/***************************************************************************
* 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
int ret_val = 1;
struct geo_params geo;
- dprintf("imsm: reshape_super called.\n");
+ dprintf("(enter)\n");
memset(&geo, 0, sizeof(struct geo_params));
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;
dprintf("imsm: info: Volume operation\n");
/* find requested device */
while (dev) {
- char *devnm =
+ char *devnm =
imsm_find_array_devnm_by_subdev(
dev->index, st->container_devnm);
if (devnm && strcmp(devnm, geo.devnm) == 0)
******************************************************************************/
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;
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");
+ dprintf("cannot read reshape_position (no reshape in progres)\n");
close(fd);
return 0;
}
- 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 {
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)
break;
if (sysfs_fd_get_ll(fd, &completed) < 0) {
- dprintf("imsm: wait_for_reshape_imsm() "
- "cannot read reshape_position (in loop)\n");
+ dprintf("cannot read reshape_position (in loop)\n");
close(fd);
return 1;
}
- } while (completed < to_complete);
+ } while (completed < position_to_set);
close(fd);
return 0;
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
}
+ /* 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:
return ret_val;
}
+
#endif /* MDASSEMBLE */
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,
.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",