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.
This commit is contained in:
parent
83d165c127
commit
c6d4ed3a32
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=219970
@ -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);
|
||||
|
@ -56,6 +56,16 @@ __FBSDID("$FreeBSD$");
|
||||
#include <geom/geom_disk.h>
|
||||
#include <geom/geom_int.h>
|
||||
|
||||
#include <dev/led/led.h>
|
||||
|
||||
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 r, int w, int e)
|
||||
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);
|
||||
@ -185,11 +202,38 @@ g_disk_kerneldump(struct bio *bp, struct disk *dp)
|
||||
g_io_deliver(bp, 0);
|
||||
}
|
||||
|
||||
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_long cmd, void * data, int fflag, struct t
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user