Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Feb 2011 15:28:27 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r218279 - projects/graid/head/sys/geom/raid
Message-ID:  <201102041528.p14FSRu1088802@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Fri Feb  4 15:28:26 2011
New Revision: 218279
URL: http://svn.freebsd.org/changeset/base/218279

Log:
  Teach RAID1 handle situations when no disk in ACTIVE state left: choose
  best disk of remaining (up to reasonable level) and make it ACTIVE.
  
  Introduce UNINITIALIZED subdisk state. It is same as NEW, except in can
  be safely promoted to ACTIVE.
  
  Store STALE subdisk state to metadata using dirty volume flag. Not exactly
  match, but closest of what we have.

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

Modified: projects/graid/head/sys/geom/raid/g_raid.c
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.c	Fri Feb  4 15:22:56 2011	(r218278)
+++ projects/graid/head/sys/geom/raid/g_raid.c	Fri Feb  4 15:28:26 2011	(r218279)
@@ -140,7 +140,7 @@ g_raid_node_event2str(int event)
 	}
 }
 
-static const char *
+const char *
 g_raid_disk_state2str(int state)
 {
 
@@ -176,7 +176,7 @@ g_raid_disk_event2str(int event)
 	}
 }
 
-static const char *
+const char *
 g_raid_subdisk_state2str(int state)
 {
 
@@ -214,7 +214,7 @@ g_raid_subdisk_event2str(int event)
 	}
 }
 
-static const char *
+const char *
 g_raid_volume_state2str(int state)
 {
 

Modified: projects/graid/head/sys/geom/raid/g_raid.h
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.h	Fri Feb  4 15:22:56 2011	(r218278)
+++ projects/graid/head/sys/geom/raid/g_raid.h	Fri Feb  4 15:28:26 2011	(r218279)
@@ -145,10 +145,11 @@ struct g_raid_disk {
 #define G_RAID_SUBDISK_S_NONE		0x00	/* Absent. */
 #define G_RAID_SUBDISK_S_FAILED		0x01	/* Failed. */
 #define G_RAID_SUBDISK_S_NEW		0x02	/* Blank. */
-#define G_RAID_SUBDISK_S_STALE		0x03	/* Dirty. */
-#define G_RAID_SUBDISK_S_REBUILD	0x04	/* Blank + rebuild. */
-#define G_RAID_SUBDISK_S_RESYNC		0x05	/* Dirty + check/repair. */
-#define G_RAID_SUBDISK_S_ACTIVE		0x06	/* Usable. */
+#define G_RAID_SUBDISK_S_REBUILD	0x03	/* Blank + rebuild. */
+#define G_RAID_SUBDISK_S_UNINITIALIZED	0x04	/* Disk of the new volume. */
+#define G_RAID_SUBDISK_S_STALE		0x05	/* Dirty. */
+#define G_RAID_SUBDISK_S_RESYNC		0x06	/* Dirty + check/repair. */
+#define G_RAID_SUBDISK_S_ACTIVE		0x07	/* Usable. */
 
 #define G_RAID_SUBDISK_E_NEW		0x01	/* A new subdisk has arrived */
 #define G_RAID_SUBDISK_E_FAILED		0x02	/* A subdisk failed, but remains in volume */
@@ -316,6 +317,9 @@ int g_raid_tr_modevent(module_t, int, vo
 
 const char * g_raid_volume_level2str(int level, int qual);
 int g_raid_volume_str2level(const char *str, int *level, int *qual);
+const char * g_raid_volume_state2str(int state);
+const char * g_raid_subdisk_state2str(int state);
+const char * g_raid_disk_state2str(int state);
 
 struct g_raid_softc * g_raid_create_node(struct g_class *mp,
     const char *name, struct g_raid_md_object *md);

Modified: projects/graid/head/sys/geom/raid/md_intel.c
==============================================================================
--- projects/graid/head/sys/geom/raid/md_intel.c	Fri Feb  4 15:22:56 2011	(r218278)
+++ projects/graid/head/sys/geom/raid/md_intel.c	Fri Feb  4 15:28:26 2011	(r218279)
@@ -644,7 +644,7 @@ nofit:
 			if (mmap0->status == INTEL_S_UNINITIALIZED) {
 				/* Freshly created uninitialized volume. */
 				g_raid_change_subdisk_state(sd,
-				    G_RAID_SUBDISK_S_NEW);
+				    G_RAID_SUBDISK_S_UNINITIALIZED);
 			} else if (mmap0->disk_idx[sd->sd_pos] & INTEL_DI_RBLD) {
 				/* Freshly inserted disk. */
 				g_raid_change_subdisk_state(sd,
@@ -1879,7 +1879,7 @@ g_raid_md_write_intel(struct g_raid_md_o
 	struct intel_raid_map *mmap0, *mmap1;
 	off_t sectorsize = 512, pos;
 	const char *version, *cv;
-	int vi, sdi, numdisks, len, state;
+	int vi, sdi, numdisks, len, state, stale;
 
 	sc = md->mdo_softc;
 	mdi = (struct g_raid_md_intel_object *)md;
@@ -1980,6 +1980,7 @@ g_raid_md_write_intel(struct g_raid_md_o
 		/* Check for any recovery in progress. */
 		state = G_RAID_SUBDISK_S_ACTIVE;
 		pos = 0x7fffffffffffffffllu;
+		stale = 0;
 		for (sdi = 0; sdi < vol->v_disks_count; sdi++) {
 			sd = &vol->v_subdisks[sdi];
 			if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD)
@@ -1987,6 +1988,8 @@ g_raid_md_write_intel(struct g_raid_md_o
 			else if (sd->sd_state == G_RAID_SUBDISK_S_RESYNC &&
 			    state != G_RAID_SUBDISK_S_REBUILD)
 				state = G_RAID_SUBDISK_S_RESYNC;
+			else if (sd->sd_state == G_RAID_SUBDISK_S_STALE)
+				stale = 1;
 			if ((sd->sd_state == G_RAID_SUBDISK_S_REBUILD ||
 			    sd->sd_state == G_RAID_SUBDISK_S_RESYNC) &&
 			     sd->sd_rebuild_pos < pos)
@@ -2000,7 +2003,7 @@ g_raid_md_write_intel(struct g_raid_md_o
 			mvol->migr_type = INTEL_MT_REPAIR;
 		} else
 			mvol->migr_state = 0;
-		mvol->dirty = vol->v_dirty;
+		mvol->dirty = (vol->v_dirty || stale);
 
 		mmap0 = intel_get_map(mvol, 0);
 
@@ -2054,7 +2057,8 @@ g_raid_md_write_intel(struct g_raid_md_o
 			if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD ||
 			    sd->sd_state == G_RAID_SUBDISK_S_RESYNC) {
 				mmap1->disk_idx[sdi] |= INTEL_DI_RBLD;
-			} else if (sd->sd_state != G_RAID_SUBDISK_S_ACTIVE) {
+			} else if (sd->sd_state != G_RAID_SUBDISK_S_ACTIVE &&
+			    sd->sd_state != G_RAID_SUBDISK_S_STALE) {
 				mmap0->disk_idx[sdi] |= INTEL_DI_RBLD;
 				if (mvol->migr_state)
 					mmap1->disk_idx[sdi] |= INTEL_DI_RBLD;

Modified: projects/graid/head/sys/geom/raid/tr_raid1.c
==============================================================================
--- projects/graid/head/sys/geom/raid/tr_raid1.c	Fri Feb  4 15:22:56 2011	(r218278)
+++ projects/graid/head/sys/geom/raid/tr_raid1.c	Fri Feb  4 15:28:26 2011	(r218279)
@@ -163,8 +163,9 @@ static int
 g_raid_tr_update_state_raid1(struct g_raid_volume *vol)
 {
 	struct g_raid_tr_raid1_object *trs;
+	struct g_raid_subdisk *sd, *bestsd;
 	u_int s;
-	int n;
+	int i, na, ns;
 
 	trs = (struct g_raid_tr_raid1_object *)vol->v_tr;
 	if (trs->trso_stopping &&
@@ -173,10 +174,44 @@ g_raid_tr_update_state_raid1(struct g_ra
 	else if (trs->trso_starting)
 		s = G_RAID_VOLUME_S_STARTING;
 	else {
-		n = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
-		if (n == vol->v_disks_count)
+		/* Make sure we have at least one ACTIVE disk. */
+		na = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
+		if (na == 0) {
+			/*
+			 * Critical situation! We have no any active disk!
+			 * Choose the best disk we have to make it active.
+			 */
+			bestsd = &vol->v_subdisks[0];
+			for (i = 1; i < vol->v_disks_count; i++) {
+				sd = &vol->v_subdisks[i];
+				if (sd->sd_state > bestsd->sd_state)
+					bestsd = sd;
+				else if (sd->sd_state == bestsd->sd_state &&
+				    (sd->sd_state == G_RAID_SUBDISK_S_REBUILD ||
+				     sd->sd_state == G_RAID_SUBDISK_S_RESYNC) &&
+				    sd->sd_rebuild_pos > bestsd->sd_rebuild_pos)
+					bestsd = sd;
+			}
+			if (bestsd->sd_state >= G_RAID_SUBDISK_S_UNINITIALIZED) {
+				/* We found reasonable candidate. */
+				G_RAID_DEBUG(1,
+				    "Promote subdisk %d from %s to ACTIVE.",
+				    bestsd->sd_pos,
+				    g_raid_subdisk_state2str(bestsd->sd_state));
+				g_raid_change_subdisk_state(bestsd,
+				    G_RAID_SUBDISK_S_ACTIVE);
+				g_raid_write_metadata(vol->v_softc,
+				    vol, bestsd, bestsd->sd_disk);
+			}
+		}
+		na = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
+		ns = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_STALE) +
+		     g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_RESYNC);
+		if (na == vol->v_disks_count)
 			s = G_RAID_VOLUME_S_OPTIMAL;
-		else if (n > 0)
+		else if (na + ns == vol->v_disks_count)
+			s = G_RAID_VOLUME_S_SUBOPTIMAL;
+		else if (na > 0)
 			s = G_RAID_VOLUME_S_DEGRADED;
 		else
 			s = G_RAID_VOLUME_S_BROKEN;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102041528.p14FSRu1088802>