meta_statconcise.c revision d7cd82522afdd890a66c7600b499590ad44e84bd
1N/A * The contents of this file are subject to the terms of the 1N/A * Common Development and Distribution License (the "License"). 1N/A * You may not use this file except in compliance with the License. 1N/A * See the License for the specific language governing permissions 1N/A * and limitations under the License. 1N/A * When distributing Covered Code, include this CDDL HEADER in each 1N/A * If applicable, add the following below this CDDL HEADER, with the 1N/A * fields enclosed by brackets "[]" replaced with your own identifying 1N/A * information: Portions Copyright [yyyy] [name of copyright owner] 1N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 1N/A * Use is subject to license terms. 1N/A#
pragma ident "%Z%%M% %I% %E% SMI" * All of the code in this file supports the addition of metastat -c output * for the verbose option of metaimport. Some of this code is also used by * The code is designed to produce the same output as metastat -c does for a * given diskset--with a couple exceptions. * The primary differences between the output for the metastat -c command and * metastat output for metaimport -v are: * - the set name is not printed next to each metadevice * - top-level state information is not printed for some metadevices * - the percent that a disk has completed resyncing is not listed * The general layout of this file is as follows: * - report_metastat_info() * This is the primary entry point for the functions in this file, with * the exception of several functions that are also called from * report_metastat_info() calls functions to read in all the the * Directory blocks and Record blocks and then process the information * needed to print out the metadevice records in the same format as * Reads in all the Directory blocks in the diskset and verifies their * validity. For each Directly block, it loops through all Directory * Entries and for each one that contains a metadevice record calls * read_md_record(). Because the output is designed to imitate the * output of metastat -c, we ignore metadevice records for * optimized resync, changelog, and translog. * Reads in a Directory Entry and its associated Record block. The * revision information for the Record block is checked and it is * determined whether or not it is a 64bit Record block or a 32bit record * block. For each valid Record block, it allocates an md_im_rec_t * structure and calls extract_mduser_data(). * - extract_mduser_data() * Populates the md_im_rec_t data structure with information about the * record's associated metadevice. Also, the name of the metadevice is * either copied from the NM namespace(if it exists there) or is generated * from the record's un_self_id. * - process_toplevel_devices() * For a given metadevice type, searchs through the md_im_rec_t **mdimpp, * list of all metadevices in the set, to find all records of the * specified type that do not have a parent and puts them on a temp list. * The temp list is then iterated through and the associated processing * - process_(trans, hotspare, hotspare_pool, soft_part, mirror, stripe, raid) * These functions are called by using the dfunc field in the mdimpp list. * Each process function only understands its own type of metadevice. Once * it processes the metadevice it was called for, it then loops through * all of the underlying metadevices. After printing the name of the * underlying metadevice, it puts in on a list to be processed. If the * underlying device is a physical device, then print_physical_device is * Once all information about the original metadevice is processed, it * loops through the list of underlying metadevices and calls the * appropriate function to process them. * - process_toplevel_softparts() * To match the output for metastat -c, all top-level softpartions * are printed out in groups based on their underlying metadevice--so that * the underlying metadevice only needs to be processed once. * - meta_get_(sm_state, raid_col_state, stripe_state, hs_state) * These functions are used to retrieve the metadevice state information. * They are also used by the metastat concise routines in * md_im_rec is a doubly linked list used to store the rb_data for each * directory entry that corresponds to a metadevice. * n_key: is set, if there is an associated entry in the NM namespace. * dfunc: is set to point to the function that processes the particular * metadevice associated with the record. * hs_record_id: is only set, if the metadevice is a hotspare. * un_self_id: is set for all other records. This is also used to generate * the name of the metadevice if there is no entry for the metadevice in * the NM namespace--n_key is not set. char *
n_name;
/* name of metadevice */ /* pointer to the unit structure for the metadevice, e.g. rb_data[0] */ * md_im_list is used to group toplevel metadevices by type and to group * the underlying devices for a particular metadevice. * MAXSIZEMDRECNAME is the value that has historically been used to allocate * space for the metadevice name * Strip blanks from string. Used for size field in concise output. * Print properly indented metadevice name, type and size for concise output. /* set up minimum field width. negative for left justified */ width = 0;
/* overflowed; no minimum field needed */ width = 0 -
width;
/* negative for left justification */ * free_mdrec_list_entry() * Removing entry from the list of metadevices in the diskset(mdimpp). * This function will not remove the dummy entry at the head of the * list, so we don't have to set mdrec equal to NULL. * Appending entry to the underlying component list. The list * is used to group all of the underlying devices before * free_md_im_list_entries() * Freeing entries on an md_im_list_t. This list is used to group * underlying components for processing and to group top-level metadevices * print_physical_device() * If a metadevice has an underlying component that is a physical * device, then this searches the pnm_rec_t list to match an entry's * n_key to the key for the underlying component. The ctd name of the * physical device is printed on the same line as the metadevice. * Given a 64bit stripe unit, compute the size of the stripe unit. * This function is a derivation of: * and any changes made to either this function or get_big_stripe_req_size() * should be reviewed to make sure the functionality in both places is correct. * total size of the 64bit stripe /* Compute the offset of the first component */ * Requestor wants to have the total size, add the sizes of * Gets the state for the underlying components(submirrors) of a mirror. * string for state of the sub-mirror /* resyncing, needs repair */ * meta_get_raid_col_state() * Gets the state for the underlying components(columns) of a raid. * string for state of the raid column * meta_get_stripe_state() * Gets the state for the underlying components of a stripe. * string for state of the stripe * Gets the state for the underlying components(hotspares) of a hotspare pool. * string for state of the hotspare * Prints unit information for a trans metadevice and calls the respective * functions to process the underlying metadevices. /* Printing name, size, and type of metadevice */ * Loops through md_im_rec_t **mdimpp list of all metadevices to find * record that matches the underlying device. * Trans devices can only have one underlying device, so once a * match is found, we are done. /* Printing name of the underlying metadevice */ * If a metadevice was not found, then the underlying device must be a * physical device. Otherwise, call the functions to process the /* process underlying component */ * Removing the md_entry from the list * Searches though list of physical devices to match hotspare record. * Prints physical device name and state of a hotspare unit. * Loops through physical namespace to find the device that matches /* Printing name of hotspare device */ /* Not removing entry, because it can be processed more than once. */ * process_hotspare_pool() * Prints concise unit information for a hotspare pool metadevice and calls a * function to process each attached hotspare device. * Printing name, size, and type of metadevice. Setting size field to * 0, so that output is the as metastat -c. /* Looping through list of attached hotspare devices. */ /* Looking for the matching record for the hotspare device. */ /* Calling function to print name of hotspare */ * Removing the md_entry from the list * Prints concise unit information for a raid metadevice and calls the * respective functions to process the underlying metadevices. /* Printing name, size, and type of metadevice */ /* Loops through raid columns to find underlying metadevices */ * Need to assume that underlying device is a physical device, * unless we find a matching metadevice record. * Loops through list of metadevices to find record that matches /* check if hotspare device enabled */ * Find matching metadevice record * for the hotspare device. /* print name of underlying metadevice */ * An underlying hotspare must be a physical device. * If support is ever added for soft-partitions under * hotspare pools, then this code should be updated to * include a search for underlying metadevices. /* process underlying components */ * Removing the md_entry from the list * Prints concise unit information for a mirror metadevice and calls the * respective functions to process the underlying metadevices. /* Printing name, size, and type of metadevice */ /* Looping through sub-mirrors to find underlying devices */ * It is not possible to have an underlying physical device * for a submirror, so there is no need to search the phys_nm /* Printing the state for the submirror */ /* process underlying components */ * Removing the md_entry from the list * Prints concise unit information for a stripe metadevice and calls the * respective functions to process the underlying metadevices. /* Printing name, size, and type of metadevice */ /* Looping through stripe rows */ * Looping through the components in each row to find the * Need to assume that underlying device is a * physical device, unless we find a matching /* if an underlying metadevice was not found */ * An underlying hotspare must be a physical device. * If support is ever added for soft-partitions under * hotspare pools, then this code should be updated to * include a search for underlying metadevices. /* Process underlying metadevices */ * Removing the md_entry from the list * Prints concise unit information for a softpart metadevice and calls the * respective functions to process the underlying metadevices. /* Printing name, size, and type of metadevice */ * Loops through md_im_rec_t **mdimpp list of all metadevices to find * record that matches the underlying device. * Softpartitions can only have one underlying device, so once a * match is found, we are done. /* Printing name of the underlying metadevice */ /* This is only executed if an underlying metadevice was not found */ /* Process underlying metadevice */ * Removing the md_entry from the list * process_toplevel_softparts() * Toplevel softpartions need to be grouped so that their underlying devices * can be printed just once. * Loops through md_im_rec_t **mdimpp list of all metadevices to find * all softpartions that are toplevel softpartitions(softparts w/out * a parent). Groups output for these entries so that the function to * process the underlying metadevice is only called once. /* Printing name, size, and type of metadevice */ * Looking for record that matches underlying /* Print name of underlying device */ * Looking for any other toplevel softpartitions with * same underlying device. We know that all other * matching metadevices, that share the same underlying * metadevice, are also soft-partitions. * Need to advance so that will not lose * position after removing processed * Removing the md_entry from the list /* Process the underlying device */ * process_toplevel_devices() * Search through list of metadevices for metadevices of md_type that do not * Need to group soft partitions so that common underlying device * are only processed once. * Search the list of metadevices to find all metadevices that match * the type and don't have a parent. Put them on a separate list * that will be processed. * Loop through list and process all top-level metadevices of a * Converts or copies the (mddb_rb_t->rb_data) metadevice record to a 64bit * Sets the dfunc field to point to the appropriate function to process the * Sets the parent field for the metadevice. * Extracts the name from the NM namespace if it is available, otherwise * generates it from the metadevice's minor number. * Setting the un_self_id or the hs_self_id, in the case of hotspare * records, for each metadevice entry. Also setting has_parent and * setting dfunc so that it points to the correct function to process * If the record was stored ondisk in 32bit format, then it is * converted to the 64bits equivalent 64bit format and the memory * for the 32bit pointer is freed. * Ondisk and incore records are always same size. * If the hsp has descriptive name we'll get /* All valid cases have been dealt with */ * If metadevice record has an entry in the NM namespace * then it is copied into the mdrec->n_name field. * If it is a hot spare pool we will find our * match by comparing the NM record's n_key * with the extracted key from the hsp_self_id * Else, match the un_self_id for the record * to the n_minor name in the NM record. * If the metadevice name is not in the namespace, then * then we will generate the name from the minor number * for the metadevice. In the case of records for a hotspare * pool we use hsp_self_id, otherwise we use un_self_id. * Generate the metadevice name for all other records * (except for hotspares, because hotspares can only * Reads the mddb_rb32_od_t or mddb_rb_t and the associated metadevice record * from the disk. Runs magic, checksum, and revision checks on the record /* Read in the appropriate record and return configurations */ * The only place to discover whether or not the record is a * 32bit or 64bit record is from the record's rb_revision field. * The mddb_rb_t and mddb_rb32_t structures are identical for the * rb_magic, rb_revision, rb_checksum, and rb_checksum_fiddle. * So we can assume that the record is a 32bit structure when we * check the record's magic number and revision and when we calculate * Checking the magic number for the record block. * Checking the revision for the record block. Must match either * revision for the current 64bit or 32bit record block. Also, * setting the flag for whether or not it is a 32bit record. * Calculating the checksum for this record block. Need * to skip the rb's checksum fiddle. /* mddb_rb_t and mddb_rb32_t differ before the rb_timestamp field */ /* Populates the fields in md_im_rec_t *tmp_mdrec. */ /* Adding record to the head of the list of all metadevices. */ * Reads the directory block and directory entries. * Runs magic, checksum, and revision checks on the directory block. /* Read in all directory blocks */ * Set ep with error code for MDE_DB_NODB. This is the * error code used in the kernel when there is a problem * with reading records in. Checks the magic number, the * revision, and the checksum for each directory block. * If db timestamp is more recent than the previously recorded * last modified timestamp, then update last modified. /* Creates dep list of all directory entries in the db */ * Process all directory entries in the directory block. * For each directory entry, read_mdrec is called to read * de_flags is set to the type of metadevice. * If directory entry does not correspond to a * specific metadevice then it is set to zero. * All namespace records(NM, SHR_NM, DID_SHR_NM) have a * value of zero in their de_flags field. * Generates the metastat -c output. Also, updates the global variable * for a last accessed timestamp. /* list of all metadevices in diskset */ /* Read in metadevice records and add entries to mdimp list. */ /* Adding a fake record to the head of the list of all metadevices. */ /* Calling functions to process all metadevices on mdimp list */ * If mdreclist is not null, then this will walk through all * elements and free them.