From df3d5a19fcb4015fa20b062d1785582e1367f82f Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 8 Dec 2005 23:00:31 +0000 Subject: [PATCH] Teach NOP GEOM class how to gather the following statistics: - number of read I/O requests, - number of write I/O requests, - number of read bytes, - number of written bytes. Add 'reset' subcommand for resetting statistics. --- sbin/geom/class/nop/geom_nop.c | 3 ++ sbin/geom/class/nop/gnop.8 | 28 +++++++++++--- sys/geom/nop/g_nop.c | 69 +++++++++++++++++++++++++++++++++- sys/geom/nop/g_nop.h | 8 +++- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/sbin/geom/class/nop/geom_nop.c b/sbin/geom/class/nop/geom_nop.c index cf72f544b56..054d52de211 100644 --- a/sbin/geom/class/nop/geom_nop.c +++ b/sbin/geom/class/nop/geom_nop.c @@ -68,5 +68,8 @@ struct g_command class_commands[] = { }, "[-fv] prov ..." }, + { "reset", G_FLAG_VERBOSE, NULL, G_NULL_OPTS, + "[-v] prov ..." + }, G_CMD_SENTINEL }; diff --git a/sbin/geom/class/nop/gnop.8 b/sbin/geom/class/nop/gnop.8 index 2663508044a..64c04ca5307 100644 --- a/sbin/geom/class/nop/gnop.8 +++ b/sbin/geom/class/nop/gnop.8 @@ -49,6 +49,10 @@ .Op Fl fv .Ar prov ... .Nm +.Cm reset +.Op Fl v +.Ar prov ... +.Nm .Cm list .Nm .Cm status @@ -62,7 +66,10 @@ The utility is used for setting up transparent providers on existing ones. Its main purpose is testing other GEOM classes, as it allows forced provider removal and I/O error simulation with a given probability. -It is also a good starting point for implementing new GEOM classes. +It also gathers the following statistics: number of read requests, number of +write requests, number of read bytes and number of wrote bytes. +In addition, it can be used as a good starting point for implementing new GEOM +class. .Pp The first argument to .Nm @@ -77,13 +84,11 @@ The kernel module will be loaded if it is not loaded already. .It Cm configure Configure existing transparent provider. -At the moment it is only used -for changing failure probability. -The kernel module -.Pa geom_nop.ko -will be loaded if it is not loaded already. +At the moment it is only used for changing failure probability. .It Cm destroy Turn off the given transparent providers. +.It Cm reset +Reset statistics for the given transparent providers. .It Cm list See .Xr geom 8 . @@ -139,6 +144,17 @@ with 50% failure probability, and how to destroy it. gnop create -v -f 50 da0 gnop destroy -v da0.nop .Ed +.Pp +The traffic statistics for the given transparent providers we can get with +.Cm list +command. +Example below shows how can we obtain number of bytes written with +.Xr newfs 8 : +.Bd -literal -offset indent +gnop create da0 +newfs /dev/da0.nop +gnop list +.Ed .Sh SEE ALSO .Xr geom 4 , .Xr geom 8 diff --git a/sys/geom/nop/g_nop.c b/sys/geom/nop/g_nop.c index 1a2cb3b058b..da9abf5cf14 100644 --- a/sys/geom/nop/g_nop.c +++ b/sys/geom/nop/g_nop.c @@ -86,6 +86,16 @@ g_nop_start(struct bio *bp) g_io_deliver(bp, ENOMEM); return; } + switch (bp->bio_cmd) { + case BIO_READ: + sc->sc_reads++; + sc->sc_readbytes += bp->bio_length; + break; + case BIO_WRITE: + sc->sc_writes++; + sc->sc_wrotebytes += bp->bio_length; + break; + } if (sc->sc_failprob > 0) { u_int rval; @@ -176,6 +186,10 @@ g_nop_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp, sc = g_malloc(sizeof(*sc), M_WAITOK); sc->sc_offset = offset; sc->sc_failprob = failprob; + sc->sc_reads = 0; + sc->sc_writes = 0; + sc->sc_readbytes = 0; + sc->sc_wrotebytes = 0; gp->softc = sc; gp->start = g_nop_start; gp->orphan = g_nop_orphan; @@ -448,6 +462,50 @@ g_nop_ctl_destroy(struct gctl_req *req, struct g_class *mp) } } +static void +g_nop_ctl_reset(struct gctl_req *req, struct g_class *mp) +{ + struct g_nop_softc *sc; + struct g_provider *pp; + const char *name; + char param[16]; + int i, *nargs; + + g_topology_assert(); + + nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); + if (nargs == NULL) { + gctl_error(req, "No '%s' argument", "nargs"); + return; + } + if (*nargs <= 0) { + gctl_error(req, "Missing device(s)."); + return; + } + + for (i = 0; i < *nargs; i++) { + snprintf(param, sizeof(param), "arg%d", i); + name = gctl_get_asciiparam(req, param); + if (name == NULL) { + gctl_error(req, "No 'arg%d' argument", i); + return; + } + if (strncmp(name, "/dev/", strlen("/dev/")) == 0) + name += strlen("/dev/"); + pp = g_provider_by_name(name); + if (pp == NULL || pp->geom->class != mp) { + G_NOP_DEBUG(1, "Provider %s is invalid.", name); + gctl_error(req, "Provider %s is invalid.", name); + return; + } + sc = pp->geom->softc; + sc->sc_reads = 0; + sc->sc_writes = 0; + sc->sc_readbytes = 0; + sc->sc_wrotebytes = 0; + } +} + static void g_nop_config(struct gctl_req *req, struct g_class *mp, const char *verb) { @@ -474,6 +532,9 @@ g_nop_config(struct gctl_req *req, struct g_class *mp, const char *verb) } else if (strcmp(verb, "destroy") == 0) { g_nop_ctl_destroy(req, mp); return; + } else if (strcmp(verb, "reset") == 0) { + g_nop_ctl_reset(req, mp); + return; } gctl_error(req, "Unknown verb."); @@ -490,7 +551,13 @@ g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, sc = gp->softc; sbuf_printf(sb, "%s%jd\n", indent, (intmax_t)sc->sc_offset); - sbuf_printf(sb, "%s%u\n", indent, sc->sc_failprob); + sbuf_printf(sb, "%s%u\n", indent, sc->sc_failprob); + sbuf_printf(sb, "%s%ju\n", indent, sc->sc_reads); + sbuf_printf(sb, "%s%ju\n", indent, sc->sc_writes); + sbuf_printf(sb, "%s%ju\n", indent, + sc->sc_readbytes); + sbuf_printf(sb, "%s%ju\n", indent, + sc->sc_writebytes); } DECLARE_GEOM_CLASS(g_nop_class, g_nop); diff --git a/sys/geom/nop/g_nop.h b/sys/geom/nop/g_nop.h index 378c3eff490..e8df8882f23 100644 --- a/sys/geom/nop/g_nop.h +++ b/sys/geom/nop/g_nop.h @@ -55,8 +55,12 @@ } while (0) struct g_nop_softc { - off_t sc_offset; - u_int sc_failprob; + off_t sc_offset; + u_int sc_failprob; + uintmax_t sc_reads; + uintmax_t sc_writes; + uintmax_t sc_readbytes; + uintmax_t sc_wrotebytes; }; #endif /* _KERNEL */