svn commit: r217918 - projects/graid/head/sys/geom/raid

Warner Losh imp at FreeBSD.org
Thu Jan 27 02:00:02 UTC 2011


Author: imp
Date: Thu Jan 27 02:00:01 2011
New Revision: 217918
URL: http://svn.freebsd.org/changeset/base/217918

Log:
  Checkpoint commit:
  
  o Kick of rebuild of the volume correctly.
  o properly create and clone the master bp for the rebuild
  o tweak a few logging items
  o add a few logging items.
  o tweak timeout goo
  o add a semi-snarky comment about some semi-lame code I wrote

Modified:
  projects/graid/head/sys/geom/raid/tr_raid1.c

Modified: projects/graid/head/sys/geom/raid/tr_raid1.c
==============================================================================
--- projects/graid/head/sys/geom/raid/tr_raid1.c	Thu Jan 27 00:36:54 2011	(r217917)
+++ projects/graid/head/sys/geom/raid/tr_raid1.c	Thu Jan 27 02:00:01 2011	(r217918)
@@ -125,19 +125,23 @@ g_raid_tr_raid1_rebuild_some(struct g_ra
     struct g_raid_subdisk *sd)
 {
 	struct g_raid_tr_raid1_object *trs;
-	struct bio *bp;
+	struct bio *bp, *bp2;
 
+/* XXX need interlock here? */
 	trs = (struct g_raid_tr_raid1_object *)tr;
 	trs->trso_recover_slabs = SD_REBUILD_CLUSTER_IDLE;
 	trs->trso_fair_io = SD_REBUILD_FAIR_IO;
 	bp = g_new_bio();
 	bp->bio_offset = sd->sd_rebuild_pos;
+	bp->bio_length = MIN(SD_REBUILD_SLAB,
+	    sd->sd_volume->v_mediasize - sd->sd_rebuild_pos);
 	bp->bio_data = trs->trso_buffer;
 	bp->bio_cmd = BIO_READ;
-	bp->bio_cflags = G_RAID_BIO_FLAG_SYNC;
-	bp->bio_caller1 = trs->trso_good_sd;
+	bp2 = g_clone_bio(bp);
+	bp2->bio_cflags = G_RAID_BIO_FLAG_SYNC;
+	bp2->bio_caller1 = trs->trso_good_sd;
 	g_raid_lock_range(sd->sd_volume,	/* Lock callback starts I/O */
-	    sd->sd_rebuild_pos, SD_REBUILD_SLAB, bp);
+	    bp2->bio_offset, bp2->bio_length, bp2);
 }
 
 static void
@@ -170,6 +174,7 @@ g_raid_tr_raid1_rebuild_finish(struct g_
 	trs->trso_failed_sd = NULL;
 	trs->trso_good_sd = NULL;
 	trs->trso_buffer = NULL;
+	vol->v_timeout = 0;
 	/* xxx transition array? */
 }
 
@@ -186,6 +191,7 @@ g_raid_tr_raid1_rebuild_abort(struct g_r
 	trs->trso_failed_sd = NULL;
 	trs->trso_good_sd = NULL;
 	trs->trso_buffer = NULL;
+	vol->v_timeout = 0;
 }
 
 static struct g_raid_subdisk *
@@ -233,10 +239,37 @@ g_raid_tr_raid1_rebuild_start(struct g_r
 	trs->trso_type = TR_RAID1_REBUILD;
 	trs->trso_failed_sd->sd_rebuild_pos = 0;
 	trs->trso_buffer = malloc(SD_REBUILD_SLAB, M_TR_raid1, M_WAITOK);
+	vol->v_to_arg = trs;
+	vol->v_timeout = g_raid_tr_raid1_idle_rebuild;
 	/* XXX what else do I need to setup the first time? */
 	g_raid_tr_raid1_rebuild_some(tr, trs->trso_failed_sd);
 }
 
+
+static void
+g_raid_tr_raid1_maybe_rebuild(struct g_raid_tr_object *tr, struct g_raid_volume *vol)
+{
+	struct g_raid_tr_raid1_object *trs;
+	int na, nr;
+	
+	/*
+	 * If we're stopped, don't do anything.  If we don't have at least
+	 * one good disk and one bad disk, we don't do anything.  And if there's
+	 * a 'good disk' stored in the trs, then we're in progress and we punt.
+	 * If we make it past all these checks, we need to rebuild.
+	 */
+	trs = (struct g_raid_tr_raid1_object *)tr;
+	if (trs->trso_stopped)
+		return;
+	na = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
+	nr = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_REBUILD);
+	if (na == 0 || nr == 0)
+		return;
+	if (trs->trso_good_sd)
+		return;
+	g_raid_tr_raid1_rebuild_start(tr, vol);
+}
+
 static int
 g_raid_tr_update_state_raid1(struct g_raid_volume *vol)
 {
@@ -261,18 +294,11 @@ g_raid_tr_update_state_raid1(struct g_ra
 				s = G_RAID_VOLUME_S_BROKEN;
 		}
 	}
+	g_raid_tr_raid1_maybe_rebuild(vol->v_tr, vol);
 	if (s != vol->v_state) {
 		g_raid_event_send(vol, G_RAID_VOLUME_S_ALIVE(s) ?
 		    G_RAID_VOLUME_E_UP : G_RAID_VOLUME_E_DOWN,
 		    G_RAID_EVENT_VOLUME);
-		if (s == G_RAID_VOLUME_S_DEGRADED) {
-			g_raid_tr_raid1_rebuild_start(vol->v_tr, vol);
-			vol->v_to_arg = trs;
-			vol->v_timeout = g_raid_tr_raid1_idle_rebuild;
-		} else {
-			vol->v_timeout = 0;
-			vol->v_to_arg = 0;
-		}
 		g_raid_change_volume_state(vol, s);
 	}
 	return (0);
@@ -289,8 +315,9 @@ g_raid_tr_event_raid1(struct g_raid_tr_o
 	vol = tr->tro_volume;
 	switch (event) {
 	case G_RAID_SUBDISK_E_NEW:
-		// XXX do I need to start a rebuild here?
-//		g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_ACTIVE);
+		printf("Current disk state is %d\n", sd->sd_state);
+		if (sd->sd_state == G_RAID_SUBDISK_S_NEW)
+			g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_REBUILD);
 		break;
 	case G_RAID_SUBDISK_E_FAILED:
 		// XXX do I need to stop a rebuild here?
@@ -517,13 +544,16 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 		 * inactive ones, we do 50MB.
 		 */
 		if (trs->trso_type == TR_RAID1_REBUILD) {
+			printf("Rebuild BIO\n");
 			vol = tr->tro_volume;
+			pbp->bio_inbed++;
 			if (bp->bio_cmd == BIO_READ) {
 				/*
 				 * The read operation finished, queue the
 				 * write and get out.
 				 */
-				pbp->bio_inbed++;
+				G_RAID_LOGREQ(1, bp,
+				    "rebuild read done. Error %d", bp->bio_error);
 				if (bp->bio_error != 0) {
 					g_raid_tr_raid1_rebuild_abort(tr, vol);
 					goto out;
@@ -533,6 +563,7 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 				cbp->bio_cflags = G_RAID_BIO_FLAG_SYNC;
 				cbp->bio_offset = bp->bio_offset; /* Necessary? */
 				cbp->bio_length = bp->bio_length;
+				G_RAID_LOGREQ(1, bp, "Queueing reguild write.");
 				g_raid_subdisk_iostart(trs->trso_failed_sd, cbp);
 				return;
 			} else {
@@ -546,15 +577,20 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 				 * SD_REBUILD_CLUSTER should be small, that
 				 * shouldn't be a problem.
 				 */
-				pbp->bio_inbed++;
+				G_RAID_LOGREQ(1, bp,
+				    "rebuild write done. Error %d", bp->bio_error);
 				if (bp->bio_error != 0) {
 					g_raid_tr_raid1_rebuild_abort(tr, vol);
 					goto out;
 				}
-				/* A lot of the following is needed when we kick of the work -- refactor */
+/* XXX A lot of the following is needed when we kick of the work -- refactor */
 				nsd = trs->trso_failed_sd;
+				if (nsd == NULL) {
+					printf("WTF?  nsd is null\n");
+					goto out;
+				}
 				g_raid_unlock_range(sd->sd_volume,
-				    nsd->sd_rebuild_pos, SD_REBUILD_SLAB);
+				    bp->bio_offset, bp->bio_length);
 				nsd->sd_rebuild_pos += pbp->bio_length;
 				if (nsd->sd_rebuild_pos >= vol->v_mediasize) {
 					g_raid_tr_raid1_rebuild_finish(tr, vol);
@@ -570,8 +606,10 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 				cbp->bio_offset = nsd->sd_rebuild_pos;
 				cbp->bio_length = MIN(SD_REBUILD_SLAB, vol->v_mediasize - nsd->sd_rebuild_pos);
 				cbp->bio_caller1 = trs->trso_good_sd;
+				G_RAID_LOGREQ(1, bp,
+				    "Rebuild read at %jd.", cbp->bio_offset);
 				g_raid_lock_range(sd->sd_volume,	/* Lock callback starts I/O */
-				    nsd->sd_rebuild_pos, SD_REBUILD_SLAB, cbp);
+				    cbp->bio_offset, cbp->bio_length, cbp);
 				goto out;
 			}
 		} else if (trs->trso_type == TR_RAID1_RESYNC) {
@@ -584,9 +622,9 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 			panic("Somehow, we think we're doing a resync");
 		}
 	}
+	printf("Woof.  bp is %p pbp is %p\n", bp, pbp);
 	if (bp->bio_error != 0 && bp->bio_cmd == BIO_READ &&
-	    pbp->bio_children == 1) {
-
+	    pbp->bio_children == 1 && bp->bio_cflags == 0) {
 		/*
 		 * Read failed on first drive.  Retry the read error on
 		 * another disk drive, if available, before erroring out the
@@ -594,7 +632,7 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 		 */
 		vol = tr->tro_volume;
 		sd->sd_read_errs++;
-		G_RAID_LOGREQ(3, bp,
+		G_RAID_LOGREQ(1, bp,
 		    "Read failure, attempting recovery. %d total read errs",
 		    sd->sd_read_errs);
 
@@ -628,10 +666,11 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 		 * We don't need to fail the raid, since its actual state is
 		 * based on the state of the subdisks.
 		 */
-		G_RAID_LOGREQ(3, bp, "Couldn't retry read, failing it");
+		G_RAID_LOGREQ(2, bp, "Couldn't retry read, failing it");
 	}
 	pbp->bio_inbed++;
-	if (pbp->bio_cmd == BIO_READ && pbp->bio_children == 2) {
+	if (pbp->bio_cmd == BIO_READ && pbp->bio_children == 2 &&
+	    bp->bio_cflags == 0) {
 		/*
 		 * If it was a read, and bio_children is 2, then we just
 		 * recovered the data from the second drive.  We should try to
@@ -663,6 +702,7 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 		 * failed, the parent's bio isn't failed since the recovered
 		 * read for that actually succeeded.
 		 */
+		G_RAID_LOGREQ(2, bp, "REMAP done %d.", bp->bio_error);
 		g_raid_unlock_range(sd->sd_volume, bp->bio_offset,
 		    bp->bio_length);
 		if (bp->bio_error) {


More information about the svn-src-projects mailing list