diff options
Diffstat (limited to 'sys/geom')
-rw-r--r-- | sys/geom/bde/g_bde_lock.c | 1 | ||||
-rw-r--r-- | sys/geom/bde/g_bde_work.c | 1 | ||||
-rw-r--r-- | sys/geom/geom.h | 27 | ||||
-rw-r--r-- | sys/geom/geom_dev.c | 3 | ||||
-rw-r--r-- | sys/geom/geom_int.h | 5 | ||||
-rw-r--r-- | sys/geom/geom_io.c | 45 | ||||
-rw-r--r-- | sys/geom/geom_kern.c | 2 | ||||
-rw-r--r-- | sys/geom/geom_stats.c | 145 | ||||
-rw-r--r-- | sys/geom/geom_stats.h | 56 | ||||
-rw-r--r-- | sys/geom/geom_subr.c | 10 |
10 files changed, 243 insertions, 52 deletions
diff --git a/sys/geom/bde/g_bde_lock.c b/sys/geom/bde/g_bde_lock.c index e625f51..75aa40b 100644 --- a/sys/geom/bde/g_bde_lock.c +++ b/sys/geom/bde/g_bde_lock.c @@ -41,7 +41,6 @@ #include <sys/stdint.h> #include <sys/lock.h> #include <sys/mutex.h> -#include <sys/time.h> #include <sys/md5.h> #ifdef _KERNEL diff --git a/sys/geom/bde/g_bde_work.c b/sys/geom/bde/g_bde_work.c index 3635869..804b5e4 100644 --- a/sys/geom/bde/g_bde_work.c +++ b/sys/geom/bde/g_bde_work.c @@ -67,7 +67,6 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/sysctl.h> -#include <sys/time.h> #include <sys/proc.h> #include <sys/kthread.h> diff --git a/sys/geom/geom.h b/sys/geom/geom.h index f406fb9..e1aac55 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -58,6 +58,7 @@ struct g_geom; struct g_consumer; struct g_provider; struct g_event; +struct g_stat; struct thread; struct bio; struct sbuf; @@ -136,28 +137,6 @@ struct g_bioq { }; /* - * A g_stat contains the statistics we collect on consumers and - * providers. - */ -struct g_stat { - void *id; - uint64_t nop; - uint64_t nend; - struct bintime it; - struct bintime wentidle; - struct { - uint64_t nop; - uint64_t nbyte; - uint64_t nmem; - uint64_t nerr; - struct bintime dt; - } ops[3]; -#define G_STAT_IDX_READ 0 -#define G_STAT_IDX_WRITE 1 -#define G_STAT_IDX_DELETE 2 -}; - -/* * A g_consumer is an attachment point for a g_provider. One g_consumer * can only be attached to one g_provider, but multiple g_consumers * can be attached to one g_provider. @@ -172,7 +151,7 @@ struct g_consumer { int acr, acw, ace; struct g_event *event; int spoiled; - struct g_stat stat; + struct g_stat *stat; }; /* @@ -191,7 +170,7 @@ struct g_provider { u_int index; off_t mediasize; u_int sectorsize; - struct g_stat stat; + struct g_stat *stat; }; /* diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index 5c1cb05..07a1df3 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -50,6 +50,7 @@ #include <sys/fcntl.h> #include <geom/geom.h> #include <geom/geom_int.h> +#include <geom/geom_stats.h> #include <machine/limits.h> static d_open_t g_dev_open; @@ -428,7 +429,7 @@ g_dev_orphan(struct g_consumer *cp) gp = cp->geom; g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, gp->name); g_topology_assert(); - if (cp->stat.nop != cp->stat.nend) /* XXX ? */ + if (cp->stat->nop != cp->stat->nend) /* XXX ? */ return; dev = gp->softc; if (dev->si_flags & SI_DUMPDEV) diff --git a/sys/geom/geom_int.h b/sys/geom/geom_int.h index 3b33501..0323e01 100644 --- a/sys/geom/geom_int.h +++ b/sys/geom/geom_int.h @@ -100,3 +100,8 @@ void g_io_schedule_up(struct thread *tp); /* geom_kern.c / geom_kernsim.c */ void g_init(void); + +/* geom_stats.c */ +void g_stat_init(void); +struct g_stat *g_stat_new(void *id); +void g_stat_delete(struct g_stat *); diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c index 842595a..865f584 100644 --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -55,6 +55,7 @@ #include <sys/errno.h> #include <geom/geom.h> #include <geom/geom_int.h> +#include <geom/geom_stats.h> static struct g_bioq g_bio_run_down; static struct g_bioq g_bio_run_up; @@ -278,25 +279,25 @@ g_io_request(struct bio *bp, struct g_consumer *cp) if (g_collectstats) { /* Collect statistics */ binuptime(&bp->bio_t0); - if (cp->stat.nop == cp->stat.nend) { + if (cp->stat->nop == cp->stat->nend) { /* Consumer is idle */ bt = bp->bio_t0; - bintime_sub(&bt, &cp->stat.wentidle); - bintime_add(&cp->stat.it, &bt); - if (pp->stat.nop == pp->stat.nend) { + bintime_sub(&bt, &cp->stat->wentidle); + bintime_add(&cp->stat->it, &bt); + if (pp->stat->nop == pp->stat->nend) { /* * NB: Provider can only be idle if the * consumer is but we cannot trust them * to have gone idle at the same time. */ bt = bp->bio_t0; - bintime_sub(&bt, &pp->stat.wentidle); - bintime_add(&pp->stat.it, &bt); + bintime_sub(&bt, &pp->stat->wentidle); + bintime_add(&pp->stat->it, &bt); } } } - cp->stat.nop++; - pp->stat.nop++; + cp->stat->nop++; + pp->stat->nop++; /* Pass it on down. */ g_trace(G_T_BIO, "bio_request(%p) from %p(%s) to %p(%s) cmd %d", @@ -339,29 +340,29 @@ g_io_deliver(struct bio *bp, int error) /* Collect statistics */ if (g_collectstats) { binuptime(&t1); - pp->stat.wentidle = t1; - cp->stat.wentidle = t1; + pp->stat->wentidle = t1; + cp->stat->wentidle = t1; if (idx >= 0) { bintime_sub(&t1, &bp->bio_t0); - bintime_add(&cp->stat.ops[idx].dt, &t1); - bintime_add(&pp->stat.ops[idx].dt, &t1); - pp->stat.ops[idx].nbyte += bp->bio_completed; - cp->stat.ops[idx].nbyte += bp->bio_completed; - pp->stat.ops[idx].nop++; - cp->stat.ops[idx].nop++; + bintime_add(&cp->stat->ops[idx].dt, &t1); + bintime_add(&pp->stat->ops[idx].dt, &t1); + pp->stat->ops[idx].nbyte += bp->bio_completed; + cp->stat->ops[idx].nbyte += bp->bio_completed; + pp->stat->ops[idx].nop++; + cp->stat->ops[idx].nop++; if (error == ENOMEM) { - cp->stat.ops[idx].nmem++; - pp->stat.ops[idx].nmem++; + cp->stat->ops[idx].nmem++; + pp->stat->ops[idx].nmem++; } else if (error != 0) { - cp->stat.ops[idx].nerr++; - pp->stat.ops[idx].nerr++; + cp->stat->ops[idx].nerr++; + pp->stat->ops[idx].nerr++; } } } - pp->stat.nend++; /* In reverse order of g_io_request() */ - cp->stat.nend++; + pp->stat->nend++; /* In reverse order of g_io_request() */ + cp->stat->nend++; if (error == ENOMEM) { printf("ENOMEM %p on %p(%s)\n", bp, pp, pp->name); diff --git a/sys/geom/geom_kern.c b/sys/geom/geom_kern.c index a885c28..a925d9a 100644 --- a/sys/geom/geom_kern.c +++ b/sys/geom/geom_kern.c @@ -49,6 +49,7 @@ #include <sys/sbuf.h> #include <geom/geom.h> #include <geom/geom_int.h> +#include <geom/geom_stats.h> MALLOC_DEFINE(M_GEOM, "GEOM", "Geom data structures"); @@ -154,6 +155,7 @@ g_init(void) { printf("Initializing GEOMetry subsystem\n"); sx_init(&topology_lock, "GEOM topology"); + g_stat_init(); g_io_init(); g_event_init(); mtx_lock(&Giant); diff --git a/sys/geom/geom_stats.c b/sys/geom/geom_stats.c new file mode 100644 index 0000000..f93be80 --- /dev/null +++ b/sys/geom/geom_stats.c @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2002 Poul-Henning Kamp + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_geom.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/bio.h> +#include <sys/conf.h> +#include <sys/disk.h> +#include <sys/malloc.h> +#include <sys/sysctl.h> +#include <sys/stdint.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <sys/lock.h> +#include <sys/mutex.h> +#include <geom/geom.h> +#include <geom/geom_int.h> +#include <geom/geom_stats.h> + +#define statsperpage (PAGE_SIZE / sizeof(struct g_stat)) + +struct statspage { + TAILQ_ENTRY(statspage) list; + struct g_stat *stat; + u_int nfree; +}; + +static TAILQ_HEAD(, statspage) pagelist = TAILQ_HEAD_INITIALIZER(pagelist); + +struct g_stat * +g_stat_new(void *id) +{ + struct g_stat *gsp; + struct statspage *spp; + u_int u; + + g_topology_assert(); + TAILQ_FOREACH(spp, &pagelist, list) { + if (spp->nfree > 0) + break; + } + if (spp == NULL) { + spp = g_malloc(sizeof *spp, M_ZERO); + TAILQ_INSERT_TAIL(&pagelist, spp, list); + spp->stat = g_malloc(PAGE_SIZE, M_ZERO); + printf("allocate another stats-page %p\n", spp->stat); + spp->nfree = statsperpage; + } + gsp = spp->stat; + for (u = 0; u < statsperpage; u++) { + if (gsp->id == NULL) + break; + gsp++; + } + spp->nfree--; + gsp->id = id; + return (gsp); +} + +void +g_stat_delete(struct g_stat *gsp) +{ + struct statspage *spp; + + bzero(gsp, sizeof *gsp); + TAILQ_FOREACH(spp, &pagelist, list) { + if (gsp >= spp->stat && gsp < (spp->stat + statsperpage)) { + spp->nfree++; + return; + } + } +} + +static d_mmap_t g_stat_mmap; + +static struct cdevsw geom_stats_cdevsw = { + /* open */ nullopen, + /* close */ nullclose, + /* read */ noread, + /* write */ nowrite, + /* ioctl */ noioctl, + /* poll */ nopoll, + /* mmap */ g_stat_mmap, + /* strtegy */ nostrategy, + /* name */ "g_stats", + /* maj */ GEOM_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0, +}; + +static int +g_stat_mmap(dev_t dev, vm_offset_t offset, int nprot) +{ + struct statspage *spp; + + if (nprot != VM_PROT_READ) + return (-1); + TAILQ_FOREACH(spp, &pagelist, list) { + if (offset == 0) + return (vtophys(spp->stat) >> PAGE_SHIFT); + offset -= PAGE_SIZE; + } + return (-1); +} + +void +g_stat_init(void) +{ + make_dev(&geom_stats_cdevsw, GEOM_MINOR_STATS, + UID_ROOT, GID_WHEEL, 0400, "geom.stats"); +} diff --git a/sys/geom/geom_stats.h b/sys/geom/geom_stats.h new file mode 100644 index 0000000..54ca880 --- /dev/null +++ b/sys/geom/geom_stats.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2002 Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _GEOM_GEOM_STATS_H_ +#define _GEOM_GEOM_STATS_H_ + +/* + * A g_stat contains the statistics we collect on consumers and + * providers. + */ +struct g_stat { + void *id; + uint64_t nop; + uint64_t nend; + struct bintime it; + struct bintime wentidle; + struct { + uint64_t nop; + uint64_t nbyte; + uint64_t nmem; + uint64_t nerr; + struct bintime dt; + } ops[3]; +#define G_STAT_IDX_READ 0 +#define G_STAT_IDX_WRITE 1 +#define G_STAT_IDX_DELETE 2 +}; + +#endif /* _GEOM_GEOM_STATS_H_ */ diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index d8b3054..237e199 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -60,6 +60,7 @@ #include <sys/sbuf.h> #include <geom/geom.h> #include <geom/geom_int.h> +#include <geom/geom_stats.h> #include <machine/stdarg.h> struct class_list_head g_classes = LIST_HEAD_INITIALIZER(g_classes); @@ -145,7 +146,7 @@ g_new_consumer(struct g_geom *gp) cp = g_malloc(sizeof *cp, M_ZERO); cp->protect = 0x020016602; cp->geom = gp; - cp->stat.id = cp; + cp->stat = g_stat_new(cp); LIST_INSERT_HEAD(&gp->consumer, cp, consumer); return(cp); } @@ -162,6 +163,7 @@ g_destroy_consumer(struct g_consumer *cp) KASSERT (cp->acw == 0, ("g_destroy_consumer with acw")); KASSERT (cp->ace == 0, ("g_destroy_consumer with ace")); LIST_REMOVE(cp, consumer); + g_stat_delete(cp->stat); g_free(cp); } @@ -185,7 +187,7 @@ g_new_providerf(struct g_geom *gp, const char *fmt, ...) LIST_INIT(&pp->consumers); pp->error = ENXIO; pp->geom = gp; - pp->stat.id = pp; + pp->stat = g_stat_new(pp); LIST_INSERT_HEAD(&gp->provider, pp, provider); g_nproviders++; g_post_event(EV_NEW_PROVIDER, NULL, NULL, pp, NULL); @@ -216,6 +218,7 @@ g_destroy_provider(struct g_provider *pp) g_nproviders--; LIST_REMOVE(pp, provider); gp = pp->geom; + g_stat_delete(pp->stat); g_free(pp); if (!(gp->flags & G_GEOM_WITHER)) return; @@ -329,7 +332,8 @@ g_detach(struct g_consumer *cp) KASSERT(cp->acr == 0, ("detach but nonzero acr")); KASSERT(cp->acw == 0, ("detach but nonzero acw")); KASSERT(cp->ace == 0, ("detach but nonzero ace")); - KASSERT(cp->stat.nop == cp->stat.nend, ("detach with active requests")); + KASSERT(cp->stat->nop == cp->stat->nend, + ("detach with active requests")); pp = cp->provider; LIST_REMOVE(cp, consumers); cp->provider = NULL; |