1168404Spjd/*- 2168404Spjd * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3168404Spjd * All rights reserved. 4168404Spjd * 5168404Spjd * Redistribution and use in source and binary forms, with or without 6168404Spjd * modification, are permitted provided that the following conditions 7168404Spjd * are met: 8168404Spjd * 1. Redistributions of source code must retain the above copyright 9168404Spjd * notice, this list of conditions and the following disclaimer. 10168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 11168404Spjd * notice, this list of conditions and the following disclaimer in the 12168404Spjd * documentation and/or other materials provided with the distribution. 13168404Spjd * 14168404Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17168404Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18168404Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19168404Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20168404Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24168404Spjd * SUCH DAMAGE. 25168404Spjd */ 26168404Spjd 27168404Spjd#include <sys/cdefs.h> 28168404Spjd__FBSDID("$FreeBSD$"); 29168404Spjd 30168404Spjd#include <sys/param.h> 31168404Spjd#include <sys/kernel.h> 32168404Spjd#include <sys/systm.h> 33168404Spjd#include <sys/malloc.h> 34168404Spjd#include <sys/sysctl.h> 35168404Spjd#include <sys/kstat.h> 36168404Spjd 37168404Spjdstatic MALLOC_DEFINE(M_KSTAT, "kstat_data", "Kernel statistics"); 38168404Spjd 39168404SpjdSYSCTL_NODE(, OID_AUTO, kstat, CTLFLAG_RW, 0, "Kernel statistics"); 40168404Spjd 41168404Spjdkstat_t * 42168404Spjdkstat_create(char *module, int instance, char *name, char *class, uchar_t type, 43168404Spjd ulong_t ndata, uchar_t flags) 44168404Spjd{ 45168404Spjd struct sysctl_oid *root; 46168404Spjd kstat_t *ksp; 47168404Spjd 48168404Spjd KASSERT(instance == 0, ("instance=%d", instance)); 49168404Spjd KASSERT(type == KSTAT_TYPE_NAMED, ("type=%hhu", type)); 50168404Spjd KASSERT(flags == KSTAT_FLAG_VIRTUAL, ("flags=%02hhx", flags)); 51168404Spjd 52168404Spjd /* 53168404Spjd * Allocate the main structure. We don't need to copy module/class/name 54168404Spjd * stuff in here, because it is only used for sysctl node creation 55168404Spjd * done in this function. 56168404Spjd */ 57168404Spjd ksp = malloc(sizeof(*ksp), M_KSTAT, M_WAITOK); 58168404Spjd ksp->ks_ndata = ndata; 59168404Spjd 60168404Spjd /* 61168404Spjd * Create sysctl tree for those statistics: 62168404Spjd * 63168404Spjd * kstat.<module>.<class>.<name>. 64168404Spjd */ 65168404Spjd sysctl_ctx_init(&ksp->ks_sysctl_ctx); 66168404Spjd root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, 67168404Spjd SYSCTL_STATIC_CHILDREN(_kstat), OID_AUTO, module, CTLFLAG_RW, 0, 68168404Spjd ""); 69168404Spjd if (root == NULL) { 70168404Spjd printf("%s: Cannot create kstat.%s tree!\n", __func__, module); 71168404Spjd sysctl_ctx_free(&ksp->ks_sysctl_ctx); 72168404Spjd free(ksp, M_KSTAT); 73168404Spjd return (NULL); 74168404Spjd } 75168404Spjd root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root), 76168404Spjd OID_AUTO, class, CTLFLAG_RW, 0, ""); 77168404Spjd if (root == NULL) { 78168404Spjd printf("%s: Cannot create kstat.%s.%s tree!\n", __func__, 79168404Spjd module, class); 80168404Spjd sysctl_ctx_free(&ksp->ks_sysctl_ctx); 81168404Spjd free(ksp, M_KSTAT); 82168404Spjd return (NULL); 83168404Spjd } 84168404Spjd root = SYSCTL_ADD_NODE(&ksp->ks_sysctl_ctx, SYSCTL_CHILDREN(root), 85168404Spjd OID_AUTO, name, CTLFLAG_RW, 0, ""); 86168404Spjd if (root == NULL) { 87168404Spjd printf("%s: Cannot create kstat.%s.%s.%s tree!\n", __func__, 88168404Spjd module, class, name); 89168404Spjd sysctl_ctx_free(&ksp->ks_sysctl_ctx); 90168404Spjd free(ksp, M_KSTAT); 91168404Spjd return (NULL); 92168404Spjd } 93168404Spjd ksp->ks_sysctl_root = root; 94168404Spjd 95168404Spjd return (ksp); 96168404Spjd} 97168404Spjd 98168404Spjdstatic int 99168404Spjdkstat_sysctl(SYSCTL_HANDLER_ARGS) 100168404Spjd{ 101168404Spjd kstat_named_t *ksent = arg1; 102168404Spjd uint64_t val; 103168404Spjd 104168404Spjd val = ksent->value.ui64; 105217616Smdf return sysctl_handle_64(oidp, &val, 0, req); 106168404Spjd} 107168404Spjd 108168404Spjdvoid 109168404Spjdkstat_install(kstat_t *ksp) 110168404Spjd{ 111168404Spjd kstat_named_t *ksent; 112168404Spjd u_int i; 113168404Spjd 114168404Spjd ksent = ksp->ks_data; 115168404Spjd for (i = 0; i < ksp->ks_ndata; i++, ksent++) { 116168404Spjd KASSERT(ksent->data_type == KSTAT_DATA_UINT64, 117168404Spjd ("data_type=%d", ksent->data_type)); 118168404Spjd SYSCTL_ADD_PROC(&ksp->ks_sysctl_ctx, 119168404Spjd SYSCTL_CHILDREN(ksp->ks_sysctl_root), OID_AUTO, ksent->name, 120217616Smdf CTLTYPE_U64 | CTLFLAG_RD, ksent, sizeof(*ksent), 121251419Ssmh kstat_sysctl, "QU", ksent->desc); 122168404Spjd } 123168404Spjd} 124168404Spjd 125168404Spjdvoid 126168404Spjdkstat_delete(kstat_t *ksp) 127168404Spjd{ 128168404Spjd 129168404Spjd sysctl_ctx_free(&ksp->ks_sysctl_ctx); 130168404Spjd free(ksp, M_KSTAT); 131168404Spjd} 132