summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>2021-01-13 09:58:45 +0100
committerJes Sorensen <jsorensen@fb.com>2021-03-08 10:12:51 -0500
commit2f86fda346e43f5bc1702a27653ff0418a8262dc (patch)
treeec4cb86887dd2da05849e6b100d18de4679bf418
parentf7a6246bab1541d7208a5f0f9f0c6cac114e38da (diff)
downloadmdadm-2f86fda346e43f5bc1702a27653ff0418a8262dc.tar.gz
imsm: use saved fds during migration
IMSM super keeps open descriptors in super->disks structure, they are reliable and should be chosen if possible. The repeatedly called open and close during reshape generates redundant udev change events on each member drive. Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com> Signed-off-by: Jes Sorensen <jsorensen@fb.com>
-rw-r--r--super-intel.c208
1 files changed, 54 insertions, 154 deletions
diff --git a/super-intel.c b/super-intel.c
index 715febf7..c3466d0c 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -3055,15 +3055,13 @@ static struct imsm_dev *imsm_get_device_during_migration(
* sector of disk)
* Parameters:
* super : imsm internal array info
- * info : general array info
* Returns:
* 0 : success
* -1 : fail
* -2 : no migration in progress
******************************************************************************/
-static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
+static int load_imsm_migr_rec(struct intel_super *super)
{
- struct mdinfo *sd;
struct dl *dl;
char nm[30];
int retval = -1;
@@ -3071,6 +3069,7 @@ static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
struct imsm_dev *dev;
struct imsm_map *map;
int slot = -1;
+ int keep_fd = 1;
/* find map under migration */
dev = imsm_get_device_during_migration(super);
@@ -3079,44 +3078,40 @@ static int load_imsm_migr_rec(struct intel_super *super, struct mdinfo *info)
if (dev == NULL)
return -2;
- if (info) {
- for (sd = info->devs ; sd ; sd = sd->next) {
- /* read only from one of the first two slots */
- if ((sd->disk.raid_disk < 0) ||
- (sd->disk.raid_disk > 1))
- continue;
+ map = get_imsm_map(dev, MAP_0);
+ if (!map)
+ return -1;
- sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
- fd = dev_open(nm, O_RDONLY);
- if (fd >= 0)
- break;
- }
- }
- if (fd < 0) {
- map = get_imsm_map(dev, MAP_0);
- for (dl = super->disks; dl; dl = dl->next) {
- /* skip spare and failed disks
- */
- if (dl->index < 0)
- continue;
- /* read only from one of the first two slots */
- if (map)
- slot = get_imsm_disk_slot(map, dl->index);
- if (map == NULL || slot > 1 || slot < 0)
- continue;
+ for (dl = super->disks; dl; dl = dl->next) {
+ /* skip spare and failed disks
+ */
+ if (dl->index < 0)
+ continue;
+ /* read only from one of the first two slots
+ */
+ slot = get_imsm_disk_slot(map, dl->index);
+ if (slot > 1 || slot < 0)
+ continue;
+
+ if (dl->fd < 0) {
sprintf(nm, "%d:%d", dl->major, dl->minor);
fd = dev_open(nm, O_RDONLY);
- if (fd >= 0)
+ if (fd >= 0) {
+ keep_fd = 0;
break;
+ }
+ } else {
+ fd = dl->fd;
+ break;
}
}
+
if (fd < 0)
- goto out;
+ return retval;
retval = read_imsm_migr_rec(fd, super);
-
-out:
- if (fd >= 0)
+ if (!keep_fd)
close(fd);
+
return retval;
}
@@ -3177,8 +3172,6 @@ static int write_imsm_migr_rec(struct supertype *st)
struct intel_super *super = st->sb;
unsigned int sector_size = super->sector_size;
unsigned long long dsize;
- char nm[30];
- int fd = -1;
int retval = -1;
struct dl *sd;
int len;
@@ -3211,26 +3204,21 @@ static int write_imsm_migr_rec(struct supertype *st)
if (map == NULL || slot > 1 || slot < 0)
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 - (MIGR_REC_SECTOR_POSITION*sector_size),
+ get_dev_size(sd->fd, NULL, &dsize);
+ if (lseek64(sd->fd, dsize - (MIGR_REC_SECTOR_POSITION *
+ sector_size),
SEEK_SET) < 0) {
pr_err("Cannot seek to anchor block: %s\n",
strerror(errno));
goto out;
}
- if ((unsigned int)write(fd, super->migr_rec_buf,
+ if ((unsigned int)write(sd->fd, super->migr_rec_buf,
MIGR_REC_BUF_SECTORS*sector_size) !=
MIGR_REC_BUF_SECTORS*sector_size) {
pr_err("Cannot write migr record block: %s\n",
strerror(errno));
goto out;
}
- close(fd);
- fd = -1;
}
if (sector_size == 4096)
convert_from_4k_imsm_migr_rec(super);
@@ -3256,8 +3244,6 @@ static int write_imsm_migr_rec(struct supertype *st)
retval = 0;
out:
- if (fd >= 0)
- close(fd);
return retval;
}
@@ -5011,7 +4997,7 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp,
}
/* load migration record */
- err = load_imsm_migr_rec(super, NULL);
+ err = load_imsm_migr_rec(super);
if (err == -1) {
/* migration is in progress,
* but migr_rec cannot be loaded,
@@ -5260,7 +5246,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname)
}
/* load migration record */
- if (load_imsm_migr_rec(super, NULL) == 0) {
+ if (load_imsm_migr_rec(super) == 0) {
/* Check for unsupported migration features */
if (check_mpb_migr_compatibility(super) != 0) {
pr_err("Unsupported migration detected");
@@ -10381,21 +10367,6 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
}
}
-static void close_targets(int *targets, int new_disks)
-{
- int i;
-
- if (!targets)
- return;
-
- for (i = 0; i < new_disks; i++) {
- if (targets[i] >= 0) {
- close(targets[i]);
- targets[i] = -1;
- }
- }
-}
-
static int imsm_get_allowed_degradation(int level, int raid_disks,
struct intel_super *super,
struct imsm_dev *dev)
@@ -10450,62 +10421,6 @@ static int imsm_get_allowed_degradation(int level, int raid_disks,
}
/*******************************************************************************
- * 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
- * super : intel super for raid10 degradation check
- * dev : intel device for raid10 degradation check
- * Returns:
- * 0 : success
- * -1 : fail
- ******************************************************************************/
-int open_backup_targets(struct mdinfo *info, int raid_disks, int *raid_fds,
- struct intel_super *super, struct imsm_dev *dev)
-{
- struct mdinfo *sd;
- int i;
- int opened = 0;
-
- for (i = 0; i < raid_disks; i++)
- raid_fds[i] = -1;
-
- 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) {
- pr_err("cannot open component\n");
- continue;
- }
- opened++;
- }
- /* check if maximum array degradation level is not exceeded
- */
- if ((raid_disks - opened) >
- imsm_get_allowed_degradation(info->new_level, raid_disks,
- super, dev)) {
- 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.
@@ -10745,13 +10660,11 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev,
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, MAP_0);
struct imsm_map *map_src = get_imsm_map(dev, MAP_1);
unsigned long long num_migr_units;
unsigned long long array_blocks;
+ struct dl *dl_disk = NULL;
memset(migr_rec, 0, sizeof(struct migr_record));
migr_rec->family_num = __cpu_to_le32(super->anchor->family_num);
@@ -10780,16 +10693,14 @@ void init_migr_record_imsm(struct supertype *st, struct imsm_dev *dev,
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)
+ for (dl_disk = super->disks; dl_disk ; dl_disk = dl_disk->next) {
+ /* ignore spares in container */
+ if (dl_disk->index < 0)
continue;
- get_dev_size(fd, NULL, &dsize);
+ get_dev_size(dl_disk->fd, NULL, &dsize);
dev_sectors = dsize / 512;
if (dev_sectors < min_dev_sectors)
min_dev_sectors = dev_sectors;
- close(fd);
}
set_migr_chkp_area_pba(migr_rec, min_dev_sectors -
RAID_DISK_RESERVED_BLOCKS_IMSM_HI);
@@ -10835,8 +10746,11 @@ int save_backup_imsm(struct supertype *st,
targets = xmalloc(new_disks * sizeof(int));
- for (i = 0; i < new_disks; i++)
- targets[i] = -1;
+ for (i = 0; i < new_disks; i++) {
+ struct dl *dl_disk = get_imsm_dl_disk(super, i);
+
+ targets[i] = dl_disk->fd;
+ }
target_offsets = xcalloc(new_disks, sizeof(unsigned long long));
@@ -10849,10 +10763,6 @@ int save_backup_imsm(struct supertype *st,
target_offsets[i] -= start/data_disks;
}
- if (open_backup_targets(info, new_disks, targets,
- super, dev))
- goto abort;
-
dest_layout = imsm_level_to_layout(map_dest->raid_level);
dest_chunk = __le16_to_cpu(map_dest->blocks_per_strip) * 512;
@@ -10876,7 +10786,6 @@ int save_backup_imsm(struct supertype *st,
abort:
if (targets) {
- close_targets(targets, new_disks);
free(targets);
}
free(target_offsets);
@@ -10903,7 +10812,7 @@ int save_checkpoint_imsm(struct supertype *st, struct mdinfo *info, int state)
unsigned long long blocks_per_unit;
unsigned long long curr_migr_unit;
- if (load_imsm_migr_rec(super, info) != 0) {
+ if (load_imsm_migr_rec(super) != 0) {
dprintf("imsm: ERROR: Cannot read migration record for checkpoint save.\n");
return 1;
}
@@ -10954,8 +10863,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
unsigned long long read_offset;
unsigned long long write_offset;
unsigned unit_len;
- int *targets = NULL;
- int new_disks, i, err;
+ int new_disks, err;
char *buf = NULL;
int retval = 1;
unsigned int sector_size = super->sector_size;
@@ -10963,6 +10871,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
unsigned long num_migr_units = get_num_migr_units(migr_rec);
char buffer[20];
int skipped_disks = 0;
+ struct dl *dl_disk;
err = sysfs_get_str(info, NULL, "array_state", (char *)buffer, 20);
if (err < 1)
@@ -10995,37 +10904,34 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
unit_len = __le32_to_cpu(migr_rec->dest_depth_per_unit) * 512;
if (posix_memalign((void **)&buf, sector_size, unit_len) != 0)
goto abort;
- targets = xcalloc(new_disks, sizeof(int));
- if (open_backup_targets(info, new_disks, targets, super, id->dev)) {
- pr_err("Cannot open some devices belonging to array.\n");
- goto abort;
- }
+ for (dl_disk = super->disks; dl_disk; dl_disk = dl_disk->next) {
+ if (dl_disk->index < 0)
+ continue;
- for (i = 0; i < new_disks; i++) {
- if (targets[i] < 0) {
+ if (dl_disk->fd < 0) {
skipped_disks++;
continue;
}
- if (lseek64(targets[i], read_offset, SEEK_SET) < 0) {
+ if (lseek64(dl_disk->fd, read_offset, SEEK_SET) < 0) {
pr_err("Cannot seek to block: %s\n",
strerror(errno));
skipped_disks++;
continue;
}
- if ((unsigned)read(targets[i], buf, unit_len) != unit_len) {
+ if (read(dl_disk->fd, buf, unit_len) != unit_len) {
pr_err("Cannot read copy area block: %s\n",
strerror(errno));
skipped_disks++;
continue;
}
- if (lseek64(targets[i], write_offset, SEEK_SET) < 0) {
+ if (lseek64(dl_disk->fd, write_offset, SEEK_SET) < 0) {
pr_err("Cannot seek to block: %s\n",
strerror(errno));
skipped_disks++;
continue;
}
- if ((unsigned)write(targets[i], buf, unit_len) != unit_len) {
+ if (write(dl_disk->fd, buf, unit_len) != unit_len) {
pr_err("Cannot restore block: %s\n",
strerror(errno));
skipped_disks++;
@@ -11049,12 +10955,6 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info)
retval = 0;
abort:
- if (targets) {
- for (i = 0; i < new_disks; i++)
- if (targets[i])
- close(targets[i]);
- free(targets);
- }
free(buf);
return retval;
}