* mutliple PPL area
*/
+/*
+ * This macro let's us ensure that no-one accidentally
+ * changes the size of a struct
+ */
+#define ASSERT_SIZE(_struct, size) \
+static inline void __assert_size_##_struct(void) \
+{ \
+ switch (0) { \
+ case 0: break; \
+ case (sizeof(struct _struct) == size): break; \
+ } \
+}
+
/* Disk configuration info. */
#define IMSM_MAX_DEVICES 255
struct imsm_disk {
#define IMSM_DISK_FILLERS 3
__u32 filler[IMSM_DISK_FILLERS]; /* 0xF5 - 0x107 MPB_DISK_FILLERS for future expansion */
};
+ASSERT_SIZE(imsm_disk, 48)
/* map selector for map managment
*/
__u32 disk_ord_tbl[1]; /* disk_ord_tbl[num_members],
* top byte contains some flags
*/
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_map, 52)
struct imsm_vol {
__u32 curr_migr_unit;
__u32 filler[4];
struct imsm_map map[1];
/* here comes another one if migr_state */
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_vol, 84)
struct imsm_dev {
__u8 volume[MAX_RAID_SERIAL_LEN];
#define IMSM_DEV_FILLERS 3
__u32 filler[IMSM_DEV_FILLERS];
struct imsm_vol vol;
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_dev, 164)
struct imsm_super {
__u8 sig[MAX_SIGNATURE_LENGTH]; /* 0x00 - 0x1F */
struct imsm_disk disk[1]; /* 0xD8 diskTbl[numDisks] */
/* here comes imsm_dev[num_raid_devs] */
/* here comes BBM logs */
-} __attribute__ ((packed));
+};
+ASSERT_SIZE(imsm_super, 264)
#define BBM_LOG_MAX_ENTRIES 254
#define BBM_LOG_MAX_LBA_ENTRY_VAL 256 /* Represents 256 LBAs */
__u32 signature; /* 0xABADB10C */
__u32 entry_count;
struct bbm_log_entry marked_block_entries[BBM_LOG_MAX_ENTRIES];
-} __attribute__ ((__packed__));
+};
+ASSERT_SIZE(bbm_log, 2040)
static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" };
__u32 rec_status; /* Status used to determine how to restart
* migration in case it aborts
* in some fashion */
- __u32 curr_migr_unit; /* 0..numMigrUnits-1 */
+ __u32 curr_migr_unit_lo; /* 0..numMigrUnits-1 */
__u32 family_num; /* Family number of MPB
* containing the RaidDev
* that is migrating */
__u32 dest_depth_per_unit; /* Num member blocks each destMap
* member disk
* advances per unit-of-operation */
- __u32 ckpt_area_pba; /* Pba of first block of ckpt copy area */
- __u32 dest_1st_member_lba; /* First member lba on first
- * stripe of destination */
- __u32 num_migr_units; /* Total num migration units-of-op */
+ __u32 ckpt_area_pba_lo; /* Pba of first block of ckpt copy area */
+ __u32 dest_1st_member_lba_lo; /* First member lba on first
+ * stripe of destination */
+ __u32 num_migr_units_lo; /* Total num migration units-of-op */
__u32 post_migr_vol_cap; /* Size of volume after
* migration completes */
__u32 post_migr_vol_cap_hi; /* Expansion space for LBA64 */
__u32 ckpt_read_disk_num; /* Which member disk in destSubMap[0] the
* migration ckpt record was read from
* (for recovered migrations) */
-} __attribute__ ((__packed__));
+ __u32 curr_migr_unit_hi; /* 0..numMigrUnits-1 high order 32 bits */
+ __u32 ckpt_area_pba_hi; /* Pba of first block of ckpt copy area
+ * high order 32 bits */
+ __u32 dest_1st_member_lba_hi; /* First member lba on first stripe of
+ * destination - high order 32 bits */
+ __u32 num_migr_units_hi; /* Total num migration units-of-op
+ * high order 32 bits */
+};
+ASSERT_SIZE(migr_record, 64)
struct md_list {
/* usage marker:
static __u32 imsm_min_reserved_sectors(struct intel_super *super);
-static int split_ull(unsigned long long n, __u32 *lo, __u32 *hi)
+static int split_ull(unsigned long long n, void *lo, void *hi)
{
if (lo == 0 || hi == 0)
return 1;
- *lo = __le32_to_cpu((unsigned)n);
- *hi = __le32_to_cpu((unsigned)(n >> 32));
+ __put_unaligned32(__cpu_to_le32((__u32)n), lo);
+ __put_unaligned32(__cpu_to_le32((n >> 32)), hi);
return 0;
}
return join_u32(dev->size_low, dev->size_high);
}
+static unsigned long long migr_chkp_area_pba(struct migr_record *migr_rec)
+{
+ if (migr_rec == NULL)
+ return 0;
+ return join_u32(migr_rec->ckpt_area_pba_lo,
+ migr_rec->ckpt_area_pba_hi);
+}
+
+static unsigned long long current_migr_unit(struct migr_record *migr_rec)
+{
+ if (migr_rec == NULL)
+ return 0;
+ return join_u32(migr_rec->curr_migr_unit_lo,
+ migr_rec->curr_migr_unit_hi);
+}
+
+static unsigned long long migr_dest_1st_member_lba(struct migr_record *migr_rec)
+{
+ if (migr_rec == NULL)
+ return 0;
+ return join_u32(migr_rec->dest_1st_member_lba_lo,
+ migr_rec->dest_1st_member_lba_hi);
+}
+
+static unsigned long long get_num_migr_units(struct migr_record *migr_rec)
+{
+ if (migr_rec == NULL)
+ return 0;
+ return join_u32(migr_rec->num_migr_units_lo,
+ migr_rec->num_migr_units_hi);
+}
+
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, &dev->size_low, &dev->size_high);
}
+static void set_migr_chkp_area_pba(struct migr_record *migr_rec,
+ unsigned long long n)
+{
+ split_ull(n, &migr_rec->ckpt_area_pba_lo, &migr_rec->ckpt_area_pba_hi);
+}
+
+static void set_current_migr_unit(struct migr_record *migr_rec,
+ unsigned long long n)
+{
+ split_ull(n, &migr_rec->curr_migr_unit_lo,
+ &migr_rec->curr_migr_unit_hi);
+}
+
+static void set_migr_dest_1st_member_lba(struct migr_record *migr_rec,
+ unsigned long long n)
+{
+ split_ull(n, &migr_rec->dest_1st_member_lba_lo,
+ &migr_rec->dest_1st_member_lba_hi);
+}
+
+static void set_num_migr_units(struct migr_record *migr_rec,
+ unsigned long long n)
+{
+ split_ull(n, &migr_rec->num_migr_units_lo,
+ &migr_rec->num_migr_units_hi);
+}
+
static unsigned long long per_dev_array_size(struct imsm_map *map)
{
unsigned long long array_size = 0;
return array_size;
}
-static struct extent *get_extents(struct intel_super *super, struct dl *dl)
+static struct extent *get_extents(struct intel_super *super, struct dl *dl,
+ int get_minimal_reservation)
{
/* find a list of used extents on the given physical device */
struct extent *rv, *e;
* regardless of whether the OROM has assigned sectors from the
* IMSM_RESERVED_SECTORS region
*/
- if (dl->index == -1)
+ if (dl->index == -1 || get_minimal_reservation)
reservation = imsm_min_reserved_sectors(super);
else
reservation = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
if (dl->index == -1)
return MPB_SECTOR_CNT;
- e = get_extents(super, dl);
+ e = get_extents(super, dl, 0);
if (!e)
return MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
return rv;
/* find last lba used by subarrays on the smallest active disk */
- e = get_extents(super, dl_min);
+ e = get_extents(super, dl_min, 0);
if (!e)
return rv;
for (i = 0; e[i].size; i++)
if (!dl)
return -EINVAL;
/* find last lba used by subarrays */
- e = get_extents(super, dl);
+ e = get_extents(super, dl, 0);
if (!e)
return -EINVAL;
for (i = 0; e[i].size; i++)
struct migr_record *migr_rec = super->migr_rec;
migr_rec->blocks_per_unit /= IMSM_4K_DIV;
- migr_rec->ckpt_area_pba /= IMSM_4K_DIV;
- migr_rec->dest_1st_member_lba /= IMSM_4K_DIV;
migr_rec->dest_depth_per_unit /= IMSM_4K_DIV;
split_ull((join_u32(migr_rec->post_migr_vol_cap,
migr_rec->post_migr_vol_cap_hi) / IMSM_4K_DIV),
&migr_rec->post_migr_vol_cap, &migr_rec->post_migr_vol_cap_hi);
+ set_migr_chkp_area_pba(migr_rec,
+ migr_chkp_area_pba(migr_rec) / IMSM_4K_DIV);
+ set_migr_dest_1st_member_lba(migr_rec,
+ migr_dest_1st_member_lba(migr_rec) / IMSM_4K_DIV);
}
void convert_to_4k_imsm_disk(struct imsm_disk *disk)
printf("Normal\n");
else
printf("Contains Data\n");
- printf(" Current Unit : %u\n",
- __le32_to_cpu(migr_rec->curr_migr_unit));
+ printf(" Current Unit : %llu\n",
+ current_migr_unit(migr_rec));
printf(" Family : %u\n",
__le32_to_cpu(migr_rec->family_num));
printf(" Ascending : %u\n",
__le32_to_cpu(migr_rec->blocks_per_unit));
printf(" Dest. Depth Per Unit : %u\n",
__le32_to_cpu(migr_rec->dest_depth_per_unit));
- printf(" Checkpoint Area pba : %u\n",
- __le32_to_cpu(migr_rec->ckpt_area_pba));
- printf(" First member lba : %u\n",
- __le32_to_cpu(migr_rec->dest_1st_member_lba));
- printf(" Total Number of Units : %u\n",
- __le32_to_cpu(migr_rec->num_migr_units));
- printf(" Size of volume : %u\n",
- __le32_to_cpu(migr_rec->post_migr_vol_cap));
- printf(" Expansion space for LBA64 : %u\n",
- __le32_to_cpu(migr_rec->post_migr_vol_cap_hi));
+ printf(" Checkpoint Area pba : %llu\n",
+ migr_chkp_area_pba(migr_rec));
+ printf(" First member lba : %llu\n",
+ migr_dest_1st_member_lba(migr_rec));
+ printf(" Total Number of Units : %llu\n",
+ get_num_migr_units(migr_rec));
+ printf(" Size of volume : %llu\n",
+ join_u32(migr_rec->post_migr_vol_cap,
+ migr_rec->post_migr_vol_cap_hi));
printf(" Record was read from : %u\n",
__le32_to_cpu(migr_rec->ckpt_read_disk_num));
struct migr_record *migr_rec = super->migr_rec;
migr_rec->blocks_per_unit *= IMSM_4K_DIV;
- migr_rec->ckpt_area_pba *= IMSM_4K_DIV;
- migr_rec->dest_1st_member_lba *= IMSM_4K_DIV;
migr_rec->dest_depth_per_unit *= IMSM_4K_DIV;
split_ull((join_u32(migr_rec->post_migr_vol_cap,
migr_rec->post_migr_vol_cap_hi) * IMSM_4K_DIV),
&migr_rec->post_migr_vol_cap,
&migr_rec->post_migr_vol_cap_hi);
+ set_migr_chkp_area_pba(migr_rec,
+ migr_chkp_area_pba(migr_rec) * IMSM_4K_DIV);
+ set_migr_dest_1st_member_lba(migr_rec,
+ migr_dest_1st_member_lba(migr_rec) * IMSM_4K_DIV);
}
void convert_from_4k(struct intel_super *super)
return 1;
}
-static void detail_super_imsm(struct supertype *st, char *homehost)
+static void detail_super_imsm(struct supertype *st, char *homehost,
+ char *subarray)
{
struct mdinfo info;
char nbuf[64];
+ struct intel_super *super = st->sb;
+ int temp_vol = super->current_vol;
+
+ if (subarray)
+ super->current_vol = strtoul(subarray, NULL, 10);
getinfo_super_imsm(st, &info, NULL);
fname_from_uuid(st, &info, nbuf, ':');
printf("\n UUID : %s\n", nbuf + 5);
+
+ super->current_vol = temp_vol;
}
-static void brief_detail_super_imsm(struct supertype *st)
+static void brief_detail_super_imsm(struct supertype *st, char *subarray)
{
struct mdinfo info;
char nbuf[64];
+ struct intel_super *super = st->sb;
+ int temp_vol = super->current_vol;
+
+ if (subarray)
+ super->current_vol = strtoul(subarray, NULL, 10);
+
getinfo_super_imsm(st, &info, NULL);
fname_from_uuid(st, &info, nbuf, ':');
printf(" UUID=%s", nbuf + 5);
+
+ super->current_vol = temp_vol;
}
-static int imsm_read_serial(int fd, char *devname, __u8 *serial);
+static int imsm_read_serial(int fd, char *devname, __u8 *serial,
+ size_t serial_buf_len);
static void fd2devname(int fd, char *name);
static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_base, int verbose)
else {
fd2devname(fd, buf);
printf(" Port%d : %s", port, buf);
- if (imsm_read_serial(fd, NULL, (__u8 *) buf) == 0)
- printf(" (%.*s)\n", MAX_RAID_SERIAL_LEN, buf);
+ if (imsm_read_serial(fd, NULL, (__u8 *)buf,
+ sizeof(buf)) == 0)
+ printf(" (%s)\n", buf);
else
printf(" ()\n");
close(fd);
return err;
}
-static int print_vmd_attached_devs(struct sys_dev *hba)
+static int print_nvme_info(struct sys_dev *hba)
{
+ char buf[1024];
struct dirent *ent;
DIR *dir;
- char path[292];
- char link[256];
- char *c, *rp;
-
- if (hba->type != SYS_DEV_VMD)
- return 1;
+ char *rp;
+ int fd;
- /* scroll through /sys/dev/block looking for devices attached to
- * this hba
- */
- dir = opendir("/sys/bus/pci/drivers/nvme");
+ dir = opendir("/sys/block/");
if (!dir)
return 1;
for (ent = readdir(dir); ent; ent = readdir(dir)) {
- int n;
-
- /* is 'ent' a device? check that the 'subsystem' link exists and
- * that its target matches 'bus'
- */
- sprintf(path, "/sys/bus/pci/drivers/nvme/%s/subsystem",
- ent->d_name);
- n = readlink(path, link, sizeof(link));
- if (n < 0 || n >= (int)sizeof(link))
- continue;
- link[n] = '\0';
- c = strrchr(link, '/');
- if (!c)
- continue;
- if (strncmp("pci", c+1, strlen("pci")) != 0)
- continue;
-
- sprintf(path, "/sys/bus/pci/drivers/nvme/%s", ent->d_name);
-
- rp = realpath(path, NULL);
- if (!rp)
- continue;
+ if (strstr(ent->d_name, "nvme")) {
+ sprintf(buf, "/sys/block/%s", ent->d_name);
+ rp = realpath(buf, NULL);
+ if (!rp)
+ continue;
+ if (path_attached_to_hba(rp, hba->path)) {
+ fd = open_dev(ent->d_name);
+ if (fd < 0) {
+ free(rp);
+ continue;
+ }
- if (path_attached_to_hba(rp, hba->path)) {
- printf(" NVMe under VMD : %s\n", rp);
+ fd2devname(fd, buf);
+ if (hba->type == SYS_DEV_VMD)
+ 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");
+ close(fd);
+ }
+ free(rp);
}
- free(rp);
}
closedir(dir);
char buf[PATH_MAX];
printf(" I/O Controller : %s (%s)\n",
vmd_domain_to_controller(hba, buf), get_sys_dev_type(hba->type));
- if (print_vmd_attached_devs(hba)) {
+ if (print_nvme_info(hba)) {
if (verbose > 0)
pr_err("failed to get devices attached to VMD domain.\n");
result |= 2;
if (entry->type == SYS_DEV_NVME) {
for (hba = list; hba; hba = hba->next) {
if (hba->type == SYS_DEV_NVME)
- printf(" NVMe Device : %s\n", hba->path);
+ print_nvme_info(hba);
}
printf("\n");
continue;
{
unsigned long long component_size;
unsigned long long dev_size = imsm_dev_size(dev);
- unsigned long long calc_dev_size = 0;
+ long long calc_dev_size = 0;
unsigned int member_disks = imsm_num_data_members(map);
if (member_disks == 0)
* 2048 blocks per each device. If the difference is higher it means
* that array size was expanded and num_data_stripes was not updated.
*/
- if ((unsigned int)abs(calc_dev_size - dev_size) >
+ if (llabs(calc_dev_size - (long long)dev_size) >
(1 << SECT_PER_MB_SHIFT) * member_disks) {
component_size = dev_size / member_disks;
dprintf("Invalid num_data_stripes in metadata; expected=%llu, found=%llu\n",
return 0;
}
(*u)->type = update_general_migration_checkpoint;
- (*u)->curr_migr_unit = __le32_to_cpu(super->migr_rec->curr_migr_unit);
+ (*u)->curr_migr_unit = current_migr_unit(super->migr_rec);
dprintf("prepared for %u\n", (*u)->curr_migr_unit);
return update_memory_size;
case MIGR_GEN_MIGR: {
__u64 blocks_per_unit = blocks_per_migr_unit(super,
dev);
- __u64 units = __le32_to_cpu(migr_rec->curr_migr_unit);
+ __u64 units = current_migr_unit(migr_rec);
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)) &&
+ (get_num_migr_units(migr_rec)-1)) &&
(super->migr_rec->rec_status ==
__cpu_to_le32(UNIT_SRC_IN_CP_AREA)))
units++;
extern int scsi_get_serial(int fd, void *buf, size_t buf_len);
static int imsm_read_serial(int fd, char *devname,
- __u8 serial[MAX_RAID_SERIAL_LEN])
+ __u8 *serial, size_t serial_buf_len)
{
char buf[50];
int rv;
- int len;
+ size_t len;
char *dest;
char *src;
unsigned int i;
len = dest - buf;
dest = buf;
- /* truncate leading characters */
- if (len > MAX_RAID_SERIAL_LEN) {
- dest += len - MAX_RAID_SERIAL_LEN;
- len = MAX_RAID_SERIAL_LEN;
+ if (len > serial_buf_len) {
+ /* truncate leading characters */
+ dest += len - serial_buf_len;
+ len = serial_buf_len;
}
- memset(serial, 0, MAX_RAID_SERIAL_LEN);
+ memset(serial, 0, serial_buf_len);
memcpy(serial, dest, len);
return 0;
char name[40];
__u8 serial[MAX_RAID_SERIAL_LEN];
- rv = imsm_read_serial(fd, devname, serial);
+ rv = imsm_read_serial(fd, devname, serial, MAX_RAID_SERIAL_LEN);
if (rv != 0)
return 2;
struct sys_dev *hba_name;
int rv = 0;
+ if (fd >= 0 && test_partition(fd)) {
+ pr_err("imsm: %s is a partition, cannot be used in IMSM\n",
+ devname);
+ return 1;
+ }
if (fd < 0 || check_env("IMSM_NO_PLATFORM")) {
super->orom = NULL;
super->hba = NULL;
{
struct imsm_super *mpb = super->anchor;
char *reason = NULL;
+ char *start = name;
+ size_t len = strlen(name);
int i;
- if (strlen(name) > MAX_RAID_SERIAL_LEN)
+ if (len > 0) {
+ while (isspace(start[len - 1]))
+ start[--len] = 0;
+ while (*start && isspace(*start))
+ ++start, --len;
+ memmove(name, start, len + 1);
+ }
+
+ if (len > MAX_RAID_SERIAL_LEN)
reason = "must be 16 characters or less";
+ else if (len == 0)
+ reason = "must be a non-empty string";
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
return 1;
}
+ if (mpb->num_disks == 0)
+ if (!get_dev_sector_size(dl->fd, dl->devname,
+ &super->sector_size))
+ return 1;
+
if (!drive_validate_sector_size(super, dl)) {
pr_err("Combining drives of different sector size in one volume is not allowed\n");
return 1;
return ret_val;
ret_val = 0;
- if (!imsm_read_serial(disk->fd, NULL, serial)) {
+ if (!imsm_read_serial(disk->fd, NULL, serial, MAX_RAID_SERIAL_LEN)) {
/* Restore disk serial number, because takeover marks disk
* as failed and adds to serial ':0' before it becomes
* a spare disk.
dd->fd = fd;
dd->e = NULL;
dd->action = DISK_ADD;
- rv = imsm_read_serial(fd, devname, dd->serial);
+ rv = imsm_read_serial(fd, devname, dd->serial, MAX_RAID_SERIAL_LEN);
if (rv) {
pr_err("failed to retrieve scsi serial, aborting\n");
if (dd->devname)
pos = 0;
i = 0;
- e = get_extents(super, dl);
+ e = get_extents(super, dl, 0);
if (!e) continue;
do {
unsigned long long esize;
}
/* retrieve the largest free space block */
- e = get_extents(super, dl);
+ e = get_extents(super, dl, 0);
maxsize = 0;
i = 0;
if (e) {
maxsize = merge_extents(super, i);
- if (!check_env("IMSM_NO_PLATFORM") &&
- mpb->num_raid_devs > 0 && size && size != maxsize) {
- pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n");
- return 0;
- }
+ if (mpb->num_raid_devs > 0 && size && size != maxsize)
+ pr_err("attempting to create a second volume with size less then remaining space.\n");
if (maxsize < size || maxsize == 0) {
if (verbose) {
if (super->orom && dl->index < 0 && mpb->num_raid_devs)
continue;
- e = get_extents(super, dl);
+ e = get_extents(super, dl, 0);
if (!e)
continue;
for (i = 1; e[i-1].size; i++)
}
maxsize = size;
}
- if (!check_env("IMSM_NO_PLATFORM") &&
- mpb->num_raid_devs > 0 && size && size != maxsize) {
- pr_err("attempting to create a second volume with size less then remaining space. Aborting...\n");
- return 0;
- }
+ if (mpb->num_raid_devs > 0 && size && size != maxsize)
+ pr_err("attempting to create a second volume with size less then remaining space.\n");
cnt = 0;
for (dl = super->disks; dl; dl = dl->next)
if (dl->e)
verbose);
}
- if (size && ((size < 1024) || (*chunk != UnSet &&
- size < (unsigned long long) *chunk))) {
- pr_err("Given size must be greater than 1M and chunk size.\n");
+ if (size && (size < 1024)) {
+ pr_err("Given size must be greater than 1M.\n");
/* Depends on algorithm in Create.c :
* if container was given (dev == NULL) return -1,
* if block device was given ( dev != NULL) return 0.
static void handle_missing(struct intel_super *super, struct imsm_dev *dev);
-static int kill_subarray_imsm(struct supertype *st)
+static int kill_subarray_imsm(struct supertype *st, char *subarray_id)
{
- /* remove the subarray currently referenced by ->current_vol */
+ /* remove the subarray currently referenced by subarray_id */
__u8 i;
struct intel_dev **dp;
struct intel_super *super = st->sb;
- __u8 current_vol = super->current_vol;
+ __u8 current_vol = strtoul(subarray_id, NULL, 10);
struct imsm_super *mpb = super->anchor;
- if (super->current_vol < 0)
+ if (mpb->num_raid_devs == 0)
return 2;
- super->current_vol = -1; /* invalidate subarray cursor */
/* block deletions that would change the uuid of active subarrays
*
append_metadata_update(st, u, sizeof(*u));
} else {
struct imsm_dev *dev;
- int i;
+ int i, namelen;
dev = get_imsm_dev(super, vol);
- strncpy((char *) dev->volume, name, MAX_RAID_SERIAL_LEN);
- dev->volume[MAX_RAID_SERIAL_LEN-1] = '\0';
+ memset(dev->volume, '\0', MAX_RAID_SERIAL_LEN);
+ namelen = min((int)strlen(name), MAX_RAID_SERIAL_LEN);
+ memcpy(dev->volume, name, namelen);
for (i = 0; i < mpb->num_raid_devs; i++) {
dev = get_imsm_dev(super, i);
handle_missing(super, dev);
int sb_errors = 0;
struct dl *d;
int spare_disks = 0;
+ int current_vol = super->current_vol;
/* do not assemble arrays when not all attributes are supported */
if (imsm_check_attributes(mpb->attributes) == 0) {
skip = 1;
if (!skip && (ord & IMSM_ORD_REBUILD))
recovery_start = 0;
-
+ if (!(ord & IMSM_ORD_REBUILD))
+ this->array.working_disks++;
/*
* if we skip some disks the array will be assmebled degraded;
* reset resync start to avoid a dirty-degraded
else
this->array.spare_disks++;
}
- if (info_d->recovery_start == MaxSector)
- this->array.working_disks++;
info_d->events = __le32_to_cpu(mpb->generation_num);
info_d->data_offset = pba_of_lba0(map);
rest = this;
}
+ super->current_vol = current_vol;
return rest;
}
set_imsm_ord_tbl_ent(map2, slot2,
idx | IMSM_ORD_REBUILD);
}
- if (map->failed_disk_num == 0xff)
+ if (map->failed_disk_num == 0xff ||
+ (!is_rebuilding(dev) && map->failed_disk_num > slot))
map->failed_disk_num = slot;
clear_disk_badblocks(super->bbm_log, ord_to_idx(ord));
disk = get_imsm_disk(super, ord_to_idx(ord));
/* check for new failures */
- if (state & DS_FAULTY) {
+ if (disk && (state & DS_FAULTY)) {
if (mark_failure(super, dev, disk, ord_to_idx(ord)))
super->updates_pending++;
}
break;
}
if (is_rebuilding(dev)) {
- dprintf_cont("while rebuilding.");
- if (map->map_state != map_state) {
- dprintf_cont(" Map state change");
- end_migration(dev, super, map_state);
+ dprintf_cont("while rebuilding ");
+ if (state & DS_FAULTY) {
+ dprintf_cont("removing failed drive ");
+ if (n == map->failed_disk_num) {
+ dprintf_cont("end migration");
+ end_migration(dev, super, map_state);
+ a->last_checkpoint = 0;
+ } else {
+ dprintf_cont("fail detected during rebuild, changing map state");
+ map->map_state = map_state;
+ }
super->updates_pending++;
- } else if (!rebuild_done) {
- break;
}
+ if (!rebuild_done)
+ break;
+
/* check if recovery is really finished */
for (mdi = a->info.devs; mdi ; mdi = mdi->next)
if (mdi->recovery_start != MaxSector) {
}
if (recovery_not_finished) {
dprintf_cont("\n");
- dprintf("Rebuild has not finished yet, state not changed");
+ dprintf_cont("Rebuild has not finished yet");
if (a->last_checkpoint < mdi->recovery_start) {
a->last_checkpoint =
mdi->recovery_start;
}
dprintf_cont(" Rebuild done, still degraded");
- dev->vol.migr_state = 0;
- set_migr_type(dev, 0);
- dev->vol.curr_migr_unit = 0;
+ end_migration(dev, super, map_state);
+ a->last_checkpoint = 0;
+ super->updates_pending++;
for (i = 0; i < map->num_members; i++) {
int idx = get_imsm_ord_tbl_ent(dev, i, MAP_0);
/* Does this unused device have the requisite free space?
* It needs to be able to cover all member volumes
*/
- ex = get_extents(super, dl);
+ ex = get_extents(super, dl, 1);
if (!ex) {
dprintf("cannot get extents\n");
continue;
remove_disk_super(super,
disk_cfg->major,
disk_cfg->minor);
+ } else {
+ disk_cfg->fd = disk->fd;
+ disk->fd = -1;
}
}
/* release allocate disk structure */
if (u->direction == R10_TO_R0) {
unsigned long long num_data_stripes;
- map->num_domains = 1;
- num_data_stripes = imsm_dev_size(dev) / 2;
- num_data_stripes /= map->blocks_per_strip;
- num_data_stripes /= map->num_domains;
- set_num_data_stripes(map, num_data_stripes);
-
/* Number of failed disks must be half of initial disk number */
if (imsm_count_failed(super, dev, MAP_0) !=
(map->num_members / 2))
map->num_domains = 1;
map->raid_level = 0;
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) {
void **space;
+ unsigned long long num_data_stripes;
+
/* update slots in current disk list */
for (dm = super->disks; dm; dm = dm->next) {
if (dm->index >= 0)
map->map_state = IMSM_T_STATE_DEGRADED;
map->num_domains = 2;
map->raid_level = 1;
+ num_data_stripes = imsm_dev_size(dev) / 2;
+ num_data_stripes /= map->blocks_per_strip;
+ num_data_stripes /= map->num_domains;
+ set_num_data_stripes(map, num_data_stripes);
+
/* replace dev<->dev_new */
dv->dev = dev_new;
}
/* sanity check that we are not affecting the uuid of
* an active array
*/
+ memset(name, 0, sizeof(name));
snprintf(name, MAX_RAID_SERIAL_LEN, "%s", (char *) u->name);
name[MAX_RAID_SERIAL_LEN] = '\0';
for (a = st->arrays; a; a = a->next)
break;
}
- snprintf((char *) dev->volume, MAX_RAID_SERIAL_LEN, "%s", name);
+ memcpy(dev->volume, name, MAX_RAID_SERIAL_LEN);
super->updates_pending++;
break;
}
break;
}
default:
- pr_err("error: unsuported process update type:(type: %d)\n", type);
+ pr_err("error: unsupported process update type:(type: %d)\n", type);
}
}
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);
+ set_num_migr_units(migr_rec, num_migr_units);
migr_rec->post_migr_vol_cap = dev->size_low;
migr_rec->post_migr_vol_cap_hi = dev->size_high;
min_dev_sectors = dev_sectors;
close(fd);
}
- migr_rec->ckpt_area_pba = __cpu_to_le32(min_dev_sectors -
+ set_migr_chkp_area_pba(migr_rec, min_dev_sectors -
RAID_DISK_RESERVED_BLOCKS_IMSM_HI);
write_imsm_migr_rec(st);
start = info->reshape_progress * 512;
for (i = 0; i < new_disks; i++) {
- target_offsets[i] = (unsigned long long)
- __le32_to_cpu(super->migr_rec->ckpt_area_pba) * 512;
+ target_offsets[i] = migr_chkp_area_pba(super->migr_rec) * 512;
/* move back copy area adderss, it will be moved forward
* in restore_stripes() using start input variable
*/
if (info->reshape_progress % blocks_per_unit)
curr_migr_unit++;
- super->migr_rec->curr_migr_unit =
- __cpu_to_le32(curr_migr_unit);
+ set_current_migr_unit(super->migr_rec, curr_migr_unit);
super->migr_rec->rec_status = __cpu_to_le32(state);
- super->migr_rec->dest_1st_member_lba =
- __cpu_to_le32(curr_migr_unit *
- __le32_to_cpu(super->migr_rec->dest_depth_per_unit));
+ set_migr_dest_1st_member_lba(super->migr_rec,
+ super->migr_rec->dest_depth_per_unit * curr_migr_unit);
+
if (write_imsm_migr_rec(st) < 0) {
dprintf("imsm: Cannot write migration record outside backup area\n");
return 1;
char *buf = NULL;
int retval = 1;
unsigned int sector_size = super->sector_size;
- 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);
+ unsigned long curr_migr_unit = current_migr_unit(migr_rec);
+ unsigned long num_migr_units = get_num_migr_units(migr_rec);
char buffer[20];
int skipped_disks = 0;
map_dest = get_imsm_map(id->dev, MAP_0);
new_disks = map_dest->num_members;
- read_offset = (unsigned long long)
- __le32_to_cpu(migr_rec->ckpt_area_pba) * 512;
+ read_offset = migr_chkp_area_pba(migr_rec) * 512;
- write_offset = ((unsigned long long)
- __le32_to_cpu(migr_rec->dest_1st_member_lba) +
+ write_offset = (migr_dest_1st_member_lba(migr_rec) +
pba_of_lba0(map_dest)) * 512;
unit_len = __le32_to_cpu(migr_rec->dest_depth_per_unit) * 512;
dprintf("for level : %i\n", geo.level);
dprintf("for raid_disks : %i\n", geo.raid_disks);
- if (experimental() == 0)
- return ret_val;
-
if (strcmp(st->container_devnm, st->devnm) == 0) {
/* On container level we can only increase number of devices. */
dprintf("imsm: info: Container operation\n");
max_position = sra->component_size * ndata;
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)) {
+ while (current_migr_unit(migr_rec) <
+ get_num_migr_units(migr_rec)) {
/* current reshape position [blocks] */
unsigned long long current_position =
__le32_to_cpu(migr_rec->blocks_per_unit)
- * __le32_to_cpu(migr_rec->curr_migr_unit);
+ * current_migr_unit(migr_rec);
unsigned long long border;
/* Check that array hasn't become failed.