Date: Thu, 3 Feb 2011 10:29:04 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r218213 - projects/graid/head/sys/geom/raid Message-ID: <201102031029.p13AT4aa042368@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Thu Feb 3 10:29:04 2011 New Revision: 218213 URL: http://svn.freebsd.org/changeset/base/218213 Log: Add support for reporting ACTIVE, REBUILD, RESYNC and FAILED states to underlying disks using BIO_GETATTR(GEOM::setstate) API. While doing it, change the way in which array start timeout is handled: do not call it directly from callout handler, but wrap it into a new event and queue in regular fashion. This is required to allow handler sleep while reporting states or writing metadata. 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 Modified: projects/graid/head/sys/geom/raid/g_raid.c ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid.c Thu Feb 3 10:17:51 2011 (r218212) +++ projects/graid/head/sys/geom/raid/g_raid.c Thu Feb 3 10:29:04 2011 (r218213) @@ -112,9 +112,10 @@ struct g_class g_raid_class = { }; static void g_raid_destroy_provider(struct g_raid_volume *vol); -static int g_raid_update_disk(struct g_raid_disk *disk, u_int state); -static int g_raid_update_subdisk(struct g_raid_subdisk *subdisk, u_int state); -static int g_raid_update_volume(struct g_raid_volume *vol, u_int state); +static int g_raid_update_disk(struct g_raid_disk *disk, u_int event); +static int g_raid_update_subdisk(struct g_raid_subdisk *subdisk, u_int event); +static int g_raid_update_volume(struct g_raid_volume *vol, u_int event); +static int g_raid_update_node(struct g_raid_softc *sc, u_int event); static void g_raid_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp); static void g_raid_start(struct bio *bp); @@ -123,6 +124,18 @@ static void g_raid_disk_done(struct bio static void g_raid_poll(struct g_raid_softc *sc); static const char * +g_raid_node_event2str(int event) +{ + + switch (event) { + case G_RAID_NODE_E_START: + return ("START"); + default: + return ("INVALID"); + } +} + +static const char * g_raid_disk_state2str(int state) { @@ -324,6 +337,41 @@ g_raid_get_subdiskname(struct g_raid_sub } void +g_raid_report_disk_state(struct g_raid_disk *disk) +{ + struct g_raid_subdisk *sd; + int len, state; + uint32_t s; + + if (disk->d_consumer == NULL) + return; + if (disk->d_state == G_RAID_DISK_S_FAILED || + disk->d_state == G_RAID_DISK_S_STALE_FAILED) { + s = G_STATE_FAILED; + } else { + state = G_RAID_SUBDISK_S_ACTIVE; + TAILQ_FOREACH(sd, &disk->d_subdisks, sd_next) { + if (sd->sd_state < state) + state = sd->sd_state; + } + if (state == G_RAID_SUBDISK_S_FAILED) + s = G_STATE_FAILED; + else if (state == G_RAID_SUBDISK_S_NEW || + state == G_RAID_SUBDISK_S_REBUILD) + s = G_STATE_REBUILD; + else if (state == G_RAID_SUBDISK_S_STALE || + state == G_RAID_SUBDISK_S_RESYNC) + s = G_STATE_RESYNC; + else + s = G_STATE_ACTIVE; + } + len = sizeof(s); + g_io_getattr("GEOM::setstate", disk->d_consumer, &len, &s); + G_RAID_DEBUG(1, "Disk %s state reported as %d.", + g_raid_get_diskname(disk), s); +} + +void g_raid_change_disk_state(struct g_raid_disk *disk, int state) { @@ -332,6 +380,7 @@ g_raid_change_disk_state(struct g_raid_d g_raid_disk_state2str(disk->d_state), g_raid_disk_state2str(state)); disk->d_state = state; + g_raid_report_disk_state(disk); } void @@ -343,6 +392,8 @@ g_raid_change_subdisk_state(struct g_rai g_raid_subdisk_state2str(sd->sd_state), g_raid_subdisk_state2str(state)); sd->sd_state = state; + if (sd->sd_disk) + g_raid_report_disk_state(sd->sd_disk); } void @@ -1058,16 +1109,14 @@ static void g_raid_handle_event(struct g_raid_softc *sc, struct g_raid_event *ep) { - if ((ep->e_flags & G_RAID_EVENT_VOLUME) != 0) { - ep->e_error = g_raid_update_volume(ep->e_tgt, - ep->e_event); - } else if ((ep->e_flags & G_RAID_EVENT_DISK) != 0) { - ep->e_error = g_raid_update_disk(ep->e_tgt, - ep->e_event); - } else if ((ep->e_flags & G_RAID_EVENT_SUBDISK) != 0) { - ep->e_error = g_raid_update_subdisk(ep->e_tgt, - ep->e_event); - } + if ((ep->e_flags & G_RAID_EVENT_VOLUME) != 0) + ep->e_error = g_raid_update_volume(ep->e_tgt, ep->e_event); + else if ((ep->e_flags & G_RAID_EVENT_DISK) != 0) + ep->e_error = g_raid_update_disk(ep->e_tgt, ep->e_event); + else if ((ep->e_flags & G_RAID_EVENT_SUBDISK) != 0) + ep->e_error = g_raid_update_subdisk(ep->e_tgt, ep->e_event); + else + ep->e_error = g_raid_update_node(ep->e_tgt, ep->e_event); if ((ep->e_flags & G_RAID_EVENT_WAIT) == 0) { KASSERT(ep->e_error == 0, ("Error cannot be handled.")); @@ -1367,6 +1416,22 @@ g_raid_update_disk(struct g_raid_disk *d return (0); } +/* + * Node event. + */ +static int +g_raid_update_node(struct g_raid_softc *sc, u_int event) +{ + sx_assert(&sc->sc_lock, SX_XLOCKED); + + G_RAID_DEBUG(2, "Event %s for node %s.", + g_raid_node_event2str(event), sc->sc_name); + + if (sc->sc_md) + G_RAID_MD_EVENT(sc->sc_md, NULL, event); + return (0); +} + static int g_raid_access(struct g_provider *pp, int acr, int acw, int ace) { Modified: projects/graid/head/sys/geom/raid/g_raid.h ============================================================================== --- projects/graid/head/sys/geom/raid/g_raid.h Thu Feb 3 10:17:51 2011 (r218212) +++ projects/graid/head/sys/geom/raid/g_raid.h Thu Feb 3 10:29:04 2011 (r218213) @@ -244,6 +244,8 @@ struct g_raid_volume { LIST_ENTRY(g_raid_volume) v_global_next; /* Global list entry. */ }; +#define G_RAID_NODE_E_START 0x01 + struct g_raid_softc { struct g_raid_md_object *sc_md; /* Metadata object. */ struct g_geom *sc_geom; /* GEOM class instance. */ @@ -340,6 +342,7 @@ int g_raid_subdisk_kerneldump(struct g_r void g_raid_kill_consumer(struct g_raid_softc *sc, struct g_consumer *cp); +void g_raid_report_disk_state(struct g_raid_disk *disk); void g_raid_change_disk_state(struct g_raid_disk *disk, int state); 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); Modified: projects/graid/head/sys/geom/raid/md_intel.c ============================================================================== --- projects/graid/head/sys/geom/raid/md_intel.c Thu Feb 3 10:17:51 2011 (r218212) +++ projects/graid/head/sys/geom/raid/md_intel.c Thu Feb 3 10:29:04 2011 (r218213) @@ -905,7 +905,7 @@ g_raid_intel_go(void *arg) sx_xlock(&sc->sc_lock); if (!mdi->mdio_started) { G_RAID_DEBUG(0, "Force node %s start due to timeout.", sc->sc_name); - g_raid_md_intel_start(sc); + g_raid_event_send(sc, G_RAID_NODE_E_START, 0); } sx_xunlock(&sc->sc_lock); } @@ -1132,9 +1132,20 @@ g_raid_md_event_intel(struct g_raid_md_o { struct g_raid_softc *sc; struct g_raid_subdisk *sd; + struct g_raid_md_intel_object *mdi; struct g_raid_md_intel_perdisk *pd; sc = md->mdo_softc; + mdi = (struct g_raid_md_intel_object *)md; + if (disk == NULL) { + switch (event) { + case G_RAID_NODE_E_START: + if (!mdi->mdio_started) + g_raid_md_intel_start(sc); + return (0); + } + return (-1); + } pd = (struct g_raid_md_intel_perdisk *)disk->d_md_data; switch (event) { case G_RAID_DISK_E_DISCONNECTED: @@ -1169,9 +1180,9 @@ g_raid_md_event_intel(struct g_raid_md_o if (g_raid_ndisks(sc, -1) == g_raid_ndisks(sc, G_RAID_DISK_S_OFFLINE)) g_raid_destroy_node(sc, 0); - break; + return (0); } - return (0); + return (-2); } static int
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201102031029.p13AT4aa042368>