__u32 mpb_size; /* 0x24 - 0x27 Size of MPB */
__u32 family_num; /* 0x28 - 0x2B Checksum from first time this config was written */
__u32 generation_num; /* 0x2C - 0x2F Incremented each time this array's MPB is written */
- __u32 reserved[2]; /* 0x30 - 0x37 */
+ __u32 error_log_size; /* 0x30 - 0x33 in bytes */
+ __u32 attributes; /* 0x34 - 0x37 */
__u8 num_disks; /* 0x38 Number of configured disks */
__u8 num_raid_devs; /* 0x39 Number of configured volumes */
- __u8 fill[2]; /* 0x3A - 0x3B */
-#define IMSM_FILLERS 39
- __u32 filler[IMSM_FILLERS]; /* 0x3C - 0xD7 RAID_MPB_FILLERS */
+ __u8 error_log_pos; /* 0x3A */
+ __u8 fill[1]; /* 0x3B */
+ __u32 cache_size; /* 0x3c - 0x40 in mb */
+ __u32 orig_family_num; /* 0x40 - 0x43 original family num */
+ __u32 pwr_cycle_count; /* 0x44 - 0x47 simulated power cycle count for array */
+ __u32 bbm_log_size; /* 0x48 - 0x4B - size of bad Block Mgmt Log in bytes */
+#define IMSM_FILLERS 35
+ __u32 filler[IMSM_FILLERS]; /* 0x4C - 0xD7 RAID_MPB_FILLERS */
struct imsm_disk disk[1]; /* 0xD8 diskTbl[numDisks] */
/* here comes imsm_dev[num_raid_devs] */
+ /* here comes BBM logs */
} __attribute__ ((packed));
+#define BBM_LOG_MAX_ENTRIES 254
+
+struct bbm_log_entry {
+ __u64 defective_block_start;
+#define UNREADABLE 0xFFFFFFFF
+ __u32 spare_block_offset;
+ __u16 remapped_marked_count;
+ __u16 disk_ordinal;
+} __attribute__ ((__packed__));
+
+struct bbm_log {
+ __u32 signature; /* 0xABADB10C */
+ __u32 entry_count;
+ __u32 reserved_spare_block_count; /* 0 */
+ __u32 reserved; /* 0xFFFF */
+ __u64 first_spare_lba;
+ struct bbm_log_entry mapped_block_entries[BBM_LOG_MAX_ENTRIES];
+} __attribute__ ((__packed__));
+
+
#ifndef MDASSEMBLE
static char *map_state_str[] = { "normal", "uninitialized", "degraded", "failed" };
#endif
char *devname;
int fd;
} *disks;
+ struct bbm_log *bbm_log;
};
struct extent {
printf(" Disks : %d\n", mpb->num_disks);
printf(" RAID Devices : %d\n", mpb->num_raid_devs);
print_imsm_disk(mpb, super->disks->index);
+ if (super->bbm_log) {
+ struct bbm_log *log = super->bbm_log;
+
+ printf("\n");
+ printf("Bad Block Management Log:\n");
+ printf(" Log Size : %d\n", __le32_to_cpu(mpb->bbm_log_size));
+ printf(" Signature : %x\n", __le32_to_cpu(log->signature));
+ printf(" Entry Count : %d\n", __le32_to_cpu(log->entry_count));
+ printf(" Spare Blocks : %d\n", __le32_to_cpu(log->reserved_spare_block_count));
+ printf(" First Spare : %llx\n", __le64_to_cpu(log->first_spare_lba));
+ }
for (i = 0; i < mpb->num_raid_devs; i++)
print_imsm_dev(__get_imsm_dev(mpb, i), super->disks->index);
for (i = 0; i < mpb->num_disks; i++) {
return 0;
}
+/* retrieve a pointer to the bbm log which starts after all raid devices */
+struct bbm_log *__get_imsm_bbm_log(struct imsm_super *mpb)
+{
+ void *ptr = NULL;
+
+ if (__le32_to_cpu(mpb->bbm_log_size)) {
+ ptr = mpb;
+ ptr += mpb->mpb_size - __le32_to_cpu(mpb->bbm_log_size);
+ }
+
+ return ptr;
+}
+
static void __free_imsm(struct intel_super *super);
/* load_imsm_mpb - read matrix metadata
return 2;
}
+ /* FIXME the BBM log is disk specific so we cannot use this global
+ * buffer for all disks. Ok for now since we only look at the global
+ * bbm_log_size parameter to gate assembly
+ */
+ super->bbm_log = __get_imsm_bbm_log(super->anchor);
+
rc = load_imsm_disk(fd, super, devname, 0);
if (rc == 0)
rc = parse_raid_devices(super);
return 1;
}
+int imsm_bbm_log_size(struct imsm_super *mpb)
+{
+ return __le32_to_cpu(mpb->bbm_log_size);
+}
+
static int validate_geometry_imsm(struct supertype *st, int level, int layout,
int raiddisks, int chunk, unsigned long long size,
char *dev, unsigned long long *freesize,
struct mdinfo *rest = NULL;
int i;
+ /* do not assemble arrays that might have bad blocks */
+ if (imsm_bbm_log_size(super->anchor)) {
+ fprintf(stderr, Name ": BBM log found in metadata. "
+ "Cannot activate array(s).\n");
+ return NULL;
+ }
+
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
struct imsm_vol *vol = &dev->vol;