]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-intel.c
imsm: fixup disk status definition endianess
[thirdparty/mdadm.git] / super-intel.c
index 7e21c45612c5c1e4edc204ca91507343647e7ddd..6676692ff9e52b836eed6ac73212aaf30cdc6e97 100644 (file)
 #define MPB_SIG_LEN (strlen(MPB_SIGNATURE))
 #define MPB_VERSION_RAID0 "1.0.00"
 #define MPB_VERSION_RAID1 "1.1.00"
+#define MPB_VERSION_MANY_VOLUMES_PER_ARRAY "1.2.00"
+#define MPB_VERSION_3OR4_DISK_ARRAY "1.2.01"
 #define MPB_VERSION_RAID5 "1.2.02"
+#define MPB_VERSION_5OR6_DISK_ARRAY "1.2.04"
+#define MPB_VERSION_CNG "1.2.06"
+#define MPB_VERSION_ATTRIBS "1.3.00"
 #define MAX_SIGNATURE_LENGTH  32
 #define MAX_RAID_SERIAL_LEN   16
+
+#define MPB_ATTRIB_CHECKSUM_VERIFY __cpu_to_le32(0x80000000)
+#define MPB_ATTRIB_PM      __cpu_to_le32(0x40000000)
+#define MPB_ATTRIB_2TB     __cpu_to_le32(0x20000000)
+#define MPB_ATTRIB_RAID0   __cpu_to_le32(0x00000001)
+#define MPB_ATTRIB_RAID1   __cpu_to_le32(0x00000002)
+#define MPB_ATTRIB_RAID10  __cpu_to_le32(0x00000004)
+#define MPB_ATTRIB_RAID1E  __cpu_to_le32(0x00000008)
+#define MPB_ATTRIB_RAID5   __cpu_to_le32(0x00000010)
+#define MPB_ATTRIB_RAIDCNG __cpu_to_le32(0x00000020)
+
 #define MPB_SECTOR_CNT 418
 #define IMSM_RESERVED_SECTORS 4096
 
@@ -42,13 +58,13 @@ struct imsm_disk {
        __u8 serial[MAX_RAID_SERIAL_LEN];/* 0xD8 - 0xE7 ascii serial number */
        __u32 total_blocks;              /* 0xE8 - 0xEB total blocks */
        __u32 scsi_id;                   /* 0xEC - 0xEF scsi ID */
+#define SPARE_DISK      __cpu_to_le32(0x01)  /* Spare */
+#define CONFIGURED_DISK __cpu_to_le32(0x02)  /* Member of some RaidDev */
+#define FAILED_DISK     __cpu_to_le32(0x04)  /* Permanent failure */
+#define USABLE_DISK     __cpu_to_le32(0x08)  /* Fully usable unless FAILED_DISK is set */
        __u32 status;                    /* 0xF0 - 0xF3 */
-#define SPARE_DISK      0x01  /* Spare */
-#define CONFIGURED_DISK 0x02  /* Member of some RaidDev */
-#define FAILED_DISK     0x04  /* Permanent failure */
-#define USABLE_DISK     0x08  /* Fully usable unless FAILED_DISK is set */
-
-#define        IMSM_DISK_FILLERS       5
+       __u32 owner_cfg_num; /* which config 0,1,2... owns this disk */ 
+#define        IMSM_DISK_FILLERS       4
        __u32 filler[IMSM_DISK_FILLERS]; /* 0xF4 - 0x107 MPB_DISK_FILLERS for future expansion */
 };
 
@@ -61,14 +77,16 @@ struct imsm_map {
        __u8  map_state;        /* Normal, Uninitialized, Degraded, Failed */
 #define IMSM_T_STATE_NORMAL 0
 #define IMSM_T_STATE_UNINITIALIZED 1
-#define IMSM_T_STATE_DEGRADED 2 /* FIXME: is this correct? */
-#define IMSM_T_STATE_FAILED 3 /* FIXME: is this correct? */
+#define IMSM_T_STATE_DEGRADED 2
+#define IMSM_T_STATE_FAILED 3
        __u8  raid_level;
 #define IMSM_T_RAID0 0
 #define IMSM_T_RAID1 1
 #define IMSM_T_RAID5 5         /* since metadata version 1.2.02 ? */
        __u8  num_members;      /* number of member disks */
-       __u8  reserved[3];
+       __u8  num_domains;      /* number of parity domains */
+       __u8  failed_disk_num;  /* valid only when state is degraded */
+       __u8  reserved[1];
        __u32 filler[7];        /* expansion area */
 #define IMSM_ORD_REBUILD (1 << 24)
        __u32 disk_ord_tbl[1];  /* disk_ord_tbl[num_members],
@@ -78,23 +96,50 @@ struct imsm_map {
 
 struct imsm_vol {
        __u32 curr_migr_unit;
-       __u32 reserved;
+       __u32 checkpoint_id;    /* id to access curr_migr_unit */
        __u8  migr_state;       /* Normal or Migrating */
+#define MIGR_INIT 0
+#define MIGR_REBUILD 1
+#define MIGR_VERIFY 2 /* analagous to echo check > sync_action */
+#define MIGR_GEN_MIGR 3
+#define MIGR_STATE_CHANGE 4
        __u8  migr_type;        /* Initializing, Rebuilding, ... */
        __u8  dirty;
-       __u8  fill[1];
-       __u32 filler[5];
+       __u8  fs_state;         /* fast-sync state for CnG (0xff == disabled) */
+       __u16 verify_errors;    /* number of mismatches */
+       __u16 bad_blocks;       /* number of bad blocks during verify */
+       __u32 filler[4];
        struct imsm_map map[1];
        /* here comes another one if migr_state */
 } __attribute__ ((packed));
 
 struct imsm_dev {
-       __u8    volume[MAX_RAID_SERIAL_LEN];
+       __u8  volume[MAX_RAID_SERIAL_LEN];
        __u32 size_low;
        __u32 size_high;
+#define DEV_BOOTABLE           __cpu_to_le32(0x01)
+#define DEV_BOOT_DEVICE                __cpu_to_le32(0x02)
+#define DEV_READ_COALESCING    __cpu_to_le32(0x04)
+#define DEV_WRITE_COALESCING   __cpu_to_le32(0x08)
+#define DEV_LAST_SHUTDOWN_DIRTY        __cpu_to_le32(0x10)
+#define DEV_HIDDEN_AT_BOOT     __cpu_to_le32(0x20)
+#define DEV_CURRENTLY_HIDDEN   __cpu_to_le32(0x40)
+#define DEV_VERIFY_AND_FIX     __cpu_to_le32(0x80)
+#define DEV_MAP_STATE_UNINIT   __cpu_to_le32(0x100)
+#define DEV_NO_AUTO_RECOVERY   __cpu_to_le32(0x200)
+#define DEV_CLONE_N_GO         __cpu_to_le32(0x400)
+#define DEV_CLONE_MAN_SYNC     __cpu_to_le32(0x800)
+#define DEV_CNG_MASTER_DISK_NUM        __cpu_to_le32(0x1000)
        __u32 status;   /* Persistent RaidDev status */
        __u32 reserved_blocks; /* Reserved blocks at beginning of volume */
-#define IMSM_DEV_FILLERS 12
+       __u8  migr_priority;
+       __u8  num_sub_vols;
+       __u8  tid;
+       __u8  cng_master_disk;
+       __u16 cache_policy;
+       __u8  cng_state;
+       __u8  cng_sub_state;
+#define IMSM_DEV_FILLERS 10
        __u32 filler[IMSM_DEV_FILLERS];
        struct imsm_vol vol;
 } __attribute__ ((packed));
@@ -546,7 +591,7 @@ static void print_imsm_disk(struct imsm_super *mpb, int index, __u32 reserved)
        printf("\n");
        snprintf(str, MAX_RAID_SERIAL_LEN + 1, "%s", disk->serial);
        printf("  Disk%02d Serial : %s\n", index, str);
-       s = __le32_to_cpu(disk->status);
+       s = disk->status;
        printf("          State :%s%s%s%s\n", s&SPARE_DISK ? " spare" : "",
                                              s&CONFIGURED_DISK ? " active" : "",
                                              s&FAILED_DISK ? " failed" : "",
@@ -845,7 +890,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info)
                disk = &super->disks->disk;
                info->data_offset = __le32_to_cpu(disk->total_blocks) - reserved;
                info->component_size = reserved;
-               s = __le32_to_cpu(disk->status);
+               s = disk->status;
                info->disk.state  = s & CONFIGURED_DISK ? (1 << MD_DISK_ACTIVE) : 0;
                info->disk.state |= s & FAILED_DISK ? (1 << MD_DISK_FAULTY) : 0;
                info->disk.state |= s & SPARE_DISK ? 0 : (1 << MD_DISK_SYNC);
@@ -1134,16 +1179,13 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
                disk_iter = __get_imsm_disk(super->anchor, i);
 
                if (serialcmp(disk_iter->serial, dl->serial) == 0) {
-                       __u32 status;
-
                        dl->disk = *disk_iter;
-                       status = __le32_to_cpu(dl->disk.status);
                        /* only set index on disks that are a member of a
                         * populated contianer, i.e. one with raid_devs
                         */
-                       if (status & FAILED_DISK)
+                       if (dl->disk.status & FAILED_DISK)
                                dl->index = -2;
-                       else if (status & SPARE_DISK)
+                       else if (dl->disk.status & SPARE_DISK)
                                dl->index = -1;
                        else
                                dl->index = i;
@@ -1155,7 +1197,7 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
        /* no match, maybe a stale failed drive */
        if (i == super->anchor->num_disks && dl->index >= 0) {
                dl->disk = *__get_imsm_disk(super->anchor, dl->index);
-               if (__le32_to_cpu(dl->disk.status) & FAILED_DISK)
+               if (dl->disk.status & FAILED_DISK)
                        dl->index = -2;
        }
 
@@ -1178,11 +1220,11 @@ static void imsm_copy_dev(struct imsm_dev *dest, struct imsm_dev *src)
  *
  * Migration is indicated by one of the following states
  * 1/ Idle (migr_state=0 map0state=normal||unitialized||degraded||failed)
- * 2/ Initialize (migr_state=1 migr_type=0 map0state=normal
+ * 2/ Initialize (migr_state=1 migr_type=MIGR_INIT map0state=normal
  *    map1state=unitialized)
- * 3/ Verify (Resync) (migr_state=1 migr_type=1 map0state=normal
+ * 3/ Verify (Resync) (migr_state=1 migr_type=MIGR_REBUILD map0state=normal
  *    map1state=normal)
- * 4/ Rebuild (migr_state=1 migr_type=1 map0state=normal
+ * 4/ Rebuild (migr_state=1 migr_type=MIGR_REBUILD map0state=normal
  *    map1state=degraded)
  */
 static void migrate(struct imsm_dev *dev, __u8 to_state, int rebuild_resync)
@@ -1458,7 +1500,6 @@ static int find_missing(struct intel_super *super)
        struct imsm_super *mpb = super->anchor;
        struct dl *dl;
        struct imsm_disk *disk;
-       __u32 status;
 
        for (i = 0; i < mpb->num_disks; i++) {
                disk = __get_imsm_disk(mpb, i);
@@ -1470,8 +1511,7 @@ static int find_missing(struct intel_super *super)
                /* ok we have a 'disk' without a live entry in
                 * super->disks
                 */
-               status = __le32_to_cpu(disk->status);
-               if (status & FAILED_DISK || !(status & USABLE_DISK))
+               if (disk->status & FAILED_DISK || !(disk->status & USABLE_DISK))
                        continue; /* never mind, already marked */
 
                dl = malloc(sizeof(*dl));
@@ -1731,7 +1771,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
        dev->reserved_blocks = __cpu_to_le32(0);
        vol = &dev->vol;
        vol->migr_state = 0;
-       vol->migr_type = 0;
+       vol->migr_type = MIGR_INIT;
        vol->dirty = 0;
        vol->curr_migr_unit = 0;
        for (i = 0; i < idx; i++) {
@@ -1823,7 +1863,6 @@ static void add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
        struct dl *dl;
        struct imsm_dev *dev;
        struct imsm_map *map;
-       __u32 status;
 
        dev = get_imsm_dev(super, super->current_vol);
        map = get_imsm_map(dev, 0);
@@ -1842,8 +1881,7 @@ static void add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
                super->anchor->num_disks++;
        }
        set_imsm_ord_tbl_ent(map, dk->number, dl->index);
-       status = CONFIGURED_DISK | USABLE_DISK;
-       dl->disk.status = __cpu_to_le32(status);
+       dl->disk.status = CONFIGURED_DISK | USABLE_DISK;
 
        /* if we are creating the first raid device update the family number */
        if (super->current_vol == 0) {
@@ -1864,7 +1902,7 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
        struct intel_super *super = st->sb;
        struct dl *dd;
        unsigned long long size;
-       __u32 status, id;
+       __u32 id;
        int rv;
        struct stat stb;
 
@@ -1896,10 +1934,9 @@ static void add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
 
        get_dev_size(fd, NULL, &size);
        size /= 512;
-       status = USABLE_DISK | SPARE_DISK;
        serialcpy(dd->disk.serial, dd->serial);
        dd->disk.total_blocks = __cpu_to_le32(size);
-       dd->disk.status = __cpu_to_le32(status);
+       dd->disk.status = USABLE_DISK | SPARE_DISK;
        if (sysfs_disk_to_scsi_id(fd, &id) == 0)
                dd->disk.scsi_id = __cpu_to_le32(id);
        else
@@ -2399,7 +2436,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st)
                        if (d == NULL)
                                skip = 1;
 
-                       s = d ? __le32_to_cpu(d->disk.status) : 0;
+                       s = d ? d->disk.status : 0;
                        if (s & FAILED_DISK)
                                skip = 1;
                        if (!(s & USABLE_DISK))
@@ -2509,8 +2546,7 @@ static __u8 imsm_check_degraded(struct intel_super *super, struct imsm_dev *dev,
                                insync = 2;
 
                        disk = get_imsm_disk(super, idx);
-                       if (!disk ||
-                           __le32_to_cpu(disk->status) & FAILED_DISK ||
+                       if (!disk || disk->status & FAILED_DISK ||
                            ord & IMSM_ORD_REBUILD)
                                insync--;
 
@@ -2548,8 +2584,7 @@ static int imsm_count_failed(struct intel_super *super, struct imsm_dev *dev)
                int idx = ord_to_idx(ord);
 
                disk = get_imsm_disk(super, idx);
-               if (!disk ||
-                   __le32_to_cpu(disk->status) & FAILED_DISK ||
+               if (!disk || disk->status & FAILED_DISK ||
                    ord & IMSM_ORD_REBUILD)
                        failed++;
        }
@@ -2564,7 +2599,7 @@ static int is_resyncing(struct imsm_dev *dev)
        if (!dev->vol.migr_state)
                return 0;
 
-       if (dev->vol.migr_type == 0)
+       if (dev->vol.migr_type == MIGR_INIT)
                return 1;
 
        migr_map = get_imsm_map(dev, 1);
@@ -2582,7 +2617,7 @@ static int is_rebuilding(struct imsm_dev *dev)
        if (!dev->vol.migr_state)
                return 0;
 
-       if (dev->vol.migr_type == 0)
+       if (dev->vol.migr_type != MIGR_REBUILD)
                return 0;
 
        migr_map = get_imsm_map(dev, 1);
@@ -2595,12 +2630,9 @@ static int is_rebuilding(struct imsm_dev *dev)
 
 static void mark_failure(struct imsm_disk *disk)
 {
-       __u32 status = __le32_to_cpu(disk->status);
-
-       if (status & FAILED_DISK)
+       if (disk->status & FAILED_DISK)
                return;
-       status |= FAILED_DISK;
-       disk->status = __cpu_to_le32(status);
+       disk->status |= FAILED_DISK;
        disk->scsi_id = __cpu_to_le32(~(__u32)0);
        memmove(&disk->serial[0], &disk->serial[1], MAX_RAID_SERIAL_LEN - 1);
 }
@@ -2648,9 +2680,10 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
        } else if (!is_resyncing(dev) && !failed) {
                /* mark the start of the init process if nothing is failed */
                dprintf("imsm: mark resync start (%llu)\n", a->resync_start);
-               map->map_state = map_state;
-               migrate(dev, IMSM_T_STATE_NORMAL,
-                       map->map_state == IMSM_T_STATE_NORMAL);
+               if (map->map_state == IMSM_T_STATE_NORMAL)
+                       migrate(dev, IMSM_T_STATE_NORMAL, MIGR_REBUILD);
+               else
+                       migrate(dev, IMSM_T_STATE_NORMAL, MIGR_INIT);
                super->updates_pending++;
        }
 
@@ -2683,7 +2716,6 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
        struct imsm_map *map = get_imsm_map(dev, 0);
        struct imsm_disk *disk;
        int failed;
-       __u32 status;
        __u32 ord;
        __u8 map_state;
 
@@ -2700,8 +2732,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
        disk = get_imsm_disk(super, ord_to_idx(ord));
 
        /* check for new failures */
-       status = __le32_to_cpu(disk->status);
-       if ((state & DS_FAULTY) && !(status & FAILED_DISK)) {
+       if ((state & DS_FAULTY) && !(disk->status & FAILED_DISK)) {
                mark_failure(disk);
                super->updates_pending++;
        }
@@ -2788,7 +2819,7 @@ static struct dl *imsm_readd(struct intel_super *super, int idx, struct active_a
                if (dl->index == i)
                        break;
 
-       if (dl && __le32_to_cpu(dl->disk.status) & FAILED_DISK)
+       if (dl && dl->disk.status & FAILED_DISK)
                dl = NULL;
 
        if (dl)
@@ -2809,7 +2840,6 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot, struct act
        int j;
        int found;
        __u32 array_start;
-       __u32 status;
        struct dl *dl;
 
        for (dl = super->disks; dl; dl = dl->next) {
@@ -2825,11 +2855,10 @@ static struct dl *imsm_add_spare(struct intel_super *super, int slot, struct act
                        continue;
 
                /* skip in use or failed drives */
-               status = __le32_to_cpu(dl->disk.status);
-               if (status & FAILED_DISK || idx == dl->index) {
+               if (dl->disk.status & FAILED_DISK || idx == dl->index) {
                        dprintf("%x:%x status ( %s%s)\n",
                        dl->major, dl->minor,
-                       status & FAILED_DISK ? "failed " : "",
+                       dl->disk.status & FAILED_DISK ? "failed " : "",
                        idx == dl->index ? "in use " : "");
                        continue;
                }
@@ -3079,7 +3108,6 @@ static void imsm_process_update(struct supertype *st,
                struct imsm_map *migr_map;
                struct active_array *a;
                struct imsm_disk *disk;
-               __u32 status;
                __u8 to_state;
                struct dl *dl;
                unsigned int found;
@@ -3108,8 +3136,7 @@ static void imsm_process_update(struct supertype *st,
                        if (i == u->slot)
                                continue;
                        disk = get_imsm_disk(super, get_imsm_disk_idx(dev, i));
-                       if (!disk ||
-                           __le32_to_cpu(disk->status) & FAILED_DISK)
+                       if (!disk || disk->status & FAILED_DISK)
                                failed++;
                }
 
@@ -3119,15 +3146,13 @@ static void imsm_process_update(struct supertype *st,
                        super->anchor->num_disks++;
                }
                disk = &dl->disk;
-               status = __le32_to_cpu(disk->status);
-               status |= CONFIGURED_DISK;
-               status &= ~SPARE_DISK;
-               disk->status = __cpu_to_le32(status);
+               disk->status |= CONFIGURED_DISK;
+               disk->status &= ~SPARE_DISK;
 
                /* mark rebuild */
                to_state = imsm_check_degraded(super, dev, failed);
                map->map_state = IMSM_T_STATE_DEGRADED;
-               migrate(dev, to_state, 1);
+               migrate(dev, to_state, MIGR_REBUILD);
                migr_map = get_imsm_map(dev, 1);
                set_imsm_ord_tbl_ent(map, u->slot, dl->index);
                set_imsm_ord_tbl_ent(migr_map, u->slot, dl->index | IMSM_ORD_REBUILD);
@@ -3240,13 +3265,10 @@ static void imsm_process_update(struct supertype *st,
                /* fix up flags */
                for (i = 0; i < map->num_members; i++) {
                        struct imsm_disk *disk;
-                       __u32 status;
 
                        disk = get_imsm_disk(super, get_imsm_disk_idx(dev, i));
-                       status = __le32_to_cpu(disk->status);
-                       status |= CONFIGURED_DISK;
-                       status &= ~SPARE_DISK;
-                       disk->status = __cpu_to_le32(status);
+                       disk->status |= CONFIGURED_DISK;
+                       disk->status &= ~SPARE_DISK;
                }
                break;
        }