2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1988, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * Use a hash for the kstat records we have read in. This is done 2N/A * to reduce the number of records that have to be looked up when 2N/A * dealing with a large configuration system. Note this hash is 2N/A * internal to libkstat only. The pointer to the hash is associated 2N/A * with the kstat_ctl_t data structure. When the kstat_ctl_t is free, the 2N/A * To force a good hashing of device paths, we need 2N/A * to scatter the hash around based on the character 2N/A * placement in the string. 2N/A * If the character is not an integer value, we simply 2N/A * multiply it by the position value in the string. 2N/A * If the character is an integer, then we use 1 of 2N/A * 4 different calculations based on the position 2N/A * the string. If we do not do this, then things like 2N/A * 1 and 2 can end up having the same hash position. 2N/A * Simple usage of a long or short value is no good 2N/A * because the length of names can get quite long. 2N/A * Extra chars in the string that we need to allow for 2N/A * spaces, underscores and others. 2N/A * Need to build a temporary string to use. 2N/A * If the entry was allocated free it up we do not care 2N/A /* Entry matches, return. */ 2N/A * We did not find the entry in the hash table. Check the kstat_t list 2N/A * and see if it is there. If it is add the entry to the hash. 2N/A * If hash_index < 0 then there is not enough information in the ksp to 2N/A * be able to figure out what to remove. 2N/A /* Walk the hash chain for the ksp. */ 2N/A /* If we found an entry, then remove it. */ 2N/A /* Free the kc_private data if present. */ 2N/A continue;
/* and try again */ 2N/A * Mating dance for variable-size kstats. 2N/A * You start with a buffer of a certain size, 2N/A * which you hope will hold all the data. 2N/A * If your buffer is too small, the kstat driver 2N/A * returns ENOMEM and sets ksp->ks_data_size to 2N/A * the current size of the kstat's data. You then 2N/A * resize your buffer and try again. In practice, 2N/A * this almost always converges in two passes. 2N/A * Has KSTAT_DATA_STRING fields. Fix the pointers. 2N/A * The offsets of the strings within the 2N/A * buffers are the same, so add the offset of 2N/A * the string to the beginning of 'data' to fix 2N/A * the pointer so that strings in 'data' don't 2N/A * point at memory in 'ksp->ks_data'. 2N/A * The buffer passed in as 'data' has string 2N/A * pointers that point within 'data'. Fix the 2N/A * pointers so they point into the same offset 2N/A * within the newly allocated buffer. 2N/A continue;
/* and try again */ 2N/A * If the current KCID is the same as kc->kc_chain_id, return 0; 2N/A * if different, update the chain and return the new KCID. 2N/A * This operation is non-destructive for unchanged kstats. 2N/A * kstat 0's data is the kstat chain, so we can get the chain 2N/A * by doing a kstat_read() of this kstat. The only fields the 2N/A * kstat driver needs are ks_kid (this identifies the kstat), 2N/A * ks_data (the pointer to our buffer), and ks_data_size (the 2N/A * size of our buffer). By zeroing the struct we set ks_data = NULL 2N/A * and ks_data_size = 0, so that kstat_read() will automatically 2N/A * determine the size and allocate space for us. We also fill in the 2N/A * name, so that truss can print something meaningful. 2N/A /* errno set by kstat_read() */ 2N/A * Chain the new headers together 2N/A * Remove all deleted kstats from the chain. 2N/A * Add all new kstats to the chain. 2N/A /* Attempt to add the entry to the hash. */