summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/geom/class/nop/geom_nop.c3
-rw-r--r--sbin/geom/class/nop/gnop.828
-rw-r--r--sys/geom/nop/g_nop.c69
-rw-r--r--sys/geom/nop/g_nop.h8
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 cf72f54..054d52d 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 2663508..64c04ca 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 1a2cb3b..da9abf5 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;
@@ -449,6 +463,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)
{
uint32_t *version;
@@ -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<Offset>%jd</Offset>\n", indent,
(intmax_t)sc->sc_offset);
- sbuf_printf(sb, "%s<Failprob>%u</Failprob>\n", indent, sc->sc_failprob);
+ sbuf_printf(sb, "%s<FailProb>%u</FailProb>\n", indent, sc->sc_failprob);
+ sbuf_printf(sb, "%s<Reads>%ju</Reads>\n", indent, sc->sc_reads);
+ sbuf_printf(sb, "%s<Writes>%ju</Writes>\n", indent, sc->sc_writes);
+ sbuf_printf(sb, "%s<ReadBytes>%ju</ReadBytess>\n", indent,
+ sc->sc_readbytes);
+ sbuf_printf(sb, "%s<WroteBytes>%ju</WroteBytes>\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 378c3ef..e8df888 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 */
OpenPOWER on IntegriCloud