Print this page
XXXX Check for uninitialized kernel statistics
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/kstat_fr.c
+++ new/usr/src/uts/common/os/kstat_fr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * Kernel statistics framework
27 27 */
28 28
29 29 #include <sys/types.h>
30 30 #include <sys/time.h>
31 31 #include <sys/systm.h>
32 32 #include <sys/vmsystm.h>
33 33 #include <sys/t_lock.h>
34 34 #include <sys/param.h>
35 35 #include <sys/errno.h>
36 36 #include <sys/vmem.h>
37 37 #include <sys/sysmacros.h>
38 38 #include <sys/cmn_err.h>
39 39 #include <sys/kstat.h>
40 40 #include <sys/sysinfo.h>
41 41 #include <sys/cpuvar.h>
42 42 #include <sys/fcntl.h>
43 43 #include <sys/flock.h>
44 44 #include <sys/vnode.h>
45 45 #include <sys/vfs.h>
46 46 #include <sys/dnlc.h>
47 47 #include <sys/var.h>
48 48 #include <sys/debug.h>
49 49 #include <sys/kobj.h>
50 50 #include <sys/avl.h>
51 51 #include <sys/pool_pset.h>
52 52 #include <sys/cpupart.h>
53 53 #include <sys/zone.h>
54 54 #include <sys/loadavg.h>
55 55 #include <vm/page.h>
56 56 #include <vm/anon.h>
57 57 #include <vm/seg_kmem.h>
58 58
59 59 /*
60 60 * Global lock to protect the AVL trees and kstat_chain_id.
61 61 */
62 62 static kmutex_t kstat_chain_lock;
63 63
64 64 /*
65 65 * Every install/delete kstat bumps kstat_chain_id. This is used by:
66 66 *
67 67 * (1) /dev/kstat, to detect changes in the kstat chain across ioctls;
68 68 *
69 69 * (2) kstat_create(), to assign a KID (kstat ID) to each new kstat.
70 70 * /dev/kstat uses the KID as a cookie for kstat lookups.
71 71 *
72 72 * We reserve the first two IDs because some kstats are created before
73 73 * the well-known ones (kstat_headers = 0, kstat_types = 1).
74 74 *
75 75 * We also bump the kstat_chain_id if a zone is gaining or losing visibility
76 76 * into a particular kstat, which is logically equivalent to a kstat being
77 77 * installed/deleted.
78 78 */
79 79
80 80 kid_t kstat_chain_id = 2;
81 81
82 82 /*
83 83 * As far as zones are concerned, there are 3 types of kstat:
84 84 *
85 85 * 1) Those which have a well-known name, and which should return per-zone data
86 86 * depending on which zone is doing the kstat_read(). sockfs:0:sock_unix_list
87 87 * is an example of this type of kstat.
88 88 *
89 89 * 2) Those which should only be exported to a particular list of zones.
90 90 * For example, in the case of nfs:*:mntinfo, we don't want zone A to be
91 91 * able to see NFS mounts associated with zone B, while we want the
92 92 * global zone to be able to see all mounts on the system.
93 93 *
94 94 * 3) Those that can be exported to all zones. Most system-related
95 95 * kstats fall within this category.
96 96 *
97 97 * An ekstat_t thus contains a list of kstats that the zone is to be
98 98 * exported to. The lookup of a name:instance:module thus translates to a
99 99 * lookup of name:instance:module:myzone; if the kstat is not exported
100 100 * to all zones, and does not have the caller's zoneid explicitly
101 101 * enumerated in the list of zones to be exported to, it is the same as
102 102 * if the kstat didn't exist.
103 103 *
104 104 * Writing to kstats is currently disallowed from within a non-global
105 105 * zone, although this restriction could be removed in the future.
106 106 */
107 107 typedef struct kstat_zone {
108 108 zoneid_t zoneid;
109 109 struct kstat_zone *next;
110 110 } kstat_zone_t;
111 111
112 112 /*
113 113 * Extended kstat structure -- for internal use only.
114 114 */
115 115 typedef struct ekstat {
116 116 kstat_t e_ks; /* the kstat itself */
117 117 size_t e_size; /* total allocation size */
118 118 kthread_t *e_owner; /* thread holding this kstat */
119 119 kcondvar_t e_cv; /* wait for owner == NULL */
120 120 avl_node_t e_avl_bykid; /* AVL tree to sort by KID */
121 121 avl_node_t e_avl_byname; /* AVL tree to sort by name */
122 122 kstat_zone_t e_zone; /* zone to export stats to */
123 123 } ekstat_t;
124 124
125 125 static uint64_t kstat_initial[8192];
126 126 static void *kstat_initial_ptr = kstat_initial;
127 127 static size_t kstat_initial_avail = sizeof (kstat_initial);
128 128 static vmem_t *kstat_arena;
129 129
130 130 #define KSTAT_ALIGN (sizeof (uint64_t))
131 131
132 132 static avl_tree_t kstat_avl_bykid;
133 133 static avl_tree_t kstat_avl_byname;
134 134
135 135 /*
136 136 * Various pointers we need to create kstats at boot time in kstat_init()
137 137 */
138 138 extern kstat_named_t *segmapcnt_ptr;
139 139 extern uint_t segmapcnt_ndata;
140 140 extern int segmap_kstat_update(kstat_t *, int);
141 141 extern kstat_named_t *biostats_ptr;
142 142 extern uint_t biostats_ndata;
143 143 extern kstat_named_t *pollstats_ptr;
144 144 extern uint_t pollstats_ndata;
145 145
146 146 extern int vac;
147 147 extern uint_t nproc;
148 148 extern time_t boot_time;
149 149 extern sysinfo_t sysinfo;
150 150 extern vminfo_t vminfo;
151 151
152 152 struct {
153 153 kstat_named_t ncpus;
154 154 kstat_named_t lbolt;
155 155 kstat_named_t deficit;
156 156 kstat_named_t clk_intr;
157 157 kstat_named_t vac;
158 158 kstat_named_t nproc;
159 159 kstat_named_t avenrun_1min;
160 160 kstat_named_t avenrun_5min;
161 161 kstat_named_t avenrun_15min;
162 162 kstat_named_t boot_time;
163 163 } system_misc_kstat = {
164 164 { "ncpus", KSTAT_DATA_UINT32 },
165 165 { "lbolt", KSTAT_DATA_UINT32 },
166 166 { "deficit", KSTAT_DATA_UINT32 },
167 167 { "clk_intr", KSTAT_DATA_UINT32 },
168 168 { "vac", KSTAT_DATA_UINT32 },
169 169 { "nproc", KSTAT_DATA_UINT32 },
170 170 { "avenrun_1min", KSTAT_DATA_UINT32 },
171 171 { "avenrun_5min", KSTAT_DATA_UINT32 },
172 172 { "avenrun_15min", KSTAT_DATA_UINT32 },
173 173 { "boot_time", KSTAT_DATA_UINT32 },
174 174 };
175 175
176 176 struct {
177 177 kstat_named_t physmem;
178 178 kstat_named_t nalloc;
179 179 kstat_named_t nfree;
180 180 kstat_named_t nalloc_calls;
181 181 kstat_named_t nfree_calls;
182 182 kstat_named_t kernelbase;
183 183 kstat_named_t econtig;
184 184 kstat_named_t freemem;
185 185 kstat_named_t availrmem;
186 186 kstat_named_t lotsfree;
187 187 kstat_named_t desfree;
188 188 kstat_named_t minfree;
189 189 kstat_named_t fastscan;
190 190 kstat_named_t slowscan;
191 191 kstat_named_t nscan;
192 192 kstat_named_t desscan;
193 193 kstat_named_t pp_kernel;
194 194 kstat_named_t pagesfree;
195 195 kstat_named_t pageslocked;
196 196 kstat_named_t pagestotal;
197 197 } system_pages_kstat = {
198 198 { "physmem", KSTAT_DATA_ULONG },
199 199 { "nalloc", KSTAT_DATA_ULONG },
200 200 { "nfree", KSTAT_DATA_ULONG },
201 201 { "nalloc_calls", KSTAT_DATA_ULONG },
202 202 { "nfree_calls", KSTAT_DATA_ULONG },
203 203 { "kernelbase", KSTAT_DATA_ULONG },
204 204 { "econtig", KSTAT_DATA_ULONG },
205 205 { "freemem", KSTAT_DATA_ULONG },
206 206 { "availrmem", KSTAT_DATA_ULONG },
207 207 { "lotsfree", KSTAT_DATA_ULONG },
208 208 { "desfree", KSTAT_DATA_ULONG },
209 209 { "minfree", KSTAT_DATA_ULONG },
210 210 { "fastscan", KSTAT_DATA_ULONG },
211 211 { "slowscan", KSTAT_DATA_ULONG },
212 212 { "nscan", KSTAT_DATA_ULONG },
213 213 { "desscan", KSTAT_DATA_ULONG },
214 214 { "pp_kernel", KSTAT_DATA_ULONG },
215 215 { "pagesfree", KSTAT_DATA_ULONG },
216 216 { "pageslocked", KSTAT_DATA_ULONG },
217 217 { "pagestotal", KSTAT_DATA_ULONG },
218 218 };
219 219
220 220 static int header_kstat_update(kstat_t *, int);
221 221 static int header_kstat_snapshot(kstat_t *, void *, int);
222 222 static int system_misc_kstat_update(kstat_t *, int);
223 223 static int system_pages_kstat_update(kstat_t *, int);
224 224
225 225 static struct {
226 226 char name[KSTAT_STRLEN];
227 227 size_t size;
228 228 uint_t min_ndata;
229 229 uint_t max_ndata;
230 230 } kstat_data_type[KSTAT_NUM_TYPES] = {
231 231 { "raw", 1, 0, INT_MAX },
232 232 { "name=value", sizeof (kstat_named_t), 0, INT_MAX },
233 233 { "interrupt", sizeof (kstat_intr_t), 1, 1 },
234 234 { "i/o", sizeof (kstat_io_t), 1, 1 },
235 235 { "event_timer", sizeof (kstat_timer_t), 0, INT_MAX },
236 236 };
237 237
238 238 int
239 239 kstat_zone_find(kstat_t *k, zoneid_t zoneid)
240 240 {
241 241 ekstat_t *e = (ekstat_t *)k;
242 242 kstat_zone_t *kz;
243 243
244 244 ASSERT(MUTEX_HELD(&kstat_chain_lock));
245 245 for (kz = &e->e_zone; kz != NULL; kz = kz->next) {
246 246 if (zoneid == ALL_ZONES || kz->zoneid == ALL_ZONES)
247 247 return (1);
248 248 if (zoneid == kz->zoneid)
249 249 return (1);
250 250 }
251 251 return (0);
252 252 }
253 253
254 254 void
255 255 kstat_zone_remove(kstat_t *k, zoneid_t zoneid)
256 256 {
257 257 ekstat_t *e = (ekstat_t *)k;
258 258 kstat_zone_t *kz, *t = NULL;
259 259
260 260 mutex_enter(&kstat_chain_lock);
261 261 if (zoneid == e->e_zone.zoneid) {
262 262 kz = e->e_zone.next;
263 263 ASSERT(kz != NULL);
264 264 e->e_zone.zoneid = kz->zoneid;
265 265 e->e_zone.next = kz->next;
266 266 goto out;
267 267 }
268 268 for (kz = &e->e_zone; kz->next != NULL; kz = kz->next) {
269 269 if (kz->next->zoneid == zoneid) {
270 270 t = kz->next;
271 271 kz->next = t->next;
272 272 break;
273 273 }
274 274 }
275 275 ASSERT(t != NULL); /* we removed something */
276 276 kz = t;
277 277 out:
278 278 kstat_chain_id++;
279 279 mutex_exit(&kstat_chain_lock);
280 280 kmem_free(kz, sizeof (*kz));
281 281 }
282 282
283 283 void
284 284 kstat_zone_add(kstat_t *k, zoneid_t zoneid)
285 285 {
286 286 ekstat_t *e = (ekstat_t *)k;
287 287 kstat_zone_t *kz;
288 288
289 289 kz = kmem_alloc(sizeof (*kz), KM_NOSLEEP);
290 290 if (kz == NULL)
291 291 return;
292 292 mutex_enter(&kstat_chain_lock);
293 293 kz->zoneid = zoneid;
294 294 kz->next = e->e_zone.next;
295 295 e->e_zone.next = kz;
296 296 kstat_chain_id++;
297 297 mutex_exit(&kstat_chain_lock);
298 298 }
299 299
300 300 /*
301 301 * Compare the list of zones for the given kstats, returning 0 if they match
302 302 * (ie, one list contains ALL_ZONES or both lists contain the same zoneid).
303 303 * In practice, this is called indirectly by kstat_hold_byname(), so one of the
304 304 * two lists always has one element, and this is an O(n) operation rather than
305 305 * O(n^2).
306 306 */
307 307 static int
308 308 kstat_zone_compare(ekstat_t *e1, ekstat_t *e2)
309 309 {
310 310 kstat_zone_t *kz1, *kz2;
311 311
312 312 ASSERT(MUTEX_HELD(&kstat_chain_lock));
313 313 for (kz1 = &e1->e_zone; kz1 != NULL; kz1 = kz1->next) {
314 314 for (kz2 = &e2->e_zone; kz2 != NULL; kz2 = kz2->next) {
315 315 if (kz1->zoneid == ALL_ZONES ||
316 316 kz2->zoneid == ALL_ZONES)
317 317 return (0);
318 318 if (kz1->zoneid == kz2->zoneid)
319 319 return (0);
320 320 }
321 321 }
322 322 return (e1->e_zone.zoneid < e2->e_zone.zoneid ? -1 : 1);
323 323 }
324 324
325 325 /*
326 326 * Support for keeping kstats sorted in AVL trees for fast lookups.
327 327 */
328 328 static int
329 329 kstat_compare_bykid(const void *a1, const void *a2)
330 330 {
331 331 const kstat_t *k1 = a1;
332 332 const kstat_t *k2 = a2;
333 333
334 334 if (k1->ks_kid < k2->ks_kid)
335 335 return (-1);
336 336 if (k1->ks_kid > k2->ks_kid)
337 337 return (1);
338 338 return (kstat_zone_compare((ekstat_t *)k1, (ekstat_t *)k2));
339 339 }
340 340
341 341 static int
342 342 kstat_compare_byname(const void *a1, const void *a2)
343 343 {
344 344 const kstat_t *k1 = a1;
345 345 const kstat_t *k2 = a2;
346 346 int s;
347 347
348 348 s = strcmp(k1->ks_module, k2->ks_module);
349 349 if (s > 0)
350 350 return (1);
351 351 if (s < 0)
352 352 return (-1);
353 353
354 354 if (k1->ks_instance < k2->ks_instance)
355 355 return (-1);
356 356 if (k1->ks_instance > k2->ks_instance)
357 357 return (1);
358 358
359 359 s = strcmp(k1->ks_name, k2->ks_name);
360 360 if (s > 0)
361 361 return (1);
362 362 if (s < 0)
363 363 return (-1);
364 364
365 365 return (kstat_zone_compare((ekstat_t *)k1, (ekstat_t *)k2));
366 366 }
367 367
368 368 static kstat_t *
369 369 kstat_hold(avl_tree_t *t, ekstat_t *template)
370 370 {
371 371 kstat_t *ksp;
372 372 ekstat_t *e;
373 373
374 374 mutex_enter(&kstat_chain_lock);
375 375 for (;;) {
376 376 ksp = avl_find(t, template, NULL);
377 377 if (ksp == NULL)
378 378 break;
379 379 e = (ekstat_t *)ksp;
380 380 if (e->e_owner == NULL) {
381 381 e->e_owner = curthread;
382 382 break;
383 383 }
384 384 cv_wait(&e->e_cv, &kstat_chain_lock);
385 385 }
386 386 mutex_exit(&kstat_chain_lock);
387 387 return (ksp);
388 388 }
389 389
390 390 void
391 391 kstat_rele(kstat_t *ksp)
392 392 {
393 393 ekstat_t *e = (ekstat_t *)ksp;
394 394
395 395 mutex_enter(&kstat_chain_lock);
396 396 ASSERT(e->e_owner == curthread);
397 397 e->e_owner = NULL;
398 398 cv_broadcast(&e->e_cv);
399 399 mutex_exit(&kstat_chain_lock);
400 400 }
401 401
402 402 kstat_t *
403 403 kstat_hold_bykid(kid_t kid, zoneid_t zoneid)
404 404 {
405 405 ekstat_t e;
406 406
407 407 e.e_ks.ks_kid = kid;
408 408 e.e_zone.zoneid = zoneid;
409 409 e.e_zone.next = NULL;
410 410
411 411 return (kstat_hold(&kstat_avl_bykid, &e));
412 412 }
413 413
414 414 kstat_t *
415 415 kstat_hold_byname(const char *ks_module, int ks_instance, const char *ks_name,
416 416 zoneid_t ks_zoneid)
417 417 {
418 418 ekstat_t e;
419 419
420 420 kstat_set_string(e.e_ks.ks_module, ks_module);
421 421 e.e_ks.ks_instance = ks_instance;
422 422 kstat_set_string(e.e_ks.ks_name, ks_name);
423 423 e.e_zone.zoneid = ks_zoneid;
424 424 e.e_zone.next = NULL;
425 425 return (kstat_hold(&kstat_avl_byname, &e));
426 426 }
427 427
428 428 static ekstat_t *
429 429 kstat_alloc(size_t size)
430 430 {
431 431 ekstat_t *e = NULL;
432 432
433 433 size = P2ROUNDUP(sizeof (ekstat_t) + size, KSTAT_ALIGN);
434 434
435 435 if (kstat_arena == NULL) {
436 436 if (size <= kstat_initial_avail) {
437 437 e = kstat_initial_ptr;
438 438 kstat_initial_ptr = (char *)kstat_initial_ptr + size;
439 439 kstat_initial_avail -= size;
440 440 }
441 441 } else {
442 442 e = vmem_alloc(kstat_arena, size, VM_NOSLEEP);
443 443 }
444 444
445 445 if (e != NULL) {
446 446 bzero(e, size);
447 447 e->e_size = size;
448 448 cv_init(&e->e_cv, NULL, CV_DEFAULT, NULL);
449 449 }
450 450
451 451 return (e);
452 452 }
453 453
454 454 static void
455 455 kstat_free(ekstat_t *e)
456 456 {
457 457 cv_destroy(&e->e_cv);
458 458 vmem_free(kstat_arena, e, e->e_size);
459 459 }
460 460
461 461 /*
462 462 * Create various system kstats.
463 463 */
464 464 void
465 465 kstat_init(void)
466 466 {
467 467 kstat_t *ksp;
468 468 ekstat_t *e;
469 469 avl_tree_t *t = &kstat_avl_bykid;
470 470
471 471 /*
472 472 * Set up the kstat vmem arena.
473 473 */
474 474 kstat_arena = vmem_create("kstat",
475 475 kstat_initial, sizeof (kstat_initial), KSTAT_ALIGN,
476 476 segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP);
477 477
478 478 /*
479 479 * Make initial kstats appear as though they were allocated.
480 480 */
481 481 for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER))
482 482 (void) vmem_xalloc(kstat_arena, e->e_size, KSTAT_ALIGN,
483 483 0, 0, e, (char *)e + e->e_size,
484 484 VM_NOSLEEP | VM_BESTFIT | VM_PANIC);
485 485
486 486 /*
487 487 * The mother of all kstats. The first kstat in the system, which
488 488 * always has KID 0, has the headers for all kstats (including itself)
489 489 * as its data. Thus, the kstat driver does not need any special
490 490 * interface to extract the kstat chain.
491 491 */
492 492 kstat_chain_id = 0;
493 493 ksp = kstat_create("unix", 0, "kstat_headers", "kstat", KSTAT_TYPE_RAW,
494 494 0, KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_VAR_SIZE);
495 495 if (ksp) {
496 496 ksp->ks_lock = &kstat_chain_lock;
497 497 ksp->ks_update = header_kstat_update;
498 498 ksp->ks_snapshot = header_kstat_snapshot;
499 499 kstat_install(ksp);
500 500 } else {
501 501 panic("cannot create kstat 'kstat_headers'");
502 502 }
503 503
504 504 ksp = kstat_create("unix", 0, "kstat_types", "kstat",
505 505 KSTAT_TYPE_NAMED, KSTAT_NUM_TYPES, 0);
506 506 if (ksp) {
507 507 int i;
508 508 kstat_named_t *kn = KSTAT_NAMED_PTR(ksp);
509 509
510 510 for (i = 0; i < KSTAT_NUM_TYPES; i++) {
511 511 kstat_named_init(&kn[i], kstat_data_type[i].name,
512 512 KSTAT_DATA_ULONG);
513 513 kn[i].value.ul = i;
514 514 }
515 515 kstat_install(ksp);
516 516 }
517 517
518 518 ksp = kstat_create("unix", 0, "sysinfo", "misc", KSTAT_TYPE_RAW,
519 519 sizeof (sysinfo_t), KSTAT_FLAG_VIRTUAL);
520 520 if (ksp) {
521 521 ksp->ks_data = (void *) &sysinfo;
522 522 kstat_install(ksp);
523 523 }
524 524
525 525 ksp = kstat_create("unix", 0, "vminfo", "vm", KSTAT_TYPE_RAW,
526 526 sizeof (vminfo_t), KSTAT_FLAG_VIRTUAL);
527 527 if (ksp) {
528 528 ksp->ks_data = (void *) &vminfo;
529 529 kstat_install(ksp);
530 530 }
531 531
532 532 ksp = kstat_create("unix", 0, "segmap", "vm", KSTAT_TYPE_NAMED,
533 533 segmapcnt_ndata, KSTAT_FLAG_VIRTUAL);
534 534 if (ksp) {
535 535 ksp->ks_data = (void *) segmapcnt_ptr;
536 536 ksp->ks_update = segmap_kstat_update;
537 537 kstat_install(ksp);
538 538 }
539 539
540 540 ksp = kstat_create("unix", 0, "biostats", "misc", KSTAT_TYPE_NAMED,
541 541 biostats_ndata, KSTAT_FLAG_VIRTUAL);
542 542 if (ksp) {
543 543 ksp->ks_data = (void *) biostats_ptr;
544 544 kstat_install(ksp);
545 545 }
546 546
547 547 ksp = kstat_create("unix", 0, "var", "misc", KSTAT_TYPE_RAW,
548 548 sizeof (struct var), KSTAT_FLAG_VIRTUAL);
549 549 if (ksp) {
550 550 ksp->ks_data = (void *) &v;
551 551 kstat_install(ksp);
552 552 }
553 553
554 554 ksp = kstat_create("unix", 0, "system_misc", "misc", KSTAT_TYPE_NAMED,
555 555 sizeof (system_misc_kstat) / sizeof (kstat_named_t),
556 556 KSTAT_FLAG_VIRTUAL);
557 557 if (ksp) {
558 558 ksp->ks_data = (void *) &system_misc_kstat;
559 559 ksp->ks_update = system_misc_kstat_update;
560 560 kstat_install(ksp);
561 561 }
562 562
563 563 ksp = kstat_create("unix", 0, "system_pages", "pages", KSTAT_TYPE_NAMED,
564 564 sizeof (system_pages_kstat) / sizeof (kstat_named_t),
565 565 KSTAT_FLAG_VIRTUAL);
566 566 if (ksp) {
567 567 ksp->ks_data = (void *) &system_pages_kstat;
568 568 ksp->ks_update = system_pages_kstat_update;
569 569 kstat_install(ksp);
570 570 }
571 571
572 572 ksp = kstat_create("poll", 0, "pollstats", "misc", KSTAT_TYPE_NAMED,
573 573 pollstats_ndata, KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
574 574
575 575 if (ksp) {
576 576 ksp->ks_data = pollstats_ptr;
577 577 kstat_install(ksp);
578 578 }
579 579 }
580 580
581 581 /*
582 582 * Caller of this should ensure that the string pointed by src
583 583 * doesn't change while kstat's lock is held. Not doing so defeats
584 584 * kstat's snapshot strategy as explained in <sys/kstat.h>
585 585 */
586 586 void
587 587 kstat_named_setstr(kstat_named_t *knp, const char *src)
588 588 {
589 589 if (knp->data_type != KSTAT_DATA_STRING)
590 590 panic("kstat_named_setstr('%p', '%p'): "
591 591 "named kstat is not of type KSTAT_DATA_STRING",
592 592 (void *)knp, (void *)src);
593 593
594 594 KSTAT_NAMED_STR_PTR(knp) = (char *)src;
595 595 if (src != NULL)
596 596 KSTAT_NAMED_STR_BUFLEN(knp) = strlen(src) + 1;
597 597 else
598 598 KSTAT_NAMED_STR_BUFLEN(knp) = 0;
599 599 }
600 600
601 601 void
602 602 kstat_set_string(char *dst, const char *src)
603 603 {
604 604 bzero(dst, KSTAT_STRLEN);
605 605 (void) strncpy(dst, src, KSTAT_STRLEN - 1);
606 606 }
607 607
608 608 void
609 609 kstat_named_init(kstat_named_t *knp, const char *name, uchar_t data_type)
610 610 {
611 611 kstat_set_string(knp->name, name);
612 612 knp->data_type = data_type;
613 613
614 614 if (data_type == KSTAT_DATA_STRING)
615 615 kstat_named_setstr(knp, NULL);
616 616 }
617 617
618 618 void
619 619 kstat_timer_init(kstat_timer_t *ktp, const char *name)
620 620 {
621 621 kstat_set_string(ktp->name, name);
622 622 }
623 623
624 624 /* ARGSUSED */
625 625 static int
626 626 default_kstat_update(kstat_t *ksp, int rw)
627 627 {
628 628 uint_t i;
629 629 size_t len = 0;
630 630 kstat_named_t *knp;
631 631
632 632 /*
633 633 * Named kstats with variable-length long strings have a standard
634 634 * way of determining how much space is needed to hold the snapshot:
635 635 */
636 636 if (ksp->ks_data != NULL && ksp->ks_type == KSTAT_TYPE_NAMED &&
637 637 (ksp->ks_flags & KSTAT_FLAG_VAR_SIZE)) {
638 638
639 639 /*
640 640 * Add in the space required for the strings
641 641 */
642 642 knp = KSTAT_NAMED_PTR(ksp);
643 643 for (i = 0; i < ksp->ks_ndata; i++, knp++) {
644 644 if (knp->data_type == KSTAT_DATA_STRING)
645 645 len += KSTAT_NAMED_STR_BUFLEN(knp);
646 646 }
647 647 ksp->ks_data_size =
648 648 ksp->ks_ndata * sizeof (kstat_named_t) + len;
649 649 }
650 650 return (0);
651 651 }
652 652
653 653 static int
654 654 default_kstat_snapshot(kstat_t *ksp, void *buf, int rw)
655 655 {
656 656 kstat_io_t *kiop;
657 657 hrtime_t cur_time;
658 658 size_t namedsz;
659 659
660 660 ksp->ks_snaptime = cur_time = gethrtime();
661 661
662 662 if (rw == KSTAT_WRITE) {
663 663 if (!(ksp->ks_flags & KSTAT_FLAG_WRITABLE))
664 664 return (EACCES);
665 665 bcopy(buf, ksp->ks_data, ksp->ks_data_size);
666 666 return (0);
667 667 }
668 668
669 669 /*
670 670 * KSTAT_TYPE_NAMED kstats are defined to have ks_ndata
671 671 * number of kstat_named_t structures, followed by an optional
672 672 * string segment. The ks_data generally holds only the
673 673 * kstat_named_t structures. So we copy it first. The strings,
674 674 * if any, are copied below. For other kstat types, ks_data holds the
675 675 * entire buffer.
676 676 */
677 677
678 678 namedsz = sizeof (kstat_named_t) * ksp->ks_ndata;
679 679 if (ksp->ks_type == KSTAT_TYPE_NAMED && ksp->ks_data_size > namedsz)
680 680 bcopy(ksp->ks_data, buf, namedsz);
681 681 else
682 682 bcopy(ksp->ks_data, buf, ksp->ks_data_size);
683 683
684 684 /*
685 685 * Apply kstat type-specific data massaging
686 686 */
687 687 switch (ksp->ks_type) {
688 688
689 689 case KSTAT_TYPE_IO:
690 690 /*
691 691 * Normalize time units and deal with incomplete transactions
692 692 */
693 693 kiop = (kstat_io_t *)buf;
694 694
695 695 scalehrtime(&kiop->wtime);
696 696 scalehrtime(&kiop->wlentime);
697 697 scalehrtime(&kiop->wlastupdate);
698 698 scalehrtime(&kiop->rtime);
699 699 scalehrtime(&kiop->rlentime);
700 700 scalehrtime(&kiop->rlastupdate);
701 701
702 702 if (kiop->wcnt != 0) {
703 703 /* like kstat_waitq_exit */
704 704 hrtime_t wfix = cur_time - kiop->wlastupdate;
705 705 kiop->wlastupdate = cur_time;
706 706 kiop->wlentime += kiop->wcnt * wfix;
707 707 kiop->wtime += wfix;
708 708 }
709 709
710 710 if (kiop->rcnt != 0) {
711 711 /* like kstat_runq_exit */
712 712 hrtime_t rfix = cur_time - kiop->rlastupdate;
713 713 kiop->rlastupdate = cur_time;
714 714 kiop->rlentime += kiop->rcnt * rfix;
715 715 kiop->rtime += rfix;
716 716 }
717 717 break;
718 718
719 719 case KSTAT_TYPE_NAMED:
720 720 /*
721 721 * Massage any long strings in at the end of the buffer
722 722 */
723 723 if (ksp->ks_data_size > namedsz) {
724 724 uint_t i;
725 725 kstat_named_t *knp = buf;
726 726 char *dst = (char *)(knp + ksp->ks_ndata);
727 727 /*
728 728 * Copy strings and update pointers
729 729 */
730 730 for (i = 0; i < ksp->ks_ndata; i++, knp++) {
731 731 if (knp->data_type == KSTAT_DATA_STRING &&
732 732 KSTAT_NAMED_STR_PTR(knp) != NULL) {
733 733 bcopy(KSTAT_NAMED_STR_PTR(knp), dst,
734 734 KSTAT_NAMED_STR_BUFLEN(knp));
735 735 KSTAT_NAMED_STR_PTR(knp) = dst;
736 736 dst += KSTAT_NAMED_STR_BUFLEN(knp);
737 737 }
738 738 }
739 739 ASSERT(dst <= ((char *)buf + ksp->ks_data_size));
740 740 }
741 741 break;
742 742 }
743 743 return (0);
744 744 }
745 745
746 746 static int
747 747 header_kstat_update(kstat_t *header_ksp, int rw)
748 748 {
749 749 int nkstats = 0;
750 750 ekstat_t *e;
751 751 avl_tree_t *t = &kstat_avl_bykid;
752 752 zoneid_t zoneid;
753 753
754 754 if (rw == KSTAT_WRITE)
755 755 return (EACCES);
756 756
757 757 ASSERT(MUTEX_HELD(&kstat_chain_lock));
758 758
759 759 zoneid = getzoneid();
760 760 for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER)) {
761 761 if (kstat_zone_find((kstat_t *)e, zoneid)) {
762 762 nkstats++;
763 763 }
764 764 }
765 765 header_ksp->ks_ndata = nkstats;
766 766 header_ksp->ks_data_size = nkstats * sizeof (kstat_t);
767 767 return (0);
768 768 }
769 769
770 770 /*
771 771 * Copy out the data section of kstat 0, which consists of the list
772 772 * of all kstat headers. By specification, these headers must be
773 773 * copied out in order of increasing KID.
774 774 */
775 775 static int
776 776 header_kstat_snapshot(kstat_t *header_ksp, void *buf, int rw)
777 777 {
778 778 ekstat_t *e;
779 779 avl_tree_t *t = &kstat_avl_bykid;
780 780 zoneid_t zoneid;
781 781
782 782 header_ksp->ks_snaptime = gethrtime();
783 783
784 784 if (rw == KSTAT_WRITE)
785 785 return (EACCES);
786 786
787 787 ASSERT(MUTEX_HELD(&kstat_chain_lock));
788 788
789 789 zoneid = getzoneid();
790 790 for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER)) {
791 791 if (kstat_zone_find((kstat_t *)e, zoneid)) {
792 792 bcopy(&e->e_ks, buf, sizeof (kstat_t));
793 793 buf = (char *)buf + sizeof (kstat_t);
794 794 }
795 795 }
796 796
797 797 return (0);
798 798 }
799 799
800 800 /* ARGSUSED */
801 801 static int
802 802 system_misc_kstat_update(kstat_t *ksp, int rw)
803 803 {
804 804 int myncpus = ncpus;
805 805 int *loadavgp = &avenrun[0];
806 806 int loadavg[LOADAVG_NSTATS];
807 807 time_t zone_boot_time;
808 808 clock_t zone_lbolt;
809 809 hrtime_t zone_hrtime;
810 810 size_t zone_nproc;
811 811
812 812 if (rw == KSTAT_WRITE)
813 813 return (EACCES);
814 814
815 815 if (!INGLOBALZONE(curproc)) {
816 816 /*
817 817 * Here we grab cpu_lock which is OK as long as no-one in the
818 818 * future attempts to lookup this particular kstat
819 819 * (unix:0:system_misc) while holding cpu_lock.
820 820 */
821 821 mutex_enter(&cpu_lock);
822 822 if (pool_pset_enabled()) {
823 823 psetid_t mypsid = zone_pset_get(curproc->p_zone);
824 824 int error;
825 825
826 826 myncpus = zone_ncpus_get(curproc->p_zone);
827 827 ASSERT(myncpus > 0);
828 828 error = cpupart_get_loadavg(mypsid, &loadavg[0],
829 829 LOADAVG_NSTATS);
830 830 ASSERT(error == 0);
831 831 loadavgp = &loadavg[0];
832 832 }
833 833 mutex_exit(&cpu_lock);
834 834 }
835 835
836 836 if (INGLOBALZONE(curproc)) {
837 837 zone_boot_time = boot_time;
838 838 zone_lbolt = ddi_get_lbolt();
839 839 zone_nproc = nproc;
840 840 } else {
841 841 struct timeval tvp;
842 842 hrt2tv(curproc->p_zone->zone_zsched->p_mstart, &tvp);
843 843 zone_boot_time = tvp.tv_sec;
844 844
845 845 zone_hrtime = gethrtime();
846 846 zone_lbolt = (clock_t)(NSEC_TO_TICK(zone_hrtime) -
847 847 NSEC_TO_TICK(curproc->p_zone->zone_zsched->p_mstart));
848 848 mutex_enter(&curproc->p_zone->zone_nlwps_lock);
849 849 zone_nproc = curproc->p_zone->zone_nprocs;
850 850 mutex_exit(&curproc->p_zone->zone_nlwps_lock);
851 851 }
852 852
853 853 system_misc_kstat.ncpus.value.ui32 = (uint32_t)myncpus;
854 854 system_misc_kstat.lbolt.value.ui32 = (uint32_t)zone_lbolt;
855 855 system_misc_kstat.deficit.value.ui32 = (uint32_t)deficit;
856 856 system_misc_kstat.clk_intr.value.ui32 = (uint32_t)zone_lbolt;
857 857 system_misc_kstat.vac.value.ui32 = (uint32_t)vac;
858 858 system_misc_kstat.nproc.value.ui32 = (uint32_t)zone_nproc;
859 859 system_misc_kstat.avenrun_1min.value.ui32 = (uint32_t)loadavgp[0];
860 860 system_misc_kstat.avenrun_5min.value.ui32 = (uint32_t)loadavgp[1];
861 861 system_misc_kstat.avenrun_15min.value.ui32 = (uint32_t)loadavgp[2];
862 862 system_misc_kstat.boot_time.value.ui32 = (uint32_t)
863 863 zone_boot_time;
864 864 return (0);
865 865 }
866 866
867 867 #ifdef __sparc
868 868 extern caddr_t econtig32;
869 869 #else /* !__sparc */
870 870 extern caddr_t econtig;
871 871 #endif /* __sparc */
872 872
873 873 /* ARGSUSED */
874 874 static int
875 875 system_pages_kstat_update(kstat_t *ksp, int rw)
876 876 {
877 877 kobj_stat_t kobj_stat;
878 878
879 879 if (rw == KSTAT_WRITE) {
880 880 return (EACCES);
881 881 }
882 882
883 883 kobj_stat_get(&kobj_stat);
884 884 system_pages_kstat.physmem.value.ul = (ulong_t)physmem;
885 885 system_pages_kstat.nalloc.value.ul = kobj_stat.nalloc;
886 886 system_pages_kstat.nfree.value.ul = kobj_stat.nfree;
887 887 system_pages_kstat.nalloc_calls.value.ul = kobj_stat.nalloc_calls;
888 888 system_pages_kstat.nfree_calls.value.ul = kobj_stat.nfree_calls;
889 889 system_pages_kstat.kernelbase.value.ul = (ulong_t)KERNELBASE;
890 890
891 891 #ifdef __sparc
892 892 /*
893 893 * kstat should REALLY be modified to also report kmem64_base and
894 894 * kmem64_end (see sun4u/os/startup.c), as the virtual address range
895 895 * [ kernelbase .. econtig ] no longer is truly reflective of the
896 896 * kernel's vallocs...
897 897 */
898 898 system_pages_kstat.econtig.value.ul = (ulong_t)econtig32;
899 899 #else /* !__sparc */
900 900 system_pages_kstat.econtig.value.ul = (ulong_t)econtig;
901 901 #endif /* __sparc */
902 902
903 903 system_pages_kstat.freemem.value.ul = (ulong_t)freemem;
904 904 system_pages_kstat.availrmem.value.ul = (ulong_t)availrmem;
905 905 system_pages_kstat.lotsfree.value.ul = (ulong_t)lotsfree;
906 906 system_pages_kstat.desfree.value.ul = (ulong_t)desfree;
907 907 system_pages_kstat.minfree.value.ul = (ulong_t)minfree;
908 908 system_pages_kstat.fastscan.value.ul = (ulong_t)fastscan;
909 909 system_pages_kstat.slowscan.value.ul = (ulong_t)slowscan;
910 910 system_pages_kstat.nscan.value.ul = (ulong_t)nscan;
911 911 system_pages_kstat.desscan.value.ul = (ulong_t)desscan;
912 912 system_pages_kstat.pagesfree.value.ul = (ulong_t)freemem;
913 913 system_pages_kstat.pageslocked.value.ul = (ulong_t)(availrmem_initial -
914 914 availrmem);
915 915 system_pages_kstat.pagestotal.value.ul = (ulong_t)total_pages;
916 916 /*
917 917 * pp_kernel represents total pages used by the kernel since the
918 918 * startup. This formula takes into account the boottime kernel
919 919 * footprint and also considers the availrmem changes because of
920 920 * user explicit page locking.
921 921 */
922 922 system_pages_kstat.pp_kernel.value.ul = (ulong_t)(physinstalled -
923 923 obp_pages - availrmem - k_anoninfo.ani_mem_resv -
924 924 anon_segkp_pages_locked - pages_locked -
925 925 pages_claimed - pages_useclaim);
926 926
927 927 return (0);
928 928 }
929 929
930 930 kstat_t *
931 931 kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
932 932 const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags)
933 933 {
934 934 return (kstat_create_zone(ks_module, ks_instance, ks_name, ks_class,
935 935 ks_type, ks_ndata, ks_flags, ALL_ZONES));
936 936 }
937 937
938 938 /*
939 939 * Allocate and initialize a kstat structure. Or, if a dormant kstat with
940 940 * the specified name exists, reactivate it. Returns a pointer to the kstat
941 941 * on success, NULL on failure. The kstat will not be visible to the
942 942 * kstat driver until kstat_install().
943 943 */
944 944 kstat_t *
945 945 kstat_create_zone(const char *ks_module, int ks_instance, const char *ks_name,
946 946 const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
947 947 zoneid_t ks_zoneid)
948 948 {
949 949 size_t ks_data_size;
950 950 kstat_t *ksp;
951 951 ekstat_t *e;
952 952 avl_index_t where;
953 953 char namebuf[KSTAT_STRLEN + 16];
954 954
955 955 if (avl_numnodes(&kstat_avl_bykid) == 0) {
956 956 avl_create(&kstat_avl_bykid, kstat_compare_bykid,
957 957 sizeof (ekstat_t), offsetof(struct ekstat, e_avl_bykid));
958 958
959 959 avl_create(&kstat_avl_byname, kstat_compare_byname,
960 960 sizeof (ekstat_t), offsetof(struct ekstat, e_avl_byname));
961 961 }
962 962
963 963 /*
964 964 * If ks_name == NULL, set the ks_name to <module><instance>.
965 965 */
966 966 if (ks_name == NULL) {
967 967 char buf[KSTAT_STRLEN];
968 968 kstat_set_string(buf, ks_module);
969 969 (void) sprintf(namebuf, "%s%d", buf, ks_instance);
970 970 ks_name = namebuf;
971 971 }
972 972
973 973 /*
974 974 * Make sure it's a valid kstat data type
975 975 */
976 976 if (ks_type >= KSTAT_NUM_TYPES) {
977 977 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
978 978 "invalid kstat type %d",
979 979 ks_module, ks_instance, ks_name, ks_type);
980 980 return (NULL);
981 981 }
982 982
983 983 /*
984 984 * Don't allow persistent virtual kstats -- it makes no sense.
985 985 * ks_data points to garbage when the client goes away.
986 986 */
987 987 if ((ks_flags & KSTAT_FLAG_PERSISTENT) &&
988 988 (ks_flags & KSTAT_FLAG_VIRTUAL)) {
989 989 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
990 990 "cannot create persistent virtual kstat",
991 991 ks_module, ks_instance, ks_name);
992 992 return (NULL);
993 993 }
994 994
995 995 /*
996 996 * Don't allow variable-size physical kstats, since the framework's
997 997 * memory allocation for physical kstat data is fixed at creation time.
998 998 */
999 999 if ((ks_flags & KSTAT_FLAG_VAR_SIZE) &&
1000 1000 !(ks_flags & KSTAT_FLAG_VIRTUAL)) {
1001 1001 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
1002 1002 "cannot create variable-size physical kstat",
1003 1003 ks_module, ks_instance, ks_name);
1004 1004 return (NULL);
1005 1005 }
1006 1006
1007 1007 /*
1008 1008 * Make sure the number of data fields is within legal range
1009 1009 */
1010 1010 if (ks_ndata < kstat_data_type[ks_type].min_ndata ||
1011 1011 ks_ndata > kstat_data_type[ks_type].max_ndata) {
1012 1012 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
1013 1013 "ks_ndata=%d out of range [%d, %d]",
1014 1014 ks_module, ks_instance, ks_name, (int)ks_ndata,
1015 1015 kstat_data_type[ks_type].min_ndata,
1016 1016 kstat_data_type[ks_type].max_ndata);
1017 1017 return (NULL);
1018 1018 }
1019 1019
1020 1020 ks_data_size = kstat_data_type[ks_type].size * ks_ndata;
1021 1021
1022 1022 /*
1023 1023 * If the named kstat already exists and is dormant, reactivate it.
1024 1024 */
1025 1025 ksp = kstat_hold_byname(ks_module, ks_instance, ks_name, ks_zoneid);
1026 1026 if (ksp != NULL) {
1027 1027 if (!(ksp->ks_flags & KSTAT_FLAG_DORMANT)) {
1028 1028 /*
1029 1029 * The named kstat exists but is not dormant --
1030 1030 * this is a kstat namespace collision.
1031 1031 */
1032 1032 kstat_rele(ksp);
1033 1033 cmn_err(CE_WARN,
1034 1034 "kstat_create('%s', %d, '%s'): namespace collision",
1035 1035 ks_module, ks_instance, ks_name);
1036 1036 return (NULL);
1037 1037 }
1038 1038 if ((strcmp(ksp->ks_class, ks_class) != 0) ||
1039 1039 (ksp->ks_type != ks_type) ||
1040 1040 (ksp->ks_ndata != ks_ndata) ||
1041 1041 (ks_flags & KSTAT_FLAG_VIRTUAL)) {
1042 1042 /*
1043 1043 * The name is the same, but the other key parameters
1044 1044 * differ from those of the dormant kstat -- bogus.
1045 1045 */
1046 1046 kstat_rele(ksp);
1047 1047 cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
1048 1048 "invalid reactivation of dormant kstat",
1049 1049 ks_module, ks_instance, ks_name);
1050 1050 return (NULL);
1051 1051 }
1052 1052 /*
1053 1053 * Return dormant kstat pointer to caller. As usual,
1054 1054 * the kstat is marked invalid until kstat_install().
1055 1055 */
1056 1056 ksp->ks_flags |= KSTAT_FLAG_INVALID;
1057 1057 kstat_rele(ksp);
1058 1058 return (ksp);
1059 1059 }
1060 1060
1061 1061 /*
1062 1062 * Allocate memory for the new kstat header and, if this is a physical
1063 1063 * kstat, the data section.
1064 1064 */
1065 1065 e = kstat_alloc(ks_flags & KSTAT_FLAG_VIRTUAL ? 0 : ks_data_size);
1066 1066 if (e == NULL) {
1067 1067 cmn_err(CE_NOTE, "kstat_create('%s', %d, '%s'): "
1068 1068 "insufficient kernel memory",
1069 1069 ks_module, ks_instance, ks_name);
1070 1070 return (NULL);
1071 1071 }
1072 1072
1073 1073 /*
1074 1074 * Initialize as many fields as we can. The caller may reset
1075 1075 * ks_lock, ks_update, ks_private, and ks_snapshot as necessary.
1076 1076 * Creators of virtual kstats may also reset ks_data. It is
1077 1077 * also up to the caller to initialize the kstat data section,
1078 1078 * if necessary. All initialization must be complete before
1079 1079 * calling kstat_install().
1080 1080 */
1081 1081 e->e_zone.zoneid = ks_zoneid;
1082 1082 e->e_zone.next = NULL;
1083 1083
1084 1084 ksp = &e->e_ks;
1085 1085 ksp->ks_crtime = gethrtime();
1086 1086 kstat_set_string(ksp->ks_module, ks_module);
1087 1087 ksp->ks_instance = ks_instance;
1088 1088 kstat_set_string(ksp->ks_name, ks_name);
1089 1089 ksp->ks_type = ks_type;
1090 1090 kstat_set_string(ksp->ks_class, ks_class);
1091 1091 ksp->ks_flags = ks_flags | KSTAT_FLAG_INVALID;
1092 1092 if (ks_flags & KSTAT_FLAG_VIRTUAL)
1093 1093 ksp->ks_data = NULL;
1094 1094 else
1095 1095 ksp->ks_data = (void *)(e + 1);
1096 1096 ksp->ks_ndata = ks_ndata;
1097 1097 ksp->ks_data_size = ks_data_size;
1098 1098 ksp->ks_snaptime = ksp->ks_crtime;
1099 1099 ksp->ks_update = default_kstat_update;
1100 1100 ksp->ks_private = NULL;
1101 1101 ksp->ks_snapshot = default_kstat_snapshot;
1102 1102 ksp->ks_lock = NULL;
1103 1103
1104 1104 mutex_enter(&kstat_chain_lock);
1105 1105
1106 1106 /*
1107 1107 * Add our kstat to the AVL trees.
1108 1108 */
1109 1109 if (avl_find(&kstat_avl_byname, e, &where) != NULL) {
1110 1110 mutex_exit(&kstat_chain_lock);
1111 1111 cmn_err(CE_WARN,
1112 1112 "kstat_create('%s', %d, '%s'): namespace collision",
1113 1113 ks_module, ks_instance, ks_name);
1114 1114 kstat_free(e);
1115 1115 return (NULL);
1116 1116 }
1117 1117 avl_insert(&kstat_avl_byname, e, where);
1118 1118
1119 1119 /*
1120 1120 * Loop around until we find an unused KID.
1121 1121 */
1122 1122 do {
1123 1123 ksp->ks_kid = kstat_chain_id++;
1124 1124 } while (avl_find(&kstat_avl_bykid, e, &where) != NULL);
1125 1125 avl_insert(&kstat_avl_bykid, e, where);
1126 1126
1127 1127 mutex_exit(&kstat_chain_lock);
1128 1128
1129 1129 return (ksp);
1130 1130 }
1131 1131
1132 1132 /*
1133 1133 * Activate a fully initialized kstat and make it visible to /dev/kstat.
1134 1134 */
1135 1135 void
1136 1136 kstat_install(kstat_t *ksp)
1137 1137 {
1138 1138 zoneid_t zoneid = ((ekstat_t *)ksp)->e_zone.zoneid;
1139 1139
1140 1140 /*
1141 1141 * If this is a variable-size kstat, it MUST provide kstat data locking
1142 1142 * to prevent data-size races with kstat readers.
1143 1143 */
1144 1144 if ((ksp->ks_flags & KSTAT_FLAG_VAR_SIZE) && ksp->ks_lock == NULL) {
1145 1145 panic("kstat_install('%s', %d, '%s'): "
1146 1146 "cannot create variable-size kstat without data lock",
1147 1147 ksp->ks_module, ksp->ks_instance, ksp->ks_name);
1148 1148 }
1149 1149
1150 1150 if (kstat_hold_bykid(ksp->ks_kid, zoneid) != ksp) {
1151 1151 cmn_err(CE_WARN, "kstat_install(%p): does not exist",
1152 1152 (void *)ksp);
1153 1153 return;
1154 1154 }
1155 1155
1156 1156 if (ksp->ks_type == KSTAT_TYPE_NAMED && ksp->ks_data != NULL) {
1157 1157 int has_long_strings = 0;
1158 1158 uint_t i;
1159 1159 kstat_named_t *knp = KSTAT_NAMED_PTR(ksp);
1160 1160
1161 1161 for (i = 0; i < ksp->ks_ndata; i++, knp++) {
1162 1162 if (knp->data_type == KSTAT_DATA_STRING) {
1163 1163 has_long_strings = 1;
1164 1164 break;
1165 1165 }
1166 1166 }
1167 1167 /*
1168 1168 * It is an error for a named kstat with fields of
1169 1169 * KSTAT_DATA_STRING to be non-virtual.
1170 1170 */
1171 1171 if (has_long_strings && !(ksp->ks_flags & KSTAT_FLAG_VIRTUAL)) {
1172 1172 panic("kstat_install('%s', %d, '%s'): "
1173 1173 "named kstat containing KSTAT_DATA_STRING "
1174 1174 "is not virtual",
1175 1175 ksp->ks_module, ksp->ks_instance,
1176 1176 ksp->ks_name);
1177 1177 }
1178 1178 /*
1179 1179 * The default snapshot routine does not handle KSTAT_WRITE
1180 1180 * for long strings.
1181 1181 */
1182 1182 if (has_long_strings && (ksp->ks_flags & KSTAT_FLAG_WRITABLE) &&
1183 1183 (ksp->ks_snapshot == default_kstat_snapshot)) {
1184 1184 panic("kstat_install('%s', %d, '%s'): "
1185 1185 "named kstat containing KSTAT_DATA_STRING "
1186 1186 "is writable but uses default snapshot routine",
1187 1187 ksp->ks_module, ksp->ks_instance, ksp->ks_name);
1188 1188 }
1189 1189 }
1190 1190
1191 1191 if (ksp->ks_flags & KSTAT_FLAG_DORMANT) {
1192 1192
1193 1193 /*
1194 1194 * We are reactivating a dormant kstat. Initialize the
1195 1195 * caller's underlying data to the value it had when the
1196 1196 * kstat went dormant, and mark the kstat as active.
1197 1197 * Grab the provider's kstat lock if it's not already held.
1198 1198 */
1199 1199 kmutex_t *lp = ksp->ks_lock;
↓ open down ↓ |
1199 lines elided |
↑ open up ↑ |
1200 1200 if (lp != NULL && MUTEX_NOT_HELD(lp)) {
1201 1201 mutex_enter(lp);
1202 1202 (void) KSTAT_UPDATE(ksp, KSTAT_WRITE);
1203 1203 mutex_exit(lp);
1204 1204 } else {
1205 1205 (void) KSTAT_UPDATE(ksp, KSTAT_WRITE);
1206 1206 }
1207 1207 ksp->ks_flags &= ~KSTAT_FLAG_DORMANT;
1208 1208 }
1209 1209
1210 +#ifdef DEBUG
1211 + /*
1212 + * Search for uninitialized kstats.
1213 + */
1214 + switch (ksp->ks_type) {
1215 + case KSTAT_TYPE_NAMED: {
1216 + uint_t i;
1217 + kstat_named_t *knp = KSTAT_NAMED_PTR(ksp);
1218 +
1219 + for (i = 0; i < ksp->ks_ndata; i++, knp++) {
1220 + if (knp->data_type > KSTAT_DATA_STRING) {
1221 + cmn_err(CE_WARN,
1222 + "kstat_install('%s', %d, '%s'): "
1223 + "invalid data type",
1224 + ksp->ks_module, ksp->ks_instance,
1225 + ksp->ks_name);
1226 + }
1227 +
1228 + /*
1229 + * If the name of this kstat is empty
1230 + * we assume it is uninitialized.
1231 + */
1232 + if (knp->name[0] == '\0') {
1233 + cmn_err(CE_WARN,
1234 + "kstat_install('%s', %d, '%s'): "
1235 + "uninitialized kstat",
1236 + ksp->ks_module, ksp->ks_instance,
1237 + ksp->ks_name);
1238 + }
1239 + }
1240 +
1241 + break;
1242 + }
1243 + default:
1244 + break;
1245 + }
1246 +#endif
1247 +
1210 1248 /*
1211 1249 * Now that the kstat is active, make it visible to the kstat driver.
1212 1250 */
1213 1251 ksp->ks_flags &= ~KSTAT_FLAG_INVALID;
1214 1252 kstat_rele(ksp);
1215 1253 }
1216 1254
1217 1255 /*
1218 1256 * Remove a kstat from the system. Or, if it's a persistent kstat,
1219 1257 * just update the data and mark it as dormant.
1220 1258 */
1221 1259 void
1222 1260 kstat_delete(kstat_t *ksp)
1223 1261 {
1224 1262 kmutex_t *lp;
1225 1263 ekstat_t *e = (ekstat_t *)ksp;
1226 1264 zoneid_t zoneid;
1227 1265 kstat_zone_t *kz;
1228 1266
1229 1267 ASSERT(ksp != NULL);
1230 1268
1231 1269 if (ksp == NULL)
1232 1270 return;
1233 1271
1234 1272 zoneid = e->e_zone.zoneid;
1235 1273
1236 1274 lp = ksp->ks_lock;
1237 1275
1238 1276 if (lp != NULL && MUTEX_HELD(lp)) {
1239 1277 panic("kstat_delete(%p): caller holds data lock %p",
1240 1278 (void *)ksp, (void *)lp);
1241 1279 }
1242 1280
1243 1281 if (kstat_hold_bykid(ksp->ks_kid, zoneid) != ksp) {
1244 1282 cmn_err(CE_WARN, "kstat_delete(%p): does not exist",
1245 1283 (void *)ksp);
1246 1284 return;
1247 1285 }
1248 1286
1249 1287 if (ksp->ks_flags & KSTAT_FLAG_PERSISTENT) {
1250 1288 /*
1251 1289 * Update the data one last time, so that all activity
1252 1290 * prior to going dormant has been accounted for.
1253 1291 */
1254 1292 KSTAT_ENTER(ksp);
1255 1293 (void) KSTAT_UPDATE(ksp, KSTAT_READ);
1256 1294 KSTAT_EXIT(ksp);
1257 1295
1258 1296 /*
1259 1297 * Mark the kstat as dormant and restore caller-modifiable
1260 1298 * fields to default values, so the kstat is readable during
1261 1299 * the dormant phase.
1262 1300 */
1263 1301 ksp->ks_flags |= KSTAT_FLAG_DORMANT;
1264 1302 ksp->ks_lock = NULL;
1265 1303 ksp->ks_update = default_kstat_update;
1266 1304 ksp->ks_private = NULL;
1267 1305 ksp->ks_snapshot = default_kstat_snapshot;
1268 1306 kstat_rele(ksp);
1269 1307 return;
1270 1308 }
1271 1309
1272 1310 /*
1273 1311 * Remove the kstat from the framework's AVL trees,
1274 1312 * free the allocated memory, and increment kstat_chain_id so
1275 1313 * /dev/kstat clients can detect the event.
1276 1314 */
1277 1315 mutex_enter(&kstat_chain_lock);
1278 1316 avl_remove(&kstat_avl_bykid, e);
1279 1317 avl_remove(&kstat_avl_byname, e);
1280 1318 kstat_chain_id++;
1281 1319 mutex_exit(&kstat_chain_lock);
1282 1320
1283 1321 kz = e->e_zone.next;
1284 1322 while (kz != NULL) {
1285 1323 kstat_zone_t *t = kz;
1286 1324
1287 1325 kz = kz->next;
1288 1326 kmem_free(t, sizeof (*t));
1289 1327 }
1290 1328 kstat_rele(ksp);
1291 1329 kstat_free(e);
1292 1330 }
1293 1331
1294 1332 void
1295 1333 kstat_delete_byname_zone(const char *ks_module, int ks_instance,
1296 1334 const char *ks_name, zoneid_t ks_zoneid)
1297 1335 {
1298 1336 kstat_t *ksp;
1299 1337
1300 1338 ksp = kstat_hold_byname(ks_module, ks_instance, ks_name, ks_zoneid);
1301 1339 if (ksp != NULL) {
1302 1340 kstat_rele(ksp);
1303 1341 kstat_delete(ksp);
1304 1342 }
1305 1343 }
1306 1344
1307 1345 void
1308 1346 kstat_delete_byname(const char *ks_module, int ks_instance, const char *ks_name)
1309 1347 {
1310 1348 kstat_delete_byname_zone(ks_module, ks_instance, ks_name, ALL_ZONES);
1311 1349 }
1312 1350
1313 1351 /*
1314 1352 * The sparc V9 versions of these routines can be much cheaper than
1315 1353 * the poor 32-bit compiler can comprehend, so they're in sparcv9_subr.s.
1316 1354 * For simplicity, however, we always feed the C versions to lint.
1317 1355 */
1318 1356 #if !defined(__sparc) || defined(lint) || defined(__lint)
1319 1357
1320 1358 void
1321 1359 kstat_waitq_enter(kstat_io_t *kiop)
1322 1360 {
1323 1361 hrtime_t new, delta;
1324 1362 ulong_t wcnt;
1325 1363
1326 1364 new = gethrtime_unscaled();
1327 1365 delta = new - kiop->wlastupdate;
1328 1366 kiop->wlastupdate = new;
1329 1367 wcnt = kiop->wcnt++;
1330 1368 if (wcnt != 0) {
1331 1369 kiop->wlentime += delta * wcnt;
1332 1370 kiop->wtime += delta;
1333 1371 }
1334 1372 }
1335 1373
1336 1374 void
1337 1375 kstat_waitq_exit(kstat_io_t *kiop)
1338 1376 {
1339 1377 hrtime_t new, delta;
1340 1378 ulong_t wcnt;
1341 1379
1342 1380 new = gethrtime_unscaled();
1343 1381 delta = new - kiop->wlastupdate;
1344 1382 kiop->wlastupdate = new;
1345 1383 wcnt = kiop->wcnt--;
1346 1384 ASSERT((int)wcnt > 0);
1347 1385 kiop->wlentime += delta * wcnt;
1348 1386 kiop->wtime += delta;
1349 1387 }
1350 1388
1351 1389 void
1352 1390 kstat_runq_enter(kstat_io_t *kiop)
1353 1391 {
1354 1392 hrtime_t new, delta;
1355 1393 ulong_t rcnt;
1356 1394
1357 1395 new = gethrtime_unscaled();
1358 1396 delta = new - kiop->rlastupdate;
1359 1397 kiop->rlastupdate = new;
1360 1398 rcnt = kiop->rcnt++;
1361 1399 if (rcnt != 0) {
1362 1400 kiop->rlentime += delta * rcnt;
1363 1401 kiop->rtime += delta;
1364 1402 }
1365 1403 }
1366 1404
1367 1405 void
1368 1406 kstat_runq_exit(kstat_io_t *kiop)
1369 1407 {
1370 1408 hrtime_t new, delta;
1371 1409 ulong_t rcnt;
1372 1410
1373 1411 new = gethrtime_unscaled();
1374 1412 delta = new - kiop->rlastupdate;
1375 1413 kiop->rlastupdate = new;
1376 1414 rcnt = kiop->rcnt--;
1377 1415 ASSERT((int)rcnt > 0);
1378 1416 kiop->rlentime += delta * rcnt;
1379 1417 kiop->rtime += delta;
1380 1418 }
1381 1419
1382 1420 void
1383 1421 kstat_waitq_to_runq(kstat_io_t *kiop)
1384 1422 {
1385 1423 hrtime_t new, delta;
1386 1424 ulong_t wcnt, rcnt;
1387 1425
1388 1426 new = gethrtime_unscaled();
1389 1427
1390 1428 delta = new - kiop->wlastupdate;
1391 1429 kiop->wlastupdate = new;
1392 1430 wcnt = kiop->wcnt--;
1393 1431 ASSERT((int)wcnt > 0);
1394 1432 kiop->wlentime += delta * wcnt;
1395 1433 kiop->wtime += delta;
1396 1434
1397 1435 delta = new - kiop->rlastupdate;
1398 1436 kiop->rlastupdate = new;
1399 1437 rcnt = kiop->rcnt++;
1400 1438 if (rcnt != 0) {
1401 1439 kiop->rlentime += delta * rcnt;
1402 1440 kiop->rtime += delta;
1403 1441 }
1404 1442 }
1405 1443
1406 1444 void
1407 1445 kstat_runq_back_to_waitq(kstat_io_t *kiop)
1408 1446 {
1409 1447 hrtime_t new, delta;
1410 1448 ulong_t wcnt, rcnt;
1411 1449
1412 1450 new = gethrtime_unscaled();
1413 1451
1414 1452 delta = new - kiop->rlastupdate;
1415 1453 kiop->rlastupdate = new;
1416 1454 rcnt = kiop->rcnt--;
1417 1455 ASSERT((int)rcnt > 0);
1418 1456 kiop->rlentime += delta * rcnt;
1419 1457 kiop->rtime += delta;
1420 1458
1421 1459 delta = new - kiop->wlastupdate;
1422 1460 kiop->wlastupdate = new;
1423 1461 wcnt = kiop->wcnt++;
1424 1462 if (wcnt != 0) {
1425 1463 kiop->wlentime += delta * wcnt;
1426 1464 kiop->wtime += delta;
1427 1465 }
1428 1466 }
1429 1467
1430 1468 #endif
1431 1469
1432 1470 void
1433 1471 kstat_timer_start(kstat_timer_t *ktp)
1434 1472 {
1435 1473 ktp->start_time = gethrtime();
1436 1474 }
1437 1475
1438 1476 void
1439 1477 kstat_timer_stop(kstat_timer_t *ktp)
1440 1478 {
1441 1479 hrtime_t etime;
1442 1480 u_longlong_t num_events;
1443 1481
1444 1482 ktp->stop_time = etime = gethrtime();
1445 1483 etime -= ktp->start_time;
1446 1484 num_events = ktp->num_events;
1447 1485 if (etime < ktp->min_time || num_events == 0)
1448 1486 ktp->min_time = etime;
1449 1487 if (etime > ktp->max_time)
1450 1488 ktp->max_time = etime;
1451 1489 ktp->elapsed_time += etime;
1452 1490 ktp->num_events = num_events + 1;
1453 1491 }
↓ open down ↓ |
234 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX