static ERL_NIF_TERM update_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ks_returner_t *ret; kstat_raw_reader_t save_raw = NULL; ks_handle_t *handle; kid_t id; ks_instance_t *ksi, *ktmp; ks_nvpair_t *nvpair, *ntmp; kstat_t *kp; int count = 0; ret = new_returner(env); if (argc < 1) { return EKSTAT_RETURN(enif_make_badarg(ret->env)); } if (!enif_get_resource(env, argv[0], kstat_handle, (void **)(&handle))) { return EKSTAT_RETURN(enif_make_badarg(ret->env)); } if ((id = kstat_chain_update(handle->ks_ctl)) == 0 && handle->ks_id != -1) { return EKSTAT_RETURN(EKSTAT_ERROR("kstat_chain_update stopped")); } if (id == -1) { return EKSTAT_RETURN(EKSTAT_ERROR("kid not valid")); } /* Free the instances list */ ksi = list_head(&handle->instances_list); while (ksi != NULL) { nvpair = list_head(&ksi->ks_nvlist); while (nvpair != NULL) { ntmp = nvpair; nvpair = list_next(&ksi->ks_nvlist, nvpair); list_remove(&ksi->ks_nvlist, ntmp); if (ntmp->data_type == KSTAT_DATA_STRING) free(ntmp->value.str.addr.ptr); free(ntmp); } ktmp = ksi; ksi = list_next(&handle->instances_list, ksi); list_remove(&handle->instances_list, ktmp); list_destroy(&ktmp->ks_nvlist); free(ktmp); } for (kp = handle->ks_ctl->kc_chain; kp != NULL; kp = kp->ks_next) { /* Don't bother storing the kstat headers */ if (strncmp(kp->ks_name, "kstat_", 6) == 0) { continue; } /* Don't bother storing raw stats we don't understand */ if (kp->ks_type == KSTAT_TYPE_RAW) { save_raw = lookup_raw_kstat_fn(kp->ks_module, kp->ks_name); if (save_raw == NULL) { continue; } } /* * Allocate a new instance and fill in the values * we know so far. */ ksi = (ks_instance_t *)(malloc(sizeof (ks_instance_t))); if (ksi == NULL) { return EKSTAT_RETURN(EKSTAT_ERROR("ks_instance_t malloc")); } list_link_init(&ksi->ks_next); (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN); (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN); (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN); ksi->ks_instance = kp->ks_instance; ksi->ks_snaptime = kp->ks_snaptime; ksi->ks_type = kp->ks_type; list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t), offsetof(ks_nvpair_t, nv_next)); SAVE_HRTIME_X(ret, ksi, "crtime", kp->ks_crtime); SAVE_HRTIME_X(ret, ksi, "snaptime", kp->ks_snaptime); /* Insert this instance into a sorted list */ ktmp = list_head(&handle->instances_list); while (ktmp != NULL && compare_instances(ksi, ktmp) < 0) { ktmp = list_next(&handle->instances_list, ktmp); } list_insert_before(&handle->instances_list, ktmp, ksi); /* Read the actual statistics */ id = kstat_read(handle->ks_ctl, kp, NULL); if (id == -1) { continue; } switch (kp->ks_type) { case KSTAT_TYPE_RAW: save_raw(ret, kp, ksi); break; case KSTAT_TYPE_NAMED: save_named(ret, kp, ksi); break; case KSTAT_TYPE_INTR: save_intr(ret, kp, ksi); break; case KSTAT_TYPE_IO: save_io(ret, kp, ksi); break; case KSTAT_TYPE_TIMER: save_timer(ret, kp, ksi); break; default: assert(B_FALSE); /* Invalid type */ break; } count++; } return EKSTAT_RETURN(EKSTAT_OK(EKSTAT_INT(count))); }
/* * Iterate over all kernel statistics and save matches. */ static void ks_instances_read(kstat_ctl_t *kc) { kstat_raw_reader_t save_raw = NULL; kid_t id; ks_selector_t *selector; ks_instance_t *ksi; ks_instance_t *tmp; kstat_t *kp; boolean_t skip; for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) { /* Don't bother storing the kstat headers */ if (strncmp(kp->ks_name, "kstat_", 6) == 0) { continue; } /* Don't bother storing raw stats we don't understand */ if (kp->ks_type == KSTAT_TYPE_RAW) { save_raw = lookup_raw_kstat_fn(kp->ks_module, kp->ks_name); if (save_raw == NULL) { #ifdef REPORT_UNKNOWN (void) fprintf(stderr, "Unknown kstat type %s:%d:%s - " "%d of size %d\n", kp->ks_module, kp->ks_instance, kp->ks_name, kp->ks_ndata, kp->ks_data_size); #endif continue; } } /* * Iterate over the list of selectors and skip * instances we dont want. We filter for statistics * later, as we dont know them yet. */ skip = B_TRUE; selector = list_head(&selector_list); while (selector != NULL) { if (ks_match(kp->ks_module, &selector->ks_module) && ks_match(kp->ks_name, &selector->ks_name)) { skip = B_FALSE; break; } selector = list_next(&selector_list, selector); } if (skip) { continue; } /* * Allocate a new instance and fill in the values * we know so far. */ ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t)); if (ksi == NULL) { perror("malloc"); exit(3); } list_link_init(&ksi->ks_next); (void) strlcpy(ksi->ks_zone, "global", KSTAT_STRLEN); (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN); (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN); (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN); ksi->ks_instance = kp->ks_instance; ksi->ks_snaptime = kp->ks_snaptime; ksi->ks_type = kp->ks_type; list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t), offsetof(ks_nvpair_t, nv_next)); SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime); SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime); if (g_pflg) { SAVE_STRING_X(ksi, "class", kp->ks_class); } /* Insert this instance into a sorted list */ tmp = list_head(&instances_list); while (tmp != NULL && compare_instances(ksi, tmp) > 0) tmp = list_next(&instances_list, tmp); list_insert_before(&instances_list, tmp, ksi); /* Read the actual statistics */ id = kstat_read(kc, kp, NULL); if (id == -1) { #ifdef REPORT_UNKNOWN perror("kstat_read"); #endif continue; } switch (kp->ks_type) { case KSTAT_TYPE_RAW: save_raw(kp, ksi); break; case KSTAT_TYPE_NAMED: save_named(kp, ksi); break; case KSTAT_TYPE_INTR: save_intr(kp, ksi); break; case KSTAT_TYPE_IO: save_io(kp, ksi); break; case KSTAT_TYPE_TIMER: save_timer(kp, ksi); break; default: assert(B_FALSE); /* Invalid type */ break; } } }