xref: /onnv-gate/usr/src/cmd/fm/modules/common/eversholt/ipath.c (revision 11416:c13e2db06244)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54436Sstephh  * Common Development and Distribution License (the "License").
64436Sstephh  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11416SStephen.Hanson@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * ipath.c -- instanced pathname module
260Sstevel@tonic-gate  *
270Sstevel@tonic-gate  * this module provides a cache of fully instantized component paths,
280Sstevel@tonic-gate  * stored in a fairly compact format.
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include "alloc.h"
340Sstevel@tonic-gate #include "out.h"
350Sstevel@tonic-gate #include "lut.h"
360Sstevel@tonic-gate #include "tree.h"
370Sstevel@tonic-gate #include "ptree.h"
380Sstevel@tonic-gate #include "itree.h"
390Sstevel@tonic-gate #include "ipath.h"
405433Saf #include "ipath_impl.h"
410Sstevel@tonic-gate #include "stats.h"
420Sstevel@tonic-gate #include "eval.h"
430Sstevel@tonic-gate #include "config.h"
440Sstevel@tonic-gate 
450Sstevel@tonic-gate static struct stats *Nipath;
460Sstevel@tonic-gate static struct stats *Nbytes;
470Sstevel@tonic-gate 
480Sstevel@tonic-gate static struct lut *Ipaths;	/* the ipath cache itself */
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * ipath_init -- initialize the ipath module
520Sstevel@tonic-gate  */
530Sstevel@tonic-gate void
ipath_init(void)540Sstevel@tonic-gate ipath_init(void)
550Sstevel@tonic-gate {
560Sstevel@tonic-gate 	Nipath = stats_new_counter("ievent.nipath", "ipath cache entries", 1);
570Sstevel@tonic-gate 	Nbytes = stats_new_counter("ievent.nbytes", "total cache size", 1);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate 
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate  * ipath_cmp -- compare two ipath entries
620Sstevel@tonic-gate  *
630Sstevel@tonic-gate  * since two ipaths containing the same components and instance
640Sstevel@tonic-gate  * numbers always point to the same cache entry, they are equal
650Sstevel@tonic-gate  * if their pointers are equal, so this function is not necessary
660Sstevel@tonic-gate  * to test if two ipaths are same.  but when inserting a new ipath
670Sstevel@tonic-gate  * into the cache, we must use the same lut comparison logic as when
680Sstevel@tonic-gate  * we're searching for it, so this function must always match the
690Sstevel@tonic-gate  * itree_epnamecmp() function's logic (see below) for searching the lut.
700Sstevel@tonic-gate  */
710Sstevel@tonic-gate static int
ipath_cmp(struct ipath * ipp1,struct ipath * ipp2)720Sstevel@tonic-gate ipath_cmp(struct ipath *ipp1, struct ipath *ipp2)
730Sstevel@tonic-gate {
740Sstevel@tonic-gate 	int i;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	ASSERT(ipp1 != NULL);
770Sstevel@tonic-gate 	ASSERT(ipp2 != NULL);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	for (i = 0; ipp1[i].s != NULL && ipp2[i].s != NULL; i++)
800Sstevel@tonic-gate 		if (ipp1[i].s != ipp2[i].s)
810Sstevel@tonic-gate 			return (ipp2[i].s - ipp1[i].s);
820Sstevel@tonic-gate 		else if (ipp1[i].i != ipp2[i].i)
830Sstevel@tonic-gate 			return (ipp2[i].i - ipp1[i].i);
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	if (ipp1[i].s == NULL && ipp2[i].s == NULL)
860Sstevel@tonic-gate 		return (0);
870Sstevel@tonic-gate 	else if (ipp1[i].s == NULL)
880Sstevel@tonic-gate 		return (1);
890Sstevel@tonic-gate 	else
900Sstevel@tonic-gate 		return (-1);
910Sstevel@tonic-gate }
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate  * ipath_epnamecmp -- compare an ipath with a struct node *epname list
950Sstevel@tonic-gate  *
960Sstevel@tonic-gate  * this function is used when searching the cache, allowing us to search
970Sstevel@tonic-gate  * a lut full of ipaths by looking directly at a struct node *epname
980Sstevel@tonic-gate  * (without having to convert it first).  the comparison logic here must
990Sstevel@tonic-gate  * exactly match itree_cmp()'s logic (see above) so lut lookups use find
1000Sstevel@tonic-gate  * the same node as lut inserts.
1010Sstevel@tonic-gate  */
1020Sstevel@tonic-gate static int
ipath_epnamecmp(struct ipath * ipp,struct node * np)1030Sstevel@tonic-gate ipath_epnamecmp(struct ipath *ipp, struct node *np)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate 	int i;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	ASSERT(np != NULL);
1080Sstevel@tonic-gate 	ASSERT(ipp != NULL);
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	for (i = 0; ipp[i].s != NULL && np != NULL; i++, np = np->u.name.next) {
1110Sstevel@tonic-gate 		ASSERTinfo(np->t == T_NAME, ptree_nodetype2str(np->t));
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 		if (ipp[i].s != np->u.name.s)
1140Sstevel@tonic-gate 			return (np->u.name.s - ipp[i].s);
1150Sstevel@tonic-gate 		else {
1160Sstevel@tonic-gate 			int inum;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 			if (np->u.name.child != NULL &&
1190Sstevel@tonic-gate 			    np->u.name.child->t == T_NUM)
1200Sstevel@tonic-gate 				inum = (int)np->u.name.child->u.ull;
1210Sstevel@tonic-gate 			else
1220Sstevel@tonic-gate 				config_getcompname(np->u.name.cp, NULL, &inum);
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 			if (ipp[i].i != inum)
1250Sstevel@tonic-gate 				return (inum - ipp[i].i);
1260Sstevel@tonic-gate 		}
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	if (ipp[i].s == NULL && np == NULL)
1300Sstevel@tonic-gate 		return (0);
1310Sstevel@tonic-gate 	else if (ipp[i].s == NULL)
1320Sstevel@tonic-gate 		return (1);
1330Sstevel@tonic-gate 	else
1340Sstevel@tonic-gate 		return (-1);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate 
1379874SStephen.Hanson@Sun.COM /*
1389874SStephen.Hanson@Sun.COM  * The following functions are only used in the "itree_create_dummy()" first
1399874SStephen.Hanson@Sun.COM  * pass at itree creation. ipath_dummy() creates paths used in the itree (see
1409874SStephen.Hanson@Sun.COM  * comment above add_event_dummy() for details). ipath_for_usednames() creates
1419874SStephen.Hanson@Sun.COM  * a different set of paths using the full names from the propagations. These
1429874SStephen.Hanson@Sun.COM  * are only used by ipath_dummy_lut() in order to set up the Usednames lut
1439874SStephen.Hanson@Sun.COM  * correctly, which in turn allows conf propteries on any alement in those
1449874SStephen.Hanson@Sun.COM  * names to be used in constraints.
1459874SStephen.Hanson@Sun.COM  */
1464436Sstephh struct lut *Usednames;
1474436Sstephh 
1484436Sstephh void
ipath_dummy_lut(struct arrow * arrowp)1494436Sstephh ipath_dummy_lut(struct arrow *arrowp)
1504436Sstephh {
1514436Sstephh 	const struct ipath *ipp;
1524436Sstephh 
1539874SStephen.Hanson@Sun.COM 	ipp = arrowp->head->myevent->ipp_un;
1544436Sstephh 	while (ipp->s != NULL) {
1554436Sstephh 		Usednames = lut_add(Usednames, (void *)ipp->s,
1564436Sstephh 		    (void *)ipp->s, NULL);
1574436Sstephh 		ipp++;
1584436Sstephh 	}
1599874SStephen.Hanson@Sun.COM 	ipp = arrowp->tail->myevent->ipp_un;
1604436Sstephh 	while (ipp->s != NULL) {
1614436Sstephh 		Usednames = lut_add(Usednames, (void *)ipp->s,
1624436Sstephh 		    (void *)ipp->s, NULL);
1634436Sstephh 		ipp++;
1644436Sstephh 	}
1654436Sstephh }
1664436Sstephh 
1674436Sstephh struct ipath *
ipath_dummy(struct node * np,struct ipath * ipp)1684436Sstephh ipath_dummy(struct node *np, struct ipath *ipp)
1694436Sstephh {
1704436Sstephh 	struct ipath *ret;
1714436Sstephh 
1724436Sstephh 	ret = ipp;
1734436Sstephh 	while (ipp[1].s != NULL)
1744436Sstephh 		ipp++;
1754436Sstephh 	if (strcmp(ipp[0].s, np->u.name.last->u.name.s) == 0)
1764436Sstephh 		return (ret);
1774436Sstephh 
1784436Sstephh 	ret = MALLOC(sizeof (*ret) * 2);
1794436Sstephh 	ret[0].s = np->u.name.last->u.name.s;
1804436Sstephh 	ret[0].i = 0;
1814436Sstephh 	ret[1].s = NULL;
1824436Sstephh 	if ((ipp = lut_lookup(Ipaths, (void *)ret,
1834436Sstephh 	    (lut_cmp)ipath_cmp)) != NULL) {
1844436Sstephh 		FREE(ret);
1854436Sstephh 		return (ipp);
1864436Sstephh 	}
1874436Sstephh 	Ipaths = lut_add(Ipaths, (void *)ret, (void *)ret, (lut_cmp)ipath_cmp);
1884436Sstephh 	stats_counter_bump(Nipath);
1894436Sstephh 	stats_counter_add(Nbytes, 2 * sizeof (struct ipath));
1904436Sstephh 	return (ret);
1914436Sstephh }
1924436Sstephh 
1939874SStephen.Hanson@Sun.COM struct ipath *
ipath_for_usednames(struct node * np)1949874SStephen.Hanson@Sun.COM ipath_for_usednames(struct node *np)
1959874SStephen.Hanson@Sun.COM {
1969874SStephen.Hanson@Sun.COM 	struct ipath *ret, *ipp;
1979874SStephen.Hanson@Sun.COM 	int i = 0;
1989874SStephen.Hanson@Sun.COM 	struct node *np2;
1999874SStephen.Hanson@Sun.COM 
2009874SStephen.Hanson@Sun.COM 	for (np2 = np; np2 != NULL; np2 = np2->u.name.next)
2019874SStephen.Hanson@Sun.COM 		i++;
2029874SStephen.Hanson@Sun.COM 	ret = MALLOC(sizeof (*ret) * (i + 1));
2039874SStephen.Hanson@Sun.COM 	for (i = 0, np2 = np; np2 != NULL; np2 = np2->u.name.next) {
2049874SStephen.Hanson@Sun.COM 		ret[i].s = np2->u.name.s;
2059874SStephen.Hanson@Sun.COM 		ret[i++].i = 0;
2069874SStephen.Hanson@Sun.COM 	}
2079874SStephen.Hanson@Sun.COM 	ret[i].s = NULL;
2089874SStephen.Hanson@Sun.COM 	if ((ipp = lut_lookup(Ipaths, (void *)ret,
2099874SStephen.Hanson@Sun.COM 	    (lut_cmp)ipath_cmp)) != NULL) {
2109874SStephen.Hanson@Sun.COM 		FREE(ret);
2119874SStephen.Hanson@Sun.COM 		return (ipp);
2129874SStephen.Hanson@Sun.COM 	}
2139874SStephen.Hanson@Sun.COM 	Ipaths = lut_add(Ipaths, (void *)ret, (void *)ret, (lut_cmp)ipath_cmp);
2149874SStephen.Hanson@Sun.COM 	stats_counter_bump(Nipath);
2159874SStephen.Hanson@Sun.COM 	stats_counter_add(Nbytes, (i + 1) * sizeof (struct ipath));
2169874SStephen.Hanson@Sun.COM 	return (ret);
2179874SStephen.Hanson@Sun.COM }
2189874SStephen.Hanson@Sun.COM 
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate  * ipath -- find instanced path in cache, or add it if necessary
2210Sstevel@tonic-gate  */
2220Sstevel@tonic-gate const struct ipath *
ipath(struct node * np)2230Sstevel@tonic-gate ipath(struct node *np)
2240Sstevel@tonic-gate {
2250Sstevel@tonic-gate 	struct ipath *ret;
2260Sstevel@tonic-gate 	int count;
2270Sstevel@tonic-gate 	struct node *namep;
2280Sstevel@tonic-gate 	int i;
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	if ((ret = lut_lookup(Ipaths, (void *)np,
2310Sstevel@tonic-gate 	    (lut_cmp)ipath_epnamecmp)) != NULL)
2320Sstevel@tonic-gate 		return (ret);	/* already in cache */
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	/*
2350Sstevel@tonic-gate 	 * not in cache, make new cache entry.
2360Sstevel@tonic-gate 	 * start by counting the length of the name.
2370Sstevel@tonic-gate 	 */
2380Sstevel@tonic-gate 	count = 0;
2390Sstevel@tonic-gate 	namep = np;
2400Sstevel@tonic-gate 	while (namep != NULL) {
2410Sstevel@tonic-gate 		ASSERTinfo(namep->t == T_NAME, ptree_nodetype2str(namep->t));
2420Sstevel@tonic-gate 		count++;
2430Sstevel@tonic-gate 		namep = namep->u.name.next;
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	ASSERT(count > 0);
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	/* allocate array for name and last NULL entry */
2490Sstevel@tonic-gate 	ret = MALLOC(sizeof (*ret) * (count + 1));
2500Sstevel@tonic-gate 	ret[count].s = NULL;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	/* fill in ipath entry */
2530Sstevel@tonic-gate 	namep = np;
2540Sstevel@tonic-gate 	i = 0;
2550Sstevel@tonic-gate 	while (namep != NULL) {
2560Sstevel@tonic-gate 		ASSERT(i < count);
2570Sstevel@tonic-gate 		ret[i].s = namep->u.name.s;
2580Sstevel@tonic-gate 		if (namep->u.name.child != NULL &&
2590Sstevel@tonic-gate 		    namep->u.name.child->t == T_NUM)
2600Sstevel@tonic-gate 			ret[i].i = (int)namep->u.name.child->u.ull;
2610Sstevel@tonic-gate 		else
2620Sstevel@tonic-gate 			config_getcompname(namep->u.name.cp, NULL, &ret[i].i);
2630Sstevel@tonic-gate 		i++;
2640Sstevel@tonic-gate 		namep = namep->u.name.next;
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	/* add it to the cache */
2680Sstevel@tonic-gate 	Ipaths = lut_add(Ipaths, (void *)ret, (void *)ret,
2690Sstevel@tonic-gate 	    (lut_cmp)ipath_cmp);
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	stats_counter_bump(Nipath);
2720Sstevel@tonic-gate 	stats_counter_add(Nbytes, (count + 1) * sizeof (struct ipath));
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	return (ret);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate /*
2780Sstevel@tonic-gate  * ipath2str -- convert ename and ipath to class@path string
2790Sstevel@tonic-gate  *
2800Sstevel@tonic-gate  * if both ename and ipp are provided (non-NULL), the resulting string
2810Sstevel@tonic-gate  * will be "class@path".  otherwise, the string will just contain the
2820Sstevel@tonic-gate  * event class name (e.g. "ereport.io.pci.device") or just the path
2830Sstevel@tonic-gate  * name (e.g. "mothboard0/hostbridge0/pcibus1/pcidev0/pcifn1"), depending
2840Sstevel@tonic-gate  * on which argument is non-NULL.
2850Sstevel@tonic-gate  */
2860Sstevel@tonic-gate char *
ipath2str(const char * ename,const struct ipath * ipp)2870Sstevel@tonic-gate ipath2str(const char *ename, const struct ipath *ipp)
2880Sstevel@tonic-gate {
2890Sstevel@tonic-gate 	int i;
2900Sstevel@tonic-gate 	size_t len = 0;
2910Sstevel@tonic-gate 	char *ret;
2920Sstevel@tonic-gate 	char *cp;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	/* count up length of class string */
2950Sstevel@tonic-gate 	if (ename != NULL)
2960Sstevel@tonic-gate 		len += strlen(ename);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	/* count up length of path string, including slash separators */
2990Sstevel@tonic-gate 	if (ipp != NULL) {
3000Sstevel@tonic-gate 		for (i = 0; ipp[i].s != NULL; i++) {
3010Sstevel@tonic-gate 			/* add slash separator, but no leading slash */
3020Sstevel@tonic-gate 			if (i != 0)
3030Sstevel@tonic-gate 				len++;
3040Sstevel@tonic-gate 			len += snprintf(NULL, 0, "%s%d", ipp[i].s, ipp[i].i);
3050Sstevel@tonic-gate 		}
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (ename != NULL && ipp != NULL)
3090Sstevel@tonic-gate 		len++;	/* room for '@' */
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	len++;	/* room for final '\0' */
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	cp = ret = MALLOC(len);
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	if (ename != NULL) {
3160Sstevel@tonic-gate 		/* construct class string */
3170Sstevel@tonic-gate 		(void) strcpy(cp, ename);
3180Sstevel@tonic-gate 		cp += strlen(cp);
3190Sstevel@tonic-gate 	}
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 	/* if doing both strings, put '@' between them */
3220Sstevel@tonic-gate 	if (ename != NULL && ipp != NULL)
3230Sstevel@tonic-gate 		*cp++ = '@';
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	if (ipp != NULL) {
3260Sstevel@tonic-gate 		/* construct path string */
3270Sstevel@tonic-gate 		for (i = 0; ipp[i].s != NULL; i++) {
3280Sstevel@tonic-gate 			if (i != 0)
3290Sstevel@tonic-gate 				*cp++ = '/';
3300Sstevel@tonic-gate 			(void) snprintf(cp, &ret[len] - cp, "%s%d",
3310Sstevel@tonic-gate 			    ipp[i].s, ipp[i].i);
3320Sstevel@tonic-gate 			cp += strlen(cp);
3330Sstevel@tonic-gate 		}
3340Sstevel@tonic-gate 	}
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	*cp++ = '\0';
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	return (ret);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate 
341*11416SStephen.Hanson@Sun.COM void
ipathlastcomp(const struct ipath * ipp)342*11416SStephen.Hanson@Sun.COM ipathlastcomp(const struct ipath *ipp)
343*11416SStephen.Hanson@Sun.COM {
344*11416SStephen.Hanson@Sun.COM 	int i;
345*11416SStephen.Hanson@Sun.COM 
346*11416SStephen.Hanson@Sun.COM 	for (i = 0; ipp[i].s != NULL; i++)
347*11416SStephen.Hanson@Sun.COM 		;
348*11416SStephen.Hanson@Sun.COM 
349*11416SStephen.Hanson@Sun.COM 	out(O_ALTFP, "newfme: add %s to Usednames", ipp[i - 1].s);
350*11416SStephen.Hanson@Sun.COM 	Usednames = lut_add(Usednames, (void *)ipp[i - 1].s,
351*11416SStephen.Hanson@Sun.COM 	    (void *)ipp[i - 1].s, NULL);
352*11416SStephen.Hanson@Sun.COM }
353*11416SStephen.Hanson@Sun.COM 
3540Sstevel@tonic-gate /*
3551414Scindi  * ipath2strlen -- calculate the len of what ipath2str() would return
3561414Scindi  */
3571414Scindi size_t
ipath2strlen(const char * ename,const struct ipath * ipp)3581414Scindi ipath2strlen(const char *ename, const struct ipath *ipp)
3591414Scindi {
3601414Scindi 	int i;
3611414Scindi 	size_t len = 0;
3621414Scindi 
3631414Scindi 	/* count up length of class string */
3641414Scindi 	if (ename != NULL)
3651414Scindi 		len += strlen(ename);
3661414Scindi 
3671414Scindi 	/* count up length of path string, including slash separators */
3681414Scindi 	if (ipp != NULL) {
3691414Scindi 		for (i = 0; ipp[i].s != NULL; i++) {
3701414Scindi 			/* add slash separator, but no leading slash */
3711414Scindi 			if (i != 0)
3721414Scindi 				len++;
3731414Scindi 			len += snprintf(NULL, 0, "%s%d", ipp[i].s, ipp[i].i);
3741414Scindi 		}
3751414Scindi 	}
3761414Scindi 
3771414Scindi 	if (ename != NULL && ipp != NULL)
3781414Scindi 		len++;	/* room for '@' */
3791414Scindi 
3801414Scindi 	return (len);
3811414Scindi }
3821414Scindi 
3831414Scindi /*
3840Sstevel@tonic-gate  * ipath_print -- print out an ename, ipath, or both with '@' between them
3850Sstevel@tonic-gate  */
3860Sstevel@tonic-gate void
ipath_print(int flags,const char * ename,const struct ipath * ipp)3870Sstevel@tonic-gate ipath_print(int flags, const char *ename, const struct ipath *ipp)
3880Sstevel@tonic-gate {
3890Sstevel@tonic-gate 	if (ename != NULL) {
3900Sstevel@tonic-gate 		out(flags|O_NONL, ename);
3910Sstevel@tonic-gate 		if (ipp != NULL)
3920Sstevel@tonic-gate 			out(flags|O_NONL, "@");
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate 	if (ipp != NULL) {
3950Sstevel@tonic-gate 		char *sep = "";
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 		while (ipp->s != NULL) {
3980Sstevel@tonic-gate 			out(flags|O_NONL, "%s%s%d", sep, ipp->s, ipp->i);
3990Sstevel@tonic-gate 			ipp++;
4000Sstevel@tonic-gate 			sep = "/";
4010Sstevel@tonic-gate 		}
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate /*ARGSUSED*/
4060Sstevel@tonic-gate static void
ipath_destructor(void * left,void * right,void * arg)4070Sstevel@tonic-gate ipath_destructor(void *left, void *right, void *arg)
4080Sstevel@tonic-gate {
4090Sstevel@tonic-gate 	struct ipath *ipp = (struct ipath *)right;
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	FREE(ipp);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate /*
4150Sstevel@tonic-gate  * ipath_fini -- free the ipath cache
4160Sstevel@tonic-gate  */
4170Sstevel@tonic-gate void
ipath_fini(void)4180Sstevel@tonic-gate ipath_fini(void)
4190Sstevel@tonic-gate {
4200Sstevel@tonic-gate 	lut_free(Ipaths, ipath_destructor, NULL);
4210Sstevel@tonic-gate 	Ipaths = NULL;
4225947Sstephh 	lut_free(Usednames, NULL, NULL);
4235947Sstephh 	Usednames = NULL;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	if (Nipath) {
4260Sstevel@tonic-gate 		stats_delete(Nipath);
4270Sstevel@tonic-gate 		Nipath = NULL;
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	if (Nbytes) {
4310Sstevel@tonic-gate 		stats_delete(Nbytes);
4320Sstevel@tonic-gate 		Nbytes = NULL;
4330Sstevel@tonic-gate 	}
4340Sstevel@tonic-gate }
435