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) 1995, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * Metadevice diskset interfaces 2N/A /* find the smallest existing replica */ 2N/A * Before we bump up the dbcnt, if we're 2N/A * running with device ids in disksets, let's 2N/A * compare the device ids otherwise we compare 2N/A * There is a possibility the device ids might 2N/A * have changed. To account for that case, we 2N/A * fallback to comparing the ctd names if the 2N/A * device id comparison fails. If we aren't running 2N/A * in device id mode and a disk has moved, the ctd's 2N/A /* Lock the set on current set members */ 2N/A /* If this is forced, don't lock other sides */ 2N/A /* We already locked this side in the caller */ 2N/A /* Skip empty slots */ 2N/A /* If this is forced, don't lock other sides */ 2N/A /* We already locked this side in the caller */ 2N/A /* If this is forced, then only care about this node */ 2N/A /* Skip empty slots */ 2N/A /* If this is forced, then only care about this node */ 2N/A /* If this is forced, don't unlock other sides */ 2N/A /* We will unlocked this side in the caller */ 2N/A /* Skip empty slots */ 2N/A /* If this is forced, don't unlock other sides */ 2N/A /* We will unlocked this side in the caller */ 2N/A /* Do not clear the key, via cl_set_setkey(NULL) this is nested */ 2N/A * Update the master block with the device id information for the disks 2N/A * in the diskset. The device id information will be consumed by the 2N/A * diskset import code in case of remotely replicated disksets. 2N/A * For the drives that have a valid diskset mddb on them, we add the 2N/A * device id for the drive to the unused portion of the mddb. 2N/A * For the drives that don't have a diskset mddb on them, we add a dummy 2N/A * master block that contains the device id for the drive. A dummy master 2N/A * block is signified by changing the master block magic number, mb_magic, 2N/A * This code is responsible primarily for adding the appropriate device id 2N/A * information to diskset disks that didn't have the information. This would 2N/A * typically occur when the OS has been upgraded from an OS release prior to 2N/A * The error path in this routine is defined as - if an error occurs while 2N/A * updating the mddb for one disk in the diskset, don't bother updating *any* 2N/A * of the mddbs because it's game over anyways as far as disaster recovery for 2N/A * that diskset is concerned. 2N/A * This code will need to be revisited if and when support for importing 2N/A * partial disksets is added. 2N/A * NOTE: This code relies heavily on the meta_repartition() working correctly 2N/A * and reformatting a drive, so that there's enough room for a dummy master 2N/A * block, every time a drive is added to a diskset. Should 2N/A * the meta_repartition() code change in future, this code will have to be 2N/A * Returns 0 on success and -1 on failure 2N/A * For every drive in the drive descriptor, iterate through all 2N/A * the mddbs present on it and check to see if mb_devid_magic is 2N/A * set. If it isn't, then update the master block with the correct 2N/A * device id information 2N/A * When the import support for remotely replicated 2N/A * disksets gets implemented, we probably want to 2N/A * inform the user that the disks won't be self 2N/A * identifying if any of these calls fails 2N/A /* if devid_str_decode fails, make sure devid is null */ 2N/A * If the disk is one of the ones that doesn't 2N/A * have a shared mddb on it, we put a dummy 2N/A * master block on it. 2N/A * if mb_setcreatetime is 0, this field was never 2N/A * filled in so do it now. 2N/A * If MDDB_MAGIC_DE is set in the 2N/A * mb_devid_magic field then we know we 2N/A * have a valid device id and we don't 2N/A * need to add it to the master block. 2N/A * This would have to be revisited if device 2N/A * ids change as a result of device id 2N/A * algorithms changing or somesuch. 2N/A * there's enough space to 2N/A * write out (push) any changes we have to the mb 2N/A * Exported Entry Points 2N/A /* Do we own the set? */ 2N/A /* We already own it, we are done. */ 2N/A /* You can not take ownership of a set that has no drives */ 2N/A /* END CHECK CODE */ 2N/A /* Lock the set on our side */ 2N/A * Find the "side" value so that it can be used to deal with 2N/A * A local sets' side 0 references records associated with 2N/A * that node's local set. As this is a non-local set, "side" 2N/A * must be modified (by adding a SKEW) before we reference 2N/A * records in the local set [setno = 0] for the non-local set 2N/A * If this set had been previously imported as a partial replicated 2N/A * diskset, then must attempt to updated any unresolved drive 2N/A * records in diskset with new devid information. Must set 2N/A * flags in drivedesc list before loading up set so that the 2N/A * md driver will fix up names and devids correctly in the 2N/A * We may have name collision here so we need to get 2N/A * the dnp using the devid and not the name. 2N/A /* if no device id, what error?) */ 2N/A * Assuming we're interested in knowing about 2N/A * whatever error occurred, but not in stopping. 2N/A /* Reget sd and dd since freed by meta_prune_cnames. */ 2N/A /* If ep has error, then there was a failure, set rval */ 2N/A /* Builds global replicated disk list */ 2N/A /* If success, then clear error structure */ 2N/A /* If ep has error, then there was a failure, set rval */ 2N/A /* Get old devid from drive record */ 2N/A * If the devid stored in the drive record 2N/A * (old_devid) matches a devid known by 2N/A * the system, then this disk has already 2N/A * been partially resolved. This situation 2N/A * could occur if a panic happened during a 2N/A * previous take of this diskset. 2N/A * Set flag to later handle fixing the master 2N/A * block on disk and turning off the unresolved 2N/A * If the devid stored in the drive record 2N/A * is on the list of replicated disks found 2N/A * during a system scan then set both flags 2N/A * so that the locator block, namespaces 2N/A * (diskset and local set), master block 2N/A * and unresolved replicated flag are updated. 2N/A * If devid stored in the drive record is 2N/A * not found then set flag to mark 2N/A * that set is still unresolved and 2N/A * continue to next drive record. 2N/A * Set flags to fix up the master block, 2N/A * locator block of the diskset, diskset 2N/A * namespace and the local set namespace. 2N/A * Check the local devid namespace to see if the disks 2N/A * have been moved. Use the local set first of all as this contains 2N/A * entries for the disks in the set. 2N/A * This is being done before the tk_own_bydd because the disks 2N/A * in the dd list could be wrong! But it should be done with the lock 2N/A * Actually do the check of the disks. 2N/A /* check failed in some unknown manner */ 2N/A * Update the dd namelist so that the rpc.metamhd 2N/A * gets the correct disks to reserve - it is the rname 2N/A * we are interested in. 2N/A * Need to save the side names key as this 2N/A * points to the namespace entry that will 2N/A * need to be updated. In addition the call 2N/A * to meta_make_sidenmlist does not actually 2N/A * set the namespace key. 2N/A * There is the possibility that there 2N/A * will be multiple disks with the same 2N/A * name but different devids in the 2N/A * drivelist. Because of this, we need 2N/A * to look for a new dnp based on devid 2N/A * null newname so we are reset for next time 2N/A /* Snarf set of traditional diskset doesn't use stale information */ 2N/A * Look at the set on all other hosts, if every other host 2N/A * has the same set with a larger genid, then we destroy this 2N/A /* Skip empty slots */ 2N/A /* Skip this node */ 2N/A /* Destroy the set */ 2N/A * If an unresolved replicated diskset, fix up diskset 2N/A * and local namespaces, master block and drive record 2N/A * with the new devid. If all drives in diskset are 2N/A * now resolved, then clear set unresolved replicated flag. 2N/A * If an error is encountered, don't fail the take, but 2N/A * don't proceed any further in resolving the replicated disks. 2N/A /* Fix up diskset and local namespaces with new devids */ 2N/A /* Fix up master block with new devids */ 2N/A /* If all drives are resolved, set OK flag in set record. */ 2N/A /* Ignore failure since no bad effect. */ 2N/A * meta_getalldevs() will ultimately force devfsadmd to create 2N/A * the /dev links for all the configured metadevices if they 2N/A * do not already exist. This ensures that once the set is 2N/A * owned all the metadevices are accessible as opposed to waiting 2N/A * for devfsadmd to create them. 2N/A * If the set doesn't have the MD_SR_MB_DEVID bit set, i.e 2N/A * the drives in the set don't have the device id information, 2N/A * then stick it in if possible. 2N/A * If updating the master block fails for whatever reason, it's 2N/A * okay. It just means the disk(s) in the diskset won't be self 2N/A /* Lock the set on current set members */ 2N/A /* Skip empty slots */ 2N/A /* We already locked this side */ 2N/A * Ignore any RPC errors on a force 2N/A * take. The set will have been taken 2N/A * above and we still need to continue. 2N/A /* update the sr_flags on all hosts */ 2N/A /* Skip empty slots */ 2N/A * Only update those nodes that 2N/A * are active (ie those that the 2N/A * set is locked on). 2N/A /* Skip empty slots */ 2N/A /* Unlocked of this side is done later */ 2N/A /* no point calling dead nodes */ 2N/A * If we get here, we need to unlock the set before the resync 2N/A * gets called, otherwise the "daemon" will hold the set lock 2N/A * until the resync is done! 2N/A /* We try to get things resync'ed, but this can fail */ 2N/A * In order to resolve the namespace major driver names and 2N/A * to have the subdrivers attempt to re-associate devts from 2N/A * the newly resolved replicated device ids, return a '2'. 2N/A * This instructs metaset to release the diskset and re-take. 2N/A * - no error was detected on the take 2N/A * - a replicated unresolved devid was resolved during take 2N/A * - take isn't being called during an import 2N/A * - this isn't already a re-take situation 2N/A /* Skip empty slots */ 2N/A /* We already unlocked this side */ 2N/A /* no point calling dead nodes */ 2N/A /* Make sure we are blocking all signals */ 2N/A /* update the sr_flags on all hosts */ 2N/A /* Skip empty slots */ 2N/A /* no point calling dead nodes */ 2N/A /* Skip empty slots */ 2N/A /* We will unlocked this side below */ 2N/A /* no point calling dead nodes */ 2N/A /* release signals back to what they were on entry */ 2N/A /* Make sure we own the set */ 2N/A /* Get the drive descriptors */ 2N/A /* Get timeout values in case we need to roll back this release */ 2N/A /* END CHECK CODE */ 2N/A /* Lock the set on our side */ 2N/A /* Make sure we are blocking all signals */ 2N/A /* Snarf set of trad diskset doesn't use stale information */ 2N/A /* release signals back to what they were on entry */