From owner-svn-src-projects@FreeBSD.ORG  Sat Jan 15 23:25:59 2011
Return-Path: <owner-svn-src-projects@FreeBSD.ORG>
Delivered-To: svn-src-projects@freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id B03CF1065675;
	Sat, 15 Jan 2011 23:25:59 +0000 (UTC) (envelope-from mav@FreeBSD.org)
Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c])
	by mx1.freebsd.org (Postfix) with ESMTP id 9F0CD8FC08;
	Sat, 15 Jan 2011 23:25:59 +0000 (UTC)
Received: from svn.freebsd.org (localhost [127.0.0.1])
	by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p0FNPxTI040863;
	Sat, 15 Jan 2011 23:25:59 GMT (envelope-from mav@svn.freebsd.org)
Received: (from mav@localhost)
	by svn.freebsd.org (8.14.3/8.14.3/Submit) id p0FNPxXk040857;
	Sat, 15 Jan 2011 23:25:59 GMT (envelope-from mav@svn.freebsd.org)
Message-Id: <201101152325.p0FNPxXk040857@svn.freebsd.org>
From: Alexander Motin <mav@FreeBSD.org>
Date: Sat, 15 Jan 2011 23:25:59 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-projects@freebsd.org
X-SVN-Group: projects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cc: 
Subject: svn commit: r217465 - projects/graid/head/sys/geom/raid
X-BeenThere: svn-src-projects@freebsd.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: "SVN commit messages for the src &quot; projects&quot;
	tree" <svn-src-projects.freebsd.org>
List-Unsubscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-projects>, 
	<mailto:svn-src-projects-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-projects>
List-Post: <mailto:svn-src-projects@freebsd.org>
List-Help: <mailto:svn-src-projects-request@freebsd.org?subject=help>
List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-projects>, 
	<mailto:svn-src-projects-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Sat, 15 Jan 2011 23:25:59 -0000

Author: mav
Date: Sat Jan 15 23:25:59 2011
New Revision: 217465
URL: http://svn.freebsd.org/changeset/base/217465

Log:
  Implement writing subdisks statuses to Intel metadata.
  
  Add function g_raid_write_metadata() - wrapper for metadata write() method
  to be used by transformation modules when they updating some statuses that
  worth to be saved. Make RAID0 transformation module to use it.

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/g_raid_md_if.m
  projects/graid/head/sys/geom/raid/md_intel.c
  projects/graid/head/sys/geom/raid/tr_raid0.c

Modified: projects/graid/head/sys/geom/raid/g_raid.c
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.c	Sat Jan 15 22:07:08 2011	(r217464)
+++ projects/graid/head/sys/geom/raid/g_raid.c	Sat Jan 15 23:25:59 2011	(r217465)
@@ -1692,6 +1692,14 @@ g_raid_destroy_geom(struct gctl_req *req
 	return (error);
 }
 
+void g_raid_write_metadata(struct g_raid_softc *sc, struct g_raid_volume *vol,
+    struct g_raid_subdisk *sd, struct g_raid_disk *disk)
+{
+
+	if (sc->sc_md)
+		G_RAID_MD_WRITE(sc->sc_md, vol, sd, disk);
+}
+
 static void
 g_raid_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
     struct g_consumer *cp, struct g_provider *pp)

Modified: projects/graid/head/sys/geom/raid/g_raid.h
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.h	Sat Jan 15 22:07:08 2011	(r217464)
+++ projects/graid/head/sys/geom/raid/g_raid.h	Sat Jan 15 23:25:59 2011	(r217465)
@@ -308,6 +308,9 @@ void g_raid_change_disk_state(struct g_r
 void g_raid_change_subdisk_state(struct g_raid_subdisk *sd, int state);
 void g_raid_change_volume_state(struct g_raid_volume *vol, int state);
 
+void g_raid_write_metadata(struct g_raid_softc *sc, struct g_raid_volume *vol,
+    struct g_raid_subdisk *sd, struct g_raid_disk *disk);
+
 u_int g_raid_ndisks(struct g_raid_softc *sc, int state);
 u_int g_raid_nsubdisks(struct g_raid_volume *vol, int state);
 #define	G_RAID_DESTROY_SOFT		0

Modified: projects/graid/head/sys/geom/raid/g_raid_md_if.m
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid_md_if.m	Sat Jan 15 22:07:08 2011	(r217464)
+++ projects/graid/head/sys/geom/raid/g_raid_md_if.m	Sat Jan 15 23:25:59 2011	(r217465)
@@ -95,6 +95,9 @@ METHOD int event {
 # write() - metadata write method.
 METHOD int write {
 	struct g_raid_md_object *md;
+	struct g_raid_volume *vol;
+	struct g_raid_subdisk *sd;
+	struct g_raid_disk *disk;
 };
 
 # free_disk() - disk destructor.

Modified: projects/graid/head/sys/geom/raid/md_intel.c
==============================================================================
--- projects/graid/head/sys/geom/raid/md_intel.c	Sat Jan 15 22:07:08 2011	(r217464)
+++ projects/graid/head/sys/geom/raid/md_intel.c	Sat Jan 15 23:25:59 2011	(r217465)
@@ -904,6 +904,8 @@ g_raid_md_event_intel(struct g_raid_md_o
 				disk->d_consumer = NULL;
 			}
 			TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
+				g_raid_change_subdisk_state(sd,
+				    G_RAID_SUBDISK_S_NONE);
 				g_raid_event_send(sd, G_RAID_SUBDISK_E_DISCONNECTED,
 				    G_RAID_EVENT_SUBDISK);
 			}
@@ -912,6 +914,11 @@ g_raid_md_event_intel(struct g_raid_md_o
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 			g_raid_destroy_disk(disk);
 		}
+
+		/* Write updated metadata to all disks. */
+		g_raid_md_write_intel(md, NULL, NULL, NULL);
+
+		/* Check if anything left. */
 		if (g_raid_ndisks(sc, G_RAID_DISK_S_NONE) == 0 &&
 		    g_raid_ndisks(sc, G_RAID_DISK_S_ACTIVE) == 0)
 			g_raid_destroy_node(sc, 0);
@@ -1111,7 +1118,7 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
 		}
 
 		/* Write metadata based on created entities. */
-		g_raid_md_write_intel(md);
+		g_raid_md_write_intel(md, NULL, NULL, NULL);
 		return (0);
 	}
 	if (strcmp(verb, "remove") == 0) {
@@ -1158,6 +1165,8 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
 					disk->d_consumer = NULL;
 				}
 				TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
+					g_raid_change_subdisk_state(sd,
+					    G_RAID_SUBDISK_S_NONE);
 					g_raid_event_send(sd, G_RAID_SUBDISK_E_DISCONNECTED,
 					    G_RAID_EVENT_SUBDISK);
 				}
@@ -1169,7 +1178,7 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
 		}
 
 		/* Write updated metadata to remaining disks. */
-		g_raid_md_write_intel(md);
+		g_raid_md_write_intel(md, NULL, NULL, NULL);
 
 		/* Check if anything left. */
 		if (g_raid_ndisks(sc, G_RAID_DISK_S_NONE) == 0 &&
@@ -1289,14 +1298,15 @@ g_raid_md_ctl_intel(struct g_raid_md_obj
 		}
 
 		/* Write updated metadata to all disks. */
-		g_raid_md_write_intel(md);
+		g_raid_md_write_intel(md, NULL, NULL, NULL);
 		return (error);
 	}
 	return (-100);
 }
 
 static int
-g_raid_md_write_intel(struct g_raid_md_object *md)
+g_raid_md_write_intel(struct g_raid_md_object *md, struct g_raid_volume *tvol,
+    struct g_raid_subdisk *tsd, struct g_raid_disk *tdisk)
 {
 	struct g_raid_softc *sc;
 	struct g_raid_volume *vol;
@@ -1306,10 +1316,10 @@ g_raid_md_write_intel(struct g_raid_md_o
 	struct g_raid_md_intel_perdisk *pd;
 	struct intel_raid_conf *meta;
 	struct intel_raid_vol *mvol;
-	struct intel_raid_map *mmap;
+	struct intel_raid_map *mmap0, *mmap1;
 	off_t sectorsize = 512;
 	const char *version, *cv;
-	int vi, sdi, numdisks, len;
+	int vi, sdi, numdisks, len, state;
 
 	sc = md->mdo_softc;
 	mdi = (struct g_raid_md_intel_object *)md;
@@ -1362,7 +1372,6 @@ g_raid_md_write_intel(struct g_raid_md_o
 	version = INTEL_VERSION_1000;
 	TAILQ_FOREACH(vol, &sc->sc_volumes, v_next) {
 		mvol = intel_get_volume(meta, vi);
-		mmap = intel_get_map(mvol, 0);
 
 		/* New metadata may have different volumes order. */
 		vol->v_md_data = (void *)(intptr_t)vi;
@@ -1406,42 +1415,86 @@ g_raid_md_write_intel(struct g_raid_md_o
 
 		strlcpy(&mvol->name[0], vol->v_name, sizeof(mvol->name));
 		mvol->total_sectors = vol->v_mediasize / sectorsize;
-		mmap->offset = sd->sd_offset / sectorsize;
-		mmap->disk_sectors = sd->sd_size / sectorsize;
-		mmap->strip_sectors = vol->v_strip_size / sectorsize;
+
+		/* Check for any recovery in progress. */
+		state = G_RAID_SUBDISK_S_ACTIVE;
+		for (sdi = 0; sdi < vol->v_disks_count; sdi++) {
+			sd = &vol->v_subdisks[sdi];
+			if (sd->sd_state == G_RAID_SUBDISK_S_REBUILD)
+				state = G_RAID_SUBDISK_S_REBUILD;
+			else if (sd->sd_state == G_RAID_SUBDISK_S_RESYNC &&
+			    state != G_RAID_SUBDISK_S_REBUILD)
+				state = G_RAID_SUBDISK_S_RESYNC;
+		}
+		if (state == G_RAID_SUBDISK_S_REBUILD) {
+			mvol->migr_state = 1;
+			mvol->migr_type = INTEL_MT_REBUILD;
+		} else if (state == G_RAID_SUBDISK_S_RESYNC) {
+			mvol->migr_state = 1;
+			mvol->migr_type = INTEL_MT_REPAIR;
+		} else
+			mvol->migr_state = 0;
+
+		mmap0 = intel_get_map(mvol, 0);
+
+		/* Write map / common part of two maps. */
+		mmap0->offset = sd->sd_offset / sectorsize;
+		mmap0->disk_sectors = sd->sd_size / sectorsize;
+		mmap0->strip_sectors = vol->v_strip_size / sectorsize;
 		if (vol->v_state == G_RAID_VOLUME_S_BROKEN)
-			mmap->status = INTEL_S_FAILURE;
+			mmap0->status = INTEL_S_FAILURE;
 		else if (vol->v_state == G_RAID_VOLUME_S_DEGRADED)
-			mmap->status = INTEL_S_DEGRADED;
+			mmap0->status = INTEL_S_DEGRADED;
 		else
-			mmap->status = INTEL_S_READY;
+			mmap0->status = INTEL_S_READY;
 		if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID0)
-			mmap->type = INTEL_T_RAID0;
+			mmap0->type = INTEL_T_RAID0;
 		else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1 ||
 		    vol->v_raid_level == G_RAID_VOLUME_RL_RAID10)
-			mmap->type = INTEL_T_RAID1;
+			mmap0->type = INTEL_T_RAID1;
 		else
-			mmap->type = INTEL_T_RAID5;
-		mmap->total_disks = vol->v_disks_count;
+			mmap0->type = INTEL_T_RAID5;
+		mmap0->total_disks = vol->v_disks_count;
 		if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID10)
-			mmap->total_domains = vol->v_disks_count / 2;
+			mmap0->total_domains = vol->v_disks_count / 2;
 		else if (vol->v_raid_level == G_RAID_VOLUME_RL_RAID1)
-			mmap->total_domains = vol->v_disks_count;
+			mmap0->total_domains = vol->v_disks_count;
 		else
-			mmap->total_domains = 1;
-		mmap->stripe_count = sd->sd_size / vol->v_strip_size /
-		    mmap->total_domains;
-		mmap->failed_disk_num = 0xff;
-		mmap->ddf = 1;
+			mmap0->total_domains = 1;
+		mmap0->stripe_count = sd->sd_size / vol->v_strip_size /
+		    mmap0->total_domains;
+		mmap0->failed_disk_num = 0xff;
+		mmap0->ddf = 1;
+
+		/* If there are two maps - copy common and update. */
+		if (mvol->migr_state) {
+			mmap1 = intel_get_map(mvol, 1);
+			memcpy(mmap1, mmap0, sizeof(struct intel_raid_map));
+			mmap0->status = INTEL_S_READY;
+		} else
+			mmap1 = NULL;
+
+		/* Write disk indexes and put rebuild flags. */
 		for (sdi = 0; sdi < vol->v_disks_count; sdi++) {
 			sd = &vol->v_subdisks[sdi];
 			pd = (struct g_raid_md_intel_perdisk *)
 			    sd->sd_disk->d_md_data;
-			mmap->disk_idx[sdi] = pd->pd_disk_pos;
-			if (sd->sd_state != G_RAID_SUBDISK_S_ACTIVE) {
-				mmap->disk_idx[sdi] |= INTEL_DI_RBLD;
-				if (mmap->failed_disk_num == 0xff)
-					mmap->failed_disk_num = sdi;
+			mmap0->disk_idx[sdi] = pd->pd_disk_pos;
+			if (mvol->migr_state)
+				mmap1->disk_idx[sdi] = pd->pd_disk_pos;
+			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) {
+				mmap0->disk_idx[sdi] |= INTEL_DI_RBLD;
+				if (mvol->migr_state)
+					mmap1->disk_idx[sdi] |= INTEL_DI_RBLD;
+			}
+			if (sd->sd_state == G_RAID_SUBDISK_S_NONE &&
+			    mmap0->failed_disk_num == 0xff) {
+				mmap0->failed_disk_num = sdi;
+				if (mvol->migr_state)
+					mmap1->failed_disk_num = sdi;
 			}
 		}
 		vi++;

Modified: projects/graid/head/sys/geom/raid/tr_raid0.c
==============================================================================
--- projects/graid/head/sys/geom/raid/tr_raid0.c	Sat Jan 15 22:07:08 2011	(r217464)
+++ projects/graid/head/sys/geom/raid/tr_raid0.c	Sat Jan 15 23:25:59 2011	(r217465)
@@ -91,9 +91,11 @@ static int
 g_raid_tr_update_state_raid0(struct g_raid_volume *vol)
 {
 	struct g_raid_tr_raid0_object *trs;
+	struct g_raid_softc *sc;
 	u_int s;
 	int n;
 
+	sc = vol->v_softc;
 	trs = (struct g_raid_tr_raid0_object *)vol->v_tr;
 	if (trs->trso_stopped)
 		s = G_RAID_VOLUME_S_STOPPED;
@@ -112,6 +114,8 @@ g_raid_tr_update_state_raid0(struct g_ra
 		    G_RAID_VOLUME_E_UP : G_RAID_VOLUME_E_DOWN,
 		    G_RAID_EVENT_VOLUME);
 		g_raid_change_volume_state(vol, s);
+		if (!trs->trso_starting && !trs->trso_stopped)
+			g_raid_write_metadata(sc, vol, NULL, NULL);
 	}
 	return (0);
 }
@@ -121,13 +125,20 @@ g_raid_tr_event_raid0(struct g_raid_tr_o
     struct g_raid_subdisk *sd, u_int event)
 {
 	struct g_raid_tr_raid0_object *trs;
+	struct g_raid_softc *sc;
 	struct g_raid_volume *vol;
+	int state;
 
 	trs = (struct g_raid_tr_raid0_object *)tr;
 	vol = tr->tro_volume;
-	if (event == G_RAID_SUBDISK_E_NEW)
+	sc = vol->v_softc;
+	if (event == G_RAID_SUBDISK_E_NEW) {
+		state = sd->sd_state;
 		g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_ACTIVE);
-	else
+		if (state != sd->sd_state &&
+		    !trs->trso_starting && !trs->trso_stopped)
+			g_raid_write_metadata(sc, vol, sd, NULL);
+	} else
 		g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_NONE);
 	g_raid_tr_update_state_raid0(vol);
 	return (0);