Date: Fri, 18 Mar 2011 21:56:39 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r219754 - projects/graid/head/sys/geom/raid Message-ID: <201103182156.p2ILudtd081042@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Fri Mar 18 21:56:39 2011 New Revision: 219754 URL: http://svn.freebsd.org/changeset/base/219754 Log: AMD RAID BIOS and Windows driver write some more values to metadata beyond range supported by ataraid(4) and Linux' dmraid. One of them is definitely 64bit per-volume rebuild/resync position. Another values look like specifying kind of activity. I am not sure about their full meaning, but looks like I can mimic behaviour good enough for BIOS to understand it. Modified: projects/graid/head/sys/geom/raid/md_promise.c Modified: projects/graid/head/sys/geom/raid/md_promise.c ============================================================================== --- projects/graid/head/sys/geom/raid/md_promise.c Fri Mar 18 18:54:00 2011 (r219753) +++ projects/graid/head/sys/geom/raid/md_promise.c Fri Mar 18 21:56:39 2011 (r219754) @@ -117,7 +117,12 @@ struct promise_raid_conf { /* Subdisks in this volume. */ char name[32]; /* Volume label. */ - uint32_t filler2[338]; + uint32_t filler2[8]; + uint32_t magic_3; /* Something related to rebuild. */ + uint64_t rebuild_lba64; /* Per-volume rebuild position. */ + uint32_t magic_4; + uint32_t magic_5; + uint32_t filler3[325]; uint32_t checksum; } __packed; @@ -213,6 +218,10 @@ g_raid_md_promise_print(struct promise_r meta->disks[i].id); } printf("name <%.32s>\n", meta->name); + printf("magic_3 0x%08x\n", meta->magic_3); + printf("rebuild_lba64 %ju\n", meta->rebuild_lba64); + printf("magic_4 0x%08x\n", meta->magic_4); + printf("magic_5 0x%08x\n", meta->magic_5); printf("=================================================\n"); } @@ -637,7 +646,7 @@ nofit: sd->sd_rebuild_pos = 0; else { sd->sd_rebuild_pos = - pd->pd_meta[sdn]->rebuild_lba * 512; + (off_t)pd->pd_meta[sdn]->rebuild_lba * 512; } } else if (!(meta->disks[md_disk_pos].flags & PROMISE_F_ONLINE)) { /* Rebuilding disk. */ @@ -1753,7 +1762,8 @@ g_raid_md_write_promise(struct g_raid_md struct g_raid_md_promise_perdisk *pd; struct g_raid_md_promise_pervolume *pv; struct promise_raid_conf *meta; - int i, j, pos; + off_t rebuild_lba64; + int i, j, pos, rebuild; sc = md->mdo_softc; mdi = (struct g_raid_md_promise_object *)md; @@ -1800,10 +1810,10 @@ g_raid_md_write_promise(struct g_raid_md meta->generation = pv->pv_generation; meta->status = PROMISE_S_VALID | PROMISE_S_ONLINE | PROMISE_S_INITED | PROMISE_S_READY; - if (vol->v_state < G_RAID_VOLUME_S_OPTIMAL) + if (vol->v_state <= G_RAID_VOLUME_S_DEGRADED) meta->status |= PROMISE_S_DEGRADED; if (vol->v_dirty) - meta->status |= PROMISE_S_MARKED; + meta->status |= PROMISE_S_MARKED; /* XXX: INVENTED! */ if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID0 || vol->v_raid_level == G_RAID_VOLUME_RL_SINGLE) meta->type = PROMISE_T_RAID0; @@ -1834,6 +1844,8 @@ g_raid_md_write_promise(struct g_raid_md meta->volume_id = pv->pv_meta->volume_id; else arc4rand(&meta->volume_id, sizeof(meta->volume_id), 0); + rebuild_lba64 = UINT64_MAX; + rebuild = 0; for (i = 0; i < vol->v_disks_count; i++) { sd = &vol->v_subdisks[i]; /* For RAID10 we need to translate order. */ @@ -1845,11 +1857,26 @@ g_raid_md_write_promise(struct g_raid_md } else if (sd->sd_state == G_RAID_SUBDISK_S_FAILED) { meta->disks[pos].flags |= PROMISE_F_DOWN | PROMISE_F_REDIR; - } else if (sd->sd_state < G_RAID_SUBDISK_S_ACTIVE) { + } else if (sd->sd_state <= G_RAID_SUBDISK_S_REBUILD) { meta->disks[pos].flags |= PROMISE_F_ONLINE | PROMISE_F_REDIR; - } else + if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD) { + rebuild_lba64 = min(rebuild_lba64, + sd->sd_rebuild_pos / 512); + } else + rebuild_lba64 = 0; + rebuild = 1; + } else { meta->disks[pos].flags |= PROMISE_F_ONLINE; + if (sd->sd_state < G_RAID_SUBDISK_S_ACTIVE) { + meta->status |= PROMISE_S_MARKED; + if (sd->sd_state == G_RAID_SUBDISK_S_RESYNC) { + rebuild_lba64 = min(rebuild_lba64, + sd->sd_rebuild_pos / 512); + } else + rebuild_lba64 = 0; + } + } if (pv->pv_meta != NULL) { meta->disks[pos].id = pv->pv_meta->disks[pos].id; } else { @@ -1859,6 +1886,28 @@ g_raid_md_write_promise(struct g_raid_md } } promise_meta_put_name(meta, vol->v_name); + + /* Try to mimic AMD BIOS rebuild/resync behavior. */ + if (rebuild_lba64 != UINT64_MAX) { + if (rebuild) + meta->magic_3 = 0x03040010UL; /* Rebuild? */ + else + meta->magic_3 = 0x03040008UL; /* Resync? */ + /* Translate from per-disk to per-volume LBA. */ + if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1 || + vol->v_raid_level == G_RAID_VOLUME_RL_RAID1E) { + rebuild_lba64 *= meta->array_width; + } else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID3 || + vol->v_raid_level == G_RAID_VOLUME_RL_RAID5) { + rebuild_lba64 *= meta->array_width - 1; + } else + rebuild_lba64 = 0; + } else + meta->magic_3 = 0x03000000UL; + meta->rebuild_lba64 = rebuild_lba64; + meta->magic_4 = 0x04010101UL; + + /* Replace per-volume metadata with new. */ if (pv->pv_meta != NULL) free(pv->pv_meta, M_MD_PROMISE); pv->pv_meta = meta; @@ -1888,8 +1937,10 @@ g_raid_md_write_promise(struct g_raid_md if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD) { pd->pd_meta[j]->rebuild_lba = sd->sd_rebuild_pos / 512; - } else + } else if (sd->sd_state < G_RAID_SUBDISK_S_REBUILD) pd->pd_meta[j]->rebuild_lba = 0; + else + pd->pd_meta[j]->rebuild_lba = UINT32_MAX; pd->pd_updated = 1; } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103182156.p2ILudtd081042>