From owner-svn-src-all@FreeBSD.ORG Thu Mar 24 19:23:42 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9325D106566C; Thu, 24 Mar 2011 19:23:42 +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 8214D8FC0A; Thu, 24 Mar 2011 19:23:42 +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 p2OJNgrI055035; Thu, 24 Mar 2011 19:23:42 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2OJNg3Z055032; Thu, 24 Mar 2011 19:23:42 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201103241923.p2OJNg3Z055032@svn.freebsd.org> From: Alexander Motin Date: Thu, 24 Mar 2011 19:23:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r219970 - head/sys/geom X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Mar 2011 19:23:42 -0000 Author: mav Date: Thu Mar 24 19:23:42 2011 New Revision: 219970 URL: http://svn.freebsd.org/changeset/base/219970 Log: MFgraid/head r218212, r218257: Introduce new type of BIO_GETATTR -- GEOM::setstate, used to inform lower GEOM about state of it's providers from the point of upper layers. Make geom_disk use led(4) subsystem to illuminate states in such fashion: FAILED - "1" (on), REBUILD - "f5" (slow blink), RESYNC - "f1" (fast blink), ACTIVE - "0" (off). LED name should be set for each disk via kern.geom.disk.%s.led sysctl. Later disk API could be extended to allow disk driver to report this info in custom way via it's own facilities. Modified: head/sys/geom/geom.h head/sys/geom/geom_disk.c Modified: head/sys/geom/geom.h ============================================================================== --- head/sys/geom/geom.h Thu Mar 24 19:11:05 2011 (r219969) +++ head/sys/geom/geom.h Thu Mar 24 19:23:42 2011 (r219970) @@ -208,6 +208,12 @@ struct g_classifier_hook { void *arg; }; +/* BIO_GETATTR("GEOM::setstate") argument values. */ +#define G_STATE_FAILED 0 +#define G_STATE_REBUILD 1 +#define G_STATE_RESYNC 2 +#define G_STATE_ACTIVE 3 + /* geom_dev.c */ struct cdev; void g_dev_print(void); Modified: head/sys/geom/geom_disk.c ============================================================================== --- head/sys/geom/geom_disk.c Thu Mar 24 19:11:05 2011 (r219969) +++ head/sys/geom/geom_disk.c Thu Mar 24 19:23:42 2011 (r219970) @@ -56,6 +56,16 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +struct g_disk_softc { + struct disk *dp; + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + char led[64]; + uint32_t state; +}; + static struct mtx g_disk_done_mtx; static g_access_t g_disk_access; @@ -76,6 +86,9 @@ static struct g_class g_disk_class = { .dumpconf = g_disk_dumpconf, }; +SYSCTL_DECL(_kern_geom); +SYSCTL_NODE(_kern_geom, OID_AUTO, disk, CTLFLAG_RW, 0, "GEOM_DISK stuff"); + static void g_disk_init(struct g_class *mp __unused) { @@ -110,13 +123,14 @@ static int g_disk_access(struct g_provider *pp, int r, int w, int e) { struct disk *dp; + struct g_disk_softc *sc; int error; g_trace(G_T_ACCESS, "g_disk_access(%s, %d, %d, %d)", pp->name, r, w, e); g_topology_assert(); - dp = pp->geom->softc; - if (dp == NULL || dp->d_destroyed) { + sc = pp->geom->softc; + if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) { /* * Allow decreasing access count even if disk is not * avaliable anymore. @@ -155,6 +169,9 @@ g_disk_access(struct g_provider *pp, int pp->name, error); g_disk_unlock_giant(dp); } + sc->state = G_STATE_ACTIVE; + if (sc->led[0] != 0) + led_set(sc->led, "0"); dp->d_flags &= ~DISKFLAG_OPEN; } return (error); @@ -186,10 +203,37 @@ g_disk_kerneldump(struct bio *bp, struct } static void +g_disk_setstate(struct bio *bp, struct g_disk_softc *sc) +{ + const char *cmd; + + memcpy(&sc->state, bp->bio_data, sizeof(sc->state)); + if (sc->led[0] != 0) { + switch (sc->state) { + case G_STATE_FAILED: + cmd = "1"; + break; + case G_STATE_REBUILD: + cmd = "f5"; + break; + case G_STATE_RESYNC: + cmd = "f1"; + break; + default: + cmd = "0"; + break; + } + led_set(sc->led, cmd); + } + g_io_deliver(bp, 0); +} + +static void g_disk_done(struct bio *bp) { struct bio *bp2; struct disk *dp; + struct g_disk_softc *sc; /* See "notes" for why we need a mutex here */ /* XXX: will witness accept a mix of Giant/unGiant drivers here ? */ @@ -201,7 +245,8 @@ g_disk_done(struct bio *bp) bp2->bio_error = bp->bio_error; bp2->bio_completed += bp->bio_completed; if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) && - (dp = bp2->bio_to->geom->softc)) { + (sc = bp2->bio_to->geom->softc) && + (dp = sc->dp)) { devstat_end_transaction_bio(dp->d_devstat, bp); } g_destroy_bio(bp); @@ -218,10 +263,12 @@ g_disk_ioctl(struct g_provider *pp, u_lo { struct g_geom *gp; struct disk *dp; + struct g_disk_softc *sc; int error; gp = pp->geom; - dp = gp->softc; + sc = gp->softc; + dp = sc->dp; if (dp->d_ioctl == NULL) return (ENOIOCTL); @@ -236,11 +283,12 @@ g_disk_start(struct bio *bp) { struct bio *bp2, *bp3; struct disk *dp; + struct g_disk_softc *sc; int error; off_t off; - dp = bp->bio_to->geom->softc; - if (dp == NULL || dp->d_destroyed) { + sc = bp->bio_to->geom->softc; + if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) { g_io_deliver(bp, ENXIO); return; } @@ -319,6 +367,8 @@ g_disk_start(struct bio *bp) break; else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump")) g_disk_kerneldump(bp, dp); + else if (!strcmp(bp->bio_attribute, "GEOM::setstate")) + g_disk_setstate(bp, sc); else error = ENOIOCTL; break; @@ -353,9 +403,10 @@ static void g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp) { struct disk *dp; + struct g_disk_softc *sc; - dp = gp->softc; - if (dp == NULL) + sc = gp->softc; + if (sc == NULL || (dp = sc->dp) == NULL) return; if (indent == NULL) { sbuf_printf(sb, " hd %u", dp->d_fwheads); @@ -378,13 +429,17 @@ g_disk_create(void *arg, int flag) struct g_geom *gp; struct g_provider *pp; struct disk *dp; + struct g_disk_softc *sc; + char tmpstr[80]; if (flag == EV_CANCEL) return; g_topology_assert(); dp = arg; + sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO); + sc->dp = dp; gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit); - gp->softc = dp; + gp->softc = sc; pp = g_new_providerf(gp, "%s", gp->name); pp->mediasize = dp->d_mediasize; pp->sectorsize = dp->d_sectorsize; @@ -394,6 +449,21 @@ g_disk_create(void *arg, int flag) pp->stripesize = dp->d_stripesize; if (bootverbose) printf("GEOM: new disk %s\n", gp->name); + sysctl_ctx_init(&sc->sysctl_ctx); + snprintf(tmpstr, sizeof(tmpstr), "GEOM disk %s", gp->name); + sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_kern_geom_disk), OID_AUTO, gp->name, + CTLFLAG_RD, 0, tmpstr); + if (sc->sysctl_tree != NULL) { + snprintf(tmpstr, sizeof(tmpstr), + "kern.geom.disk.%s.led", gp->name); + TUNABLE_STR_FETCH(tmpstr, sc->led, sizeof(sc->led)); + SYSCTL_ADD_STRING(&sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "led", + CTLFLAG_RW | CTLFLAG_TUN, sc->led, sizeof(sc->led), + "LED name"); + } + pp->private = sc; dp->d_geom = gp; g_error_provider(pp, 0); } @@ -403,11 +473,22 @@ g_disk_destroy(void *ptr, int flag) { struct disk *dp; struct g_geom *gp; + struct g_disk_softc *sc; g_topology_assert(); dp = ptr; gp = dp->d_geom; if (gp != NULL) { + sc = gp->softc; + if (sc->sysctl_tree != NULL) { + sysctl_ctx_free(&sc->sysctl_ctx); + sc->sysctl_tree = NULL; + } + if (sc->led[0] != 0) { + led_set(sc->led, "0"); + sc->led[0] = 0; + } + g_free(sc); gp->softc = NULL; g_wither_geom(gp, ENXIO); }