imsm: Add support for copy area and backup operations
This patch adds methods of manipulating migration record: init_migr_record_imsm() - initiate migration record at the beginning of the reshape process write_imsm_migr_rec() - saves migration record to array. Migration record is stored on 2 first disks in array only. save_backup_imsm() - saves critical data stripes to Migration Copy Area and updates the current migration unit status. Uses restore_stripes() to format a destination stripe, and to write it to the Migration Copy Area. save_checkpoint_imsm() - Updates the current unit status in the migration record. Migration record is written to 2 first array disks only (similar to reading operation). Signed-off-by: Maciej Trela <maciej.trela@intel.com> Signed-off-by: Adam Kwolek <adam.kwolek@intel.com> Signed-off-by: Krzysztof Wojcik <krzysztof.wojcik@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
afbbf073ed
commit
687629c2b2
279
super-intel.c
279
super-intel.c
|
@ -1877,6 +1877,57 @@ out:
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function: write_imsm_migr_rec
|
||||
* Description: Function writes imsm migration record
|
||||
* (at the last sector of disk)
|
||||
* Parameters:
|
||||
* super : imsm internal array info
|
||||
* Returns:
|
||||
* 0 : success
|
||||
* -1 : if fail
|
||||
******************************************************************************/
|
||||
static int write_imsm_migr_rec(struct supertype *st)
|
||||
{
|
||||
struct intel_super *super = st->sb;
|
||||
unsigned long long dsize;
|
||||
char nm[30];
|
||||
int fd = -1;
|
||||
int retval = -1;
|
||||
struct dl *sd;
|
||||
|
||||
for (sd = super->disks ; sd ; sd = sd->next) {
|
||||
/* write to 2 first slots only */
|
||||
if ((sd->index < 0) || (sd->index > 1))
|
||||
continue;
|
||||
sprintf(nm, "%d:%d", sd->major, sd->minor);
|
||||
fd = dev_open(nm, O_RDWR);
|
||||
if (fd < 0)
|
||||
continue;
|
||||
get_dev_size(fd, NULL, &dsize);
|
||||
if (lseek64(fd, dsize - 512, SEEK_SET) < 0) {
|
||||
fprintf(stderr,
|
||||
Name ": Cannot seek to anchor block: %s\n",
|
||||
strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
if (write(fd, super->migr_rec_buf, 512) != 512) {
|
||||
fprintf(stderr,
|
||||
Name ": Cannot write migr record block: %s\n",
|
||||
strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
out:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info, char *dmap)
|
||||
{
|
||||
struct intel_super *super = st->sb;
|
||||
|
@ -7256,6 +7307,234 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function: open_backup_targets
|
||||
* Description: Function opens file descriptors for all devices given in
|
||||
* info->devs
|
||||
* Parameters:
|
||||
* info : general array info
|
||||
* raid_disks : number of disks
|
||||
* raid_fds : table of device's file descriptors
|
||||
* Returns:
|
||||
* 0 : success
|
||||
* -1 : fail
|
||||
******************************************************************************/
|
||||
int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds)
|
||||
{
|
||||
struct mdinfo *sd;
|
||||
|
||||
for (sd = info->devs ; sd ; sd = sd->next) {
|
||||
char *dn;
|
||||
|
||||
if (sd->disk.state & (1<<MD_DISK_FAULTY)) {
|
||||
dprintf("disk is faulty!!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((sd->disk.raid_disk >= raid_disks) ||
|
||||
(sd->disk.raid_disk < 0))
|
||||
continue;
|
||||
|
||||
dn = map_dev(sd->disk.major,
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function: init_migr_record_imsm
|
||||
* Description: Function inits imsm migration record
|
||||
* Parameters:
|
||||
* super : imsm internal array info
|
||||
* dev : device under migration
|
||||
* info : general array info to find the smallest device
|
||||
* Returns:
|
||||
* none
|
||||
******************************************************************************/
|
||||
void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev,
|
||||
struct mdinfo *info)
|
||||
{
|
||||
struct intel_super *super = st->sb;
|
||||
struct migr_record *migr_rec = super->migr_rec;
|
||||
int new_data_disks;
|
||||
unsigned long long dsize, dev_sectors;
|
||||
long long unsigned min_dev_sectors = -1LLU;
|
||||
struct mdinfo *sd;
|
||||
char nm[30];
|
||||
int fd;
|
||||
struct imsm_map *map_dest = get_imsm_map(dev, 0);
|
||||
struct imsm_map *map_src = get_imsm_map(dev, 1);
|
||||
unsigned long long num_migr_units;
|
||||
|
||||
unsigned long long array_blocks =
|
||||
(((unsigned long long)__le32_to_cpu(dev->size_high)) << 32) +
|
||||
__le32_to_cpu(dev->size_low);
|
||||
|
||||
memset(migr_rec, 0, sizeof(struct migr_record));
|
||||
migr_rec->family_num = __cpu_to_le32(super->anchor->family_num);
|
||||
|
||||
/* only ascending reshape supported now */
|
||||
migr_rec->ascending_migr = __cpu_to_le32(1);
|
||||
|
||||
migr_rec->dest_depth_per_unit = GEN_MIGR_AREA_SIZE /
|
||||
max(map_dest->blocks_per_strip, map_src->blocks_per_strip);
|
||||
migr_rec->dest_depth_per_unit *= map_dest->blocks_per_strip;
|
||||
new_data_disks = imsm_num_data_members(dev, 0);
|
||||
migr_rec->blocks_per_unit =
|
||||
__cpu_to_le32(migr_rec->dest_depth_per_unit * new_data_disks);
|
||||
migr_rec->dest_depth_per_unit =
|
||||
__cpu_to_le32(migr_rec->dest_depth_per_unit);
|
||||
|
||||
num_migr_units =
|
||||
array_blocks / __le32_to_cpu(migr_rec->blocks_per_unit);
|
||||
|
||||
if (array_blocks % __le32_to_cpu(migr_rec->blocks_per_unit))
|
||||
num_migr_units++;
|
||||
migr_rec->num_migr_units = __cpu_to_le32(num_migr_units);
|
||||
|
||||
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);
|
||||
fd = dev_open(nm, O_RDONLY);
|
||||
if (fd < 0)
|
||||
continue;
|
||||
get_dev_size(fd, NULL, &dsize);
|
||||
dev_sectors = dsize / 512;
|
||||
if (dev_sectors < min_dev_sectors)
|
||||
min_dev_sectors = dev_sectors;
|
||||
close(fd);
|
||||
}
|
||||
migr_rec->ckpt_area_pba = __cpu_to_le32(min_dev_sectors -
|
||||
RAID_DISK_RESERVED_BLOCKS_IMSM_HI);
|
||||
|
||||
write_imsm_migr_rec(st);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function: save_backup_imsm
|
||||
* Description: Function saves critical data stripes to Migration Copy Area
|
||||
* and updates the current migration unit status.
|
||||
* Use restore_stripes() to form a destination stripe,
|
||||
* and to write it to the Copy Area.
|
||||
* Parameters:
|
||||
* st : supertype information
|
||||
* info : general array info
|
||||
* buf : input buffer
|
||||
* write_offset : address of data to backup
|
||||
* length : length of data to backup (blocks_per_unit)
|
||||
* Returns:
|
||||
* 0 : success
|
||||
*, -1 : fail
|
||||
******************************************************************************/
|
||||
int save_backup_imsm(struct supertype *st,
|
||||
struct imsm_dev *dev,
|
||||
struct mdinfo *info,
|
||||
void *buf,
|
||||
int new_data,
|
||||
int length)
|
||||
{
|
||||
int rv = -1;
|
||||
struct intel_super *super = st->sb;
|
||||
unsigned long long *target_offsets = NULL;
|
||||
int *targets = NULL;
|
||||
int i;
|
||||
struct imsm_map *map_dest = get_imsm_map(dev, 0);
|
||||
int new_disks = map_dest->num_members;
|
||||
|
||||
targets = malloc(new_disks * sizeof(int));
|
||||
if (!targets)
|
||||
goto abort;
|
||||
|
||||
target_offsets = malloc(new_disks * sizeof(unsigned long long));
|
||||
if (!target_offsets)
|
||||
goto abort;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (open_backup_targets(info, new_disks, targets))
|
||||
goto abort;
|
||||
|
||||
if (restore_stripes(targets, /* list of dest devices */
|
||||
target_offsets, /* migration record offsets */
|
||||
new_disks,
|
||||
info->new_chunk,
|
||||
info->new_level,
|
||||
info->new_layout,
|
||||
-1, /* source backup file descriptor */
|
||||
0, /* input buf offset
|
||||
* always 0 buf is already offset */
|
||||
0,
|
||||
length,
|
||||
buf) != 0) {
|
||||
fprintf(stderr, Name ": Error restoring stripes\n");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
|
||||
abort:
|
||||
if (targets) {
|
||||
for (i = 0; i < new_disks; i++)
|
||||
if (targets[i] >= 0)
|
||||
close(targets[i]);
|
||||
free(targets);
|
||||
}
|
||||
free(target_offsets);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function: save_checkpoint_imsm
|
||||
* Description: Function called for current unit status update
|
||||
* in the migration record. It writes it to disk.
|
||||
* Parameters:
|
||||
* super : imsm internal array info
|
||||
* info : general array info
|
||||
* Returns:
|
||||
* 0: success
|
||||
* 1: failure
|
||||
******************************************************************************/
|
||||
int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state)
|
||||
{
|
||||
struct intel_super *super = st->sb;
|
||||
load_imsm_migr_rec(super, info);
|
||||
if (__le32_to_cpu(super->migr_rec->blocks_per_unit) == 0) {
|
||||
dprintf("ERROR: blocks_per_unit = 0!!!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
super->migr_rec->curr_migr_unit =
|
||||
__cpu_to_le32(info->reshape_progress /
|
||||
__le32_to_cpu(super->migr_rec->blocks_per_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));
|
||||
if (write_imsm_migr_rec(st) < 0) {
|
||||
dprintf("imsm: Cannot write migration record "
|
||||
"outside backup area\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char disk_by_path[] = "/dev/disk/by-path/";
|
||||
|
||||
static const char *imsm_get_disk_controller_domain(const char *path)
|
||||
|
|
Loading…
Reference in New Issue