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
5b5016cbbSstephh * Common Development and Distribution License (the "License").
6b5016cbbSstephh * 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*705e9f42SStephen Hanson * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate *
257c478bd9Sstevel@tonic-gate * ipath.c -- instanced pathname module
267c478bd9Sstevel@tonic-gate *
277c478bd9Sstevel@tonic-gate * this module provides a cache of fully instantized component paths,
287c478bd9Sstevel@tonic-gate * stored in a fairly compact format.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include "alloc.h"
347c478bd9Sstevel@tonic-gate #include "out.h"
357c478bd9Sstevel@tonic-gate #include "lut.h"
367c478bd9Sstevel@tonic-gate #include "tree.h"
377c478bd9Sstevel@tonic-gate #include "ptree.h"
387c478bd9Sstevel@tonic-gate #include "itree.h"
397c478bd9Sstevel@tonic-gate #include "ipath.h"
406cb1ca52Saf #include "ipath_impl.h"
417c478bd9Sstevel@tonic-gate #include "stats.h"
427c478bd9Sstevel@tonic-gate #include "eval.h"
437c478bd9Sstevel@tonic-gate #include "config.h"
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate static struct stats *Nipath;
467c478bd9Sstevel@tonic-gate static struct stats *Nbytes;
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate static struct lut *Ipaths; /* the ipath cache itself */
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate * ipath_init -- initialize the ipath module
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate void
ipath_init(void)547c478bd9Sstevel@tonic-gate ipath_init(void)
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate Nipath = stats_new_counter("ievent.nipath", "ipath cache entries", 1);
577c478bd9Sstevel@tonic-gate Nbytes = stats_new_counter("ievent.nbytes", "total cache size", 1);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate * ipath_cmp -- compare two ipath entries
627c478bd9Sstevel@tonic-gate *
637c478bd9Sstevel@tonic-gate * since two ipaths containing the same components and instance
647c478bd9Sstevel@tonic-gate * numbers always point to the same cache entry, they are equal
657c478bd9Sstevel@tonic-gate * if their pointers are equal, so this function is not necessary
667c478bd9Sstevel@tonic-gate * to test if two ipaths are same. but when inserting a new ipath
677c478bd9Sstevel@tonic-gate * into the cache, we must use the same lut comparison logic as when
687c478bd9Sstevel@tonic-gate * we're searching for it, so this function must always match the
697c478bd9Sstevel@tonic-gate * itree_epnamecmp() function's logic (see below) for searching the lut.
707c478bd9Sstevel@tonic-gate */
717c478bd9Sstevel@tonic-gate static int
ipath_cmp(struct ipath * ipp1,struct ipath * ipp2)727c478bd9Sstevel@tonic-gate ipath_cmp(struct ipath *ipp1, struct ipath *ipp2)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate int i;
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate ASSERT(ipp1 != NULL);
777c478bd9Sstevel@tonic-gate ASSERT(ipp2 != NULL);
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate for (i = 0; ipp1[i].s != NULL && ipp2[i].s != NULL; i++)
807c478bd9Sstevel@tonic-gate if (ipp1[i].s != ipp2[i].s)
817c478bd9Sstevel@tonic-gate return (ipp2[i].s - ipp1[i].s);
827c478bd9Sstevel@tonic-gate else if (ipp1[i].i != ipp2[i].i)
837c478bd9Sstevel@tonic-gate return (ipp2[i].i - ipp1[i].i);
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate if (ipp1[i].s == NULL && ipp2[i].s == NULL)
867c478bd9Sstevel@tonic-gate return (0);
877c478bd9Sstevel@tonic-gate else if (ipp1[i].s == NULL)
887c478bd9Sstevel@tonic-gate return (1);
897c478bd9Sstevel@tonic-gate else
907c478bd9Sstevel@tonic-gate return (-1);
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate * ipath_epnamecmp -- compare an ipath with a struct node *epname list
957c478bd9Sstevel@tonic-gate *
967c478bd9Sstevel@tonic-gate * this function is used when searching the cache, allowing us to search
977c478bd9Sstevel@tonic-gate * a lut full of ipaths by looking directly at a struct node *epname
987c478bd9Sstevel@tonic-gate * (without having to convert it first). the comparison logic here must
997c478bd9Sstevel@tonic-gate * exactly match itree_cmp()'s logic (see above) so lut lookups use find
1007c478bd9Sstevel@tonic-gate * the same node as lut inserts.
1017c478bd9Sstevel@tonic-gate */
1027c478bd9Sstevel@tonic-gate static int
ipath_epnamecmp(struct ipath * ipp,struct node * np)1037c478bd9Sstevel@tonic-gate ipath_epnamecmp(struct ipath *ipp, struct node *np)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate int i;
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate ASSERT(np != NULL);
1087c478bd9Sstevel@tonic-gate ASSERT(ipp != NULL);
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate for (i = 0; ipp[i].s != NULL && np != NULL; i++, np = np->u.name.next) {
1117c478bd9Sstevel@tonic-gate ASSERTinfo(np->t == T_NAME, ptree_nodetype2str(np->t));
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate if (ipp[i].s != np->u.name.s)
1147c478bd9Sstevel@tonic-gate return (np->u.name.s - ipp[i].s);
1157c478bd9Sstevel@tonic-gate else {
1167c478bd9Sstevel@tonic-gate int inum;
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate if (np->u.name.child != NULL &&
1197c478bd9Sstevel@tonic-gate np->u.name.child->t == T_NUM)
1207c478bd9Sstevel@tonic-gate inum = (int)np->u.name.child->u.ull;
1217c478bd9Sstevel@tonic-gate else
1227c478bd9Sstevel@tonic-gate config_getcompname(np->u.name.cp, NULL, &inum);
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate if (ipp[i].i != inum)
1257c478bd9Sstevel@tonic-gate return (inum - ipp[i].i);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate if (ipp[i].s == NULL && np == NULL)
1307c478bd9Sstevel@tonic-gate return (0);
1317c478bd9Sstevel@tonic-gate else if (ipp[i].s == NULL)
1327c478bd9Sstevel@tonic-gate return (1);
1337c478bd9Sstevel@tonic-gate else
1347c478bd9Sstevel@tonic-gate return (-1);
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate
1376e1fa242SStephen Hanson /*
1386e1fa242SStephen Hanson * The following functions are only used in the "itree_create_dummy()" first
1396e1fa242SStephen Hanson * pass at itree creation. ipath_dummy() creates paths used in the itree (see
1406e1fa242SStephen Hanson * comment above add_event_dummy() for details). ipath_for_usednames() creates
1416e1fa242SStephen Hanson * a different set of paths using the full names from the propagations. These
1426e1fa242SStephen Hanson * are only used by ipath_dummy_lut() in order to set up the Usednames lut
1436e1fa242SStephen Hanson * correctly, which in turn allows conf propteries on any alement in those
1446e1fa242SStephen Hanson * names to be used in constraints.
1456e1fa242SStephen Hanson */
146b5016cbbSstephh struct lut *Usednames;
147b5016cbbSstephh
148b5016cbbSstephh void
ipath_dummy_lut(struct arrow * arrowp)149b5016cbbSstephh ipath_dummy_lut(struct arrow *arrowp)
150b5016cbbSstephh {
151b5016cbbSstephh const struct ipath *ipp;
152b5016cbbSstephh
1536e1fa242SStephen Hanson ipp = arrowp->head->myevent->ipp_un;
154b5016cbbSstephh while (ipp->s != NULL) {
155b5016cbbSstephh Usednames = lut_add(Usednames, (void *)ipp->s,
156b5016cbbSstephh (void *)ipp->s, NULL);
157b5016cbbSstephh ipp++;
158b5016cbbSstephh }
1596e1fa242SStephen Hanson ipp = arrowp->tail->myevent->ipp_un;
160b5016cbbSstephh while (ipp->s != NULL) {
161b5016cbbSstephh Usednames = lut_add(Usednames, (void *)ipp->s,
162b5016cbbSstephh (void *)ipp->s, NULL);
163b5016cbbSstephh ipp++;
164b5016cbbSstephh }
165b5016cbbSstephh }
166b5016cbbSstephh
167b5016cbbSstephh struct ipath *
ipath_dummy(struct node * np,struct ipath * ipp)168b5016cbbSstephh ipath_dummy(struct node *np, struct ipath *ipp)
169b5016cbbSstephh {
170b5016cbbSstephh struct ipath *ret;
171b5016cbbSstephh
172b5016cbbSstephh ret = ipp;
173b5016cbbSstephh while (ipp[1].s != NULL)
174b5016cbbSstephh ipp++;
175b5016cbbSstephh if (strcmp(ipp[0].s, np->u.name.last->u.name.s) == 0)
176b5016cbbSstephh return (ret);
177b5016cbbSstephh
178b5016cbbSstephh ret = MALLOC(sizeof (*ret) * 2);
179b5016cbbSstephh ret[0].s = np->u.name.last->u.name.s;
180b5016cbbSstephh ret[0].i = 0;
181b5016cbbSstephh ret[1].s = NULL;
182b5016cbbSstephh if ((ipp = lut_lookup(Ipaths, (void *)ret,
183b5016cbbSstephh (lut_cmp)ipath_cmp)) != NULL) {
184b5016cbbSstephh FREE(ret);
185b5016cbbSstephh return (ipp);
186b5016cbbSstephh }
187b5016cbbSstephh Ipaths = lut_add(Ipaths, (void *)ret, (void *)ret, (lut_cmp)ipath_cmp);
188b5016cbbSstephh stats_counter_bump(Nipath);
189b5016cbbSstephh stats_counter_add(Nbytes, 2 * sizeof (struct ipath));
190b5016cbbSstephh return (ret);
191b5016cbbSstephh }
192b5016cbbSstephh
1936e1fa242SStephen Hanson struct ipath *
ipath_for_usednames(struct node * np)1946e1fa242SStephen Hanson ipath_for_usednames(struct node *np)
1956e1fa242SStephen Hanson {
1966e1fa242SStephen Hanson struct ipath *ret, *ipp;
1976e1fa242SStephen Hanson int i = 0;
1986e1fa242SStephen Hanson struct node *np2;
1996e1fa242SStephen Hanson
2006e1fa242SStephen Hanson for (np2 = np; np2 != NULL; np2 = np2->u.name.next)
2016e1fa242SStephen Hanson i++;
2026e1fa242SStephen Hanson ret = MALLOC(sizeof (*ret) * (i + 1));
2036e1fa242SStephen Hanson for (i = 0, np2 = np; np2 != NULL; np2 = np2->u.name.next) {
2046e1fa242SStephen Hanson ret[i].s = np2->u.name.s;
2056e1fa242SStephen Hanson ret[i++].i = 0;
2066e1fa242SStephen Hanson }
2076e1fa242SStephen Hanson ret[i].s = NULL;
2086e1fa242SStephen Hanson if ((ipp = lut_lookup(Ipaths, (void *)ret,
2096e1fa242SStephen Hanson (lut_cmp)ipath_cmp)) != NULL) {
2106e1fa242SStephen Hanson FREE(ret);
2116e1fa242SStephen Hanson return (ipp);
2126e1fa242SStephen Hanson }
2136e1fa242SStephen Hanson Ipaths = lut_add(Ipaths, (void *)ret, (void *)ret, (lut_cmp)ipath_cmp);
2146e1fa242SStephen Hanson stats_counter_bump(Nipath);
2156e1fa242SStephen Hanson stats_counter_add(Nbytes, (i + 1) * sizeof (struct ipath));
2166e1fa242SStephen Hanson return (ret);
2176e1fa242SStephen Hanson }
2186e1fa242SStephen Hanson
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate * ipath -- find instanced path in cache, or add it if necessary
2217c478bd9Sstevel@tonic-gate */
2227c478bd9Sstevel@tonic-gate const struct ipath *
ipath(struct node * np)2237c478bd9Sstevel@tonic-gate ipath(struct node *np)
2247c478bd9Sstevel@tonic-gate {
2257c478bd9Sstevel@tonic-gate struct ipath *ret;
2267c478bd9Sstevel@tonic-gate int count;
2277c478bd9Sstevel@tonic-gate struct node *namep;
2287c478bd9Sstevel@tonic-gate int i;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate if ((ret = lut_lookup(Ipaths, (void *)np,
2317c478bd9Sstevel@tonic-gate (lut_cmp)ipath_epnamecmp)) != NULL)
2327c478bd9Sstevel@tonic-gate return (ret); /* already in cache */
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate * not in cache, make new cache entry.
2367c478bd9Sstevel@tonic-gate * start by counting the length of the name.
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate count = 0;
2397c478bd9Sstevel@tonic-gate namep = np;
2407c478bd9Sstevel@tonic-gate while (namep != NULL) {
2417c478bd9Sstevel@tonic-gate ASSERTinfo(namep->t == T_NAME, ptree_nodetype2str(namep->t));
2427c478bd9Sstevel@tonic-gate count++;
2437c478bd9Sstevel@tonic-gate namep = namep->u.name.next;
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate ASSERT(count > 0);
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate /* allocate array for name and last NULL entry */
2497c478bd9Sstevel@tonic-gate ret = MALLOC(sizeof (*ret) * (count + 1));
2507c478bd9Sstevel@tonic-gate ret[count].s = NULL;
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /* fill in ipath entry */
2537c478bd9Sstevel@tonic-gate namep = np;
2547c478bd9Sstevel@tonic-gate i = 0;
2557c478bd9Sstevel@tonic-gate while (namep != NULL) {
2567c478bd9Sstevel@tonic-gate ASSERT(i < count);
2577c478bd9Sstevel@tonic-gate ret[i].s = namep->u.name.s;
2587c478bd9Sstevel@tonic-gate if (namep->u.name.child != NULL &&
2597c478bd9Sstevel@tonic-gate namep->u.name.child->t == T_NUM)
2607c478bd9Sstevel@tonic-gate ret[i].i = (int)namep->u.name.child->u.ull;
2617c478bd9Sstevel@tonic-gate else
2627c478bd9Sstevel@tonic-gate config_getcompname(namep->u.name.cp, NULL, &ret[i].i);
2637c478bd9Sstevel@tonic-gate i++;
2647c478bd9Sstevel@tonic-gate namep = namep->u.name.next;
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /* add it to the cache */
2687c478bd9Sstevel@tonic-gate Ipaths = lut_add(Ipaths, (void *)ret, (void *)ret,
2697c478bd9Sstevel@tonic-gate (lut_cmp)ipath_cmp);
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate stats_counter_bump(Nipath);
2727c478bd9Sstevel@tonic-gate stats_counter_add(Nbytes, (count + 1) * sizeof (struct ipath));
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate return (ret);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate * ipath2str -- convert ename and ipath to class@path string
2797c478bd9Sstevel@tonic-gate *
2807c478bd9Sstevel@tonic-gate * if both ename and ipp are provided (non-NULL), the resulting string
2817c478bd9Sstevel@tonic-gate * will be "class@path". otherwise, the string will just contain the
2827c478bd9Sstevel@tonic-gate * event class name (e.g. "ereport.io.pci.device") or just the path
2837c478bd9Sstevel@tonic-gate * name (e.g. "mothboard0/hostbridge0/pcibus1/pcidev0/pcifn1"), depending
2847c478bd9Sstevel@tonic-gate * on which argument is non-NULL.
2857c478bd9Sstevel@tonic-gate */
2867c478bd9Sstevel@tonic-gate char *
ipath2str(const char * ename,const struct ipath * ipp)2877c478bd9Sstevel@tonic-gate ipath2str(const char *ename, const struct ipath *ipp)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate int i;
2907c478bd9Sstevel@tonic-gate size_t len = 0;
2917c478bd9Sstevel@tonic-gate char *ret;
2927c478bd9Sstevel@tonic-gate char *cp;
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /* count up length of class string */
2957c478bd9Sstevel@tonic-gate if (ename != NULL)
2967c478bd9Sstevel@tonic-gate len += strlen(ename);
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate /* count up length of path string, including slash separators */
2997c478bd9Sstevel@tonic-gate if (ipp != NULL) {
3007c478bd9Sstevel@tonic-gate for (i = 0; ipp[i].s != NULL; i++) {
3017c478bd9Sstevel@tonic-gate /* add slash separator, but no leading slash */
3027c478bd9Sstevel@tonic-gate if (i != 0)
3037c478bd9Sstevel@tonic-gate len++;
3047c478bd9Sstevel@tonic-gate len += snprintf(NULL, 0, "%s%d", ipp[i].s, ipp[i].i);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate if (ename != NULL && ipp != NULL)
3097c478bd9Sstevel@tonic-gate len++; /* room for '@' */
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate len++; /* room for final '\0' */
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate cp = ret = MALLOC(len);
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate if (ename != NULL) {
3167c478bd9Sstevel@tonic-gate /* construct class string */
3177c478bd9Sstevel@tonic-gate (void) strcpy(cp, ename);
3187c478bd9Sstevel@tonic-gate cp += strlen(cp);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /* if doing both strings, put '@' between them */
3227c478bd9Sstevel@tonic-gate if (ename != NULL && ipp != NULL)
3237c478bd9Sstevel@tonic-gate *cp++ = '@';
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate if (ipp != NULL) {
3267c478bd9Sstevel@tonic-gate /* construct path string */
3277c478bd9Sstevel@tonic-gate for (i = 0; ipp[i].s != NULL; i++) {
3287c478bd9Sstevel@tonic-gate if (i != 0)
3297c478bd9Sstevel@tonic-gate *cp++ = '/';
3307c478bd9Sstevel@tonic-gate (void) snprintf(cp, &ret[len] - cp, "%s%d",
3317c478bd9Sstevel@tonic-gate ipp[i].s, ipp[i].i);
3327c478bd9Sstevel@tonic-gate cp += strlen(cp);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate *cp++ = '\0';
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate return (ret);
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate
341*705e9f42SStephen Hanson void
ipathlastcomp(const struct ipath * ipp)342*705e9f42SStephen Hanson ipathlastcomp(const struct ipath *ipp)
343*705e9f42SStephen Hanson {
344*705e9f42SStephen Hanson int i;
345*705e9f42SStephen Hanson
346*705e9f42SStephen Hanson for (i = 0; ipp[i].s != NULL; i++)
347*705e9f42SStephen Hanson ;
348*705e9f42SStephen Hanson
349*705e9f42SStephen Hanson out(O_ALTFP, "newfme: add %s to Usednames", ipp[i - 1].s);
350*705e9f42SStephen Hanson Usednames = lut_add(Usednames, (void *)ipp[i - 1].s,
351*705e9f42SStephen Hanson (void *)ipp[i - 1].s, NULL);
352*705e9f42SStephen Hanson }
353*705e9f42SStephen Hanson
3547aec1d6eScindi /*
3557aec1d6eScindi * ipath2strlen -- calculate the len of what ipath2str() would return
3567aec1d6eScindi */
3577aec1d6eScindi size_t
ipath2strlen(const char * ename,const struct ipath * ipp)3587aec1d6eScindi ipath2strlen(const char *ename, const struct ipath *ipp)
3597aec1d6eScindi {
3607aec1d6eScindi int i;
3617aec1d6eScindi size_t len = 0;
3627aec1d6eScindi
3637aec1d6eScindi /* count up length of class string */
3647aec1d6eScindi if (ename != NULL)
3657aec1d6eScindi len += strlen(ename);
3667aec1d6eScindi
3677aec1d6eScindi /* count up length of path string, including slash separators */
3687aec1d6eScindi if (ipp != NULL) {
3697aec1d6eScindi for (i = 0; ipp[i].s != NULL; i++) {
3707aec1d6eScindi /* add slash separator, but no leading slash */
3717aec1d6eScindi if (i != 0)
3727aec1d6eScindi len++;
3737aec1d6eScindi len += snprintf(NULL, 0, "%s%d", ipp[i].s, ipp[i].i);
3747aec1d6eScindi }
3757aec1d6eScindi }
3767aec1d6eScindi
3777aec1d6eScindi if (ename != NULL && ipp != NULL)
3787aec1d6eScindi len++; /* room for '@' */
3797aec1d6eScindi
3807aec1d6eScindi return (len);
3817aec1d6eScindi }
3827aec1d6eScindi
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate * ipath_print -- print out an ename, ipath, or both with '@' between them
3857c478bd9Sstevel@tonic-gate */
3867c478bd9Sstevel@tonic-gate void
ipath_print(int flags,const char * ename,const struct ipath * ipp)3877c478bd9Sstevel@tonic-gate ipath_print(int flags, const char *ename, const struct ipath *ipp)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate if (ename != NULL) {
3907c478bd9Sstevel@tonic-gate out(flags|O_NONL, ename);
3917c478bd9Sstevel@tonic-gate if (ipp != NULL)
3927c478bd9Sstevel@tonic-gate out(flags|O_NONL, "@");
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate if (ipp != NULL) {
3957c478bd9Sstevel@tonic-gate char *sep = "";
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate while (ipp->s != NULL) {
3987c478bd9Sstevel@tonic-gate out(flags|O_NONL, "%s%s%d", sep, ipp->s, ipp->i);
3997c478bd9Sstevel@tonic-gate ipp++;
4007c478bd9Sstevel@tonic-gate sep = "/";
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4067c478bd9Sstevel@tonic-gate static void
ipath_destructor(void * left,void * right,void * arg)4077c478bd9Sstevel@tonic-gate ipath_destructor(void *left, void *right, void *arg)
4087c478bd9Sstevel@tonic-gate {
4097c478bd9Sstevel@tonic-gate struct ipath *ipp = (struct ipath *)right;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate FREE(ipp);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate * ipath_fini -- free the ipath cache
4167c478bd9Sstevel@tonic-gate */
4177c478bd9Sstevel@tonic-gate void
ipath_fini(void)4187c478bd9Sstevel@tonic-gate ipath_fini(void)
4197c478bd9Sstevel@tonic-gate {
4207c478bd9Sstevel@tonic-gate lut_free(Ipaths, ipath_destructor, NULL);
4217c478bd9Sstevel@tonic-gate Ipaths = NULL;
42227134bdaSstephh lut_free(Usednames, NULL, NULL);
42327134bdaSstephh Usednames = NULL;
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate if (Nipath) {
4267c478bd9Sstevel@tonic-gate stats_delete(Nipath);
4277c478bd9Sstevel@tonic-gate Nipath = NULL;
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate if (Nbytes) {
4317c478bd9Sstevel@tonic-gate stats_delete(Nbytes);
4327c478bd9Sstevel@tonic-gate Nbytes = NULL;
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate }
435