"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "super-intel.c" between
mdadm-4.2-rc1.tar.xz and mdadm-4.2-rc2.tar.xz

About: mdadm is a tool for creating, managing and monitoring device arrays using the "md" driver in Linux, also known as Software RAID arrays.

super-intel.c  (mdadm-4.2-rc1.tar.xz):super-intel.c  (mdadm-4.2-rc2.tar.xz)
skipping to change at line 697 skipping to change at line 697
{ {
struct sys_dev *list, *elem; struct sys_dev *list, *elem;
char *disk_path; char *disk_path;
if ((list = find_intel_devices()) == NULL) if ((list = find_intel_devices()) == NULL)
return 0; return 0;
if (fd < 0) if (fd < 0)
disk_path = (char *) devname; disk_path = (char *) devname;
else else
disk_path = diskfd_to_devpath(fd); disk_path = diskfd_to_devpath(fd, 1, NULL);
if (!disk_path) if (!disk_path)
return 0; return 0;
for (elem = list; elem; elem = elem->next) for (elem = list; elem; elem = elem->next)
if (path_attached_to_hba(disk_path, elem->path)) if (path_attached_to_hba(disk_path, elem->path))
return elem; return elem;
if (disk_path != devname) if (disk_path != devname)
free(disk_path); free(disk_path);
skipping to change at line 1231 skipping to change at line 1231
(((unsigned long long)__le32_to_cpu(hi)) << 32); (((unsigned long long)__le32_to_cpu(hi)) << 32);
} }
static unsigned long long total_blocks(struct imsm_disk *disk) static unsigned long long total_blocks(struct imsm_disk *disk)
{ {
if (disk == NULL) if (disk == NULL)
return 0; return 0;
return join_u32(disk->total_blocks_lo, disk->total_blocks_hi); return join_u32(disk->total_blocks_lo, disk->total_blocks_hi);
} }
/**
* imsm_num_data_members() - get data drives count for an array.
* @map: Map to analyze.
*
* num_data_members value represents minimal count of drives for level.
* The name of the property could be misleading for RAID5 with asymmetric layout
* because some data required to be calculated from parity.
* The property is extracted from level and num_members value.
*
* Return: num_data_members value on success, zero otherwise.
*/
static __u8 imsm_num_data_members(struct imsm_map *map)
{
switch (get_imsm_raid_level(map)) {
case 0:
return map->num_members;
case 1:
case 10:
return map->num_members / 2;
case 5:
return map->num_members - 1;
default:
dprintf("unsupported raid level\n");
return 0;
}
}
static unsigned long long pba_of_lba0(struct imsm_map *map) static unsigned long long pba_of_lba0(struct imsm_map *map)
{ {
if (map == NULL) if (map == NULL)
return 0; return 0;
return join_u32(map->pba_of_lba0_lo, map->pba_of_lba0_hi); return join_u32(map->pba_of_lba0_lo, map->pba_of_lba0_hi);
} }
static unsigned long long blocks_per_member(struct imsm_map *map) static unsigned long long blocks_per_member(struct imsm_map *map)
{ {
if (map == NULL) if (map == NULL)
skipping to change at line 1304 skipping to change at line 1331
return 0; return 0;
return join_u32(migr_rec->num_migr_units_lo, return join_u32(migr_rec->num_migr_units_lo,
migr_rec->num_migr_units_hi); migr_rec->num_migr_units_hi);
} }
static void set_total_blocks(struct imsm_disk *disk, unsigned long long n) static void set_total_blocks(struct imsm_disk *disk, unsigned long long n)
{ {
split_ull(n, &disk->total_blocks_lo, &disk->total_blocks_hi); split_ull(n, &disk->total_blocks_lo, &disk->total_blocks_hi);
} }
/**
* set_num_domains() - Set number of domains for an array.
* @map: Map to be updated.
*
* num_domains property represents copies count of each data drive, thus make
* it meaningful only for RAID1 and RAID10. IMSM supports two domains for
* raid1 and raid10.
*/
static void set_num_domains(struct imsm_map *map)
{
int level = get_imsm_raid_level(map);
if (level == 1 || level == 10)
map->num_domains = 2;
else
map->num_domains = 1;
}
static void set_pba_of_lba0(struct imsm_map *map, unsigned long long n) static void set_pba_of_lba0(struct imsm_map *map, unsigned long long n)
{ {
split_ull(n, &map->pba_of_lba0_lo, &map->pba_of_lba0_hi); split_ull(n, &map->pba_of_lba0_lo, &map->pba_of_lba0_hi);
} }
static void set_blocks_per_member(struct imsm_map *map, unsigned long long n) static void set_blocks_per_member(struct imsm_map *map, unsigned long long n)
{ {
split_ull(n, &map->blocks_per_member_lo, &map->blocks_per_member_hi); split_ull(n, &map->blocks_per_member_lo, &map->blocks_per_member_hi);
} }
static void set_num_data_stripes(struct imsm_map *map, unsigned long long n) static void set_num_data_stripes(struct imsm_map *map, unsigned long long n)
{ {
split_ull(n, &map->num_data_stripes_lo, &map->num_data_stripes_hi); split_ull(n, &map->num_data_stripes_lo, &map->num_data_stripes_hi);
} }
/**
* update_num_data_stripes() - Calculate and update num_data_stripes value.
* @map: map to be updated.
* @dev_size: size of volume.
*
* num_data_stripes value is addictionally divided by num_domains, therefore for
* levels where num_domains is not 1, nds is a part of real value.
*/
static void update_num_data_stripes(struct imsm_map *map,
unsigned long long dev_size)
{
unsigned long long nds = dev_size / imsm_num_data_members(map);
nds /= map->num_domains;
nds /= map->blocks_per_strip;
set_num_data_stripes(map, nds);
}
static void set_vol_curr_migr_unit(struct imsm_dev *dev, unsigned long long n) static void set_vol_curr_migr_unit(struct imsm_dev *dev, unsigned long long n)
{ {
if (dev == NULL) if (dev == NULL)
return; return;
split_ull(n, &dev->vol.curr_migr_unit_lo, &dev->vol.curr_migr_unit_hi); split_ull(n, &dev->vol.curr_migr_unit_lo, &dev->vol.curr_migr_unit_hi);
} }
static void set_imsm_dev_size(struct imsm_dev *dev, unsigned long long n) static void set_imsm_dev_size(struct imsm_dev *dev, unsigned long long n)
{ {
skipping to change at line 1666 skipping to change at line 1729
printf(" Sector Size : %u\n", super->sector_size); printf(" Sector Size : %u\n", super->sector_size);
sz = imsm_dev_size(dev); sz = imsm_dev_size(dev);
printf(" Array Size : %llu%s\n", printf(" Array Size : %llu%s\n",
(unsigned long long)sz * 512 / super->sector_size, (unsigned long long)sz * 512 / super->sector_size,
human_size(sz * 512)); human_size(sz * 512));
sz = blocks_per_member(map); sz = blocks_per_member(map);
printf(" Per Dev Size : %llu%s\n", printf(" Per Dev Size : %llu%s\n",
(unsigned long long)sz * 512 / super->sector_size, (unsigned long long)sz * 512 / super->sector_size,
human_size(sz * 512)); human_size(sz * 512));
printf(" Sector Offset : %llu\n", printf(" Sector Offset : %llu\n",
pba_of_lba0(map)); pba_of_lba0(map) * 512 / super->sector_size);
printf(" Num Stripes : %llu\n", printf(" Num Stripes : %llu\n",
num_data_stripes(map)); num_data_stripes(map));
printf(" Chunk Size : %u KiB", printf(" Chunk Size : %u KiB",
__le16_to_cpu(map->blocks_per_strip) / 2); __le16_to_cpu(map->blocks_per_strip) / 2);
if (map2) if (map2)
printf(" <-- %u KiB", printf(" <-- %u KiB",
__le16_to_cpu(map2->blocks_per_strip) / 2); __le16_to_cpu(map2->blocks_per_strip) / 2);
printf("\n"); printf("\n");
printf(" Reserved : %d\n", __le32_to_cpu(dev->reserved_blocks)); printf(" Reserved : %d\n", __le32_to_cpu(dev->reserved_blocks));
printf(" Migrate State : "); printf(" Migrate State : ");
skipping to change at line 2126 skipping to change at line 2189
super->sector_size); super->sector_size);
examine_migr_rec_imsm(super); examine_migr_rec_imsm(super);
} }
static void brief_examine_super_imsm(struct supertype *st, int verbose) static void brief_examine_super_imsm(struct supertype *st, int verbose)
{ {
/* We just write a generic IMSM ARRAY entry */ /* We just write a generic IMSM ARRAY entry */
struct mdinfo info; struct mdinfo info;
char nbuf[64]; char nbuf[64];
struct intel_super *super = st->sb;
if (!super->anchor->num_raid_devs) {
printf("ARRAY metadata=imsm\n");
return;
}
getinfo_super_imsm(st, &info, NULL); getinfo_super_imsm(st, &info, NULL);
fname_from_uuid(st, &info, nbuf, ':'); fname_from_uuid(st, &info, nbuf, ':');
printf("ARRAY metadata=imsm UUID=%s\n", nbuf + 5); printf("ARRAY metadata=imsm UUID=%s\n", nbuf + 5);
} }
static void brief_examine_subarrays_imsm(struct supertype *st, int verbose) static void brief_examine_subarrays_imsm(struct supertype *st, int verbose)
{ {
/* We just write a generic IMSM ARRAY entry */ /* We just write a generic IMSM ARRAY entry */
struct mdinfo info; struct mdinfo info;
skipping to change at line 2249 skipping to change at line 2306
dir = opendir("/sys/dev/block"); dir = opendir("/sys/dev/block");
if (!dir) if (!dir)
return 1; return 1;
for (ent = readdir(dir); ent; ent = readdir(dir)) { for (ent = readdir(dir); ent; ent = readdir(dir)) {
int fd; int fd;
char model[64]; char model[64];
char vendor[64]; char vendor[64];
char buf[1024]; char buf[1024];
int major, minor; int major, minor;
char *device; char device[PATH_MAX];
char *c; char *c;
int port; int port;
int type; int type;
if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2) if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
continue; continue;
path = devt_to_devpath(makedev(major, minor)); path = devt_to_devpath(makedev(major, minor), 1, NULL);
if (!path) if (!path)
continue; continue;
if (!path_attached_to_hba(path, hba_path)) { if (!path_attached_to_hba(path, hba_path)) {
free(path); free(path);
path = NULL; path = NULL;
continue; continue;
} }
/* retrieve the scsi device type */ /* retrieve the scsi device */
if (asprintf(&device, "/sys/dev/block/%d:%d/device/xxxxxxx", majo if (!devt_to_devpath(makedev(major, minor), 1, device)) {
r, minor) < 0) {
if (verbose > 0) if (verbose > 0)
pr_err("failed to allocate 'device'\n"); pr_err("failed to get device\n");
err = 2; err = 2;
break; break;
} }
sprintf(device, "/sys/dev/block/%d:%d/device/type", major, minor) if (devpath_to_char(device, "type", buf, sizeof(buf), 0)) {
;
if (load_sys(device, buf, sizeof(buf)) != 0) {
if (verbose > 0)
pr_err("failed to read device type for %s\n",
path);
err = 2; err = 2;
free(device);
break; break;
} }
type = strtoul(buf, NULL, 10); type = strtoul(buf, NULL, 10);
/* if it's not a disk print the vendor and model */ /* if it's not a disk print the vendor and model */
if (!(type == 0 || type == 7 || type == 14)) { if (!(type == 0 || type == 7 || type == 14)) {
vendor[0] = '\0'; vendor[0] = '\0';
model[0] = '\0'; model[0] = '\0';
sprintf(device, "/sys/dev/block/%d:%d/device/vendor", maj
or, minor); if (devpath_to_char(device, "vendor", buf,
if (load_sys(device, buf, sizeof(buf)) == 0) { sizeof(buf), 0) == 0) {
strncpy(vendor, buf, sizeof(vendor)); strncpy(vendor, buf, sizeof(vendor));
vendor[sizeof(vendor) - 1] = '\0'; vendor[sizeof(vendor) - 1] = '\0';
c = (char *) &vendor[sizeof(vendor) - 1]; c = (char *) &vendor[sizeof(vendor) - 1];
while (isspace(*c) || *c == '\0') while (isspace(*c) || *c == '\0')
*c-- = '\0'; *c-- = '\0';
} }
sprintf(device, "/sys/dev/block/%d:%d/device/model", majo
r, minor); if (devpath_to_char(device, "model", buf,
if (load_sys(device, buf, sizeof(buf)) == 0) { sizeof(buf), 0) == 0) {
strncpy(model, buf, sizeof(model)); strncpy(model, buf, sizeof(model));
model[sizeof(model) - 1] = '\0'; model[sizeof(model) - 1] = '\0';
c = (char *) &model[sizeof(model) - 1]; c = (char *) &model[sizeof(model) - 1];
while (isspace(*c) || *c == '\0') while (isspace(*c) || *c == '\0')
*c-- = '\0'; *c-- = '\0';
} }
if (vendor[0] && model[0]) if (vendor[0] && model[0])
sprintf(buf, "%.64s %.64s", vendor, model); sprintf(buf, "%.64s %.64s", vendor, model);
else else
skipping to change at line 2322 skipping to change at line 2376
case 4: case 4:
case 5: sprintf(buf, "cdrom"); break; case 5: sprintf(buf, "cdrom"); break;
case 6: sprintf(buf, "scanner"); break; case 6: sprintf(buf, "scanner"); break;
case 8: sprintf(buf, "media_changer"); break; case 8: sprintf(buf, "media_changer"); break;
case 9: sprintf(buf, "comm"); break; case 9: sprintf(buf, "comm"); break;
case 12: sprintf(buf, "raid"); break; case 12: sprintf(buf, "raid"); break;
default: sprintf(buf, "unknown"); default: sprintf(buf, "unknown");
} }
} else } else
buf[0] = '\0'; buf[0] = '\0';
free(device);
/* chop device path to 'host%d' and calculate the port number */ /* chop device path to 'host%d' and calculate the port number */
c = strchr(&path[hba_len], '/'); c = strchr(&path[hba_len], '/');
if (!c) { if (!c) {
if (verbose > 0) if (verbose > 0)
pr_err("%s - invalid path name\n", path + hba_len ); pr_err("%s - invalid path name\n", path + hba_len );
err = 2; err = 2;
break; break;
} }
*c = '\0'; *c = '\0';
skipping to change at line 2388 skipping to change at line 2441
for (i = 0; i < port_count; i++) for (i = 0; i < port_count; i++)
if (port_mask & (1 << i)) if (port_mask & (1 << i))
printf(" Port%d : - no device attached - \n", i); printf(" Port%d : - no device attached - \n", i);
} }
return err; return err;
} }
static int print_nvme_info(struct sys_dev *hba) static int print_nvme_info(struct sys_dev *hba)
{ {
char buf[1024];
char *device_path;
struct dirent *ent; struct dirent *ent;
DIR *dir; DIR *dir;
int fd;
dir = opendir("/sys/block/"); dir = opendir("/sys/block/");
if (!dir) if (!dir)
return 1; return 1;
for (ent = readdir(dir); ent; ent = readdir(dir)) { for (ent = readdir(dir); ent; ent = readdir(dir)) {
if (strstr(ent->d_name, "nvme")) { char ns_path[PATH_MAX];
fd = open_dev(ent->d_name); char cntrl_path[PATH_MAX];
if (fd < 0) char buf[PATH_MAX];
continue; int fd = -1;
if (!imsm_is_nvme_supported(fd, 0)) { if (!strstr(ent->d_name, "nvme"))
if (fd >= 0) goto skip;
close(fd);
continue;
}
device_path = diskfd_to_devpath(fd); fd = open_dev(ent->d_name);
if (!device_path) { if (fd < 0)
close(fd); goto skip;
continue;
}
if (path_attached_to_hba(device_path, hba->path)) { if (!diskfd_to_devpath(fd, 0, ns_path) ||
fd2devname(fd, buf); !diskfd_to_devpath(fd, 1, cntrl_path))
if (hba->type == SYS_DEV_VMD) goto skip;
printf(" NVMe under VMD : %s", buf);
else if (hba->type == SYS_DEV_NVME) if (!path_attached_to_hba(cntrl_path, hba->path))
printf(" NVMe Device : %s", buf); goto skip;
if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
sizeof(buf))) if (!imsm_is_nvme_namespace_supported(fd, 0))
printf(" (%s)\n", buf); goto skip;
else
printf("()\n"); fd2devname(fd, buf);
} if (hba->type == SYS_DEV_VMD)
free(device_path); printf(" NVMe under VMD : %s", buf);
else if (hba->type == SYS_DEV_NVME)
printf(" NVMe Device : %s", buf);
if (!imsm_read_serial(fd, NULL, (__u8 *)buf,
sizeof(buf)))
printf(" (%s)\n", buf);
else
printf("()\n");
skip:
if (fd > -1)
close(fd); close(fd);
}
} }
closedir(dir); closedir(dir);
return 0; return 0;
} }
static void print_found_intel_controllers(struct sys_dev *elem) static void print_found_intel_controllers(struct sys_dev *elem)
{ {
for (; elem; elem = elem->next) { for (; elem; elem = elem->next) {
pr_err("found Intel(R) "); pr_err("found Intel(R) ");
skipping to change at line 2883 skipping to change at line 2938
int level = get_imsm_raid_level(lo); int level = get_imsm_raid_level(lo);
if (level == 1 || level == 10) { if (level == 1 || level == 10) {
struct imsm_map *hi = get_imsm_map(dev, MAP_1); struct imsm_map *hi = get_imsm_map(dev, MAP_1);
return hi->num_domains; return hi->num_domains;
} else } else
return num_stripes_per_unit_resync(dev); return num_stripes_per_unit_resync(dev);
} }
static __u8 imsm_num_data_members(struct imsm_map *map)
{
/* named 'imsm_' because raid0, raid1 and raid10
* counter-intuitively have the same number of data disks
*/
switch (get_imsm_raid_level(map)) {
case 0:
return map->num_members;
break;
case 1:
case 10:
return map->num_members/2;
case 5:
return map->num_members - 1;
default:
dprintf("unsupported raid level\n");
return 0;
}
}
static unsigned long long calc_component_size(struct imsm_map *map, static unsigned long long calc_component_size(struct imsm_map *map,
struct imsm_dev *dev) struct imsm_dev *dev)
{ {
unsigned long long component_size; unsigned long long component_size;
unsigned long long dev_size = imsm_dev_size(dev); unsigned long long dev_size = imsm_dev_size(dev);
long long calc_dev_size = 0; long long calc_dev_size = 0;
unsigned int member_disks = imsm_num_data_members(map); unsigned int member_disks = imsm_num_data_members(map);
if (member_disks == 0) if (member_disks == 0)
return 0; return 0;
skipping to change at line 3195 skipping to change at line 3230
update_memory_size = update_memory_size =
sizeof(struct imsm_update_general_migration_checkpoint); sizeof(struct imsm_update_general_migration_checkpoint);
*u = xcalloc(1, update_memory_size); *u = xcalloc(1, update_memory_size);
if (*u == NULL) { if (*u == NULL) {
dprintf("error: cannot get memory\n"); dprintf("error: cannot get memory\n");
return 0; return 0;
} }
(*u)->type = update_general_migration_checkpoint; (*u)->type = update_general_migration_checkpoint;
(*u)->curr_migr_unit = current_migr_unit(super->migr_rec); (*u)->curr_migr_unit = current_migr_unit(super->migr_rec);
dprintf("prepared for %llu\n", (*u)->curr_migr_unit); dprintf("prepared for %llu\n", (unsigned long long)(*u)->curr_migr_unit);
return update_memory_size; return update_memory_size;
} }
static void imsm_update_metadata_locally(struct supertype *st, static void imsm_update_metadata_locally(struct supertype *st,
void *buf, int len); void *buf, int len);
/******************************************************************************* /*******************************************************************************
* Function: write_imsm_migr_rec * Function: write_imsm_migr_rec
* Description: Function writes imsm migration record * Description: Function writes imsm migration record
skipping to change at line 3916 skipping to change at line 3951
} }
static void imsm_copy_dev(struct imsm_dev *dest, struct imsm_dev *src) static void imsm_copy_dev(struct imsm_dev *dest, struct imsm_dev *src)
{ {
memcpy(dest, src, sizeof_imsm_dev(src, 0)); memcpy(dest, src, sizeof_imsm_dev(src, 0));
} }
static int compare_super_imsm(struct supertype *st, struct supertype *tst, static int compare_super_imsm(struct supertype *st, struct supertype *tst,
int verbose) int verbose)
{ {
/* /* return:
* return:
* 0 same, or first was empty, and second was copied * 0 same, or first was empty, and second was copied
* 1 second had wrong number * 1 sb are different
* 2 wrong uuid
* 3 wrong other info
*/ */
struct intel_super *first = st->sb; struct intel_super *first = st->sb;
struct intel_super *sec = tst->sb; struct intel_super *sec = tst->sb;
if (!first) { if (!first) {
st->sb = tst->sb; st->sb = tst->sb;
tst->sb = NULL; tst->sb = NULL;
return 0; return 0;
} }
/* in platform dependent environment test if the disks /* in platform dependent environment test if the disks
* use the same Intel hba * use the same Intel hba
* If not on Intel hba at all, allow anything. * if not on Intel hba at all, allow anything.
* doesn't check HBAs if num_raid_devs is not set, as it means
* it is a free floating spare, and all spares regardless of HBA type
* will fall into separate container during the assembly
*/ */
if (!check_env("IMSM_NO_PLATFORM") && first->hba && sec->hba) { if (first->hba && sec->hba && first->anchor->num_raid_devs != 0) {
if (first->hba->type != sec->hba->type) { if (first->hba->type != sec->hba->type) {
if (verbose) if (verbose)
pr_err("HBAs of devices do not match %s != %s\n", pr_err("HBAs of devices do not match %s != %s\n",
get_sys_dev_type(first->hba->type), get_sys_dev_type(first->hba->type),
get_sys_dev_type(sec->hba->type)); get_sys_dev_type(sec->hba->type));
return 3; return 1;
} }
if (first->orom != sec->orom) { if (first->orom != sec->orom) {
if (verbose) if (verbose)
pr_err("HBAs of devices do not match %s != %s\n", pr_err("HBAs of devices do not match %s != %s\n",
first->hba->pci_id, sec->hba->pci_id); first->hba->pci_id, sec->hba->pci_id);
return 3; return 1;
} }
} }
/* if an anchor does not have num_raid_devs set then it is a free
* floating spare
*/
if (first->anchor->num_raid_devs > 0 && if (first->anchor->num_raid_devs > 0 &&
sec->anchor->num_raid_devs > 0) { sec->anchor->num_raid_devs > 0) {
/* Determine if these disks might ever have been /* Determine if these disks might ever have been
* related. Further disambiguation can only take place * related. Further disambiguation can only take place
* in load_super_imsm_all * in load_super_imsm_all
*/ */
__u32 first_family = first->anchor->orig_family_num; __u32 first_family = first->anchor->orig_family_num;
__u32 sec_family = sec->anchor->orig_family_num; __u32 sec_family = sec->anchor->orig_family_num;
if (memcmp(first->anchor->sig, sec->anchor->sig, if (memcmp(first->anchor->sig, sec->anchor->sig,
MAX_SIGNATURE_LENGTH) != 0) MAX_SIGNATURE_LENGTH) != 0)
return 3; return 1;
if (first_family == 0) if (first_family == 0)
first_family = first->anchor->family_num; first_family = first->anchor->family_num;
if (sec_family == 0) if (sec_family == 0)
sec_family = sec->anchor->family_num; sec_family = sec->anchor->family_num;
if (first_family != sec_family) if (first_family != sec_family)
return 3; return 1;
} }
/* if 'first' is a spare promote it to a populated mpb with sec's /* if an anchor does not have num_raid_devs set then it is a free
* family number * floating spare. don't assosiate spare with any array, as during assembl
*/ y
if (first->anchor->num_raid_devs == 0 && * spares shall fall into separate container, from which they can be moved
sec->anchor->num_raid_devs > 0) { * when necessary
int i; */
struct intel_dev *dv; if (first->anchor->num_raid_devs ^ sec->anchor->num_raid_devs)
struct imsm_dev *dev; return 1;
/* we need to copy raid device info from sec if an allocation
* fails here we don't associate the spare
*/
for (i = 0; i < sec->anchor->num_raid_devs; i++) {
dv = xmalloc(sizeof(*dv));
dev = xmalloc(sizeof_imsm_dev(get_imsm_dev(sec, i), 1));
dv->dev = dev;
dv->index = i;
dv->next = first->devlist;
first->devlist = dv;
}
if (i < sec->anchor->num_raid_devs) {
/* allocation failure */
free_devlist(first);
pr_err("imsm: failed to associate spare\n");
return 3;
}
first->anchor->num_raid_devs = sec->anchor->num_raid_devs;
first->anchor->orig_family_num = sec->anchor->orig_family_num;
first->anchor->family_num = sec->anchor->family_num;
memcpy(first->anchor->sig, sec->anchor->sig, MAX_SIGNATURE_LENGTH
);
for (i = 0; i < sec->anchor->num_raid_devs; i++)
imsm_copy_dev(get_imsm_dev(first, i), get_imsm_dev(sec, i
));
}
return 0; return 0;
} }
static void fd2devname(int fd, char *name) static void fd2devname(int fd, char *name)
{ {
struct stat st;
char path[256];
char dname[PATH_MAX];
char *nm; char *nm;
int rv;
name[0] = '\0';
if (fstat(fd, &st) != 0)
return;
sprintf(path, "/sys/dev/block/%d:%d",
major(st.st_rdev), minor(st.st_rdev));
rv = readlink(path, dname, sizeof(dname)-1); nm = fd2kname(fd);
if (rv <= 0) if (!nm)
return; return;
dname[rv] = '\0'; snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm);
nm = strrchr(dname, '/');
if (nm) {
nm++;
snprintf(name, MAX_RAID_SERIAL_LEN, "/dev/%s", nm);
}
} }
static int nvme_get_serial(int fd, void *buf, size_t buf_len) static int nvme_get_serial(int fd, void *buf, size_t buf_len)
{ {
char path[60]; char path[PATH_MAX];
char *name = fd2kname(fd); char *name = fd2kname(fd);
if (!name) if (!name)
return 1; return 1;
if (strncmp(name, "nvme", 4) != 0) if (strncmp(name, "nvme", 4) != 0)
return 1; return 1;
snprintf(path, sizeof(path) - 1, "/sys/block/%s/device/serial", name); if (!diskfd_to_devpath(fd, 1, path))
return 1;
return load_sys(path, buf, buf_len); return devpath_to_char(path, "serial", buf, buf_len, 0);
} }
extern int scsi_get_serial(int fd, void *buf, size_t buf_len); extern int scsi_get_serial(int fd, void *buf, size_t buf_len);
static int imsm_read_serial(int fd, char *devname, static int imsm_read_serial(int fd, char *devname,
__u8 *serial, size_t serial_buf_len) __u8 *serial, size_t serial_buf_len)
{ {
char buf[50]; char buf[50];
int rv; int rv;
size_t len; size_t len;
skipping to change at line 4554 skipping to change at line 4545
if (err) if (err)
return err; return err;
err = parse_raid_devices(super); err = parse_raid_devices(super);
if (err) if (err)
return err; return err;
err = load_bbm_log(super); err = load_bbm_log(super);
clear_hi(super); clear_hi(super);
return err; return err;
} }
static void __free_imsm_disk(struct dl *d) static void __free_imsm_disk(struct dl *d, int close_fd)
{ {
if (d->fd >= 0) if (close_fd && d->fd > -1)
close(d->fd); close(d->fd);
if (d->devname) if (d->devname)
free(d->devname); free(d->devname);
if (d->e) if (d->e)
free(d->e); free(d->e);
free(d); free(d);
} }
static void free_imsm_disks(struct intel_super *super) static void free_imsm_disks(struct intel_super *super)
{ {
struct dl *d; struct dl *d;
while (super->disks) { while (super->disks) {
d = super->disks; d = super->disks;
super->disks = d->next; super->disks = d->next;
__free_imsm_disk(d); __free_imsm_disk(d, 1);
} }
while (super->disk_mgmt_list) { while (super->disk_mgmt_list) {
d = super->disk_mgmt_list; d = super->disk_mgmt_list;
super->disk_mgmt_list = d->next; super->disk_mgmt_list = d->next;
__free_imsm_disk(d); __free_imsm_disk(d, 1);
} }
while (super->missing) { while (super->missing) {
d = super->missing; d = super->missing;
super->missing = d->next; super->missing = d->next;
__free_imsm_disk(d); __free_imsm_disk(d, 1);
} }
} }
/* free all the pieces hanging off of a super pointer */ /* free all the pieces hanging off of a super pointer */
static void __free_imsm(struct intel_super *super, int free_disks) static void __free_imsm(struct intel_super *super, int free_disks)
{ {
struct intel_hba *elem, *next; struct intel_hba *elem, *next;
if (super->buf) { if (super->buf) {
skipping to change at line 5298 skipping to change at line 5289
int rv; int rv;
int retry; int retry;
if (test_partition(fd)) if (test_partition(fd))
/* IMSM not allowed on partitions */ /* IMSM not allowed on partitions */
return 1; return 1;
free_super_imsm(st); free_super_imsm(st);
super = alloc_super(); super = alloc_super();
if (!get_dev_sector_size(fd, NULL, &super->sector_size))
return 1;
if (!super) if (!super)
return 1; return 1;
if (!get_dev_sector_size(fd, NULL, &super->sector_size)) {
free_imsm(super);
return 1;
}
/* Load hba and capabilities if they exist. /* Load hba and capabilities if they exist.
* But do not preclude loading metadata in case capabilities or hba are * But do not preclude loading metadata in case capabilities or hba are
* non-compliant and ignore_hw_compat is set. * non-compliant and ignore_hw_compat is set.
*/ */
rv = find_intel_hba_capability(fd, super, devname); rv = find_intel_hba_capability(fd, super, devname);
/* no orom/efi or non-intel hba of the disk */ /* no orom/efi or non-intel hba of the disk */
if (rv != 0 && st->ignore_hw_compat == 0) { if (rv != 0 && st->ignore_hw_compat == 0) {
if (devname) if (devname)
pr_err("No OROM/EFI properties for %s\n", devname); pr_err("No OROM/EFI properties for %s\n", devname);
free_imsm(super); free_imsm(super);
skipping to change at line 5485 skipping to change at line 5479
struct imsm_super *mpb = super->anchor; struct imsm_super *mpb = super->anchor;
struct intel_dev *dv; struct intel_dev *dv;
struct imsm_dev *dev; struct imsm_dev *dev;
struct imsm_vol *vol; struct imsm_vol *vol;
struct imsm_map *map; struct imsm_map *map;
int idx = mpb->num_raid_devs; int idx = mpb->num_raid_devs;
int i; int i;
int namelen; int namelen;
unsigned long long array_blocks; unsigned long long array_blocks;
size_t size_old, size_new; size_t size_old, size_new;
unsigned long long num_data_stripes;
unsigned int data_disks; unsigned int data_disks;
unsigned long long size_per_member; unsigned long long size_per_member;
if (super->orom && mpb->num_raid_devs >= super->orom->vpa) { if (super->orom && mpb->num_raid_devs >= super->orom->vpa) {
pr_err("This imsm-container already has the maximum of %d volumes \n", super->orom->vpa); pr_err("This imsm-container already has the maximum of %d volumes \n", super->orom->vpa);
return 0; return 0;
} }
/* ensure the mpb is large enough for the new data */ /* ensure the mpb is large enough for the new data */
size_old = __le32_to_cpu(mpb->mpb_size); size_old = __le32_to_cpu(mpb->mpb_size);
skipping to change at line 5603 skipping to change at line 5596
map->ddf = 1; map->ddf = 1;
if (info->level == 1 && info->raid_disks > 2) { if (info->level == 1 && info->raid_disks > 2) {
free(dev); free(dev);
free(dv); free(dv);
pr_err("imsm does not support more than 2 disksin a raid1 volume\ n"); pr_err("imsm does not support more than 2 disksin a raid1 volume\ n");
return 0; return 0;
} }
map->raid_level = info->level; map->raid_level = info->level;
if (info->level == 10) { if (info->level == 10)
map->raid_level = 1; map->raid_level = 1;
map->num_domains = info->raid_disks / 2; set_num_domains(map);
} else if (info->level == 1)
map->num_domains = info->raid_disks;
else
map->num_domains = 1;
/* info->size is only int so use the 'size' parameter instead */
num_data_stripes = size_per_member / info_to_blocks_per_strip(info);
num_data_stripes /= map->num_domains;
set_num_data_stripes(map, num_data_stripes);
size_per_member += NUM_BLOCKS_DIRTY_STRIPE_REGION; size_per_member += NUM_BLOCKS_DIRTY_STRIPE_REGION;
set_blocks_per_member(map, info_to_blocks_per_member(info, set_blocks_per_member(map, info_to_blocks_per_member(info,
size_per_member / size_per_member /
BLOCKS_PER_KB)); BLOCKS_PER_KB));
map->num_members = info->raid_disks; map->num_members = info->raid_disks;
update_num_data_stripes(map, array_blocks);
for (i = 0; i < map->num_members; i++) { for (i = 0; i < map->num_members; i++) {
/* initialized in add_to_super */ /* initialized in add_to_super */
set_imsm_ord_tbl_ent(map, i, IMSM_ORD_REBUILD); set_imsm_ord_tbl_ent(map, i, IMSM_ORD_REBUILD);
} }
mpb->num_raid_devs++; mpb->num_raid_devs++;
mpb->num_raid_devs_created++; mpb->num_raid_devs_created++;
dev->my_vol_raid_dev_num = mpb->num_raid_devs_created; dev->my_vol_raid_dev_num = mpb->num_raid_devs_created;
if (s->consistency_policy <= CONSISTENCY_POLICY_RESYNC) { if (s->consistency_policy <= CONSISTENCY_POLICY_RESYNC) {
dev->rwh_policy = RWH_MULTIPLE_OFF; dev->rwh_policy = RWH_MULTIPLE_OFF;
skipping to change at line 5938 skipping to change at line 5923
dd = xcalloc(sizeof(*dd), 1); dd = xcalloc(sizeof(*dd), 1);
dd->major = major(stb.st_rdev); dd->major = major(stb.st_rdev);
dd->minor = minor(stb.st_rdev); dd->minor = minor(stb.st_rdev);
dd->devname = devname ? xstrdup(devname) : NULL; dd->devname = devname ? xstrdup(devname) : NULL;
dd->fd = fd; dd->fd = fd;
dd->e = NULL; dd->e = NULL;
dd->action = DISK_ADD; dd->action = DISK_ADD;
rv = imsm_read_serial(fd, devname, dd->serial, MAX_RAID_SERIAL_LEN); rv = imsm_read_serial(fd, devname, dd->serial, MAX_RAID_SERIAL_LEN);
if (rv) { if (rv) {
pr_err("failed to retrieve scsi serial, aborting\n"); pr_err("failed to retrieve scsi serial, aborting\n");
if (dd->devname) __free_imsm_disk(dd, 0);
free(dd->devname);
free(dd);
abort(); abort();
} }
if (super->hba && ((super->hba->type == SYS_DEV_NVME) || if (super->hba && ((super->hba->type == SYS_DEV_NVME) ||
(super->hba->type == SYS_DEV_VMD))) { (super->hba->type == SYS_DEV_VMD))) {
int i; int i;
char *devpath = diskfd_to_devpath(fd); char cntrl_path[PATH_MAX];
char controller_path[PATH_MAX]; char *cntrl_name;
char *controller_name; char pci_dev_path[PATH_MAX];
if (!devpath) { if (!diskfd_to_devpath(fd, 2, pci_dev_path) ||
pr_err("failed to get devpath, aborting\n"); !diskfd_to_devpath(fd, 1, cntrl_path)) {
if (dd->devname) pr_err("failed to get dev paths, aborting\n");
free(dd->devname); __free_imsm_disk(dd, 0);
free(dd);
return 1; return 1;
} }
snprintf(controller_path, PATH_MAX-1, "%s/device", devpath); cntrl_name = basename(cntrl_path);
controller_name = basename(devpath);
if (is_multipath_nvme(fd)) if (is_multipath_nvme(fd))
pr_err("%s controller supports Multi-Path I/O, Intel (R) pr_err("%s controller supports Multi-Path I/O, Intel (R)
VROC does not support multipathing\n", controller_name); VROC does not support multipathing\n",
cntrl_name);
free(devpath);
if (!imsm_is_nvme_supported(dd->fd, 1)) { if (devpath_to_vendor(pci_dev_path) == 0x8086) {
if (dd->devname)
free(dd->devname);
free(dd);
return 1;
}
if (devpath_to_vendor(controller_path) == 0x8086) {
/* /*
* If Intel's NVMe drive has serial ended with * If Intel's NVMe drive has serial ended with
* "-A","-B","-1" or "-2" it means that this is "x8" * "-A","-B","-1" or "-2" it means that this is "x8"
* device (double drive on single PCIe card). * device (double drive on single PCIe card).
* User should be warned about potential data loss. * User should be warned about potential data loss.
*/ */
for (i = MAX_RAID_SERIAL_LEN-1; i > 0; i--) { for (i = MAX_RAID_SERIAL_LEN-1; i > 0; i--) {
/* Skip empty character at the end */ /* Skip empty character at the end */
if (dd->serial[i] == 0) if (dd->serial[i] == 0)
continue; continue;
skipping to change at line 6000 skipping to change at line 5973
pr_err("\tThe action you are about to tak e may put your data at risk.\n" pr_err("\tThe action you are about to tak e may put your data at risk.\n"
"\tPlease note that x8 devices ma y consist of two separate x4 devices " "\tPlease note that x8 devices ma y consist of two separate x4 devices "
"located on a single PCIe port.\n " "located on a single PCIe port.\n "
"\tRAID 0 is the only supported c onfiguration for this type of x8 device.\n"); "\tRAID 0 is the only supported c onfiguration for this type of x8 device.\n");
break; break;
} }
} else if (super->hba->type == SYS_DEV_VMD && super->orom && } else if (super->hba->type == SYS_DEV_VMD && super->orom &&
!imsm_orom_has_tpv_support(super->orom)) { !imsm_orom_has_tpv_support(super->orom)) {
pr_err("\tPlatform configuration does not support non-Int el NVMe drives.\n" pr_err("\tPlatform configuration does not support non-Int el NVMe drives.\n"
"\tPlease refer to Intel(R) RSTe/VROC user guide.\ n"); "\tPlease refer to Intel(R) RSTe/VROC user guide.\ n");
free(dd->devname); __free_imsm_disk(dd, 0);
free(dd);
return 1; return 1;
} }
} }
get_dev_size(fd, NULL, &size); get_dev_size(fd, NULL, &size);
if (!get_dev_sector_size(fd, NULL, &member_sector_size)) if (!get_dev_sector_size(fd, NULL, &member_sector_size)) {
__free_imsm_disk(dd, 0);
return 1; return 1;
}
if (super->sector_size == 0) { if (super->sector_size == 0) {
/* this a first device, so sector_size is not set yet */ /* this a first device, so sector_size is not set yet */
super->sector_size = member_sector_size; super->sector_size = member_sector_size;
} }
/* clear migr_rec when adding disk to container */ /* clear migr_rec when adding disk to container */
memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE); memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE);
if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*member_sector_size, if (lseek64(fd, size - MIGR_REC_SECTOR_POSITION*member_sector_size,
SEEK_SET) >= 0) { SEEK_SET) >= 0) {
skipping to change at line 6676 skipping to change at line 6650
if (!mpb) if (!mpb)
return 1; return 1;
if (super->sector_size == 4096) if (super->sector_size == 4096)
convert_to_4k(super); convert_to_4k(super);
return store_imsm_mpb(fd, mpb); return store_imsm_mpb(fd, mpb);
} }
static int validate_geometry_imsm_container(struct supertype *st, int level, static int validate_geometry_imsm_container(struct supertype *st, int level,
int layout, int raiddisks, int chunk, int raiddisks,
unsigned long long size,
unsigned long long data_offset, unsigned long long data_offset,
char *dev, char *dev,
unsigned long long *freesize, unsigned long long *freesize,
int verbose) int verbose)
{ {
int fd; int fd;
unsigned long long ldsize; unsigned long long ldsize;
struct intel_super *super; struct intel_super *super = NULL;
int rv = 0; int rv = 0;
if (level != LEVEL_CONTAINER) if (level != LEVEL_CONTAINER)
return 0; return 0;
if (!dev) if (!dev)
return 1; return 1;
fd = open(dev, O_RDONLY|O_EXCL, 0); fd = dev_open(dev, O_RDONLY|O_EXCL);
if (fd < 0) { if (fd < 0) {
if (verbose > 0) if (verbose > 0)
pr_err("imsm: Cannot open %s: %s\n", pr_err("imsm: Cannot open %s: %s\n",
dev, strerror(errno)); dev, strerror(errno));
return 0; return 0;
} }
if (!get_dev_size(fd, dev, &ldsize)) { if (!get_dev_size(fd, dev, &ldsize))
close(fd); goto exit;
return 0;
}
/* capabilities retrieve could be possible /* capabilities retrieve could be possible
* note that there is no fd for the disks in array. * note that there is no fd for the disks in array.
*/ */
super = alloc_super(); super = alloc_super();
if (!super) { if (!super)
close(fd); goto exit;
return 0;
} if (!get_dev_sector_size(fd, NULL, &super->sector_size))
if (!get_dev_sector_size(fd, NULL, &super->sector_size)) { goto exit;
close(fd);
free_imsm(super);
return 0;
}
rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL); rv = find_intel_hba_capability(fd, super, verbose > 0 ? dev : NULL);
if (rv != 0) { if (rv != 0) {
#if DEBUG #if DEBUG
char str[256]; char str[256];
fd2devname(fd, str); fd2devname(fd, str);
dprintf("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); fd, str, super->orom, rv, raiddisks);
#endif #endif
/* no orom/efi or non-intel hba of the disk */ /* no orom/efi or non-intel hba of the disk */
close(fd); rv = 0;
free_imsm(super); goto exit;
return 0;
} }
close(fd);
if (super->orom) { if (super->orom) {
if (raiddisks > super->orom->tds) { if (raiddisks > super->orom->tds) {
if (verbose) if (verbose)
pr_err("%d exceeds maximum number of platform sup ported disks: %d\n", pr_err("%d exceeds maximum number of platform sup ported disks: %d\n",
raiddisks, super->orom->tds); raiddisks, super->orom->tds);
free_imsm(super); goto exit;
return 0;
} }
if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 && if ((super->orom->attr & IMSM_OROM_ATTR_2TB_DISK) == 0 &&
(ldsize >> 9) >> 32 > 0) { (ldsize >> 9) >> 32 > 0) {
if (verbose) if (verbose)
pr_err("%s exceeds maximum platform supported siz e\n", dev); pr_err("%s exceeds maximum platform supported siz e\n", dev);
free_imsm(super); goto exit;
return 0;
} }
}
*freesize = avail_size_imsm(st, ldsize >> 9, data_offset); if (super->hba->type == SYS_DEV_VMD ||
free_imsm(super); super->hba->type == SYS_DEV_NVME) {
if (!imsm_is_nvme_namespace_supported(fd, 1)) {
if (verbose)
pr_err("NVMe namespace %s is not supporte
d by IMSM\n",
basename(dev));
goto exit;
}
}
}
if (freesize)
*freesize = avail_size_imsm(st, ldsize >> 9, data_offset);
rv = 1;
exit:
if (super)
free_imsm(super);
close(fd);
return 1; return rv;
} }
static unsigned long long find_size(struct extent *e, int *idx, int num_extents) static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
{ {
const unsigned long long base_start = e[*idx].start; const unsigned long long base_start = e[*idx].start;
unsigned long long end = base_start + e[*idx].size; unsigned long long end = base_start + e[*idx].size;
int i; int i;
if (base_start == end) if (base_start == end)
return 0; return 0;
skipping to change at line 6986 skipping to change at line 6963
* this hba * this hba
*/ */
dir = opendir("/sys/dev/block"); dir = opendir("/sys/dev/block");
for (ent = dir ? readdir(dir) : NULL; ent; ent = readdir(dir)) { for (ent = dir ? readdir(dir) : NULL; ent; ent = readdir(dir)) {
int fd; int fd;
char buf[1024]; char buf[1024];
int major, minor; int major, minor;
char *path = NULL; char *path = NULL;
if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2) if (sscanf(ent->d_name, "%d:%d", &major, &minor) != 2)
continue; continue;
path = devt_to_devpath(makedev(major, minor)); path = devt_to_devpath(makedev(major, minor), 1, NULL);
if (!path) if (!path)
continue; continue;
if (!path_attached_to_hba(path, hba_path)) { if (!path_attached_to_hba(path, hba_path)) {
free(path); free(path);
path = NULL; path = NULL;
continue; continue;
} }
free(path); free(path);
path = NULL; path = NULL;
fd = dev_open(ent->d_name, O_RDONLY); fd = dev_open(ent->d_name, O_RDONLY);
skipping to change at line 7606 skipping to change at line 7583
int consistency_policy, int verbose) int consistency_policy, int verbose)
{ {
int fd, cfd; int fd, cfd;
struct mdinfo *sra; struct mdinfo *sra;
int is_member = 0; int is_member = 0;
/* load capability /* load capability
* if given unused devices create a container * if given unused devices create a container
* if given given devices in a container create a member volume * if given given devices in a container create a member volume
*/ */
if (level == LEVEL_CONTAINER) { if (level == LEVEL_CONTAINER)
/* Must be a fresh device to add to a container */ /* Must be a fresh device to add to a container */
return validate_geometry_imsm_container(st, level, layout, return validate_geometry_imsm_container(st, level, raiddisks,
raiddisks, data_offset, dev,
*chunk, freesize, verbose);
size, data_offset,
dev, freesize,
verbose);
}
/* /*
* Size is given in sectors. * Size is given in sectors.
*/ */
if (size && (size < 2048)) { if (size && (size < 2048)) {
pr_err("Given size must be greater than 1M.\n"); pr_err("Given size must be greater than 1M.\n");
/* Depends on algorithm in Create.c : /* Depends on algorithm in Create.c :
* if container was given (dev == NULL) return -1, * if container was given (dev == NULL) return -1,
* if block device was given ( dev != NULL) return 0. * if block device was given ( dev != NULL) return 0.
*/ */
skipping to change at line 8109 skipping to change at line 8082
* reset resync start to avoid a dirty-degraded * reset resync start to avoid a dirty-degraded
* situation when performing the intial sync * situation when performing the intial sync
*/ */
if (skip) if (skip)
missing++; missing++;
if (!(dev->vol.dirty & RAIDVOL_DIRTY)) { if (!(dev->vol.dirty & RAIDVOL_DIRTY)) {
if ((!able_to_resync(level, missing) || if ((!able_to_resync(level, missing) ||
recovery_start == 0)) recovery_start == 0))
this->resync_start = MaxSector; this->resync_start = MaxSector;
} else {
/*
* FIXME handle dirty degraded
*/
} }
if (skip) if (skip)
continue; continue;
info_d = xcalloc(1, sizeof(*info_d)); info_d = xcalloc(1, sizeof(*info_d));
info_d->next = this->devs; info_d->next = this->devs;
this->devs = info_d; this->devs = info_d;
info_d->disk.number = d->index; info_d->disk.number = d->index;
skipping to change at line 9321 skipping to change at line 9290
prev = NULL; prev = NULL;
for (dl = super->disks; dl; dl = dl->next) { for (dl = super->disks; dl; dl = dl->next) {
if (dl->major == major && dl->minor == minor) { if (dl->major == major && dl->minor == minor) {
/* remove */ /* remove */
if (prev) if (prev)
prev->next = dl->next; prev->next = dl->next;
else else
super->disks = dl->next; super->disks = dl->next;
dl->next = NULL; dl->next = NULL;
__free_imsm_disk(dl); __free_imsm_disk(dl, 1);
dprintf("removed %x:%x\n", major, minor); dprintf("removed %x:%x\n", major, minor);
break; break;
} }
prev = dl; prev = dl;
} }
return 0; return 0;
} }
static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind ex); static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind ex);
skipping to change at line 9371 skipping to change at line 9340
if (disk->index == -1) { if (disk->index == -1) {
remove_disk_super(super, remove_disk_super(super,
disk_cfg->major, disk_cfg->major,
disk_cfg->minor); disk_cfg->minor);
} else { } else {
disk_cfg->fd = disk->fd; disk_cfg->fd = disk->fd;
disk->fd = -1; disk->fd = -1;
} }
} }
/* release allocate disk structure */ /* release allocate disk structure */
__free_imsm_disk(disk_cfg); __free_imsm_disk(disk_cfg, 1);
} }
} }
return check_degraded; return check_degraded;
} }
static int apply_reshape_migration_update(struct imsm_update_reshape_migration * u, static int apply_reshape_migration_update(struct imsm_update_reshape_migration * u,
struct intel_super *super, struct intel_super *super,
void ***space_list) void ***space_list)
{ {
struct intel_dev *id; struct intel_dev *id;
skipping to change at line 9446 skipping to change at line 9415
set_imsm_ord_tbl_ent(map, set_imsm_ord_tbl_ent(map,
map->num_members - 1, map->num_members - 1,
ord); ord);
} }
id->dev = new_dev; id->dev = new_dev;
tofree = (void **)dev; tofree = (void **)dev;
/* update chunk size /* update chunk size
*/ */
if (u->new_chunksize > 0) { if (u->new_chunksize > 0) {
unsigned long long num_data_stripes;
struct imsm_map *dest_map = struct imsm_map *dest_map =
get_imsm_map(dev, MAP_0); get_imsm_map(dev, MAP_0);
int used_disks = int used_disks =
imsm_num_data_members(dest_map); imsm_num_data_members(dest_map);
if (used_disks == 0) if (used_disks == 0)
return ret_val; return ret_val;
map->blocks_per_strip = map->blocks_per_strip =
__cpu_to_le16(u->new_chunksize * 2); __cpu_to_le16(u->new_chunksize * 2);
num_data_stripes = update_num_data_stripes(map, imsm_dev_size(dev));
imsm_dev_size(dev) / used_disks;
num_data_stripes /= map->blocks_per_strip;
num_data_stripes /= map->num_domains;
set_num_data_stripes(map, num_data_stripes);
} }
/* ensure blocks_per_member has valid value /* ensure blocks_per_member has valid value
*/ */
set_blocks_per_member(map, set_blocks_per_member(map,
per_dev_array_size(map) + per_dev_array_size(map) +
NUM_BLOCKS_DIRTY_STRIPE_REGION); NUM_BLOCKS_DIRTY_STRIPE_REGION);
/* add disk /* add disk
*/ */
skipping to change at line 9535 skipping to change at line 9499
dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev); dprintf("imsm: Error: Wrong subdev: %i\n", u->subdev);
return ret_val; return ret_val;
} }
for (id = super->devlist ; id; id = id->next) { for (id = super->devlist ; id; id = id->next) {
if (id->index == (unsigned)u->subdev) { if (id->index == (unsigned)u->subdev) {
struct imsm_dev *dev = get_imsm_dev(super, u->subdev); struct imsm_dev *dev = get_imsm_dev(super, u->subdev);
struct imsm_map *map = get_imsm_map(dev, MAP_0); struct imsm_map *map = get_imsm_map(dev, MAP_0);
int used_disks = imsm_num_data_members(map); int used_disks = imsm_num_data_members(map);
unsigned long long blocks_per_member; unsigned long long blocks_per_member;
unsigned long long num_data_stripes;
unsigned long long new_size_per_disk; unsigned long long new_size_per_disk;
if (used_disks == 0) if (used_disks == 0)
return 0; return 0;
/* calculate new size /* calculate new size
*/ */
new_size_per_disk = u->new_size / used_disks; new_size_per_disk = u->new_size / used_disks;
blocks_per_member = new_size_per_disk + blocks_per_member = new_size_per_disk +
NUM_BLOCKS_DIRTY_STRIPE_REGION; NUM_BLOCKS_DIRTY_STRIPE_REGION;
num_data_stripes = new_size_per_disk /
map->blocks_per_strip;
num_data_stripes /= map->num_domains;
dprintf("(size: %llu, blocks per member: %llu, num_data_s
tipes: %llu)\n",
u->new_size, new_size_per_disk,
num_data_stripes);
set_blocks_per_member(map, blocks_per_member);
set_num_data_stripes(map, num_data_stripes);
imsm_set_array_size(dev, u->new_size);
imsm_set_array_size(dev, u->new_size);
set_blocks_per_member(map, blocks_per_member);
update_num_data_stripes(map, u->new_size);
ret_val = 1; ret_val = 1;
break; break;
} }
} }
return ret_val; return ret_val;
} }
static int prepare_spare_to_activate(struct supertype *st, static int prepare_spare_to_activate(struct supertype *st,
struct imsm_update_activate_spare *u) struct imsm_update_activate_spare *u)
skipping to change at line 9837 skipping to change at line 9794
dev = dv->dev; dev = dv->dev;
break; break;
} }
if (dev == NULL) if (dev == NULL)
return 0; return 0;
map = get_imsm_map(dev, MAP_0); map = get_imsm_map(dev, MAP_0);
if (u->direction == R10_TO_R0) { if (u->direction == R10_TO_R0) {
unsigned long long num_data_stripes;
/* Number of failed disks must be half of initial disk number */ /* Number of failed disks must be half of initial disk number */
if (imsm_count_failed(super, dev, MAP_0) != if (imsm_count_failed(super, dev, MAP_0) !=
(map->num_members / 2)) (map->num_members / 2))
return 0; return 0;
/* iterate through devices to mark removed disks as spare */ /* iterate through devices to mark removed disks as spare */
for (dm = super->disks; dm; dm = dm->next) { for (dm = super->disks; dm; dm = dm->next) {
if (dm->disk.status & FAILED_DISK) { if (dm->disk.status & FAILED_DISK) {
int idx = dm->index; int idx = dm->index;
/* update indexes on the disk list */ /* update indexes on the disk list */
/* FIXME this loop-with-the-loop looks wrong, I'm not convinced /* FIXME this loop-with-the-loop looks wrong, I'm not convinced
the index values will end up being correct.... NB */ the index values will end up being correct.... NB */
for (du = super->disks; du; du = du->next) for (du = super->disks; du; du = du->next)
if (du->index > idx) if (du->index > idx)
du->index--; du->index--;
/* mark as spare disk */ /* mark as spare disk */
mark_spare(dm); mark_spare(dm);
} }
} }
/* update map */ /* update map */
map->num_members = map->num_members / 2; map->num_members /= map->num_domains;
map->map_state = IMSM_T_STATE_NORMAL; map->map_state = IMSM_T_STATE_NORMAL;
map->num_domains = 1;
map->raid_level = 0; map->raid_level = 0;
set_num_domains(map);
update_num_data_stripes(map, imsm_dev_size(dev));
map->failed_disk_num = -1; map->failed_disk_num = -1;
num_data_stripes = imsm_dev_size(dev) / 2;
num_data_stripes /= map->blocks_per_strip;
set_num_data_stripes(map, num_data_stripes);
} }
if (u->direction == R0_TO_R10) { if (u->direction == R0_TO_R10) {
void **space; void **space;
unsigned long long num_data_stripes;
/* update slots in current disk list */ /* update slots in current disk list */
for (dm = super->disks; dm; dm = dm->next) { for (dm = super->disks; dm; dm = dm->next) {
if (dm->index >= 0) if (dm->index >= 0)
dm->index *= 2; dm->index *= 2;
} }
/* create new *missing* disks */ /* create new *missing* disks */
for (i = 0; i < map->num_members; i++) { for (i = 0; i < map->num_members; i++) {
space = *space_list; space = *space_list;
if (!space) if (!space)
skipping to change at line 9906 skipping to change at line 9858
} }
/* create new dev and map */ /* create new dev and map */
space = *space_list; space = *space_list;
if (!space) if (!space)
return 0; return 0;
*space_list = *space; *space_list = *space;
dev_new = (void *)space; dev_new = (void *)space;
memcpy(dev_new, dev, sizeof(*dev)); memcpy(dev_new, dev, sizeof(*dev));
/* update new map */ /* update new map */
map = get_imsm_map(dev_new, MAP_0); map = get_imsm_map(dev_new, MAP_0);
map->num_members = map->num_members * 2;
map->map_state = IMSM_T_STATE_DEGRADED; map->map_state = IMSM_T_STATE_DEGRADED;
map->num_domains = 2;
map->raid_level = 1; map->raid_level = 1;
num_data_stripes = imsm_dev_size(dev) / 2; set_num_domains(map);
num_data_stripes /= map->blocks_per_strip; map->num_members = map->num_members * map->num_domains;
num_data_stripes /= map->num_domains; update_num_data_stripes(map, imsm_dev_size(dev));
set_num_data_stripes(map, num_data_stripes);
/* replace dev<->dev_new */ /* replace dev<->dev_new */
dv->dev = dev_new; dv->dev = dev_new;
} }
/* update disk order table */ /* update disk order table */
for (du = super->disks; du; du = du->next) for (du = super->disks; du; du = du->next)
if (du->index >= 0) if (du->index >= 0)
set_imsm_ord_tbl_ent(map, du->index, du->index); set_imsm_ord_tbl_ent(map, du->index, du->index);
for (du = super->missing; du; du = du->next) for (du = super->missing; du; du = du->next)
if (du->index >= 0) { if (du->index >= 0) {
skipping to change at line 10572 skipping to change at line 10522
continue; continue;
entry->disk_ordinal--; entry->disk_ordinal--;
} }
mpb->num_disks--; mpb->num_disks--;
super->updates_pending++; super->updates_pending++;
if (*dlp) { if (*dlp) {
struct dl *dl = *dlp; struct dl *dl = *dlp;
*dlp = (*dlp)->next; *dlp = (*dlp)->next;
__free_imsm_disk(dl); __free_imsm_disk(dl, 1);
} }
} }
static int imsm_get_allowed_degradation(int level, int raid_disks, static int imsm_get_allowed_degradation(int level, int raid_disks,
struct intel_super *super, struct intel_super *super,
struct imsm_dev *dev) struct imsm_dev *dev)
{ {
switch (level) { switch (level) {
case 1: case 1:
case 10:{ case 10:{
skipping to change at line 10649 skipping to change at line 10599
******************************************************************************/ ******************************************************************************/
int validate_container_imsm(struct mdinfo *info) int validate_container_imsm(struct mdinfo *info)
{ {
if (check_env("IMSM_NO_PLATFORM")) if (check_env("IMSM_NO_PLATFORM"))
return 0; return 0;
struct sys_dev *idev; struct sys_dev *idev;
struct sys_dev *hba = NULL; struct sys_dev *hba = NULL;
struct sys_dev *intel_devices = find_intel_devices(); struct sys_dev *intel_devices = find_intel_devices();
char *dev_path = devt_to_devpath(makedev(info->disk.major, char *dev_path = devt_to_devpath(makedev(info->disk.major,
info->dis k.minor)); info->disk.minor), 1, NULL);
for (idev = intel_devices; idev; idev = idev->next) { for (idev = intel_devices; idev; idev = idev->next) {
if (dev_path && strstr(dev_path, idev->path)) { if (dev_path && strstr(dev_path, idev->path)) {
hba = idev; hba = idev;
break; break;
} }
} }
if (dev_path) if (dev_path)
free(dev_path); free(dev_path);
if (!hba) { if (!hba) {
pr_err("WARNING - Cannot detect HBA for device %s!\n", pr_err("WARNING - Cannot detect HBA for device %s!\n",
devid2kname(makedev(info->disk.major, info->disk. minor))); devid2kname(makedev(info->disk.major, info->disk. minor)));
return 1; return 1;
} }
const struct imsm_orom *orom = get_orom_by_device_id(hba->dev_id); const struct imsm_orom *orom = get_orom_by_device_id(hba->dev_id);
struct mdinfo *dev; struct mdinfo *dev;
for (dev = info->next; dev; dev = dev->next) { for (dev = info->next; dev; dev = dev->next) {
dev_path = devt_to_devpath(makedev(dev->disk.major, dev->disk.min dev_path = devt_to_devpath(makedev(dev->disk.major,
or)); dev->disk.minor), 1, NULL);
struct sys_dev *hba2 = NULL; struct sys_dev *hba2 = NULL;
for (idev = intel_devices; idev; idev = idev->next) { for (idev = intel_devices; idev; idev = idev->next) {
if (dev_path && strstr(dev_path, idev->path)) { if (dev_path && strstr(dev_path, idev->path)) {
hba2 = idev; hba2 = idev;
break; break;
} }
} }
if (dev_path) if (dev_path)
free(dev_path); free(dev_path);
skipping to change at line 11128 skipping to change at line 11079
if (dl_disk->fd < 0) { if (dl_disk->fd < 0) {
skipped_disks++; skipped_disks++;
continue; continue;
} }
if (lseek64(dl_disk->fd, read_offset, SEEK_SET) < 0) { if (lseek64(dl_disk->fd, read_offset, SEEK_SET) < 0) {
pr_err("Cannot seek to block: %s\n", pr_err("Cannot seek to block: %s\n",
strerror(errno)); strerror(errno));
skipped_disks++; skipped_disks++;
continue; continue;
} }
if (read(dl_disk->fd, buf, unit_len) != unit_len) { if (read(dl_disk->fd, buf, unit_len) != (ssize_t)unit_len) {
pr_err("Cannot read copy area block: %s\n", pr_err("Cannot read copy area block: %s\n",
strerror(errno)); strerror(errno));
skipped_disks++; skipped_disks++;
continue; continue;
} }
if (lseek64(dl_disk->fd, write_offset, SEEK_SET) < 0) { if (lseek64(dl_disk->fd, write_offset, SEEK_SET) < 0) {
pr_err("Cannot seek to block: %s\n", pr_err("Cannot seek to block: %s\n",
strerror(errno)); strerror(errno));
skipped_disks++; skipped_disks++;
continue; continue;
} }
if (write(dl_disk->fd, buf, unit_len) != unit_len) { if (write(dl_disk->fd, buf, unit_len) != (ssize_t)unit_len) {
pr_err("Cannot restore block: %s\n", pr_err("Cannot restore block: %s\n",
strerror(errno)); strerror(errno));
skipped_disks++; skipped_disks++;
continue; continue;
} }
} }
if (skipped_disks > imsm_get_allowed_degradation(info->new_level, if (skipped_disks > imsm_get_allowed_degradation(info->new_level,
new_disks, new_disks,
super, super,
skipping to change at line 11182 skipping to change at line 11133
char disk_path[PATH_MAX]; char disk_path[PATH_MAX];
char *drv=NULL; char *drv=NULL;
struct stat st; struct stat st;
strcpy(disk_path, disk_by_path); strcpy(disk_path, disk_by_path);
strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1); strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1);
if (stat(disk_path, &st) == 0) { if (stat(disk_path, &st) == 0) {
struct sys_dev* hba; struct sys_dev* hba;
char *path; char *path;
path = devt_to_devpath(st.st_rdev); path = devt_to_devpath(st.st_rdev, 1, NULL);
if (path == NULL) if (path == NULL)
return "unknown"; return "unknown";
hba = find_disk_attached_hba(-1, path); hba = find_disk_attached_hba(-1, path);
if (hba && hba->type == SYS_DEV_SAS) if (hba && hba->type == SYS_DEV_SAS)
drv = "isci"; drv = "isci";
else if (hba && hba->type == SYS_DEV_SATA) else if (hba && hba->type == SYS_DEV_SATA)
drv = "ahci"; drv = "ahci";
else if (hba && hba->type == SYS_DEV_VMD) else if (hba && hba->type == SYS_DEV_VMD)
drv = "vmd"; drv = "vmd";
else if (hba && hba->type == SYS_DEV_NVME) else if (hba && hba->type == SYS_DEV_NVME)
skipping to change at line 11824 skipping to change at line 11775
unsigned int disc_count = imsm_num_data_members(map); unsigned int disc_count = imsm_num_data_members(map);
struct geo_params geo; struct geo_params geo;
struct imsm_update_size_change *update; struct imsm_update_size_change *update;
unsigned long long calc_size = per_dev_array_size(map) * disc_cou nt; unsigned long long calc_size = per_dev_array_size(map) * disc_cou nt;
unsigned long long d_size = imsm_dev_size(dev); unsigned long long d_size = imsm_dev_size(dev);
int u_size; int u_size;
if (calc_size == d_size || dev->vol.migr_type == MIGR_GEN_MIGR) if (calc_size == d_size || dev->vol.migr_type == MIGR_GEN_MIGR)
continue; continue;
/* There is a difference, verify that imsm_dev_size is /* There is a difference, confirm that imsm_dev_size is
* rounded correctly and push update. * smaller and push update.
*/ */
if (d_size != round_size_to_mb(d_size, disc_count)) { if (d_size > calc_size) {
dprintf("imsm: Size of volume %d is not rounded correctly pr_err("imsm: dev size of subarray %d is incorrect\n",
\n", i);
i);
goto exit; goto exit;
} }
memset(&geo, 0, sizeof(struct geo_params)); memset(&geo, 0, sizeof(struct geo_params));
geo.size = d_size; geo.size = d_size;
u_size = imsm_create_metadata_update_for_size_change(st, &geo, u_size = imsm_create_metadata_update_for_size_change(st, &geo,
&update); &update);
if (u_size < 1) { if (u_size < 1) {
dprintf("imsm: Cannot prepare size change update\n"); dprintf("imsm: Cannot prepare size change update\n");
goto exit; goto exit;
} }
 End of changes. 104 change blocks. 
289 lines changed or deleted 233 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)