dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / stat / common / walkers.c
blobadf6d6eb6ff6100971d35f44ff71323faf65f320
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include "statcommon.h"
30 #include <string.h>
31 #include <errno.h>
33 /* max size of report change annotations */
34 #define LIST_SIZE 512
36 static char cpus_added[LIST_SIZE];
37 static char cpus_removed[LIST_SIZE];
39 static int
40 cpu_walk(struct snapshot *old, struct snapshot *new,
41 snapshot_cb cb, void *data)
43 int changed = 0;
44 int i;
46 /* CPUs can change state but not re-order */
47 for (i = 0; i < new->s_nr_cpus; i++) {
48 struct cpu_snapshot *cpu = NULL;
49 struct cpu_snapshot *newcpu = &new->s_cpus[i];
50 if (old)
51 cpu = &old->s_cpus[i];
52 cb(cpu, newcpu, data);
53 if (cpu == NULL)
54 changed = 1;
55 else {
57 * We only care about off/on line transitions
59 if ((CPU_ACTIVE(cpu) && !CPU_ACTIVE(newcpu)) ||
60 (!CPU_ACTIVE(cpu) && CPU_ACTIVE(newcpu)))
61 changed = 1;
62 if ((new->s_types & SNAP_PSETS) &&
63 cpu->cs_pset_id != newcpu->cs_pset_id)
64 changed = 1;
69 return (changed);
72 static int
73 pset_walk(struct snapshot *old, struct snapshot *new,
74 snapshot_cb cb, void *data)
76 int i = 0;
77 int j = 0;
78 int changed = 0;
80 while (old && i < old->s_nr_psets && j < new->s_nr_psets) {
81 if (old->s_psets[i].ps_id < new->s_psets[j].ps_id) {
82 cb(&old->s_psets[i], NULL, data);
83 i++;
84 changed = 1;
85 } else if (old->s_psets[i].ps_id > new->s_psets[j].ps_id) {
86 cb(NULL, &new->s_psets[j], data);
87 j++;
88 changed = 1;
89 } else {
90 cb(&old->s_psets[i], &new->s_psets[j], data);
91 i++;
92 j++;
96 while (old && i < old->s_nr_psets) {
97 cb(&old->s_psets[i], NULL, data);
98 i++;
99 changed = 1;
102 while (j < new->s_nr_psets) {
103 cb(NULL, &new->s_psets[j], data);
104 j++;
105 changed = 1;
108 return (changed);
111 static int
112 iodev_walk(struct iodev_snapshot *d1, struct iodev_snapshot *d2,
113 snapshot_cb cb, void *data)
115 int changed = 0;
117 while (d1 && d2) {
118 if (strcmp(d1->is_name, d2->is_name) < 0) {
119 changed = 1;
120 cb(d1, NULL, data);
121 (void) iodev_walk(d1->is_children, NULL, cb, data);
122 d1 = d1->is_next;
123 } else if (strcmp(d1->is_name, d2->is_name) > 0) {
124 changed = 1;
125 cb(NULL, d2, data);
126 (void) iodev_walk(NULL, d2->is_children, cb, data);
127 d2 = d2->is_next;
128 } else {
129 cb(d1, d2, data);
130 changed |= iodev_walk(d1->is_children,
131 d2->is_children, cb, data);
132 d1 = d1->is_next;
133 d2 = d2->is_next;
137 while (d1) {
138 changed = 1;
139 cb(d1, NULL, data);
140 (void) iodev_walk(d1->is_children, NULL, cb, data);
141 d1 = d1->is_next;
144 while (d2) {
145 changed = 1;
146 cb(NULL, d2, data);
147 (void) iodev_walk(NULL, d2->is_children, cb, data);
148 d2 = d2->is_next;
151 return (changed);
155 snapshot_walk(enum snapshot_types type, struct snapshot *old,
156 struct snapshot *new, snapshot_cb cb, void *data)
158 int changed = 0;
160 switch (type) {
161 case SNAP_CPUS:
162 changed = cpu_walk(old, new, cb, data);
163 break;
165 case SNAP_PSETS:
166 changed = pset_walk(old, new, cb, data);
167 break;
169 case SNAP_CONTROLLERS:
170 case SNAP_IODEVS:
171 case SNAP_IOPATHS_LI:
172 case SNAP_IOPATHS_LTI:
173 changed = iodev_walk(old ? old->s_iodevs : NULL,
174 new->s_iodevs, cb, data);
175 break;
177 default:
178 break;
181 return (changed);
184 static void
185 add_nr_to_list(char *buf, unsigned long nr)
187 char tmp[LIST_SIZE];
189 (void) snprintf(tmp, LIST_SIZE, "%lu", nr);
191 if (strlen(buf))
192 (void) strlcat(buf, ", ", LIST_SIZE);
194 (void) strlcat(buf, tmp, LIST_SIZE);
197 static void
198 cpu_report(void *v1, void *v2, void *data)
200 int *pset = (int *)data;
201 struct cpu_snapshot *c1 = (struct cpu_snapshot *)v1;
202 struct cpu_snapshot *c2 = (struct cpu_snapshot *)v2;
204 if (*pset && c1->cs_pset_id != c2->cs_pset_id) {
205 (void) printf("<<processor %d moved from pset: %d to: %d>>\n",
206 c1->cs_id, c1->cs_pset_id, c2->cs_pset_id);
209 if (c1->cs_state == c2->cs_state)
210 return;
212 if (CPU_ONLINE(c1->cs_state) && !CPU_ONLINE(c2->cs_state))
213 add_nr_to_list(cpus_removed, c1->cs_id);
215 if (!CPU_ONLINE(c1->cs_state) && CPU_ONLINE(c2->cs_state))
216 add_nr_to_list(cpus_added, c2->cs_id);
219 /*ARGSUSED*/
220 static void
221 pset_report(void *v1, void *v2, void *data)
223 struct pset_snapshot *p1 = (struct pset_snapshot *)v1;
224 struct pset_snapshot *p2 = (struct pset_snapshot *)v2;
226 if (p2 == NULL) {
227 (void) printf("<<pset destroyed: %u>>\n", p1->ps_id);
228 return;
231 if (p1 == NULL)
232 (void) printf("<<pset created: %u>>\n", p2->ps_id);
235 static void
236 get_child_list(struct iodev_snapshot *iodev, char *buf)
238 char tmp[LIST_SIZE];
239 struct iodev_snapshot *pos = iodev->is_children;
241 while (pos) {
242 if (pos->is_type == IODEV_PARTITION) {
243 add_nr_to_list(buf, pos->is_id.id);
244 } else if (pos->is_type == IODEV_DISK) {
245 if (strlen(buf))
246 (void) strlcat(buf, ", ", LIST_SIZE);
247 (void) strlcat(buf, "t", LIST_SIZE);
248 (void) strlcat(buf, pos->is_id.tid, LIST_SIZE);
249 (void) strlcat(buf, "d", LIST_SIZE);
250 *tmp = '\0';
251 add_nr_to_list(tmp, pos->is_id.id);
252 (void) strlcat(buf, tmp, LIST_SIZE);
254 pos = pos->is_next;
258 static void
259 iodev_changed(struct iodev_snapshot *iodev, int added)
261 char tmp[LIST_SIZE];
262 int is_disk = iodev->is_type == IODEV_DISK;
263 char *name = iodev->is_name;
265 if (iodev->is_pretty)
266 name = iodev->is_pretty;
268 switch (iodev->is_type) {
269 case IODEV_IOPATH_LT:
270 case IODEV_IOPATH_LI:
271 case IODEV_IOPATH_LTI:
272 (void) printf("<<multi-path %s: %s>>\n",
273 added ? "added" : "removed", name);
274 break;
275 case IODEV_PARTITION:
276 (void) printf("<<partition %s: %s>>\n",
277 added ? "added" : "removed", name);
278 break;
279 case IODEV_NFS:
280 (void) printf("<<NFS %s: %s>>\n",
281 added ? "mounted" : "unmounted", name);
282 break;
283 case IODEV_TAPE:
284 (void) printf("<<device %s: %s>>\n",
285 added ? "added" : "removed", name);
286 break;
287 case IODEV_CONTROLLER:
288 case IODEV_DISK:
289 *tmp = '\0';
290 get_child_list(iodev, tmp);
291 (void) printf("<<%s %s: %s", is_disk ? "disk" : "controller",
292 added ? "added" : "removed", name);
293 if (!*tmp) {
294 (void) printf(">>\n");
295 return;
297 (void) printf(" (%s %s)>>\n", is_disk ? "slices" : "disks",
298 tmp);
299 break;
303 static void
304 iodev_report(struct iodev_snapshot *d1, struct iodev_snapshot *d2)
306 while (d1 && d2) {
307 if (iodev_cmp(d1, d2) < 0) {
308 iodev_changed(d1, 0);
309 d1 = d1->is_next;
310 } else if (iodev_cmp(d1, d2) > 0) {
311 iodev_changed(d2, 1);
312 d2 = d2->is_next;
313 } else {
314 iodev_report(d1->is_children, d2->is_children);
315 d1 = d1->is_next;
316 d2 = d2->is_next;
320 while (d1) {
321 iodev_changed(d1, 0);
322 d1 = d1->is_next;
325 while (d2) {
326 iodev_changed(d2, 1);
327 d2 = d2->is_next;
331 void
332 snapshot_report_changes(struct snapshot *old, struct snapshot *new)
334 int pset;
336 if (old == NULL || new == NULL)
337 return;
339 if (old->s_types != new->s_types)
340 return;
342 pset = old->s_types & SNAP_PSETS;
344 cpus_removed[0] = '\0';
345 cpus_added[0] = '\0';
347 if (old->s_types & SNAP_CPUS)
348 (void) snapshot_walk(SNAP_CPUS, old, new, cpu_report, &pset);
350 if (cpus_added[0]) {
351 (void) printf("<<processors added: %s>>\n",
352 cpus_added);
354 if (cpus_removed[0]) {
355 (void) printf("<<processors removed: %s>>\n",
356 cpus_removed);
358 if (pset) {
359 (void) snapshot_walk(SNAP_PSETS, old, new,
360 pset_report, NULL);
363 iodev_report(old->s_iodevs, new->s_iodevs);
366 /*ARGSUSED*/
367 static void
368 dummy_cb(void *v1, void *v2, void *data)
373 snapshot_has_changed(struct snapshot *old, struct snapshot *new)
375 int ret = 0;
376 int cpu_mask = SNAP_CPUS | SNAP_PSETS | SNAP_SYSTEM;
377 int iodev_mask = SNAP_CONTROLLERS | SNAP_IODEVS |
378 SNAP_IOPATHS_LI | SNAP_IOPATHS_LTI;
380 if (old == NULL)
381 return (1);
383 if (new == NULL)
384 return (EINVAL);
386 if (old->s_types != new->s_types)
387 return (EINVAL);
389 if (!ret && (old->s_types & cpu_mask))
390 ret = snapshot_walk(SNAP_CPUS, old, new, dummy_cb, NULL);
391 if (!ret && (old->s_types & SNAP_PSETS))
392 ret = snapshot_walk(SNAP_PSETS, old, new, dummy_cb, NULL);
393 if (!ret && (old->s_types & iodev_mask))
394 ret = snapshot_walk(SNAP_IODEVS, old, new, dummy_cb, NULL);
396 return (ret);