#define MAX_SIGNATURE_LENGTH 32
#define MAX_RAID_SERIAL_LEN 16
-#define MPB_ATTRIB_CHECKSUM_VERIFY __cpu_to_le32(0x80000000)
-#define MPB_ATTRIB_PM __cpu_to_le32(0x40000000)
-#define MPB_ATTRIB_2TB __cpu_to_le32(0x20000000)
-#define MPB_ATTRIB_RAID0 __cpu_to_le32(0x00000001)
-#define MPB_ATTRIB_RAID1 __cpu_to_le32(0x00000002)
-#define MPB_ATTRIB_RAID10 __cpu_to_le32(0x00000004)
-#define MPB_ATTRIB_RAID1E __cpu_to_le32(0x00000008)
-#define MPB_ATTRIB_RAID5 __cpu_to_le32(0x00000010)
-#define MPB_ATTRIB_RAIDCNG __cpu_to_le32(0x00000020)
+/* supports RAID0 */
+#define MPB_ATTRIB_RAID0 __cpu_to_le32(0x00000001)
+/* supports RAID1 */
+#define MPB_ATTRIB_RAID1 __cpu_to_le32(0x00000002)
+/* supports RAID10 */
+#define MPB_ATTRIB_RAID10 __cpu_to_le32(0x00000004)
+/* supports RAID1E */
+#define MPB_ATTRIB_RAID1E __cpu_to_le32(0x00000008)
+/* supports RAID5 */
+#define MPB_ATTRIB_RAID5 __cpu_to_le32(0x00000010)
+/* supports RAID CNG */
+#define MPB_ATTRIB_RAIDCNG __cpu_to_le32(0x00000020)
+/* supports expanded stripe sizes of 256K, 512K and 1MB */
+#define MPB_ATTRIB_EXP_STRIPE_SIZE __cpu_to_le32(0x00000040)
+
+/* The OROM Support RST Caching of Volumes */
+#define MPB_ATTRIB_NVM __cpu_to_le32(0x02000000)
+/* The OROM supports creating disks greater than 2TB */
+#define MPB_ATTRIB_2TB_DISK __cpu_to_le32(0x04000000)
+/* The OROM supports Bad Block Management */
+#define MPB_ATTRIB_BBM __cpu_to_le32(0x08000000)
+
+/* THe OROM Supports NVM Caching of Volumes */
+#define MPB_ATTRIB_NEVER_USE2 __cpu_to_le32(0x10000000)
+/* The OROM supports creating volumes greater than 2TB */
+#define MPB_ATTRIB_2TB __cpu_to_le32(0x20000000)
+/* originally for PMP, now it's wasted b/c. Never use this bit! */
+#define MPB_ATTRIB_NEVER_USE __cpu_to_le32(0x40000000)
+/* Verify MPB contents against checksum after reading MPB */
+#define MPB_ATTRIB_CHECKSUM_VERIFY __cpu_to_le32(0x80000000)
+
+/* Define all supported attributes that have to be accepted by mdadm
+ */
+#define MPB_ATTRIB_SUPPORTED (MPB_ATTRIB_CHECKSUM_VERIFY | \
+ MPB_ATTRIB_2TB | \
+ MPB_ATTRIB_2TB_DISK | \
+ MPB_ATTRIB_RAID0 | \
+ MPB_ATTRIB_RAID1 | \
+ MPB_ATTRIB_RAID10 | \
+ MPB_ATTRIB_RAID5 | \
+ MPB_ATTRIB_EXP_STRIPE_SIZE)
+
+/* Define attributes that are unused but not harmful */
+#define MPB_ATTRIB_IGNORED (MPB_ATTRIB_NEVER_USE)
#define MPB_SECTOR_CNT 2210
#define IMSM_RESERVED_SECTORS 4096
struct extent *e; /* for determining freespace @ create */
int raiddisk; /* slot to fill in autolayout */
enum action action;
- } *disks;
+ } *disks, *current_disk;
struct dl *disk_mgmt_list; /* list of disks to add/remove while mdmon
active */
struct dl *missing; /* disks removed while we weren't looking */
{
return &mpb->sig[MPB_SIG_LEN];
}
-#endif
+#endif
/* retrieve a disk directly from the anchor when the anchor is known to be
* up-to-date, currently only at load time
break;
}
}
+#endif /* MDASSEMBLE */
+/*******************************************************************************
+ * function: imsm_check_attributes
+ * Description: Function checks if features represented by attributes flags
+ * are supported by mdadm.
+ * Parameters:
+ * attributes - Attributes read from metadata
+ * Returns:
+ * 0 - passed attributes contains unsupported features flags
+ * 1 - all features are supported
+ ******************************************************************************/
+static int imsm_check_attributes(__u32 attributes)
+{
+ int ret_val = 1;
+ __u32 not_supported = MPB_ATTRIB_SUPPORTED^0xffffffff;
+
+ not_supported &= ~MPB_ATTRIB_IGNORED;
+
+ not_supported &= attributes;
+ if (not_supported) {
+ fprintf(stderr, Name "(IMSM): Unsupported attributes : %x\n",
+ (unsigned)__le32_to_cpu(not_supported));
+ if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
+ dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY \n");
+ not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
+ }
+ if (not_supported & MPB_ATTRIB_2TB) {
+ dprintf("\t\tMPB_ATTRIB_2TB\n");
+ not_supported ^= MPB_ATTRIB_2TB;
+ }
+ if (not_supported & MPB_ATTRIB_RAID0) {
+ dprintf("\t\tMPB_ATTRIB_RAID0\n");
+ not_supported ^= MPB_ATTRIB_RAID0;
+ }
+ if (not_supported & MPB_ATTRIB_RAID1) {
+ dprintf("\t\tMPB_ATTRIB_RAID1\n");
+ not_supported ^= MPB_ATTRIB_RAID1;
+ }
+ if (not_supported & MPB_ATTRIB_RAID10) {
+ dprintf("\t\tMPB_ATTRIB_RAID10\n");
+ not_supported ^= MPB_ATTRIB_RAID10;
+ }
+ if (not_supported & MPB_ATTRIB_RAID1E) {
+ dprintf("\t\tMPB_ATTRIB_RAID1E\n");
+ not_supported ^= MPB_ATTRIB_RAID1E;
+ }
+ if (not_supported & MPB_ATTRIB_RAID5) {
+ dprintf("\t\tMPB_ATTRIB_RAID5\n");
+ not_supported ^= MPB_ATTRIB_RAID5;
+ }
+ if (not_supported & MPB_ATTRIB_RAIDCNG) {
+ dprintf("\t\tMPB_ATTRIB_RAIDCNG\n");
+ not_supported ^= MPB_ATTRIB_RAIDCNG;
+ }
+ if (not_supported & MPB_ATTRIB_BBM) {
+ dprintf("\t\tMPB_ATTRIB_BBM\n");
+ not_supported ^= MPB_ATTRIB_BBM;
+ }
+ if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
+ dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY (== MPB_ATTRIB_LEGACY)\n");
+ not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
+ }
+ if (not_supported & MPB_ATTRIB_EXP_STRIPE_SIZE) {
+ dprintf("\t\tMPB_ATTRIB_EXP_STRIP_SIZE\n");
+ not_supported ^= MPB_ATTRIB_EXP_STRIPE_SIZE;
+ }
+ if (not_supported & MPB_ATTRIB_2TB_DISK) {
+ dprintf("\t\tMPB_ATTRIB_2TB_DISK\n");
+ not_supported ^= MPB_ATTRIB_2TB_DISK;
+ }
+ if (not_supported & MPB_ATTRIB_NEVER_USE2) {
+ dprintf("\t\tMPB_ATTRIB_NEVER_USE2\n");
+ not_supported ^= MPB_ATTRIB_NEVER_USE2;
+ }
+ if (not_supported & MPB_ATTRIB_NEVER_USE) {
+ dprintf("\t\tMPB_ATTRIB_NEVER_USE\n");
+ not_supported ^= MPB_ATTRIB_NEVER_USE;
+ }
+
+ if (not_supported)
+ dprintf(Name "(IMSM): Unknown attributes : %x\n", not_supported);
+
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
+#ifndef MDASSEMBLE
static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *map);
static void examine_super_imsm(struct supertype *st, char *homehost)
printf(" Orig Family : %08x\n", __le32_to_cpu(mpb->orig_family_num));
printf(" Family : %08x\n", __le32_to_cpu(mpb->family_num));
printf(" Generation : %08x\n", __le32_to_cpu(mpb->generation_num));
+ printf(" Attributes : ");
+ if (imsm_check_attributes(mpb->attributes))
+ printf("All supported\n");
+ else
+ printf("not supported\n");
getinfo_super_imsm(st, &info, NULL);
fname_from_uuid(st, &info, nbuf, ':');
printf(" UUID : %s\n", nbuf + 5);
fd2devname(fd, buf);
printf(" Port%d : %s", port, buf);
if (imsm_read_serial(fd, NULL, (__u8 *) buf) == 0)
- printf(" (%s)\n", buf);
+ printf(" (%.*s)\n", MAX_RAID_SERIAL_LEN, buf);
else
- printf("()\n");
+ printf(" ()\n");
}
close(fd);
free(path);
return err;
}
-
-
static void print_found_intel_controllers(struct sys_dev *elem)
{
for (; elem; elem = elem->next) {
return retval;
}
+#ifndef MDASSEMBLE
/*******************************************************************************
* function: imsm_create_metadata_checkpoint_update
* Description: It creates update for checkpoint change.
close(fd);
return retval;
}
+#endif /* MDASSEMBLE */
static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap)
{
if (prev_map)
map_to_analyse = prev_map;
- dl = super->disks;
+ dl = super->current_disk;
info->container_member = super->current_vol;
info->array.raid_disks = map->num_members;
/* conversion is happening as RAID5 */
info->array.level = 5;
info->array.layout = ALGORITHM_PARITY_N;
- info->array.raid_disks += 1;
info->delta_disks -= 1;
break;
default:
info->new_chunk = info->array.chunk_size;
info->delta_disks = 0;
}
- info->disk.major = 0;
- info->disk.minor = 0;
+
if (dl) {
info->disk.major = dl->major;
info->disk.minor = dl->minor;
+ info->disk.number = dl->index;
+ info->disk.raid_disk = get_imsm_disk_slot(map_to_analyse,
+ dl->index);
}
info->data_offset = __le32_to_cpu(map_to_analyse->pba_of_lba0);
unsigned long long array_blocks;
int used_disks;
+ if (__le32_to_cpu(migr_rec->ascending_migr) &&
+ (units <
+ (__le32_to_cpu(migr_rec->num_migr_units)-1)) &&
+ (super->migr_rec->rec_status ==
+ __cpu_to_le32(UNIT_SRC_IN_CP_AREA)))
+ units++;
+
info->reshape_progress = blocks_per_unit * units;
dprintf("IMSM: General Migration checkpoint : %llu "
"(%llu) -> read reshape progress : %llu\n",
- units, blocks_per_unit, info->reshape_progress);
+ (unsigned long long)units,
+ (unsigned long long)blocks_per_unit,
+ info->reshape_progress);
used_disks = imsm_num_data_members(dev, 1);
if (used_disks > 0) {
devname);
return 1;
}
- set_imsm_ord_tbl_ent(map, dk->number, dl->index);
+ set_imsm_ord_tbl_ent(map, dk->raid_disk, dl->index);
dl->disk.status = CONFIGURED_DISK;
/* if we are creating the first raid device update the family number */
mpb->family_num = __cpu_to_le32(sum);
mpb->orig_family_num = mpb->family_num;
}
-
+ super->current_disk = dl;
return 0;
}
return 0;
}
-static int is_gen_migration(struct imsm_dev *dev);
-
static int write_super_imsm(struct supertype *st, int doclose)
{
struct intel_super *super = st->sb;
get_dev_size(d->fd, NULL, &dsize);
if (lseek64(d->fd, dsize - 512, SEEK_SET) >= 0) {
- write(d->fd, super->migr_rec_buf, 512);
+ if (write(d->fd, super->migr_rec_buf, 512) != 512)
+ perror("Write migr_rec failed");
}
}
if (doclose) {
return 0;
}
+static int imsm_default_chunk(const struct imsm_orom *orom)
+{
+ /* up to 512 if the plaform supports it, otherwise the platform max.
+ * 128 if no platform detected
+ */
+ int fs = max(7, orom ? fls(orom->sss) : 0);
+
+ return min(512, (1 << fs));
+}
#define pr_vrb(fmt, arg...) (void) (verbose && fprintf(stderr, Name fmt, ##arg))
/*
level, raiddisks, raiddisks > 1 ? "s" : "");
return 0;
}
- if (super->orom && level != 1) {
- if (chunk && (*chunk == 0 || *chunk == UnSet))
- *chunk = imsm_orom_default_chunk(super->orom);
- else if (chunk && !imsm_orom_has_chunk(super->orom, *chunk)) {
- pr_vrb(": platform does not support a chunk size of: "
- "%d\n", *chunk);
- return 0;
- }
+
+ if (chunk && (*chunk == 0 || *chunk == UnSet))
+ *chunk = imsm_default_chunk(super->orom);
+
+ if (super->orom && chunk && !imsm_orom_has_chunk(super->orom, *chunk)) {
+ pr_vrb(": platform does not support a chunk size of: "
+ "%d\n", *chunk);
+ return 0;
}
+
if (layout != imsm_level_to_layout(level)) {
if (level == 5)
pr_vrb(": imsm raid 5 only supports the left-asymmetric layout\n");
if (level && layout && *layout == UnSet)
*layout = imsm_level_to_layout(*level);
- if (chunk && (*chunk == UnSet || *chunk == 0) &&
- super && super->orom)
- *chunk = imsm_orom_default_chunk(super->orom);
+ if (chunk && (*chunk == UnSet || *chunk == 0))
+ *chunk = imsm_default_chunk(super->orom);
}
static void handle_missing(struct intel_super *super, struct imsm_dev *dev);
static int is_gen_migration(struct imsm_dev *dev)
{
+ if (dev == NULL)
+ return 0;
+
if (!dev->vol.migr_state)
return 0;
rebuild->recovery_start = units * blocks_per_migr_unit(super, dev);
}
+#ifndef MDASSEMBLE
static int recover_backup_imsm(struct supertype *st, struct mdinfo *info);
+#endif
static struct mdinfo *container_content_imsm(struct supertype *st, char *subarray)
{
struct dl *d;
int spare_disks = 0;
+ /* do not assemble arrays when not all attributes are supported */
+ if (imsm_check_attributes(mpb->attributes) == 0) {
+ fprintf(stderr, Name ": IMSM metadata loading not allowed "
+ "due to attributes incompatibility.\n");
+ return NULL;
+ }
+
/* check for bad blocks */
if (imsm_bbm_log_size(super->anchor))
bbm_errors = 1;
update_recovery_start(super, dev, this);
this->array.spare_disks += spare_disks;
+#ifndef MDASSEMBLE
/* check for reshape */
if (this->reshape_active == 1)
recover_backup_imsm(st, this);
-
+#endif
rest = this;
}
} else {
if (a->last_checkpoint == 0 && a->prev_action == reshape) {
/* for some reason we aborted the reshape.
- * Better clean up
+ *
+ * disable automatic metadata rollback
+ * user action is required to recover process
*/
+ if (0) {
struct imsm_map *map2 = get_imsm_map(dev, 1);
dev->vol.migr_state = 0;
dev->vol.migr_type = 0;
dev->vol.curr_migr_unit = 0;
memcpy(map, map2, sizeof_imsm_map(map2));
super->updates_pending++;
+ }
}
if (a->last_checkpoint >= a->info.component_size) {
unsigned long long array_blocks;
for (du = super->missing; du; du = du->next)
if (du->index >= 0) {
set_imsm_ord_tbl_ent(map, du->index, du->index);
- mark_missing(dev_new, &du->disk, du->index);
+ mark_missing(dv->dev, &du->disk, du->index);
}
return 1;
__free_imsm_disk(dl);
}
}
-
+#endif /* MDASSEMBLE */
/*******************************************************************************
* Function: open_backup_targets
* Description: Function opens file descriptors for all devices given in
return 0;
}
+#ifndef MDASSEMBLE
/*******************************************************************************
* Function: init_migr_record_imsm
* Description: Function inits imsm migration record
int new_disks = map_dest->num_members;
int dest_layout = 0;
int dest_chunk;
+ unsigned long long start;
+ int data_disks = imsm_num_data_members(dev, 0);
targets = malloc(new_disks * sizeof(int));
if (!targets)
goto abort;
+ for (i = 0; i < new_disks; i++)
+ targets[i] = -1;
+
target_offsets = malloc(new_disks * sizeof(unsigned long long));
if (!target_offsets)
goto abort;
+ start = info->reshape_progress * 512;
for (i = 0; i < new_disks; i++) {
- targets[i] = -1;
target_offsets[i] = (unsigned long long)
__le32_to_cpu(super->migr_rec->ckpt_area_pba) * 512;
+ /* move back copy area adderss, it will be moved forward
+ * in restore_stripes() using start input variable
+ */
+ target_offsets[i] -= start/data_disks;
}
if (open_backup_targets(info, new_disks, targets))
goto abort;
- if (map_dest->raid_level != 0)
- dest_layout = ALGORITHM_LEFT_ASYMMETRIC;
+ dest_layout = imsm_level_to_layout(map_dest->raid_level);
dest_chunk = __le16_to_cpu(map_dest->blocks_per_strip) * 512;
if (restore_stripes(targets, /* list of dest devices */
-1, /* source backup file descriptor */
0, /* input buf offset
* always 0 buf is already offseted */
- 0,
+ start,
length,
buf) != 0) {
fprintf(stderr, Name ": Error restoring stripes\n");
int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state)
{
struct intel_super *super = st->sb;
+ unsigned long long blocks_per_unit;
+ unsigned long long curr_migr_unit;
+
if (load_imsm_migr_rec(super, info) != 0) {
dprintf("imsm: ERROR: Cannot read migration record "
"for checkpoint save.\n");
return 1;
}
- if (__le32_to_cpu(super->migr_rec->blocks_per_unit) == 0) {
+ blocks_per_unit = __le32_to_cpu(super->migr_rec->blocks_per_unit);
+ if (blocks_per_unit == 0) {
dprintf("imsm: no migration in progress.\n");
return 2;
}
+ curr_migr_unit = info->reshape_progress / blocks_per_unit;
+ /* check if array is alligned to copy area
+ * if it is not alligned, add one to current migration unit value
+ * this can happend on array reshape finish only
+ */
+ if (info->reshape_progress % blocks_per_unit)
+ curr_migr_unit++;
super->migr_rec->curr_migr_unit =
- __cpu_to_le32(info->reshape_progress /
- __le32_to_cpu(super->migr_rec->blocks_per_unit));
+ __cpu_to_le32(curr_migr_unit);
super->migr_rec->rec_status = __cpu_to_le32(state);
super->migr_rec->dest_1st_member_lba =
- __cpu_to_le32((__le32_to_cpu(super->migr_rec->curr_migr_unit))
- * __le32_to_cpu(super->migr_rec->dest_depth_per_unit));
+ __cpu_to_le32(curr_migr_unit *
+ __le32_to_cpu(super->migr_rec->dest_depth_per_unit));
if (write_imsm_migr_rec(st) < 0) {
dprintf("imsm: Cannot write migration record "
"outside backup area\n");
return 0;
}
-static __u64 blocks_per_migr_unit(struct intel_super *super,
- struct imsm_dev *dev);
-
/*******************************************************************************
* Function: recover_backup_imsm
* Description: Function recovers critical data from the Migration Copy Area
int retval = 1;
unsigned long curr_migr_unit = __le32_to_cpu(migr_rec->curr_migr_unit);
unsigned long num_migr_units = __le32_to_cpu(migr_rec->num_migr_units);
- int ascending = __le32_to_cpu(migr_rec->ascending_migr);
char buffer[20];
int skipped_disks = 0;
int max_degradation;
strerror(errno));
goto abort;
}
- if (read(targets[i], buf, unit_len) != unit_len) {
+ if ((unsigned)read(targets[i], buf, unit_len) != unit_len) {
fprintf(stderr,
Name ": Cannot read copy area block: %s\n",
strerror(errno));
strerror(errno));
goto abort;
}
- if (write(targets[i], buf, unit_len) != unit_len) {
+ if ((unsigned)write(targets[i], buf, unit_len) != unit_len) {
fprintf(stderr,
Name ": Cannot restore block: %s\n",
strerror(errno));
goto abort;
}
- if (ascending && curr_migr_unit < (num_migr_units-1))
- curr_migr_unit++;
-
- migr_rec->curr_migr_unit = __le32_to_cpu(curr_migr_unit);
- super->migr_rec->rec_status = __cpu_to_le32(UNIT_SRC_NORMAL);
- if (write_imsm_migr_rec(st) == 0) {
- __u64 blocks_per_unit = blocks_per_migr_unit(super, id->dev);
- info->reshape_progress = curr_migr_unit * blocks_per_unit;
+ if (save_checkpoint_imsm(st, info, UNIT_SRC_NORMAL)) {
+ /* ignore error == 2, this can mean end of reshape here
+ */
+ dprintf("imsm: Cannot write checkpoint to "
+ "migration record (UNIT_SRC_NORMAL) during restart\n");
+ } else
retval = 0;
- }
abort:
if (targets) {
|| delta_disks > spares->array.spare_disks) {
fprintf(stderr, Name ": imsm: ERROR: Cannot get spare devices "
"for %s.\n", geo->dev_name);
+ i = -1;
goto abort;
}
dprintf("imsm: info: Volume operation\n");
/* find requested device */
while (dev) {
- imsm_find_array_minor_by_subdev(dev->index, st->container_dev, &devnum);
- if (devnum == geo.dev_id)
+ if (imsm_find_array_minor_by_subdev(
+ dev->index, st->container_dev, &devnum) == 0
+ && devnum == geo.dev_id)
break;
dev = dev->next;
}
* reshape process reach new position
* Parameters:
* sra : general array info
- * to_complete : new sync_max position
* ndata : number of disks in new array's layout
* Returns:
* 0 : success,
* 1 : there is no reshape in progress,
* -1 : fail
******************************************************************************/
-int wait_for_reshape_imsm(struct mdinfo *sra, unsigned long long to_complete,
- int ndata)
+int wait_for_reshape_imsm(struct mdinfo *sra, int ndata)
{
int fd = sysfs_get_fd(sra, NULL, "reshape_position");
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;
- struct timeval timeout;
-
- if (fd < 0)
+ if (fd < 0) {
+ dprintf("imsm: wait_for_reshape_imsm() "
+ "cannot open reshape_position\n");
return 1;
+ }
- sysfs_fd_get_ll(fd, &completed);
+ if (sysfs_fd_get_ll(fd, &completed) < 0) {
+ dprintf("imsm: wait_for_reshape_imsm() "
+ "cannot read reshape_position (no reshape in progres)\n");
+ close(fd);
+ return 0;
+ }
- if (to_complete == 0) {/* reshape till the end of array */
- sysfs_set_str(sra, NULL, "sync_max", "max");
- to_complete = MaxSector;
- } else {
- if (completed > to_complete) {
- close(fd);
- return -1;
- }
- if (sysfs_set_num(sra, NULL, "sync_max",
- to_complete / ndata) != 0) {
- close(fd);
- return -1;
- }
+ if (completed > to_complete) {
+ dprintf("imsm: wait_for_reshape_imsm() "
+ "wrong next position to set %llu (%llu)\n",
+ to_complete, completed);
+ 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",
+ position_to_set);
+ close(fd);
+ return -1;
}
- /* FIXME should not need a timeout at all */
- timeout.tv_sec = 30;
- timeout.tv_usec = 0;
do {
char action[20];
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
- select(fd+1, NULL, NULL, &rfds, &timeout);
+ select(fd+1, &rfds, NULL, NULL, 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");
close(fd);
return 1;
}
- if (sysfs_get_str(sra, NULL, "sync_action",
- action, 20) > 0 &&
- strncmp(action, "reshape", 7) != 0)
- break;
} while (completed < to_complete);
close(fd);
return 0;
struct intel_super *super = st->sb;
struct intel_dev *dv = NULL;
struct imsm_dev *dev = NULL;
- struct imsm_map *map_src, *map_dest;
+ struct imsm_map *map_src;
int migr_vol_qan = 0;
int ndata, odata; /* [bytes] */
int chunk; /* [bytes] */
unsigned long long max_position; /* array size [bytes] */
unsigned long long next_step; /* [blocks]/[bytes] */
unsigned long long old_data_stripe_length;
- unsigned long long new_data_stripe_length;
unsigned long long start_src; /* [bytes] */
unsigned long long start; /* [bytes] */
unsigned long long start_buf_shift; /* [bytes] */
map_src = get_imsm_map(dev, 1);
if (map_src == NULL)
goto abort;
- map_dest = get_imsm_map(dev, 0);
ndata = imsm_num_data_members(dev, 0);
odata = imsm_num_data_members(dev, 1);
migr_rec = super->migr_rec;
- /* [bytes] */
- sra->new_chunk = __le16_to_cpu(map_dest->blocks_per_strip) * 512;
- sra->new_level = map_dest->raid_level;
- new_data_stripe_length = sra->new_chunk * ndata;
-
/* initialize migration record for start condition */
if (sra->reshape_progress == 0)
init_migr_record_imsm(st, dev, sra);
+ else {
+ if (__le32_to_cpu(migr_rec->rec_status) != UNIT_SRC_NORMAL) {
+ dprintf("imsm: cannot restart migration when data "
+ "are present in copy area.\n");
+ goto abort;
+ }
+ }
/* size for data */
buf_size = __le32_to_cpu(migr_rec->blocks_per_unit) * 512;
}
max_position = sra->component_size * ndata;
- if (map_src->raid_level != 0)
- source_layout = ALGORITHM_LEFT_ASYMMETRIC;
+ source_layout = imsm_level_to_layout(map_src->raid_level);
while (__le32_to_cpu(migr_rec->curr_migr_unit) <
__le32_to_cpu(migr_rec->num_migr_units)) {
"migration record (UNIT_SRC_IN_CP_AREA)\n");
goto abort;
}
- /* decrease backup_blocks */
- if (backup_blocks > (unsigned long)next_step)
- backup_blocks -= next_step;
- else
- backup_blocks = 0;
+ } else {
+ /* set next step to use whole border area */
+ border /= next_step;
+ if (border > 1)
+ next_step *= border;
}
/* When data backed up, checkpoint stored,
* kick the kernel to reshape unit of data
*/
next_step = next_step + sra->reshape_progress;
+ /* limit next step to array max position */
+ if (next_step > max_position)
+ next_step = max_position;
sysfs_set_num(sra, NULL, "suspend_lo", sra->reshape_progress);
sysfs_set_num(sra, NULL, "suspend_hi", next_step);
+ sra->reshape_progress = next_step;
/* wait until reshape finish */
- if (wait_for_reshape_imsm(sra, next_step, ndata) < 0) {
+ if (wait_for_reshape_imsm(sra, ndata) < 0) {
dprintf("wait_for_reshape_imsm returned error!\n");
goto abort;
}
- sra->reshape_progress = next_step;
-
if (save_checkpoint_imsm(st, sra, UNIT_SRC_NORMAL) == 1) {
/* ignore error == 2, this can mean end of reshape here
*/
.get_disk_controller_domain = imsm_get_disk_controller_domain,
.reshape_super = imsm_reshape_super,
.manage_reshape = imsm_manage_reshape,
+ .recover_backup = recover_backup_imsm,
#endif
.match_home = match_home_imsm,
.uuid_from_super= uuid_from_super_imsm,
.match_metadata_desc = match_metadata_desc_imsm,
.container_content = container_content_imsm,
- .recover_backup = recover_backup_imsm,
.external = 1,
.name = "imsm",