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 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 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 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 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 * 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 * 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 * 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 * 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 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 3547c478bd9Sstevel@tonic-gate /* 3557aec1d6eScindi * ipath2strlen -- calculate the len of what ipath2str() would return 3567aec1d6eScindi */ 3577aec1d6eScindi size_t 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 3837aec1d6eScindi /* 3847c478bd9Sstevel@tonic-gate * ipath_print -- print out an ename, ipath, or both with '@' between them 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate void 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 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 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