Skip site navigation (1)Skip section navigation (2)
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>