xref: /illumos-gate/usr/src/cmd/stat/common/walkers.c (revision 37fbbce5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*37fbbce5Scth  * Common Development and Distribution License (the "License").
6*37fbbce5Scth  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*37fbbce5Scth  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include "statcommon.h"
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <errno.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /* max size of report change annotations */
347c478bd9Sstevel@tonic-gate #define	LIST_SIZE 512
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate static char cpus_added[LIST_SIZE];
377c478bd9Sstevel@tonic-gate static char cpus_removed[LIST_SIZE];
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate static int
cpu_walk(struct snapshot * old,struct snapshot * new,snapshot_cb cb,void * data)407c478bd9Sstevel@tonic-gate cpu_walk(struct snapshot *old, struct snapshot *new,
417c478bd9Sstevel@tonic-gate     snapshot_cb cb, void *data)
427c478bd9Sstevel@tonic-gate {
437c478bd9Sstevel@tonic-gate 	int changed = 0;
447c478bd9Sstevel@tonic-gate 	int i;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 	/* CPUs can change state but not re-order */
477c478bd9Sstevel@tonic-gate 	for (i = 0; i < new->s_nr_cpus; i++) {
487c478bd9Sstevel@tonic-gate 		struct cpu_snapshot *cpu = NULL;
497c478bd9Sstevel@tonic-gate 		struct cpu_snapshot *newcpu = &new->s_cpus[i];
507c478bd9Sstevel@tonic-gate 		if (old)
517c478bd9Sstevel@tonic-gate 			cpu = &old->s_cpus[i];
527c478bd9Sstevel@tonic-gate 		cb(cpu, newcpu, data);
537c478bd9Sstevel@tonic-gate 		if (cpu == NULL)
547c478bd9Sstevel@tonic-gate 			changed = 1;
557c478bd9Sstevel@tonic-gate 		else {
567c478bd9Sstevel@tonic-gate 			/*
577c478bd9Sstevel@tonic-gate 			 * We only care about off/on line transitions
587c478bd9Sstevel@tonic-gate 			 */
597c478bd9Sstevel@tonic-gate 			if ((CPU_ACTIVE(cpu) && !CPU_ACTIVE(newcpu)) ||
607c478bd9Sstevel@tonic-gate 			    (!CPU_ACTIVE(cpu) && CPU_ACTIVE(newcpu)))
617c478bd9Sstevel@tonic-gate 				changed = 1;
627c478bd9Sstevel@tonic-gate 			if ((new->s_types & SNAP_PSETS) &&
637c478bd9Sstevel@tonic-gate 				cpu->cs_pset_id != newcpu->cs_pset_id)
647c478bd9Sstevel@tonic-gate 				changed = 1;
657c478bd9Sstevel@tonic-gate 		}
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 	}
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	return (changed);
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate static int
pset_walk(struct snapshot * old,struct snapshot * new,snapshot_cb cb,void * data)737c478bd9Sstevel@tonic-gate pset_walk(struct snapshot *old, struct snapshot *new,
747c478bd9Sstevel@tonic-gate     snapshot_cb cb, void *data)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	int i = 0;
777c478bd9Sstevel@tonic-gate 	int j = 0;
787c478bd9Sstevel@tonic-gate 	int changed = 0;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	while (old && i < old->s_nr_psets && j < new->s_nr_psets) {
817c478bd9Sstevel@tonic-gate 		if (old->s_psets[i].ps_id < new->s_psets[j].ps_id) {
827c478bd9Sstevel@tonic-gate 			cb(&old->s_psets[i], NULL, data);
837c478bd9Sstevel@tonic-gate 			i++;
847c478bd9Sstevel@tonic-gate 			changed = 1;
857c478bd9Sstevel@tonic-gate 		} else if (old->s_psets[i].ps_id > new->s_psets[j].ps_id) {
867c478bd9Sstevel@tonic-gate 			cb(NULL, &new->s_psets[j], data);
877c478bd9Sstevel@tonic-gate 			j++;
887c478bd9Sstevel@tonic-gate 			changed = 1;
897c478bd9Sstevel@tonic-gate 		} else {
907c478bd9Sstevel@tonic-gate 			cb(&old->s_psets[i], &new->s_psets[j], data);
917c478bd9Sstevel@tonic-gate 			i++;
927c478bd9Sstevel@tonic-gate 			j++;
937c478bd9Sstevel@tonic-gate 		}
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	while (old && i < old->s_nr_psets) {
977c478bd9Sstevel@tonic-gate 		cb(&old->s_psets[i], NULL, data);
987c478bd9Sstevel@tonic-gate 		i++;
997c478bd9Sstevel@tonic-gate 		changed = 1;
1007c478bd9Sstevel@tonic-gate 	}
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	while (j < new->s_nr_psets) {
1037c478bd9Sstevel@tonic-gate 		cb(NULL, &new->s_psets[j], data);
1047c478bd9Sstevel@tonic-gate 		j++;
1057c478bd9Sstevel@tonic-gate 		changed = 1;
1067c478bd9Sstevel@tonic-gate 	}
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	return (changed);
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate static int
iodev_walk(struct iodev_snapshot * d1,struct iodev_snapshot * d2,snapshot_cb cb,void * data)1127c478bd9Sstevel@tonic-gate iodev_walk(struct iodev_snapshot *d1, struct iodev_snapshot *d2,
1137c478bd9Sstevel@tonic-gate     snapshot_cb cb, void *data)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	int changed = 0;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	while (d1 && d2) {
1187c478bd9Sstevel@tonic-gate 		if (strcmp(d1->is_name, d2->is_name) < 0) {
1197c478bd9Sstevel@tonic-gate 			changed = 1;
1207c478bd9Sstevel@tonic-gate 			cb(d1, NULL, data);
1217c478bd9Sstevel@tonic-gate 			(void) iodev_walk(d1->is_children, NULL, cb, data);
1227c478bd9Sstevel@tonic-gate 			d1 = d1->is_next;
1237c478bd9Sstevel@tonic-gate 		} else if (strcmp(d1->is_name, d2->is_name) > 0) {
1247c478bd9Sstevel@tonic-gate 			changed = 1;
1257c478bd9Sstevel@tonic-gate 			cb(NULL, d2, data);
1267c478bd9Sstevel@tonic-gate 			(void) iodev_walk(NULL, d2->is_children, cb, data);
1277c478bd9Sstevel@tonic-gate 			d2 = d2->is_next;
1287c478bd9Sstevel@tonic-gate 		} else {
1297c478bd9Sstevel@tonic-gate 			cb(d1, d2, data);
1307c478bd9Sstevel@tonic-gate 			changed |= iodev_walk(d1->is_children,
1317c478bd9Sstevel@tonic-gate 					d2->is_children, cb, data);
1327c478bd9Sstevel@tonic-gate 			d1 = d1->is_next;
1337c478bd9Sstevel@tonic-gate 			d2 = d2->is_next;
1347c478bd9Sstevel@tonic-gate 		}
1357c478bd9Sstevel@tonic-gate 	}
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	while (d1) {
1387c478bd9Sstevel@tonic-gate 		changed = 1;
1397c478bd9Sstevel@tonic-gate 		cb(d1, NULL, data);
1407c478bd9Sstevel@tonic-gate 		(void) iodev_walk(d1->is_children, NULL, cb, data);
1417c478bd9Sstevel@tonic-gate 		d1 = d1->is_next;
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	while (d2) {
1457c478bd9Sstevel@tonic-gate 		changed = 1;
1467c478bd9Sstevel@tonic-gate 		cb(NULL, d2, data);
1477c478bd9Sstevel@tonic-gate 		(void) iodev_walk(NULL, d2->is_children, cb, data);
1487c478bd9Sstevel@tonic-gate 		d2 = d2->is_next;
1497c478bd9Sstevel@tonic-gate 	}
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	return (changed);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate int
snapshot_walk(enum snapshot_types type,struct snapshot * old,struct snapshot * new,snapshot_cb cb,void * data)1557c478bd9Sstevel@tonic-gate snapshot_walk(enum snapshot_types type, struct snapshot *old,
1567c478bd9Sstevel@tonic-gate     struct snapshot *new, snapshot_cb cb, void *data)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	int changed = 0;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	switch (type) {
1617c478bd9Sstevel@tonic-gate 	case SNAP_CPUS:
1627c478bd9Sstevel@tonic-gate 		changed = cpu_walk(old, new, cb, data);
1637c478bd9Sstevel@tonic-gate 		break;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	case SNAP_PSETS:
1667c478bd9Sstevel@tonic-gate 		changed = pset_walk(old, new, cb, data);
1677c478bd9Sstevel@tonic-gate 		break;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	case SNAP_CONTROLLERS:
1707c478bd9Sstevel@tonic-gate 	case SNAP_IODEVS:
171*37fbbce5Scth 	case SNAP_IOPATHS_LI:
172*37fbbce5Scth 	case SNAP_IOPATHS_LTI:
1737c478bd9Sstevel@tonic-gate 		changed = iodev_walk(old ? old->s_iodevs : NULL,
1747c478bd9Sstevel@tonic-gate 		    new->s_iodevs, cb, data);
1757c478bd9Sstevel@tonic-gate 		break;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	default:
1787c478bd9Sstevel@tonic-gate 		break;
1797c478bd9Sstevel@tonic-gate 	}
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	return (changed);
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate static void
add_nr_to_list(char * buf,unsigned long nr)1857c478bd9Sstevel@tonic-gate add_nr_to_list(char *buf, unsigned long nr)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	char tmp[LIST_SIZE];
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	(void) snprintf(tmp, LIST_SIZE, "%lu", nr);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	if (strlen(buf))
1927c478bd9Sstevel@tonic-gate 		(void) strlcat(buf, ", ", LIST_SIZE);
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	(void) strlcat(buf, tmp, LIST_SIZE);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate static void
cpu_report(void * v1,void * v2,void * data)1987c478bd9Sstevel@tonic-gate cpu_report(void *v1, void *v2, void *data)
1997c478bd9Sstevel@tonic-gate {
2007c478bd9Sstevel@tonic-gate 	int *pset = (int *)data;
2017c478bd9Sstevel@tonic-gate 	struct cpu_snapshot *c1 = (struct cpu_snapshot *)v1;
2027c478bd9Sstevel@tonic-gate 	struct cpu_snapshot *c2 = (struct cpu_snapshot *)v2;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if (*pset && c1->cs_pset_id != c2->cs_pset_id) {
2057c478bd9Sstevel@tonic-gate 		(void) printf("<<processor %d moved from pset: %d to: %d>>\n",
2067c478bd9Sstevel@tonic-gate 		    c1->cs_id, c1->cs_pset_id, c2->cs_pset_id);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	if (c1->cs_state == c2->cs_state)
2107c478bd9Sstevel@tonic-gate 		return;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	if (CPU_ONLINE(c1->cs_state) && !CPU_ONLINE(c2->cs_state))
2137c478bd9Sstevel@tonic-gate 		add_nr_to_list(cpus_removed, c1->cs_id);
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	if (!CPU_ONLINE(c1->cs_state) && CPU_ONLINE(c2->cs_state))
2167c478bd9Sstevel@tonic-gate 		add_nr_to_list(cpus_added, c2->cs_id);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2207c478bd9Sstevel@tonic-gate static void
pset_report(void * v1,void * v2,void * data)2217c478bd9Sstevel@tonic-gate pset_report(void *v1, void *v2, void *data)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 	struct pset_snapshot *p1 = (struct pset_snapshot *)v1;
2247c478bd9Sstevel@tonic-gate 	struct pset_snapshot *p2 = (struct pset_snapshot *)v2;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	if (p2 == NULL) {
2277c478bd9Sstevel@tonic-gate 		(void) printf("<<pset destroyed: %u>>\n", p1->ps_id);
2287c478bd9Sstevel@tonic-gate 		return;
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	if (p1 == NULL)
2327c478bd9Sstevel@tonic-gate 		(void) printf("<<pset created: %u>>\n", p2->ps_id);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate static void
get_child_list(struct iodev_snapshot * iodev,char * buf)2367c478bd9Sstevel@tonic-gate get_child_list(struct iodev_snapshot *iodev, char *buf)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate 	char tmp[LIST_SIZE];
2397c478bd9Sstevel@tonic-gate 	struct iodev_snapshot *pos = iodev->is_children;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	while (pos) {
2427c478bd9Sstevel@tonic-gate 		if (pos->is_type == IODEV_PARTITION) {
2437c478bd9Sstevel@tonic-gate 			add_nr_to_list(buf, pos->is_id.id);
2447c478bd9Sstevel@tonic-gate 		} else if (pos->is_type == IODEV_DISK) {
2457c478bd9Sstevel@tonic-gate 			if (strlen(buf))
2467c478bd9Sstevel@tonic-gate 				(void) strlcat(buf, ", ", LIST_SIZE);
2477c478bd9Sstevel@tonic-gate 			(void) strlcat(buf, "t", LIST_SIZE);
2487c478bd9Sstevel@tonic-gate 			(void) strlcat(buf, pos->is_id.tid, LIST_SIZE);
2497c478bd9Sstevel@tonic-gate 			(void) strlcat(buf, "d", LIST_SIZE);
2507c478bd9Sstevel@tonic-gate 			*tmp = '\0';
2517c478bd9Sstevel@tonic-gate 			add_nr_to_list(tmp, pos->is_id.id);
2527c478bd9Sstevel@tonic-gate 			(void) strlcat(buf, tmp, LIST_SIZE);
2537c478bd9Sstevel@tonic-gate 		}
2547c478bd9Sstevel@tonic-gate 		pos = pos->is_next;
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate static void
iodev_changed(struct iodev_snapshot * iodev,int added)2597c478bd9Sstevel@tonic-gate iodev_changed(struct iodev_snapshot *iodev, int added)
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate 	char tmp[LIST_SIZE];
2627c478bd9Sstevel@tonic-gate 	int is_disk = iodev->is_type == IODEV_DISK;
2637c478bd9Sstevel@tonic-gate 	char *name = iodev->is_name;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	if (iodev->is_pretty)
2667c478bd9Sstevel@tonic-gate 		name = iodev->is_pretty;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	switch (iodev->is_type) {
269*37fbbce5Scth 	case IODEV_IOPATH_LT:
270*37fbbce5Scth 	case IODEV_IOPATH_LI:
271*37fbbce5Scth 	case IODEV_IOPATH_LTI:
2727c478bd9Sstevel@tonic-gate 		(void) printf("<<multi-path %s: %s>>\n",
2737c478bd9Sstevel@tonic-gate 		    added ? "added" : "removed", name);
2747c478bd9Sstevel@tonic-gate 		break;
2757c478bd9Sstevel@tonic-gate 	case IODEV_PARTITION:
2767c478bd9Sstevel@tonic-gate 		(void) printf("<<partition %s: %s>>\n",
2777c478bd9Sstevel@tonic-gate 		    added ? "added" : "removed", name);
2787c478bd9Sstevel@tonic-gate 		break;
2797c478bd9Sstevel@tonic-gate 	case IODEV_NFS:
2807c478bd9Sstevel@tonic-gate 		(void) printf("<<NFS %s: %s>>\n",
2817c478bd9Sstevel@tonic-gate 		    added ? "mounted" : "unmounted", name);
2827c478bd9Sstevel@tonic-gate 		break;
2837c478bd9Sstevel@tonic-gate 	case IODEV_TAPE:
2847c478bd9Sstevel@tonic-gate 		(void) printf("<<device %s: %s>>\n",
2857c478bd9Sstevel@tonic-gate 		    added ? "added" : "removed", name);
2867c478bd9Sstevel@tonic-gate 		break;
2877c478bd9Sstevel@tonic-gate 	case IODEV_CONTROLLER:
2887c478bd9Sstevel@tonic-gate 	case IODEV_DISK:
2897c478bd9Sstevel@tonic-gate 		*tmp = '\0';
2907c478bd9Sstevel@tonic-gate 		get_child_list(iodev, tmp);
2917c478bd9Sstevel@tonic-gate 		(void) printf("<<%s %s: %s", is_disk ? "disk" : "controller",
2927c478bd9Sstevel@tonic-gate 		    added ? "added" : "removed", name);
2937c478bd9Sstevel@tonic-gate 		if (!*tmp) {
2947c478bd9Sstevel@tonic-gate 			(void) printf(">>\n");
2957c478bd9Sstevel@tonic-gate 			return;
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 		(void) printf(" (%s %s)>>\n", is_disk ? "slices" : "disks",
2987c478bd9Sstevel@tonic-gate 		    tmp);
2997c478bd9Sstevel@tonic-gate 		break;
3007c478bd9Sstevel@tonic-gate 	};
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate static void
iodev_report(struct iodev_snapshot * d1,struct iodev_snapshot * d2)3047c478bd9Sstevel@tonic-gate iodev_report(struct iodev_snapshot *d1, struct iodev_snapshot *d2)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate 	while (d1 && d2) {
3077c478bd9Sstevel@tonic-gate 		if (iodev_cmp(d1, d2) < 0) {
3087c478bd9Sstevel@tonic-gate 			iodev_changed(d1, 0);
3097c478bd9Sstevel@tonic-gate 			d1 = d1->is_next;
3107c478bd9Sstevel@tonic-gate 		} else if (iodev_cmp(d1, d2) > 0) {
3117c478bd9Sstevel@tonic-gate 			iodev_changed(d2, 1);
3127c478bd9Sstevel@tonic-gate 			d2 = d2->is_next;
3137c478bd9Sstevel@tonic-gate 		} else {
3147c478bd9Sstevel@tonic-gate 			iodev_report(d1->is_children, d2->is_children);
3157c478bd9Sstevel@tonic-gate 			d1 = d1->is_next;
3167c478bd9Sstevel@tonic-gate 			d2 = d2->is_next;
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	while (d1) {
3217c478bd9Sstevel@tonic-gate 		iodev_changed(d1, 0);
3227c478bd9Sstevel@tonic-gate 		d1 = d1->is_next;
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	while (d2) {
3267c478bd9Sstevel@tonic-gate 		iodev_changed(d2, 1);
3277c478bd9Sstevel@tonic-gate 		d2 = d2->is_next;
3287c478bd9Sstevel@tonic-gate 	}
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate void
snapshot_report_changes(struct snapshot * old,struct snapshot * new)3327c478bd9Sstevel@tonic-gate snapshot_report_changes(struct snapshot *old, struct snapshot *new)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate 	int pset;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	if (old == NULL || new == NULL)
3377c478bd9Sstevel@tonic-gate 		return;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	if (old->s_types != new->s_types)
3407c478bd9Sstevel@tonic-gate 		return;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	pset = old->s_types & SNAP_PSETS;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	cpus_removed[0] = '\0';
3457c478bd9Sstevel@tonic-gate 	cpus_added[0] = '\0';
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	if (old->s_types & SNAP_CPUS)
3487c478bd9Sstevel@tonic-gate 		(void) snapshot_walk(SNAP_CPUS, old, new, cpu_report, &pset);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	if (cpus_added[0]) {
3517c478bd9Sstevel@tonic-gate 		(void) printf("<<processors added: %s>>\n",
3527c478bd9Sstevel@tonic-gate 		    cpus_added);
3537c478bd9Sstevel@tonic-gate 	}
3547c478bd9Sstevel@tonic-gate 	if (cpus_removed[0]) {
3557c478bd9Sstevel@tonic-gate 		(void) printf("<<processors removed: %s>>\n",
3567c478bd9Sstevel@tonic-gate 		    cpus_removed);
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate 	if (pset) {
3597c478bd9Sstevel@tonic-gate 		(void) snapshot_walk(SNAP_PSETS, old, new,
3607c478bd9Sstevel@tonic-gate 		    pset_report, NULL);
3617c478bd9Sstevel@tonic-gate 	}
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	iodev_report(old->s_iodevs, new->s_iodevs);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3677c478bd9Sstevel@tonic-gate static void
dummy_cb(void * v1,void * v2,void * data)3687c478bd9Sstevel@tonic-gate dummy_cb(void *v1, void *v2, void *data)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate int
snapshot_has_changed(struct snapshot * old,struct snapshot * new)3737c478bd9Sstevel@tonic-gate snapshot_has_changed(struct snapshot *old, struct snapshot *new)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	int ret = 0;
3767c478bd9Sstevel@tonic-gate 	int cpu_mask = SNAP_CPUS | SNAP_PSETS | SNAP_SYSTEM;
377*37fbbce5Scth 	int iodev_mask = SNAP_CONTROLLERS | SNAP_IODEVS |
378*37fbbce5Scth 			SNAP_IOPATHS_LI | SNAP_IOPATHS_LTI;
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	if (old == NULL)
3817c478bd9Sstevel@tonic-gate 		return (1);
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	if (new == NULL)
3847c478bd9Sstevel@tonic-gate 		return (EINVAL);
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	if (old->s_types != new->s_types)
3877c478bd9Sstevel@tonic-gate 		return (EINVAL);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	if (!ret && (old->s_types & cpu_mask))
3907c478bd9Sstevel@tonic-gate 		ret = snapshot_walk(SNAP_CPUS, old, new, dummy_cb, NULL);
3917c478bd9Sstevel@tonic-gate 	if (!ret && (old->s_types & SNAP_PSETS))
3927c478bd9Sstevel@tonic-gate 		ret = snapshot_walk(SNAP_PSETS, old, new, dummy_cb, NULL);
3937c478bd9Sstevel@tonic-gate 	if (!ret && (old->s_types & iodev_mask))
3947c478bd9Sstevel@tonic-gate 		ret = snapshot_walk(SNAP_IODEVS, old, new, dummy_cb, NULL);
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	return (ret);
3977c478bd9Sstevel@tonic-gate }
398