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) 1992, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * Just in case we're not in a build environment, make sure that 2N/A * TEXT_DOMAIN gets set to something. 2N/A * hotspares utilities 2N/A * FUNCTION: meta_get_hsp_names() 2N/A * INPUT: sp - the set name to get hotspares from 2N/A * options - options from the command line 2N/A * OUTPUT: hspnlpp - list of all hotspare names 2N/A * ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 success 2N/A * PURPOSE: returns a list of all hotspares in the metadb 2N/A * for all devices in the specified set 2N/A /* we must have a set */ 2N/A /* get number of devices */ 2N/A /* malloc minor number buffer to be filled by ioctl */ 2N/A /* append to list */ 2N/A * get information of a specific hotspare pool from driver 2N/A /* should have a set */ 2N/A /* get size of unit structure */ 2N/A /* get actual unit structure */ 2N/A * free hotspare pool unit 2N/A * get hotspare pool unit (common) 2N/A /* allocate hotspares */ 2N/A /* if empty hotspare pool, we are done */ 2N/A /* get name, refcount */ 2N/A /* get hotspare name */ 2N/A /* get hotspare state */ 2N/A /* cleanup, return success */ 2N/A /* cleanup, return error */ 2N/A * get hotspare pool unit 2N/A * check hotspare pool for dev 2N/A /* should be in the same set */ 2N/A /* look in hotspares */ 2N/A /* return success */ 2N/A * check to see if we're in a hotspare pool 2N/A /* should have a set */ 2N/A /* for each hotspare pool */ 2N/A /* check hotspare pool */ 2N/A /* cleanup, return success */ 2N/A /* make sure we have a disk */ 2N/A /* check to ensure that it is not already in use */ 2N/A /* make sure it is in the set */ 2N/A /* make sure its not in a metadevice */ 2N/A /* return success */ 2N/A /* print hotspares */ 2N/A /* print hotspare */ 2N/A * then just print out the cxtxdxsx or the dx, metainit 2N/A * will assume the default, otherwise we need the full 2N/A * pathname to make sure this works as we intend. 2N/A /* not standard path, print full pathname */ 2N/A /* standard path, just print ctd or d value */ 2N/A /* terminate last line */ 2N/A /* cleanup, return error */ 2N/A * hotspare state name 2N/A * This allows the length 2N/A * of the ctd to vary from small to large without 2N/A * if the length is to short to print out all of the header 2N/A "%s: 1 hot spare (1 big device)\n\t%-*.*s " 2N/A "%-12.12s%-8.6s\t\t%s\n",
2N/A "%s: 1 hot spare\n\t%-*.*s %-12.12s%-8.6s\t\t%s\n",
2N/A * This allows the length 2N/A * of the ctd to vary from small to large without 2N/A "%s: %u hot spares (%d big device(s))\n\t%-*.*s " 2N/A "%-12.12s%-8.6s\t\t%s\n",
2N/A "%-12.12s%-8.6s\t\t%s\n",
2N/A /* print hotspares */ 2N/A /* populate the key in the name_p structure */ 2N/A /* determine if devid does NOT exist */ 2N/A /* print hotspare */ 2N/A * This allows the length 2N/A * of the ctd to vary from small to large without 2N/A " %-*s %-12s %lld blocks\t%s\n",
2N/A " %-*s\t %-11s %8lld blocks%s\t%s\n",
2N/A /* add extra line */ 2N/A /* cleanup, return error */ 2N/A /* should have same set */ 2N/A /* print all hsps */ 2N/A /* cleanup, return success */ 2N/A /* get unit structure */ 2N/A /* print appropriate detail */ 2N/A * check for valid hotspare pool 2N/A * invalidate hotspare pool info 2N/A * FUNCTION: del_hsp_name_mn_sides() 2N/A * INPUT: sp - set name 2N/A * curside - side of this node 2N/A * key - key of records to delete 2N/A * OUTPUT: ep - error information 2N/A * PURPOSE: There are name records for each side in a set. This 2N/A * function deletes the records associated with the specified 2N/A * key for all sides except curside. This function is used 2N/A * when the set is a multinode set. 2N/A * FUNCTION: del_hsp_name_trad_sides() 2N/A * INPUT: sp - set name 2N/A * curside - side of this node 2N/A * key - key of records to delete 2N/A * OUTPUT: ep - error information 2N/A * PURPOSE: There are name records for each side in a set. This 2N/A * function deletes the records associated with the specified 2N/A * key for all sides except curside. This function is used 2N/A * when the set is a traditional set. 2N/A * FUNCTION: del_hsp_keys() 2N/A * INPUT: sp - set name 2N/A * hspid - ID of records to delete 2N/A * OUTPUT: ep - error information 2N/A * RETURNS: 0 - success 2N/A * PURPOSE: Remove the NM records associated with hspid from all sides 2N/A * of the set. Missing records are not considered to be an 2N/A * error. The key associated with the current side is removed 2N/A * This function is very similar to del_key_name(), except it 2N/A * does not require any device look up. This is because the 2N/A * hot spare pool is not a device. 2N/A * If there is no key, this means that the hot spare was created 2N/A * before the introduction of friendly names. Thus, the is no NM 2N/A * record and nothing for us to do in this function. 2N/A /* Find our current side */ 2N/A * If not the local set, we need to process the non-local sides 2N/A /* Multinode set. Sides are in a linked list. */ 2N/A /* Sides are in an array. */ 2N/A /* Now delete the name for the current side. */ 2N/A * FUNCTION: add_hsp_name_mn_sides() 2N/A * INPUT: sp - set name 2N/A * curside - side number for this node 2N/A * key - key to use for the name record 2N/A * hsp_name - name of the hot spare 2N/A * OUTPUT: ep - error information 2N/A * RETURNS: 0 indicates success, and -1 indicates failure. 2N/A * PURPOSE: Once the name record has been added for the current side, 2N/A * this function adds the record to the remaining sides. This 2N/A * function is to be used when the set is a multinode set. 2N/A * The side designated by curside will be ignored when adding 2N/A * FUNCTION: add_hsp_name_trad_sides() 2N/A * INPUT: sp - set name 2N/A * curside - side number for this node 2N/A * key - key to use for the name record 2N/A * hsp_name - name of the hot spare 2N/A * OUTPUT: ep - error information 2N/A * RETURNS: 0 indicates success, and -1 indicates failure. 2N/A * PURPOSE: Once the name record has been added for the current side, 2N/A * this function adds the record to the remaining sides. This 2N/A * function is to be used when the set is a traditional set. 2N/A * The side designated by curside will be ignored when adding 2N/A * FUNCTION: add_hsp_name() 2N/A * INPUT: sp - Name of the set containing the hsp 2N/A * hsp_name - Hot spare pool name to be added 2N/A * OUTPUT: ep - Error information 2N/A * RETURNS: If successful the key of the newly added record is 2N/A * returned. MD_KEYBAD is returned to indicate a failure. 2N/A * PURPOSE: This function creates a new NM record containing the name 2N/A * of the hotspare pool. A record containing the name is 2N/A * added to each active side, but the record is added first to 2N/A * the current side. This function is modeled on 2N/A * add_key_name() in meta_namespace. The difference is that 2N/A * there is no device associated with a hot spare pool 2N/A /* First add the record for the side of the current node. */ 2N/A /* Make sure that we can use the key */ 2N/A * Now that we have a key, we will use it to add a record to the 2N/A * rest of the sides in the set. For multinode sets, the sides are 2N/A * in a linked list that is anchored on the set descriptor. For 2N/A * traditional sets the side information is in an array in the set 2N/A /* Multinode set. Sides are in linked list. */ 2N/A /* Traditional set. Sides are in an array. */ 2N/A /* Get rid records that we added. */ 2N/A /* should have a set */ 2N/A /* setup hotspare pool info */ 2N/A /* Get key for hot spare pool name record. */ 2N/A /* First see if the name record already exists. */ 2N/A * If the error is ENOENT, then we will create a 2N/A * hot spare pool name records. For other types of 2N/A * errors, however, we'll bail out. 2N/A /* make sure that the name isn't already in use */ 2N/A /* add empty hotspare pool */ 2N/A /* If DOIT is not set, it's a dryrun */ 2N/A /* If DOIT is not set, it's a dryrun */ 2N/A /* should be in same set */ 2N/A /* In dryrun mode (DOIT not set) we must not alter the mddb */ 2N/A /* store name in namespace */ 2N/A /* print success message */ 2N/A "%s: Hotspare pool is setup\n"),
2N/A "%s: Hotspare is added\n"),
2N/A "%s: Hotspares are added\n"),
2N/A /* return success */ 2N/A * FUNCTION: meta_hsp_delete() 2N/A * INPUT: sp - Name of the set containing the hsp 2N/A * hspnp - Hot spare pool name information 2N/A * options - Options from command line 2N/A * OUTPUT: ep - Error information 2N/A * RETURNS: 0 on success and -1 on failure. 2N/A * PURPOSE: Common code to delete an empty hot spare pool. 2N/A /* setup hotspare pool info */ 2N/A /* If DOIT is not set, it's a dryrun */ 2N/A /* Remove hsp record. */ 2N/A /* Get rid of hsp NM records */ 2N/A * delete hotspares from pool 2N/A /* should have a set */ 2N/A /* setup hotspare pool info */ 2N/A /* delete empty hotspare pool */ 2N/A /* delete hotspares */ 2N/A /* If DOIT is not set, it's a dryrun */ 2N/A /* should be in same set */ 2N/A /* delete hotspare */ 2N/A /* print success message */ 2N/A "%s: Hotspare pool is cleared\n"),
2N/A "%s: Hotspare is deleted\n"),
2N/A "%s: Hotspares are deleted\n"),
2N/A /* return success */ 2N/A * replace hotspare in pool 2N/A /* should be in same set */ 2N/A /* save new binding incase this is a rebind where oldnp==newnp */ 2N/A /* invalidate, then get the hotspare (fill in oldnp from metadb) */ 2N/A /* the old device binding is now established */ 2N/A * check for the case where oldnp and newnp indicate the same 2N/A * device, but the dev_t of the device has changed between old 2N/A * and new. This is called a rebind. On entry the dev_t 2N/A * represents the new device binding determined from the 2N/A * filesystem (meta_getdev). After calling meta_get_hsp 2N/A * oldnp (and maybe newnp if this is a rebind) is updated based 2N/A * to the old binding from the metadb (done by metakeyname). 2N/A * Save a copy of the devid associated with the new disk, the reason 2N/A * is that the meta_check_hotspare() call could cause the devid to 2N/A * be changed to that of the devid that is currently stored in the 2N/A * replica namespace for the disk in question. This devid could be 2N/A * stale if we are replacing the disk. The function that overwrites 2N/A * the devid is dr2drivedesc(). 2N/A * Copy back the saved devid. 2N/A /* In dryrun mode (DOIT not set) we must not alter the mddb */ 2N/A /* store name in namespace */ 2N/A * We are 'rebind'ing a disk that is in a diskset so as well 2N/A * as updating the diskset's namespace the local set needs 2N/A * to be updated because it also contains a reference to the 2N/A * In dryrun mode (DOIT not set) we must not alter 2N/A /* replace hotspare */ 2N/A /* If DOIT is not set, it's a dryrun */ 2N/A "%s: Hotspare %s is replaced with %s\n"),
2N/A /* return success */ 2N/A /* should have a set */ 2N/A /* setup device info */ 2N/A /* If DOIT is not set, it's a dryrun */ 2N/A /* get the list of hotspare names */ 2N/A /* enable hotspares for each components */ 2N/A /* get the file_system dev binding */ 2N/A * search for the component in each hotspare pool 2N/A * and replace it (instead of enable) if the binding 2N/A * in_hsp will call meta_get_hsp which will fill 2N/A * in hspnp with metadb version of component 2N/A * check for the case where the dev_t has 2N/A * changed between the filesystem and the 2N/A * metadb. This is called a rebind, and 2N/A * is handled by meta_hs_replace. 2N/A * establish file system binding 2N/A /* enable the component in all hotspares that use it */ 2N/A /* enable hotspare */ 2N/A * Are we dealing with a non-local set? If so need to update 2N/A * the local namespace so that the disk record has the correct 2N/A * Failed to update the local set. Nothing to 2N/A * do here apart from report the error. The 2N/A * namespace is most likely broken and some 2N/A * form of remedial recovery is going to 2N/A "hotspare %s is enabled\n"),
2N/A /* clear whole cache */ 2N/A /* return success */ 2N/A * check for dups in the hsp itself 2N/A /* check hotspares */ 2N/A /* check hotspare */ 2N/A /* check this hsp too */ 2N/A /* return success */ 2N/A /* if we're not doing anything, return success */ 2N/A /* cleanup, return success */ 2N/A * NOTE: this functions is metainit(1m)'s command line parser! 2N/A /* see if it exists already */ 2N/A /* parse general options */ 2N/A /* parse hotspares */ 2N/A /* parse hotspare name */ 2N/A /* we should be at the end */ 2N/A /* create hotspare pool */ 2N/A /* cleanup, return error */ 2N/A * reset hotspare pool 2N/A /* should have the same set */ 2N/A /* reset all hotspares */ 2N/A /* for each hotspare pool */ 2N/A /* reset hotspare pool */ 2N/A * If this is a multi-node set, we send a series 2N/A * of individual metaclear commands. 2N/A /* cleanup, return success */ 2N/A /* get unit structure */ 2N/A /* make sure nobody owns us */ 2N/A /* clear hotspare pool members */ 2N/A /* clear hotspare */ 2N/A /* If DOIT is not set, it's a dryrun */ 2N/A /* clear hotspare pool */ 2N/A "%s: Hotspare pool is cleared\n"),
2N/A /* clear subdevices (nothing to do) */ 2N/A /* cleanup, return success */