svn commit: r226012 - projects/geom-events/sys/geom/raid

Lev A. Serebryakov lev at FreeBSD.org
Tue Oct 4 17:09:10 UTC 2011


Author: lev (ports committer)
Date: Tue Oct  4 17:09:10 2011
New Revision: 226012
URL: http://svn.freebsd.org/changeset/base/226012

Log:
    Add geom_notify_*() calls to geom_raid.
  
    It is not a trivial change.
    To determine state of volume(s) after disk disconnection,
  new method to raid transformation object interface (g_raid_tr)
  was added:
  
  METHOD int getvolstatus {
  	struct g_raid_tr_object *tr;
  	struct g_raid_volume *volume;
  };
  
    This method should return state (G_RAID_VOLUME_S_XXX) of
  the given voulme.
  
    Also, some trnasformation modules have status detection
  code factored out from g_raid_tr_update_state_NAME code.
  
    And some hasn't, as they perform active actions in this
  method and getvolstatus() method should be passive one.

Modified:
  projects/geom-events/sys/geom/raid/g_raid.c
  projects/geom-events/sys/geom/raid/g_raid.h
  projects/geom-events/sys/geom/raid/g_raid_tr_if.m
  projects/geom-events/sys/geom/raid/md_intel.c
  projects/geom-events/sys/geom/raid/md_jmicron.c
  projects/geom-events/sys/geom/raid/md_nvidia.c
  projects/geom-events/sys/geom/raid/md_promise.c
  projects/geom-events/sys/geom/raid/md_sii.c
  projects/geom-events/sys/geom/raid/tr_concat.c
  projects/geom-events/sys/geom/raid/tr_raid0.c
  projects/geom-events/sys/geom/raid/tr_raid1.c
  projects/geom-events/sys/geom/raid/tr_raid1e.c

Modified: projects/geom-events/sys/geom/raid/g_raid.c
==============================================================================
--- projects/geom-events/sys/geom/raid/g_raid.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/g_raid.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -585,6 +585,36 @@ g_raid_get_subdisk(struct g_raid_volume 
 	return (NULL);
 }
 
+/*
+ * Send event about disk disconnection for volume with proper status
+ */
+void
+g_raid_notify_volume(struct g_raid_volume *vol, struct g_raid_disk *disk)
+{
+	if (!vol->v_tr) {
+		g_notify_disconnect(vol->v_provider, disk->d_consumer, G_NOTIFY_DISCONNECT_UNKNOWN);
+		return;
+	}
+	switch (G_RAID_TR_GETVOLSTATUS(vol->v_tr, vol)) {
+	case G_RAID_VOLUME_S_BROKEN:
+		g_notify_disconnect(vol->v_provider, disk->d_consumer, G_NOTIFY_DISCONNECT_DEAD);
+		break;
+	case G_RAID_VOLUME_S_DEGRADED:
+	case G_RAID_VOLUME_S_SUBOPTIMAL:
+		g_notify_disconnect(vol->v_provider, disk->d_consumer, G_NOTIFY_DISCONNECT_FIXABLE);
+		break;
+	case G_RAID_VOLUME_S_OPTIMAL:
+		g_notify_disconnect(vol->v_provider, disk->d_consumer, G_NOTIFY_DISCONNECT_ALIVE);
+		break;
+	case G_RAID_VOLUME_S_STARTING:
+	case G_RAID_VOLUME_S_UNSUPPORTED:
+	case G_RAID_VOLUME_S_STOPPED:
+	default:
+		g_notify_disconnect(vol->v_provider, disk->d_consumer, G_NOTIFY_DISCONNECT_UNKNOWN);
+		break;
+	}
+}
+
 struct g_consumer *
 g_raid_open_consumer(struct g_raid_softc *sc, const char *name)
 {

Modified: projects/geom-events/sys/geom/raid/g_raid.h
==============================================================================
--- projects/geom-events/sys/geom/raid/g_raid.h	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/g_raid.h	Tue Oct  4 17:09:10 2011	(r226012)
@@ -397,6 +397,8 @@ int g_raid_lock_range(struct g_raid_volu
     struct bio *ignore, void *argp);
 int g_raid_unlock_range(struct g_raid_volume *vol, off_t off, off_t len);
 
+void g_raid_notify_volume(struct g_raid_volume *vol, struct g_raid_disk *disk);
+
 g_ctl_req_t g_raid_ctl;
 #endif	/* _KERNEL */
 

Modified: projects/geom-events/sys/geom/raid/g_raid_tr_if.m
==============================================================================
--- projects/geom-events/sys/geom/raid/g_raid_tr_if.m	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/g_raid_tr_if.m	Tue Oct  4 17:09:10 2011	(r226012)
@@ -100,6 +100,12 @@ METHOD int kerneldump {
 	size_t length;
 } DEFAULT g_raid_tr_kerneldump_common;
 
+# getvolstatus() - check status of volume, based on status of subdisks
+METHOD int getvolstatus {
+	struct g_raid_tr_object *tr;
+	struct g_raid_volume *volume;
+};
+
 # locked() - callback method for lock().
 METHOD int locked {
 	struct g_raid_tr_object *tr;

Modified: projects/geom-events/sys/geom/raid/md_intel.c
==============================================================================
--- projects/geom-events/sys/geom/raid/md_intel.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/md_intel.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -1323,20 +1323,23 @@ g_raid_md_event_intel(struct g_raid_md_o
 		/* If disk was assigned, just update statuses. */
 		if (pd->pd_disk_pos >= 0) {
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
-			if (disk->d_consumer) {
-				g_raid_kill_consumer(sc, disk->d_consumer);
-				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);
+				/* Notify about changes in volume */
+				g_raid_notify_volume(sd->sd_volume, disk);
+			}
+			if (disk->d_consumer) {
+				g_raid_kill_consumer(sc, disk->d_consumer);
+				disk->d_consumer = NULL;
 			}
 		} else {
 			/* Otherwise -- delete. */
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 			g_raid_destroy_disk(disk);
+			/* Disk was not assigned, so no volumes, nothing to report */
 		}
 
 		/* Write updated metadata to all disks. */

Modified: projects/geom-events/sys/geom/raid/md_jmicron.c
==============================================================================
--- projects/geom-events/sys/geom/raid/md_jmicron.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/md_jmicron.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -986,20 +986,24 @@ g_raid_md_event_jmicron(struct g_raid_md
 		/* If disk was assigned, just update statuses. */
 		if (pd->pd_disk_pos >= 0) {
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
-			if (disk->d_consumer) {
-				g_raid_kill_consumer(sc, disk->d_consumer);
-				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);
+
+				/* Notify about changes in volume */
+				g_raid_notify_volume(sd->sd_volume, disk);
+			}
+			if (disk->d_consumer) {
+				g_raid_kill_consumer(sc, disk->d_consumer);
+				disk->d_consumer = NULL;
 			}
 		} else {
 			/* Otherwise -- delete. */
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 			g_raid_destroy_disk(disk);
+			/* Disk was not assigned, so no volumes, nothing to report */
 		}
 
 		/* Write updated metadata to all disks. */

Modified: projects/geom-events/sys/geom/raid/md_nvidia.c
==============================================================================
--- projects/geom-events/sys/geom/raid/md_nvidia.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/md_nvidia.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -982,20 +982,24 @@ g_raid_md_event_nvidia(struct g_raid_md_
 		/* If disk was assigned, just update statuses. */
 		if (pd->pd_disk_pos >= 0) {
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
-			if (disk->d_consumer) {
-				g_raid_kill_consumer(sc, disk->d_consumer);
-				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);
+
+				/* Notify about changes in volume */
+				g_raid_notify_volume(sd->sd_volume, disk);
+			}
+			if (disk->d_consumer) {
+				g_raid_kill_consumer(sc, disk->d_consumer);
+				disk->d_consumer = NULL;
 			}
 		} else {
 			/* Otherwise -- delete. */
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 			g_raid_destroy_disk(disk);
+			/* Disk was not assigned, so no volumes, nothing to report */
 		}
 
 		if (mdi->mdio_started) {

Modified: projects/geom-events/sys/geom/raid/md_promise.c
==============================================================================
--- projects/geom-events/sys/geom/raid/md_promise.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/md_promise.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -1154,12 +1154,17 @@ g_raid_md_event_promise(struct g_raid_md
     struct g_raid_disk *disk, u_int event)
 {
 	struct g_raid_softc *sc;
+	struct g_raid_subdisk *sd;
 
 	sc = md->mdo_softc;
 	if (disk == NULL)
 		return (-1);
 	switch (event) {
 	case G_RAID_DISK_E_DISCONNECTED:
+		TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) {
+			/* Notify about changes in volume */
+			g_raid_notify_volume(sd->sd_volume, disk);
+		}
 		/* Delete disk. */
 		g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 		g_raid_destroy_disk(disk);

Modified: projects/geom-events/sys/geom/raid/md_sii.c
==============================================================================
--- projects/geom-events/sys/geom/raid/md_sii.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/md_sii.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -1073,20 +1073,23 @@ g_raid_md_event_sii(struct g_raid_md_obj
 		/* If disk was assigned, just update statuses. */
 		if (pd->pd_disk_pos >= 0) {
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_OFFLINE);
-			if (disk->d_consumer) {
-				g_raid_kill_consumer(sc, disk->d_consumer);
-				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);
+				/* Notify about changes in volume */
+				g_raid_notify_volume(sd->sd_volume, disk);
+			}
+			if (disk->d_consumer) {
+				g_raid_kill_consumer(sc, disk->d_consumer);
+				disk->d_consumer = NULL;
 			}
 		} else {
 			/* Otherwise -- delete. */
 			g_raid_change_disk_state(disk, G_RAID_DISK_S_NONE);
 			g_raid_destroy_disk(disk);
+			/* Disk was not assigned, so no volumes, nothing to report */
 		}
 
 		/* Write updated metadata to all disks. */

Modified: projects/geom-events/sys/geom/raid/tr_concat.c
==============================================================================
--- projects/geom-events/sys/geom/raid/tr_concat.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/tr_concat.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -55,6 +55,7 @@ static g_raid_tr_stop_t g_raid_tr_stop_c
 static g_raid_tr_iostart_t g_raid_tr_iostart_concat;
 static g_raid_tr_iodone_t g_raid_tr_iodone_concat;
 static g_raid_tr_kerneldump_t g_raid_tr_kerneldump_concat;
+static g_raid_tr_getvolstatus_t g_raid_tr_getvolstatus_concat;
 static g_raid_tr_free_t g_raid_tr_free_concat;
 
 static kobj_method_t g_raid_tr_concat_methods[] = {
@@ -65,6 +66,7 @@ static kobj_method_t g_raid_tr_concat_me
 	KOBJMETHOD(g_raid_tr_iostart,	g_raid_tr_iostart_concat),
 	KOBJMETHOD(g_raid_tr_iodone,	g_raid_tr_iodone_concat),
 	KOBJMETHOD(g_raid_tr_kerneldump,	g_raid_tr_kerneldump_concat),
+	KOBJMETHOD(g_raid_tr_getvolstatus,	g_raid_tr_getvolstatus_concat),
 	KOBJMETHOD(g_raid_tr_free,	g_raid_tr_free_concat),
 	{ 0, 0 }
 };
@@ -98,25 +100,11 @@ g_raid_tr_update_state_concat(struct g_r
 	struct g_raid_softc *sc;
 	off_t size;
 	u_int s;
-	int i, n, f;
+	int i;
 
 	sc = vol->v_softc;
 	trs = (struct g_raid_tr_concat_object *)vol->v_tr;
-	if (trs->trso_stopped)
-		s = G_RAID_VOLUME_S_STOPPED;
-	else if (trs->trso_starting)
-		s = G_RAID_VOLUME_S_STARTING;
-	else {
-		n = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
-		f = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_FAILED);
-		if (n + f == vol->v_disks_count) {
-			if (f == 0)
-				s = G_RAID_VOLUME_S_OPTIMAL;
-			else
-				s = G_RAID_VOLUME_S_SUBOPTIMAL;
-		} else
-			s = G_RAID_VOLUME_S_BROKEN;
-	}
+	s = g_raid_tr_getvolstatus_concat(vol->v_tr, vol);
 	if (s != vol->v_state) {
 
 		/*
@@ -316,6 +304,31 @@ g_raid_tr_kerneldump_concat(struct g_rai
 	return (0);
 }
 
+static int
+g_raid_tr_getvolstatus_concat(struct g_raid_tr_object *tr, struct g_raid_volume *volume)
+{
+	struct g_raid_tr_concat_object *trs;
+	int n, f;
+
+	trs = (struct g_raid_tr_concat_object *)tr;
+	KASSERT(tr == volume->v_tr, ("Invalid transformation object"));
+	if (trs->trso_stopped)
+		return G_RAID_VOLUME_S_STOPPED;
+	else if (trs->trso_starting)
+		return G_RAID_VOLUME_S_STARTING;
+	else {
+		n = g_raid_nsubdisks(volume, G_RAID_SUBDISK_S_ACTIVE);
+		f = g_raid_nsubdisks(volume, G_RAID_SUBDISK_S_FAILED);
+		if (n + f == volume->v_disks_count) {
+			if (f == 0)
+				return G_RAID_VOLUME_S_OPTIMAL;
+			else
+				return G_RAID_VOLUME_S_SUBOPTIMAL;
+		}
+	}
+	return G_RAID_VOLUME_S_BROKEN;
+}
+
 static void
 g_raid_tr_iodone_concat(struct g_raid_tr_object *tr,
     struct g_raid_subdisk *sd,struct bio *bp)

Modified: projects/geom-events/sys/geom/raid/tr_raid0.c
==============================================================================
--- projects/geom-events/sys/geom/raid/tr_raid0.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/tr_raid0.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -55,6 +55,7 @@ static g_raid_tr_stop_t g_raid_tr_stop_r
 static g_raid_tr_iostart_t g_raid_tr_iostart_raid0;
 static g_raid_tr_iodone_t g_raid_tr_iodone_raid0;
 static g_raid_tr_kerneldump_t g_raid_tr_kerneldump_raid0;
+static g_raid_tr_getvolstatus_t g_raid_tr_getvolstatus_raid0;
 static g_raid_tr_free_t g_raid_tr_free_raid0;
 
 static kobj_method_t g_raid_tr_raid0_methods[] = {
@@ -65,6 +66,7 @@ static kobj_method_t g_raid_tr_raid0_met
 	KOBJMETHOD(g_raid_tr_iostart,	g_raid_tr_iostart_raid0),
 	KOBJMETHOD(g_raid_tr_iodone,	g_raid_tr_iodone_raid0),
 	KOBJMETHOD(g_raid_tr_kerneldump,	g_raid_tr_kerneldump_raid0),
+	KOBJMETHOD(g_raid_tr_getvolstatus,	g_raid_tr_getvolstatus_raid0),
 	KOBJMETHOD(g_raid_tr_free,	g_raid_tr_free_raid0),
 	{ 0, 0 }
 };
@@ -95,25 +97,10 @@ g_raid_tr_update_state_raid0(struct g_ra
 	struct g_raid_tr_raid0_object *trs;
 	struct g_raid_softc *sc;
 	u_int s;
-	int n, f;
 
 	sc = vol->v_softc;
 	trs = (struct g_raid_tr_raid0_object *)vol->v_tr;
-	if (trs->trso_stopped)
-		s = G_RAID_VOLUME_S_STOPPED;
-	else if (trs->trso_starting)
-		s = G_RAID_VOLUME_S_STARTING;
-	else {
-		n = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE);
-		f = g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_FAILED);
-		if (n + f == vol->v_disks_count) {
-			if (f == 0)
-				s = G_RAID_VOLUME_S_OPTIMAL;
-			else
-				s = G_RAID_VOLUME_S_SUBOPTIMAL;
-		} else
-			s = G_RAID_VOLUME_S_BROKEN;
-	}
+	s = g_raid_tr_getvolstatus_raid0(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,
@@ -299,6 +286,31 @@ g_raid_tr_kerneldump_raid0(struct g_raid
 	return (0);
 }
 
+static int
+g_raid_tr_getvolstatus_raid0(struct g_raid_tr_object *tr, struct g_raid_volume *volume)
+{
+	struct g_raid_tr_raid0_object *trs;
+	int n, f;
+
+	trs = (struct g_raid_tr_raid0_object *)tr;
+	KASSERT(tr == volume->v_tr, ("Invalid transformation object"));
+	if (trs->trso_stopped)
+		return G_RAID_VOLUME_S_STOPPED;
+	else if (trs->trso_starting)
+		return G_RAID_VOLUME_S_STARTING;
+	else {
+		n = g_raid_nsubdisks(volume, G_RAID_SUBDISK_S_ACTIVE);
+		f = g_raid_nsubdisks(volume, G_RAID_SUBDISK_S_FAILED);
+		if (n + f == volume->v_disks_count) {
+			if (f == 0)
+				return G_RAID_VOLUME_S_OPTIMAL;
+			else
+				return G_RAID_VOLUME_S_SUBOPTIMAL;
+		}
+	}
+	return G_RAID_VOLUME_S_BROKEN;
+}
+
 static void
 g_raid_tr_iodone_raid0(struct g_raid_tr_object *tr,
     struct g_raid_subdisk *sd,struct bio *bp)

Modified: projects/geom-events/sys/geom/raid/tr_raid1.c
==============================================================================
--- projects/geom-events/sys/geom/raid/tr_raid1.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/tr_raid1.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -109,6 +109,7 @@ static g_raid_tr_stop_t g_raid_tr_stop_r
 static g_raid_tr_iostart_t g_raid_tr_iostart_raid1;
 static g_raid_tr_iodone_t g_raid_tr_iodone_raid1;
 static g_raid_tr_kerneldump_t g_raid_tr_kerneldump_raid1;
+static g_raid_tr_getvolstatus_t g_raid_tr_getvolstatus_raid1;
 static g_raid_tr_locked_t g_raid_tr_locked_raid1;
 static g_raid_tr_idle_t g_raid_tr_idle_raid1;
 static g_raid_tr_free_t g_raid_tr_free_raid1;
@@ -120,7 +121,8 @@ static kobj_method_t g_raid_tr_raid1_met
 	KOBJMETHOD(g_raid_tr_stop,	g_raid_tr_stop_raid1),
 	KOBJMETHOD(g_raid_tr_iostart,	g_raid_tr_iostart_raid1),
 	KOBJMETHOD(g_raid_tr_iodone,	g_raid_tr_iodone_raid1),
-	KOBJMETHOD(g_raid_tr_kerneldump, g_raid_tr_kerneldump_raid1),
+	KOBJMETHOD(g_raid_tr_kerneldump,	g_raid_tr_kerneldump_raid1),
+	KOBJMETHOD(g_raid_tr_getvolstatus,	g_raid_tr_getvolstatus_raid1),
 	KOBJMETHOD(g_raid_tr_locked,	g_raid_tr_locked_raid1),
 	KOBJMETHOD(g_raid_tr_idle,	g_raid_tr_idle_raid1),
 	KOBJMETHOD(g_raid_tr_free,	g_raid_tr_free_raid1),
@@ -306,6 +308,7 @@ g_raid_tr_raid1_rebuild_finish(struct g_
 	g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_ACTIVE);
 	sd->sd_rebuild_pos = 0;
 	g_raid_tr_raid1_rebuild_done(trs);
+	g_notify_sync_stop(sd->sd_volume->v_provider, 1);
 }
 
 static void
@@ -340,6 +343,7 @@ g_raid_tr_raid1_rebuild_abort(struct g_r
 		}
 		g_raid_tr_raid1_rebuild_done(trs);
 	}
+	g_notify_sync_stop(vol->v_provider, 0);
 }
 
 static void
@@ -402,6 +406,9 @@ g_raid_tr_raid1_rebuild_start(struct g_r
 	trs->trso_type = TR_RAID1_REBUILD;
 	trs->trso_buffer = malloc(g_raid1_rebuild_slab, M_TR_RAID1, M_WAITOK);
 	trs->trso_meta_update = g_raid1_rebuild_meta_update;
+
+	g_notify_sync_start(vol->v_provider);
+
 	g_raid_tr_raid1_rebuild_some(tr);
 }
 
@@ -947,6 +954,33 @@ g_raid_tr_kerneldump_raid1(struct g_raid
 }
 
 static int
+g_raid_tr_getvolstatus_raid1(struct g_raid_tr_object *tr, struct g_raid_volume *volume)
+{
+	struct g_raid_tr_raid1_object *trs;
+	int na, ns;
+
+	trs = (struct g_raid_tr_raid1_object *)tr;
+	KASSERT(tr == volume->v_tr, ("Invalid transformation object"));
+	if (trs->trso_stopping &&
+	    (trs->trso_flags & TR_RAID1_F_DOING_SOME) == 0)
+		return G_RAID_VOLUME_S_STOPPED;
+	else if (trs->trso_starting)
+		return G_RAID_VOLUME_S_STARTING;
+	else {
+		na = g_raid_nsubdisks(volume, G_RAID_SUBDISK_S_ACTIVE);
+		ns = g_raid_nsubdisks(volume, G_RAID_SUBDISK_S_STALE) +
+		     g_raid_nsubdisks(volume, G_RAID_SUBDISK_S_RESYNC);
+		if (na == volume->v_disks_count)
+			return G_RAID_VOLUME_S_OPTIMAL;
+		else if (na + ns == volume->v_disks_count)
+			return G_RAID_VOLUME_S_SUBOPTIMAL;
+		else if (na > 0)
+			return G_RAID_VOLUME_S_DEGRADED;
+	}
+	return G_RAID_VOLUME_S_BROKEN;
+}
+
+static int
 g_raid_tr_locked_raid1(struct g_raid_tr_object *tr, void *argp)
 {
 	struct bio *bp;

Modified: projects/geom-events/sys/geom/raid/tr_raid1e.c
==============================================================================
--- projects/geom-events/sys/geom/raid/tr_raid1e.c	Tue Oct  4 17:08:24 2011	(r226011)
+++ projects/geom-events/sys/geom/raid/tr_raid1e.c	Tue Oct  4 17:09:10 2011	(r226012)
@@ -113,6 +113,7 @@ static g_raid_tr_stop_t g_raid_tr_stop_r
 static g_raid_tr_iostart_t g_raid_tr_iostart_raid1e;
 static g_raid_tr_iodone_t g_raid_tr_iodone_raid1e;
 static g_raid_tr_kerneldump_t g_raid_tr_kerneldump_raid1e;
+static g_raid_tr_getvolstatus_t g_raid_tr_getvolstatus_raid1e;
 static g_raid_tr_locked_t g_raid_tr_locked_raid1e;
 static g_raid_tr_idle_t g_raid_tr_idle_raid1e;
 static g_raid_tr_free_t g_raid_tr_free_raid1e;
@@ -124,7 +125,8 @@ static kobj_method_t g_raid_tr_raid1e_me
 	KOBJMETHOD(g_raid_tr_stop,	g_raid_tr_stop_raid1e),
 	KOBJMETHOD(g_raid_tr_iostart,	g_raid_tr_iostart_raid1e),
 	KOBJMETHOD(g_raid_tr_iodone,	g_raid_tr_iodone_raid1e),
-	KOBJMETHOD(g_raid_tr_kerneldump, g_raid_tr_kerneldump_raid1e),
+	KOBJMETHOD(g_raid_tr_kerneldump,	g_raid_tr_kerneldump_raid1e),
+	KOBJMETHOD(g_raid_tr_getvolstatus,	g_raid_tr_getvolstatus_raid1e),
 	KOBJMETHOD(g_raid_tr_locked,	g_raid_tr_locked_raid1e),
 	KOBJMETHOD(g_raid_tr_idle,	g_raid_tr_idle_raid1e),
 	KOBJMETHOD(g_raid_tr_free,	g_raid_tr_free_raid1e),
@@ -194,6 +196,88 @@ g_raid_tr_taste_raid1e(struct g_raid_tr_
 }
 
 static int
+g_raid_tr_getvolstatus_raid1e_even(struct g_raid_volume *vol)
+{
+	struct g_raid_softc *sc;
+	struct g_raid_subdisk *sd, *bestsd, *worstsd;
+	int i, j, state, sstate;
+
+	sc = vol->v_softc;
+	state = G_RAID_VOLUME_S_OPTIMAL;
+	for (i = 0; i < vol->v_disks_count / N; i++) {
+		bestsd = &vol->v_subdisks[i * N];
+		for (j = 1; j < N; j++) {
+			sd = &vol->v_subdisks[i * N + j];
+			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;
+		}
+		worstsd = &vol->v_subdisks[i * N];
+		for (j = 1; j < N; j++) {
+			sd = &vol->v_subdisks[i * N + j];
+			if (sd->sd_state < worstsd->sd_state)
+				worstsd = sd;
+		}
+		if (worstsd->sd_state == G_RAID_SUBDISK_S_ACTIVE)
+			sstate = G_RAID_VOLUME_S_OPTIMAL;
+		else if (worstsd->sd_state >= G_RAID_SUBDISK_S_STALE)
+			sstate = G_RAID_VOLUME_S_SUBOPTIMAL;
+		else if (bestsd->sd_state == G_RAID_SUBDISK_S_ACTIVE)
+			sstate = G_RAID_VOLUME_S_DEGRADED;
+		else
+			sstate = G_RAID_VOLUME_S_BROKEN;
+		if (sstate < state)
+			state = sstate;
+	}
+	return (state);
+}
+
+static int
+g_raid_tr_getvolstatus_raid1e_odd(struct g_raid_volume *vol)
+{
+	struct g_raid_softc *sc;
+	struct g_raid_subdisk *sd, *bestsd, *worstsd;
+	int i, j, state, sstate;
+
+	sc = vol->v_softc;
+	if (g_raid_nsubdisks(vol, G_RAID_SUBDISK_S_ACTIVE) ==
+	    vol->v_disks_count)
+		return (G_RAID_VOLUME_S_OPTIMAL);
+	state = G_RAID_VOLUME_S_OPTIMAL;
+	for (i = 0; i < vol->v_disks_count; i++) {
+		bestsd = &vol->v_subdisks[i];
+		worstsd = &vol->v_subdisks[i];
+		for (j = 1; j < N; j++) {
+			sd = &vol->v_subdisks[(i + j) % vol->v_disks_count];
+			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 (sd->sd_state < worstsd->sd_state)
+				worstsd = sd;
+		}
+		if (worstsd->sd_state == G_RAID_SUBDISK_S_ACTIVE)
+			sstate = G_RAID_VOLUME_S_OPTIMAL;
+		else if (worstsd->sd_state >= G_RAID_SUBDISK_S_STALE)
+			sstate = G_RAID_VOLUME_S_SUBOPTIMAL;
+		else if (bestsd->sd_state >= G_RAID_SUBDISK_S_STALE)
+			sstate = G_RAID_VOLUME_S_DEGRADED;
+		else
+			sstate = G_RAID_VOLUME_S_BROKEN;
+		if (sstate < state)
+			state = sstate;
+	}
+	return (state);
+}
+
+static int
 g_raid_tr_update_state_raid1e_even(struct g_raid_volume *vol)
 {
 	struct g_raid_softc *sc;
@@ -386,6 +470,7 @@ g_raid_tr_raid1e_rebuild_finish(struct g
 	g_raid_change_subdisk_state(sd, G_RAID_SUBDISK_S_ACTIVE);
 	sd->sd_rebuild_pos = 0;
 	g_raid_tr_raid1e_rebuild_done(trs);
+	g_notify_sync_stop(sd->sd_volume->v_provider, 1);
 }
 
 static void
@@ -417,6 +502,7 @@ g_raid_tr_raid1e_rebuild_abort(struct g_
 		}
 		g_raid_tr_raid1e_rebuild_done(trs);
 	}
+	g_notify_sync_stop(vol->v_provider, 0);
 }
 
 static void
@@ -548,6 +634,9 @@ g_raid_tr_raid1e_rebuild_start(struct g_
 	trs->trso_type = TR_RAID1E_REBUILD;
 	trs->trso_buffer = malloc(g_raid1e_rebuild_slab, M_TR_RAID1E, M_WAITOK);
 	trs->trso_meta_update = g_raid1e_rebuild_meta_update;
+
+	g_notify_sync_start(vol->v_provider);
+
 	g_raid_tr_raid1e_rebuild_some(tr);
 }
 
@@ -1173,6 +1262,26 @@ nextdisk:
 }
 
 static int
+g_raid_tr_getvolstatus_raid1e(struct g_raid_tr_object *tr, struct g_raid_volume *volume)
+{
+	struct g_raid_tr_raid1e_object *trs;
+
+	trs = (struct g_raid_tr_raid1e_object *)tr;
+	KASSERT(tr == volume->v_tr, ("Invalid transformation object"));
+	if (trs->trso_stopping &&
+	    (trs->trso_flags & TR_RAID1E_F_DOING_SOME) == 0)
+		return G_RAID_VOLUME_S_STOPPED;
+	else if (trs->trso_starting)
+		return G_RAID_VOLUME_S_STARTING;
+	else {
+		if ((volume->v_disks_count % N) == 0)
+			return g_raid_tr_getvolstatus_raid1e_even(volume);
+		else
+			return g_raid_tr_getvolstatus_raid1e_odd(volume);
+	}
+}
+
+static int
 g_raid_tr_locked_raid1e(struct g_raid_tr_object *tr, void *argp)
 {
 	struct bio *bp;


More information about the svn-src-projects mailing list