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) 2001, 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 * soft partition operations 2N/A * Soft Partitions provide a virtual disk mechanism which is used to 2N/A * divide a large volume into many small pieces, each appearing as a 2N/A * separate device. A soft partition consists of a series of extents, 2N/A * each having an offset and a length. The extents are logically 2N/A * contiguous, so where the first extent leaves off the second extent 2N/A * picks up. Which extent a given "virtual offset" belongs to is 2N/A * dependent on the size of all the previous extents in the soft 2N/A * Soft partitions are represented in memory by an extent node 2N/A * (sp_ext_node_t) which contains all of the information necessary to 2N/A * create a unit structure and update the on-disk format, called 2N/A * "watermarks". These extent nodes are typically kept in a doubly 2N/A * linked list and are manipulated by list manipulation routines. A 2N/A * list of extents may represent all of the soft partitions on a volume, 2N/A * a single soft partition, or perhaps just a set of extents that need 2N/A * to be updated. Extent lists may be sorted by extent or by name/seq#, 2N/A * depending on which compare function is used. Most of the routines 2N/A * require the list be sorted by offset to work, and that's the typical 2N/A * In order to do an allocation, knowledge of all soft partitions on the 2N/A * volume is required. Then free space is determined from the space 2N/A * that is not allocated, and new allocations can be made from the free 2N/A * space. Once the new allocations are made, a unit structure is created 2N/A * and the watermarks are updated. The status is then changed to "okay" 2N/A * on the unit structure to commit the transaction. If updating the 2N/A * watermarks fails, the unit structure is in an intermediate state and 2N/A * the driver will not allow access to the device. 2N/A * A typical sequence of events is: 2N/A * 1. Fetch the list of names for all soft partitions on a volume 2N/A * meta_sp_get_by_component() 2N/A * 2. Construct an extent list from the name list 2N/A * meta_sp_extlist_from_namelist() 2N/A * 3. Fill the gaps in the extent list with free extents 2N/A * meta_sp_list_freefill() 2N/A * 4. Allocate from the free extents 2N/A * meta_sp_alloc_by_len() 2N/A * meta_sp_alloc_by_list() 2N/A * 5. Create the unit structure from the extent list 2N/A * meta_sp_createunit() 2N/A * meta_sp_updateunit() 2N/A * 6. Write out the watermarks 2N/A * meta_sp_update_wm() 2N/A * 7. Set the status to "Okay" 2N/A * meta_sp_setstatus() 2N/A/* Extent node compare function for list sorting */ 2N/A/* Function Prototypes */ 2N/A/* Debugging Functions */ 2N/A/* Misc Support Functions */ 2N/A/* Extent List Manipulation Functions */ 2N/A/* Extent List Query Functions */ 2N/A/* Extent Allocation Functions */ 2N/A/* Extent List Population Functions */ 2N/A/* Print (metastat) Functions */ 2N/A/* Watermark Manipulation Functions */ 2N/A/* Unit Structure Manipulation Functions */ 2N/A/* Reset (metaclear) Functions */ 2N/A/* Recovery (metarecover) Functions */ 2N/A * ************************************************************************** 2N/A * Debugging Functions * 2N/A * ************************************************************************** 2N/A /* print the common fields we know about */ 2N/A /* sp-specific fields */ 2N/A /* print extent information */ 2N/A * FUNCTION: meta_sp_parsesize() 2N/A * INPUT: s - the string to parse 2N/A * OUTPUT: *szp - disk block count (0 for "all") 2N/A * RETURNS: -1 for error, 0 for success 2N/A * PURPOSE: parses the command line parameter that specifies the 2N/A * requested size of a soft partition. The input string 2N/A * is either the literal "all" or a numeric value 2N/A * followed by a single character, b for disk blocks, k 2N/A * for kilobytes, m for megabytes, g for gigabytes, or t 2N/A * for terabytes. p for petabytes and e for exabytes 2N/A * have been added as undocumented features for future 2N/A * expansion. For example, 100m is 100 megabytes, while 2N/A * 50g is 50 gigabytes. All values are rounded up to the 2N/A * nearest block size. 2N/A /* Check for literal "all" */ 2N/A * FUNCTION: meta_sp_parsesizestring() 2N/A * INPUT: s - the string to parse 2N/A * OUTPUT: *szp - disk block count 2N/A * RETURNS: -1 for error, 0 for success 2N/A * PURPOSE: parses a string that specifies size. The input string is a 2N/A * numeric value followed by a single character, b for disk blocks, 2N/A * k for kilobytes, m for megabytes, g for gigabytes, or t for 2N/A * terabytes. p for petabytes and e for exabytes have been added 2N/A * as undocumented features for future expansion. For example, 2N/A * 100m is 100 megabytes, while 50g is 50 gigabytes. All values 2N/A * are rounded up to the nearest block size. 2N/A * make sure block offset does not overflow 2^64 bytes. 2N/A len *
1024ULL*
1024ULL*
1024ULL*
1024ULL*
1024ULL,
2N/A len *
1024ULL*
1024ULL*
1024ULL*
1024ULL*
1024ULL*
1024ULL,
2N/A * FUNCTION: meta_sp_setgeom() 2N/A * INPUT: np - the underlying device to setup geometry for 2N/A * compnp - the underlying device to setup geometry for 2N/A * mp - the unit structure to set the geometry for 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 otherwise 2N/A * PURPOSE: establishes geometry information for a device 2N/A * FUNCTION: meta_sp_setstatus() 2N/A * INPUT: sp - the set name for the devices to set the status on 2N/A * minors - an array of minor numbers of devices to set status on 2N/A * num_units - number of entries in the array 2N/A * status - status value to set all units to 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 success 2N/A * PURPOSE: sets the status of one or more soft partitions to the 2N/A /* update status of all soft partitions to the status passed in */ 2N/A * FUNCTION: meta_get_sp_names() 2N/A * INPUT: sp - the set name to get soft partitions from 2N/A * options - options from the command line 2N/A * OUTPUT: nlpp - list of all soft partition names 2N/A * ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 success 2N/A * PURPOSE: returns a list of all soft partitions in the metadb 2N/A * for all devices in the specified set 2N/A * FUNCTION: meta_get_by_component() 2N/A * INPUT: sp - the set name to get soft partitions from 2N/A * compnp - the name of the device containing the soft 2N/A * partitions that will be returned 2N/A * force - 0 - reads cached namelist if available, 2N/A * 1 - reloads cached namelist, frees old namelist 2N/A * OUTPUT: nlpp - list of all soft partition names 2N/A * ep - return error pointer 2N/A * RETURNS: int - -1 error, otherwise the number of soft partitions 2N/A * found on the component (0 = none found). 2N/A * PURPOSE: returns a list of all soft partitions on a given device 2N/A * from the metadb information 2N/A /* return a copy of the cached list */ 2N/A /* free the cache and reset values to zeros to prepare for a new list */ 2N/A /* get all the softpartitions first of all */ 2N/A * Now for each sp, see if it resides on the component we 2N/A * are interested in, if so then add it to our list 2N/A /* get the unit structure */ 2N/A * If the current soft partition is not on the same 2N/A * component, continue the search. If it is on the same 2N/A * component, add it to our namelist. 2N/A /* not on the same device, check the next one */ 2N/A /* it's on the same drive */ 2N/A * Check for overlapping partitions if the component is not 2N/A * if they're on the same drive, neither 2N/A * should be a metadevice if one isn't 2N/A /* in this case it's not an error for them to overlap */ 2N/A /* Component is on the same device, add to the used list */ 2N/A * FUNCTION: meta_sp_get_default_alignment() 2N/A * INPUT: sp - the pertinent set name 2N/A * compnp - the name of the underlying component 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: sp_ext_length_t =0: no default alignment 2N/A * >0: default alignment 2N/A * PURPOSE: returns the default alignment for soft partitions to 2N/A * be built on top of the specified component or 2N/A * We treat raw devices as opaque, and assume nothing about 2N/A * their alignment requirements. 2N/A * We already know it's a metadevice from the previous test; 2N/A * metagetmiscname() will tell us which metadevice type we 2N/A * For a mirror, we want to deal with the stripe that is the 2N/A * primary side. If it happens to be asymmetrically 2N/A * configured, there is no simple way to fake a universal 2N/A * alignment. There's a chance that the least common 2N/A * denominator of the set of interlaces from all stripes of 2N/A * all submirrors would do it, but nobody that really cared 2N/A * that much about this issue would create an asymmetric 2N/A * config to start with. 2N/A * If the component underlying the soft partition is a mirror, 2N/A * then at the exit of this loop, compnp will have been 2N/A * updated to describe the first active submirror. 2N/A * Handle stripes and submirrors identically; just return the 2N/A * interlace of the first row. 2N/A * Raid is even more straightforward; the interlace applies to 2N/A * the entire device. 2N/A * If we have arrived here with the alignment still not set, 2N/A * then we expect the error to have been set by one of the 2N/A * routines we called. If neither is the case, something has 2N/A * really gone wrong above. (Probably the submirror walk 2N/A * failed to produce a valid submirror, but that would be 2N/A * FUNCTION: meta_check_insp() 2N/A * INPUT: sp - the set name for the device to check 2N/A * np - the name of the device to check 2N/A * slblk - the starting offset of the device to check 2N/A * nblks - the number of blocks in the device to check 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 - device contains soft partitions 2N/A * -1 - device does not contain soft partitions 2N/A * PURPOSE: determines whether a device contains any soft partitions 2N/A /* check set pointer */ 2N/A * Get a list of the soft partitions that currently reside on 2N/A * the component. We should ALWAYS force reload the cache, 2N/A * because if we're using the md.tab, we must rebuild 2N/A * the list because it won't contain the previous (if any) 2N/A /* find all soft partitions on the component */ 2N/A * ************************************************************************** 2N/A * Extent List Manipulation Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_cmp_by_nameseq() 2N/A * INPUT: e1 - first node to compare 2N/A * e2 - second node to compare 2N/A * RETURNS: int - =0 - nodes are equal 2N/A * <0 - e1 should go before e2 2N/A * >0 - e1 should go after e2 2N/A * PURPOSE: used for sorted list inserts to build a list sorted by 2N/A * name first and sequence number second. 2N/A /* the names are equal, compare sequence numbers */ 2N/A /* sequence numbers are also equal */ 2N/A * FUNCTION: meta_sp_cmp_by_offset() 2N/A * INPUT: e1 - first node to compare 2N/A * e2 - second node to compare 2N/A * RETURNS: int - =0 - nodes are equal 2N/A * <0 - e1 should go before e2 2N/A * >0 - e1 should go after e2 2N/A * PURPOSE: used for sorted list inserts to build a list sorted by offset 2N/A /* offsets are equal */ 2N/A * FUNCTION: meta_sp_list_insert() 2N/A * INPUT: sp - the set name for the device the node belongs to 2N/A * np - the name of the device the node belongs to 2N/A * head - the head of the list, must be NULL for empty list 2N/A * offset - the physical offset of this extent in sectors 2N/A * length - the length of this extent in sectors 2N/A * type - the type of the extent being inserted 2N/A * seq - the sequence number of the extent being inserted 2N/A * flags - extent flags (eg. whether it needs to be updated) 2N/A * compare - the compare function to use 2N/A * OUTPUT: head - points to the new head if a node was inserted 2N/A * PURPOSE: inserts an extent node into a sorted doubly linked list. 2N/A * The sort order is determined by the compare function. 2N/A * Memory is allocated for the node in this function and it 2N/A * is up to the caller to free it, possibly using 2N/A * meta_sp_list_free(). If a node is inserted at the 2N/A * beginning of the list, the head pointer is updated to 2N/A * point to the new first node. 2N/A /* Don't bother adding zero length nodes */ 2N/A /* allocate and fill in new ext_node */ 2N/A /* first node in the list */ 2N/A /* the first node has a bigger offset, so insert before it */ 2N/A * find the next node whose offset is greater than 2N/A * the one we want to insert, or the end of the list. 2N/A /* link the new node in after the current node */ 2N/A * FUNCTION: meta_sp_list_free() 2N/A * INPUT: head - the head of the list, must be NULL for empty list 2N/A * OUTPUT: head - points to NULL on return 2N/A * PURPOSE: walks a double linked extent list and frees each node 2N/A * FUNCTION: meta_sp_list_remove() 2N/A * INPUT: head - the head of the list, must be NULL for empty list 2N/A * ext - the extent to remove, must be a member of the list 2N/A * OUTPUT: head - points to the new head of the list 2N/A * PURPOSE: unlinks the node specified by ext from the list and 2N/A * frees it, possibly moving the head pointer forward if 2N/A * the head is the node being removed. 2N/A * FUNCTION: meta_sp_list_size() 2N/A * INPUT: head - the head of the list, must be NULL for empty list 2N/A * exttype - the type of the extents to sum 2N/A * exclude_wm - subtract space for extent headers from total 2N/A * RETURNS: sp_ext_length_t - the sum of all of the lengths 2N/A * PURPOSE: sums the lengths of all extents in the list matching the 2N/A * specified type. This could be used for computing the 2N/A * amount of free or used space, for example. 2N/A * FUNCTION: meta_sp_list_find() 2N/A * INPUT: head - the head of the list, must be NULL for empty list 2N/A * offset - the offset contained by the node to find 2N/A * RETURNS: sp_ext_node_t * - the node containing the requested offset 2N/A * or NULL if no such nodes were found. 2N/A * PURPOSE: finds a node in a list containing the requested offset 2N/A * (inclusive). If multiple nodes contain this offset then 2N/A * only the first will be returned, though typically these 2N/A * lists are managed with non-overlapping nodes. 2N/A * *The list MUST be sorted by offset for this function to work.* 2N/A /* check if the offset lies within this extent */ 2N/A * the requested extent should always be a 2N/A * subset of an extent in the list. 2N/A * FUNCTION: meta_sp_list_freefill() 2N/A * INPUT: head - the head of the list, must be NULL for empty list 2N/A * size - the size of the volume this extent list is 2N/A * OUTPUT: head - the new head of the list 2N/A * PURPOSE: finds gaps in the extent list and fills them with a free 2N/A * node. If there is a gap at the beginning the head 2N/A * pointer will be changed to point to the new free node. 2N/A * If there is free space at the end, the last free extent 2N/A * will extend all the way out to the size specified. 2N/A * *The list MUST be sorted by offset for this function to work.* 2N/A /* pad inverse list out to the end */ 2N/A "holes freefilled:\n");
2N/A * FUNCTION: meta_sp_list_dump() 2N/A * INPUT: head - the head of the list, must be NULL for empty list 2N/A * PURPOSE: dumps the entire extent list to stdout for easy debugging 2N/A "Addr",
"Seq#",
"Type",
"Offset",
"Length",
"Flags",
"Prev",
2N/A * FUNCTION: meta_sp_list_overlaps() 2N/A * INPUT: head - the head of the list, must be NULL for empty list 2N/A * RETURNS: int - 1 if extents overlap, 0 if ok 2N/A * PURPOSE: checks a list for overlaps. The list MUST be sorted by 2N/A * offset for this function to work properly. 2N/A * ************************************************************************** 2N/A * Extent Allocation Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_alloc_by_ext() 2N/A * INPUT: sp - the set name for the device the node belongs to 2N/A * np - the name of the device the node belongs to 2N/A * head - the head of the list, must be NULL for empty list 2N/A * free_ext - the free extent being allocated from 2N/A * alloc_offset - the offset of the allocation 2N/A * alloc_len - the length of the allocation 2N/A * seq - the sequence number of the allocation 2N/A * OUTPUT: head - the new head pointer 2N/A * PURPOSE: allocates a portion of the free extent free_ext. The 2N/A * allocated portion starts at alloc_offset and is 2N/A * alloc_length long. Both (alloc_offset) and (alloc_offset + 2N/A * alloc_length) must be contained within the free extent. 2N/A * The free extent is split into as many as 3 pieces - a 2N/A * free extent containing [ free_offset .. alloc_offset ), an 2N/A * allocated extent containing the range [ alloc_offset .. 2N/A * alloc_end ], and another free extent containing the 2N/A * range ( alloc_end .. free_end ]. If either of the two 2N/A * new free extents would be zero length, they are not created. 2N/A * Finally, the original free extent is removed. All newly 2N/A * created extents have the EXTFLG_UPDATE flag set. 2N/A /* allocated extent must be a subset of the free extent */ 2N/A * FUNCTION: meta_sp_alloc_by_len() 2N/A * INPUT: sp - the set name for the device the node belongs to 2N/A * np - the name of the device the node belongs to 2N/A * head - the head of the list, must be NULL for empty list 2N/A * *lp - the requested length to allocate 2N/A * last_off - the last offset already allocated. 2N/A * alignment - the desired extent alignmeent 2N/A * OUTPUT: head - the new head pointer 2N/A * *lp - the length allocated 2N/A * RETURNS: int - -1 if error, the number of new extents on success 2N/A * PURPOSE: allocates extents from free space to satisfy the requested 2N/A * length. If requested length is zero, allocates all 2N/A * remaining free space. This function provides the meat 2N/A * of the extent allocation algorithm. Allocation is a 2N/A * three tier process: 2N/A * 1. If last_off is nonzero and there is free space following 2N/A * that node, then it is extended to allocate as much of that 2N/A * free space as possible. This is useful for metattach. 2N/A * 2. If a free extent can be found to satisfy the remaining 2N/A * requested space, then satisfy the rest of the request 2N/A * 3. Start allocating space from any remaining free extents until 2N/A * the remainder of the request is satisified. 2N/A * If alignment is non-zero, then every extent modified 2N/A * or newly allocated will be aligned modulo alignment, 2N/A * with a length that is an integer multiple of 2N/A * The EXTFLG_UPDATE flag is set for all nodes (free and 2N/A * allocated) that require updated watermarks. 2N/A * This algorithm may have a negative impact on fragmentation 2N/A * in pathological cases and may be improved if it turns out 2N/A * to be a problem. This may be exacerbated by particularly 2N/A * NOTE: It's confusing, so it demands an explanation: 2N/A * - len is used to represent requested data space; it 2N/A * does not include room for a watermark. On each full 2N/A * or partial allocation, len will be decremented by 2N/A * alloc_len (see next paragraph) until it reaches 2N/A * - alloc_len is used to represent data space allocated 2N/A * from a particular extent; it does not include space 2N/A * for a watermark. In the rare event that a_length 2N/A * (see next paragraph) is equal to MD_SP_WMSIZE, 2N/A * alloc_len will be zero and the resulting MD_SP_WMSIZE 2N/A * fragment of space will be utterly unusable. 2N/A * - a_length is used to represent all space to be 2N/A * allocated from a particular extent; it DOES include 2N/A * space for a watermark. 2N/A /* We're DOA if we can't read *lp */ 2N/A * Process the nominal case first: we've been given an actual 2N/A * size argument, rather than the literal "all" 2N/A * Short circuit the check for free space. This may 2N/A * tell us we have enough space when we really don't 2N/A * because each extent loses space to a watermark, but 2N/A * it will always tell us there isn't enough space 2N/A * correctly. Worst case we do some extra work. 2N/A * First see if we can extend the last extent for an 2N/A * The offset test reflects the 2N/A * inclusion of the watermark in the extent 2N/A * If we decided not to align here, we should 2N/A * also reset "alignment" so we don't bother 2N/A * If a free extent follows our last allocated 2N/A * extent, then remove the last allocated 2N/A * extent and increase the size of the free 2N/A * extent to overlap it, then allocate the 2N/A * total space from the new free extent. 2N/A /* No watermark space needed */ 2N/A * now remove the original allocated 2N/A * node. We may have overlapping 2N/A * extents for a short time before 2N/A * this node is removed. 2N/A * Next, see if we can find a single allocation for 2N/A * the remainder. This may make fragmentation worse 2N/A * in some cases, but there's no good way to allocate 2N/A * that doesn't have a highly fragmented corner case. 2N/A * The length test should include space for 2N/A * Shortcut for extents that have been 2N/A * previously added to pad out the 2N/A * Round up so the data space begins 2N/A * on a properly aligned boundary. 2N/A * This is only necessary in case the 2N/A * watermark size is ever greater than 2N/A * one. It'll never happen, of 2N/A * course; we'll get rid of watermarks 2N/A * before we make 'em bigger. 2N/A * Adjust the length to account for 2N/A * the space lost above (if any) 2N/A * If the request could not be satisfied by extending 2N/A * the last extent or by a single extent, then put 2N/A * multiple smaller extents together until the request 2N/A * Shortcut for extents that have been 2N/A * previously added to pad out the 2N/A * Round up so the data space begins 2N/A * on a properly aligned boundary. 2N/A * This is only necessary in case the 2N/A * watermark size is ever greater than 2N/A * one. It'll never happen, of 2N/A * course; we'll get rid of watermarks 2N/A * before we make 'em bigger. 2N/A * Adjust the length to account for 2N/A * the space lost above (if any) 2N/A * Adjust the length to be properly 2N/A * aligned if it is NOT to be the 2N/A * last extent in the soft partition. 2N/A * meta_sp_alloc_by_ext() expects the 2N/A * allocation length to include the watermark 2N/A * size, which is why we don't simply pass in 2N/A * If there was not enough space we can throw it all 2N/A * away since no real work has been done yet. 2N/A * Otherwise, the literal "all" was specified: allocate all 2N/A * available free space. Don't bother with alignment. 2N/A /* First, extend the last extent if this is a grow */ 2N/A * If a free extent follows our last allocated 2N/A * extent, then remove the last allocated 2N/A * extent and increase the size of the free 2N/A * extent to overlap it, then allocate the 2N/A * total space from the new free extent. 2N/A * now remove the original allocated 2N/A * node. We may have overlapping 2N/A * extents for a short time before 2N/A * this node is removed. 2N/A /* Next, grab all remaining free space */ 2N/A * meta_sp_alloc_by_ext() expects the 2N/A * allocation length to include the 2N/A * watermark size, which is why we 2N/A * don't simply pass in alloc_len 2N/A * Make sure the callers hit a no space error if we 2N/A * didn't actually find anything. 2N/A * FUNCTION: meta_sp_alloc_by_list() 2N/A * INPUT: sp - the set name for the device the node belongs to 2N/A * np - the name of the device the node belongs to 2N/A * head - the head of the list, must be NULL for empty list 2N/A * oblist - an extent list containing requested nodes to allocate 2N/A * OUTPUT: head - the new head pointer 2N/A * RETURNS: int - -1 if error, the number of new extents on success 2N/A * PURPOSE: allocates extents from free space to satisfy the requested 2N/A * extent list. This is primarily used for the -o/-b options 2N/A * where the user may specifically request extents to allocate. 2N/A * Each extent in the oblist must be a subset (inclusive) of a 2N/A * free extent and may not overlap each other. This 2N/A * function sets the EXTFLG_UPDATE flag for each node that 2N/A * requires a watermark update after allocating. 2N/A /* Make sure the allocation is within the free extent */ 2N/A * ************************************************************************** 2N/A * Extent List Population Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_extlist_from_namelist() 2N/A * INPUT: sp - the set name for the device the node belongs to 2N/A * spnplp - the namelist of soft partitions to build a list from 2N/A * OUTPUT: extlist - the extent list built from the SPs in the namelist 2N/A * ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: builds an extent list representing the soft partitions 2N/A * specified in the namelist. Each extent in each soft 2N/A * partition is added to the list with the type EXTTYP_ALLOC. 2N/A * The EXTFLG_UPDATE flag is not set on any nodes. Each 2N/A * extent in the list includes the space occupied by the 2N/A * watermark, which is not included in the unit structures. 2N/A * Now go through the soft partitions and add a node to the used 2N/A * list for each allocated extent. 2N/A /* get the unit structure */ 2N/A * subtract from offset and add to the length 2N/A * to account for the watermark, which is not 2N/A * contained in the extents in the unit structure. 2N/A * FUNCTION: meta_sp_extlist_from_wm() 2N/A * INPUT: sp - the set name for the device the node belongs to 2N/A * compnp - the name of the device to scan watermarks on 2N/A * OUTPUT: extlist - the extent list built from the SPs in the namelist 2N/A * ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: builds an extent list representing the soft partitions 2N/A * specified in the namelist. Each extent in each soft 2N/A * partition is added to the list with the type EXTTYP_ALLOC. 2N/A * The EXTFLG_UPDATE flag is not set on any nodes. Each 2N/A * extent in the list includes the space occupied by the 2N/A * watermark, which is not included in the unit structures. 2N/A /* get the set and name pointers */ 2N/A * For the MN set, meta_init_make_device needs to 2N/A * be run on all the nodes so the entries for the 2N/A * softpart device name and its comp can be created 2N/A * in the same order in the replica namespace. If 2N/A * we have it run on mdmn_do_iocset then the mddbs 2N/A * will be out of sync between master node and slave 2N/A /* insert watermark into extent list */ 2N/A /* if we see the end watermark, we're done */ 2N/A /* clear out set and name pointers for next iteration */ 2N/A * ************************************************************************** 2N/A * Print (metastat) Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_short_print() 2N/A * INPUT: msp - the unit structure to display 2N/A * fp - the file pointer to send output to 2N/A * options - print options from the command line processor 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: display a short report of the soft partition in md.tab 2N/A * form, primarily used for metastat -p. 2N/A /* print name and -p */ 2N/A /* print the component */ 2N/A * Always print the full path name 2N/A /* print out each extent */ 2N/A * FUNCTION: meta_sp_status_to_name() 2N/A * INPUT: xsp_status - the status value to convert to a string 2N/A * tstate - transient errored device state. If set the 2N/A * device is Unavailable 2N/A * RETURNS: char * - a pointer to the string representing the status value 2N/A * PURPOSE: return an internationalized string representing the 2N/A * status value for a soft partition. The strings are 2N/A * strdup'd and must be freed by the caller. 2N/A * Check to see if we have MD_INACCESSIBLE set. This is the only valid 2N/A * value for an 'Unavailable' return. tstate can be set because of 2N/A * other multi-node reasons (e.g. ABR being set) 2N/A * FUNCTION: meta_sp_report() 2N/A * INPUT: sp - the set name for the unit being displayed 2N/A * msp - the unit structure to display 2N/A * nlpp - pass back the large devs 2N/A * fp - the file pointer to send output to 2N/A * options - print options from the command line processor 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: print a full report of the device specified 2N/A /* Determine if device is available before displaying status */ 2N/A /* print out "State" to be consistent with other metadevices */ 2N/A " State: %s - Application Based Recovery (ABR)\n"),
2N/A /* print component details */ 2N/A * Building a format string on the fly that will 2N/A * be used in (f)printf. This allows the length 2N/A * of the ctd to vary from small to large without 2N/A "\t%-*.*s %-12.12s %-5.5s %s\n",
2N/A /* populate the key in the name_p structure */ 2N/A /* determine if devid does NOT exist */ 2N/A * This allows the length 2N/A * of the ctd to vary from small to large without 2N/A /* print the headers */ 2N/A /* print out each extent */ 2N/A /* If PRINT_TIMES option is ever supported, add output here */ 2N/A /* separate records with a newline */ 2N/A * FUNCTION: meta_sp_print() 2N/A * INPUT: sp - the set name for the unit being displayed 2N/A * np - the name of the device to print 2N/A * fname - ??? not used 2N/A * fp - the file pointer to send output to 2N/A * options - print options from the command line processor 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: print a full report of the device specified by metastat. 2N/A * This is the main entry point for printing. 2N/A /* should always have the same set */ 2N/A /* print all the soft partitions */ 2N/A /* recusively print them out */ 2N/A * one problem with the rval of -1 here is that 2N/A * the error gets "lost" when the next device is 2N/A * printed, but we want to print them all anyway. 2N/A /* clean up, return success */ 2N/A /* get the unit structure */ 2N/A /* check for parented */ 2N/A /* print appropriate detail */ 2N/A * Print underlying metadevices if they are parented to us and 2N/A * if the info for the underlying metadevice has not been printed. 2N/A /* get the unit structure for the subdevice */ 2N/A /* If info not already printed, recurse */ 2N/A * ************************************************************************** 2N/A * Watermark Manipulation Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_get_start() 2N/A * INPUT: sp - the operating set 2N/A * np - device upon which the sp is being built 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: daddr_t - -1 if error, otherwise the start block 2N/A * PURPOSE: Encapsulate the determination of the start block of the 2N/A * device upon which the sp is built or being built. 2N/A * FUNCTION: meta_sp_update_wm_common() 2N/A * INPUT: sp - the operating set 2N/A * msp - a pointer to the XDR unit structure 2N/A * extlist - the extent list specifying watermarks to update 2N/A * iocval - either MD_IOC_SPUPDATEWM or MD_MN_IOC_SPUPDATEWM 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: steps backwards through the extent list updating 2N/A * watermarks for all extents with the EXTFLG_UPDATE flag 2N/A * set. Writing the watermarks guarantees consistency when 2N/A * extents must be broken into pieces since the original 2N/A * watermark will be the last to be updated, and will be 2N/A * changed to point to a new watermark that is already 2N/A * known to be consistent. If one of the writes fails, the 2N/A * original watermark stays intact and none of the changes 2N/A * find the last node so we can write the watermarks backwards 2N/A * and count watermarks to update so we can allocate space 2N/A /* update watermark */ 2N/A /* fill in the volume name and set name */ 2N/A /* Generate the checksum */ 2N/A /* record the extent offset */ 2N/A /* Advance the placeholders */ 2N/A * FUNCTION: meta_sp_clear_wm() 2N/A * INPUT: sp - the operating set 2N/A * msp - the unit structure for the soft partition to clear 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: steps through the extents for a soft partition unit and 2N/A * creates an extent list designed to mark all of the 2N/A * watermarks for those extents as free. The extent list 2N/A * is then passed to meta_sp_update_wm() to actually write 2N/A * the watermarks out. 2N/A /* for each watermark must set the flag to SP_FREE */ 2N/A /* update watermarks */ 2N/A * FUNCTION: meta_sp_read_wm() 2N/A * INPUT: sp - setname for component 2N/A * compnp - mdname_t for component 2N/A * offset - the offset of the watermark to read (sectors) 2N/A * OUTPUT: wm - the watermark structure to read into 2N/A * ep - return error pointer 2N/A * RETURNS: int - -1 if error, 0 on success 2N/A * PURPOSE: seeks out to the requested offset and reads a watermark. 2N/A * It then verifies that the magic number is correct and 2N/A * that the checksum is valid, returning an error if either 2N/A * make sure block offset does not overflow 2^64 bytes and it's a 2N/A * multiple of the block size. 2N/A "Extent header read failed, block %llu.\n"),
offset);
2N/A /* make sure magic number is correct */ 2N/A "found incorrect magic number %x, expected %x.\n"),
2N/A * Pass NULL for the device name as we don't have 2N/A * valid watermark contents. 2N/A "found incorrect checksum %x.\n"),
2N/A * ************************************************************************** 2N/A * ************************************************************************** 2N/A * IMPORTANT NOTE: This is a static function that assumes that 2N/A * its input parameters have been checked and 2N/A * have valid values that lie within acceptable 2N/A * FUNCTION: meta_sp_enough_space() 2N/A * INPUT: desired_number_of_sps - the number of soft partitions desired; 2N/A * desired_sp_size - the desired soft partition size in blocks; 2N/A * extent_listpp - a reference to a reference to an extent 2N/A * list that lists the extents on a device; 2N/A * must be a reference to a reference to a 2N/A * alignment - the desired data space alignment for the sp's 2N/A * OUTPUT: boolean_t return value 2N/A * RETURNS: boolean_t - B_TRUE if there's enough space in the extent 2N/A * list to create the desired soft partitions, 2N/A * B_FALSE if there's not enough space 2N/A * PURPOSE: determines whether there's enough free space in an extent 2N/A * list to allow creation of a set of soft partitions 2N/A * Use the extent allocation algorithm implemented by 2N/A * meta_sp_alloc_by_len() to test whether the free 2N/A * extents in the extent list referenced by *extent_listpp 2N/A * contain enough space to accomodate a soft partition 2N/A * of size desired_ext_length. 2N/A * Repeat the test <desired_number_of_sps> times 2N/A * or until it fails, whichever comes first, 2N/A * each time allocating the extents required to 2N/A * create the soft partition without actually 2N/A * creating the soft partition. 2N/A * IMPORTANT NOTE: This is a static function that calls other functions 2N/A * that check its mdsetnamep and device_mdnamep 2N/A * input parameters, but expects extent_listpp to 2N/A * be a initialized to a valid address to which 2N/A * it can write a reference to the extent list that 2N/A * FUNCTION: meta_sp_get_extent_list() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the device for 2N/A * which the extents are to be listed 2N/A * device_mdnamep - a reference to the mdname_t structure 2N/A * for the device for which the extents 2N/A * OUTPUT: *extent_listpp - a reference to the extent list for 2N/A * the device; NULL if the function fails 2N/A * *ep - the libmeta error encountered, if any 2N/A * RETURNS: boolean_t - B_TRUE if the function call was successful, 2N/A * PURPOSE: gets the extent list for a device 2N/A "meta_sp_get_extent_list:meta_sp_get_start");
2N/A "meta_sp_get_extent_list:metagetsize");
2N/A * Sanity check: the start block will have skipped an integer 2N/A * number of cylinders, C. C will usually be zero. If (C > 0), 2N/A * and the disk slice happens to only be C cylinders in total 2N/A * size, we'll fail this check. 2N/A * After this point, we will have allocated resources, so any 2N/A * failure returns must be through the supplied "fail" label 2N/A * to properly deallocate things. 2N/A * Create an empty extent list that starts one watermark past 2N/A * the start block of the device and ends one watermark before 2N/A * the end of the device. 2N/A * Get the list of soft partitions that are already on the 2N/A "meta_sp_get_extent_list:meta_sp_get_by_component");
2N/A * If there are soft partitions on the device, add the 2N/A * extents used in them to the extent list. 2N/A "meta_sp_extlist_from_namelist");
2N/A * Add free extents to the extent list to represent 2N/A * the remaining regions of free space on the 2N/A * meta_sp_list_free sets *extent_listpp to NULL. 2N/A * IMPORTANT NOTE: This is a static function that calls other functions 2N/A * that check its mdsetnamep and mddrivenamep 2N/A * input parameters, but expects extent_listpp to 2N/A * be a initialized to a valid address to which 2N/A * it can write a reference to the extent list that 2N/A * FUNCTION: meta_sp_get_extent_list_for_drive() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the drive for 2N/A * which the extents are to be listed 2N/A * mddrivenamep - a reference to the mddrivename_t structure 2N/A * for the drive for which the extents 2N/A * OUTPUT: *extent_listpp - a reference to the extent list for 2N/A * the drive; NULL if the function fails 2N/A * RETURNS: boolean_t - B_TRUE if the function call was successful, 2N/A * PURPOSE: gets the extent list for a drive when the entire drive 2N/A * is to be soft partitioned 2N/A * Create an extent list that starts with 2N/A * a reserved extent that ends at the start 2N/A * of the usable space on slice zero of the 2N/A * proposed VTOC, ends with an extent that 2N/A * reserves space for a watermark at the end 2N/A * of slice zero, and contains a single free 2N/A * extent that occupies the rest of the space 2N/A * Don't use metagetstart() or metagetsize() to 2N/A * find the usable space. They query the mdname_t 2N/A * structure that represents an actual device to 2N/A * determine the amount of space on the device that 2N/A * contains metadata and the total amount of space 2N/A * on the device. Since this function creates a 2N/A * proposed extent list that doesn't reflect the 2N/A * state of an actual device, there's no mdname_t 2N/A * structure to be queried. 2N/A * When a drive is reformatted to prepare for 2N/A * soft partitioning, all of slice seven is 2N/A * reserved for metadata, all of slice zero is 2N/A * available for soft partitioning, and all other 2N/A * slices on the drive are empty. The proposed 2N/A * extent list for the drive therefore contains 2N/A * only three extents: a reserved extent that ends 2N/A * at the start of the usable space on slice zero, 2N/A * a single free extent that occupies all the usable 2N/A * space on slice zero, and an ending extent that 2N/A * reserves space for a watermark at the end of 2N/A * FUNCTION: meta_sp_can_create_sps() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the device for 2N/A * which the extents are to be listed 2N/A * mdnamep - a reference to the mdname_t of the device 2N/A * on which the soft parititions are to be created 2N/A * number_of_sps - the desired number of soft partitions 2N/A * sp_size - the desired soft partition size 2N/A * OUTPUT: boolean_t return value 2N/A * RETURNS: boolean_t - B_TRUE if the soft partitionns can be created, 2N/A * PURPOSE: determines whether a set of soft partitions can be created 2N/A * We don't really care about an error return from the 2N/A * alignment call; that will just result in passing zero, 2N/A * which will be interpreted as no alignment. 2N/A * FUNCTION: meta_sp_can_create_sps_on_drive() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the drive for 2N/A * which the extents are to be listed 2N/A * mddrivenamep - a reference to the mddrivename_t of the drive 2N/A * on which the soft parititions are to be created 2N/A * number_of_sps - the desired number of soft partitions 2N/A * sp_size - the desired soft partition size 2N/A * OUTPUT: boolean_t return value 2N/A * RETURNS: boolean_t - B_TRUE if the soft partitionns can be created, 2N/A * PURPOSE: determines whether a set of soft partitions can be created 2N/A * on a drive if the entire drive is soft partitioned 2N/A * We don't care about alignment on the space call because 2N/A * we're specifically dealing with a drive, which will have no 2N/A * inherent alignment. 2N/A * FUNCTION: meta_sp_get_free_space() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the device for 2N/A * which the free space is to be returned 2N/A * mdnamep - a reference to the mdname_t of the device 2N/A * for which the free space is to be returned 2N/A * OUTPUT: blkcnt_t return value 2N/A * RETURNS: blkcnt_t - the number of blocks of free space on the device 2N/A * PURPOSE: returns the number of blocks of free space on a device 2N/A * Subtract a safety margin for watermarks when 2N/A * computing the number of blocks available for 2N/A * use. The actual number of watermarks can't 2N/A * be calculated without knowing the exact numbers 2N/A * and sizes of both the free extents and the soft 2N/A * partitions to be created. The calculation is 2N/A * highly complex and error-prone even if those 2N/A * quantities are known. The approximate value 2N/A * 10 * MD_SP_WMSIZE is within a few blocks of the 2N/A * correct value in all practical cases. 2N/A * FUNCTION: meta_sp_get_free_space_on_drive() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the drive for 2N/A * which the free space is to be returned 2N/A * mddrivenamep - a reference to the mddrivename_t of the drive 2N/A * for which the free space is to be returned 2N/A * OUTPUT: blkcnt_t return value 2N/A * RETURNS: blkcnt_t - the number of blocks of free space on the drive 2N/A * PURPOSE: returns the number of blocks of space usable for soft 2N/A * partitions on an entire drive, if the entire drive is 2N/A * Subtract a safety margin for watermarks when 2N/A * computing the number of blocks available for 2N/A * use. The actual number of watermarks can't 2N/A * be calculated without knowing the exact numbers 2N/A * and sizes of both the free extents and the soft 2N/A * partitions to be created. The calculation is 2N/A * highly complex and error-prone even if those 2N/A * quantities are known. The approximate value 2N/A * 10 * MD_SP_WMSIZE is within a few blocks of the 2N/A * correct value in all practical cases. 2N/A * FUNCTION: meta_sp_get_number_of_possible_sps() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the device for 2N/A * which the number of possible soft partitions 2N/A * mdnamep - a reference to the mdname_t of the device 2N/A * for which the number of possible soft partitions 2N/A * OUTPUT: int return value 2N/A * RETURNS: int - the number of soft partitions of the desired size 2N/A * that can be created on the device 2N/A * PURPOSE: returns the number of soft partitions of a given size 2N/A * that can be created on a device 2N/A * Keep allocating space from the extent list 2N/A * for soft partitions of the desired size until 2N/A * there's not enough free space left in the list 2N/A * for another soft partiition of that size. 2N/A * Add one to the number of possible soft partitions 2N/A * for each soft partition for which there is 2N/A * enough free space left. 2N/A * FUNCTION: meta_sp_get_number_of_possible_sps_on_drive() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the drive for 2N/A * which the number of possible soft partitions 2N/A * mddrivenamep - a reference to the mddrivename_t of the drive 2N/A * for which the number of possible soft partitions 2N/A * sp_size - the size in blocks of the proposed soft partitions 2N/A * OUTPUT: int return value 2N/A * RETURNS: int - the number of soft partitions of the desired size 2N/A * that can be created on the drive 2N/A * PURPOSE: returns the number of soft partitions of a given size 2N/A * that can be created on a drive, if the entire drive is 2N/A * Keep allocating space from the extent list 2N/A * for soft partitions of the desired size until 2N/A * there's not enough free space left in the list 2N/A * for another soft partition of that size. 2N/A * Add one to the number of possible soft partitions 2N/A * for each soft partition for which there is 2N/A * enough free space left. 2N/A * Since it's a drive, not a metadevice, make no 2N/A * assumptions about alignment. 2N/A * FUNCTION: meta_sp_get_possible_sp_size() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the device for 2N/A * which the possible soft partition size 2N/A * mdnamep - a reference to the mdname_t of the device 2N/A * for which the possible soft partition size 2N/A * number_of_sps - the desired number of soft partitions 2N/A * OUTPUT: blkcnt_t return value 2N/A * RETURNS: blkcnt_t - the possible soft partition size in blocks 2N/A * PURPOSE: returns the maximum possible size of each of a given number of 2N/A * soft partitions of equal size that can be created on a device 2N/A * To compensate for space that may have been 2N/A * occupied by watermarks, reduce sp_size by a 2N/A * number of blocks equal to the number of soft 2N/A * partitions desired, and test again to see 2N/A * whether the desired number of soft partitions 2N/A * FUNCTION: meta_sp_get_possible_sp_size_on_drive() 2N/A * INPUT: mdsetnamep - a reference to the mdsetname_t structure 2N/A * for the set containing the drive for 2N/A * which the possible soft partition size 2N/A * mddrivenamep - a reference to the mddrivename_t of the drive 2N/A * for which the possible soft partition size 2N/A * number_of_sps - the desired number of soft partitions 2N/A * OUTPUT: blkcnt_t return value 2N/A * RETURNS: blkcnt_t - the possible soft partition size in blocks 2N/A * PURPOSE: returns the maximum possible size of each of a given number of 2N/A * soft partitions of equal size that can be created on a drive 2N/A * if the entire drive is soft partitioned 2N/A * To compensate for space that may have been 2N/A * occupied by watermarks, reduce sp_size by a 2N/A * number of blocks equal to the number of soft 2N/A * partitions desired, and test again to see 2N/A * whether the desired number of soft partitions 2N/A * ************************************************************************** 2N/A * Unit Structure Manipulation Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_fillextarray() 2N/A * INPUT: mp - the unit structure to fill 2N/A * extlist - the list of extents to fill with 2N/A * PURPOSE: fills in the unit structure extent list with the extents 2N/A * specified by extlist. Only extents in extlist with the 2N/A * EXTFLG_UPDATE flag are changed in the unit structure, 2N/A * and the index into the unit structure is the sequence 2N/A * number in the extent list. After all of the nodes have 2N/A * been updated the virtual offsets in the unit structure 2N/A * are updated to reflect the new lengths. 2N/A /* go through the allocation list and fill in our unit structure */ 2N/A * FUNCTION: meta_sp_createunit() 2N/A * INPUT: np - the name of the device to create a unit structure for 2N/A * compnp - the name of the device the soft partition is on 2N/A * extlist - the extent list to populate the new unit with 2N/A * numexts - the number of extents in the extent list 2N/A * len - the total size of the soft partition (sectors) 2N/A * status - the initial status of the unit structure 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: mp_unit_t * - the new unit structure. 2N/A * PURPOSE: allocates and fills in a new soft partition unit 2N/A * structure to be passed to the soft partitioning driver 2N/A /* fill in fields in common unit structure */ 2N/A /* set up geometry */ 2N/A /* if we're building on metadevice we can't parent */ 2N/A /* fill soft partition-specific fields */ 2N/A /* mdname_t start_blk field is not 64-bit! */ 2N/A /* fill in the extent array */ 2N/A * FUNCTION: meta_sp_updateunit() 2N/A * INPUT: np - name structure for the metadevice being updated 2N/A * old_un - the original unit structure that is being updated 2N/A * extlist - the extent list to populate the new unit with 2N/A * grow_len - the amount by which the partition is being grown 2N/A * numexts - the number of extents in the extent list 2N/A * ep - return error pointer 2N/A * RETURNS: mp_unit_t * - the updated unit structure 2N/A * PURPOSE: allocates and fills in a new soft partition unit structure to 2N/A * be passed to the soft partitioning driver for creation. The 2N/A * old unit structure is first copied in, and then the updated 2N/A * extents are changed in the new unit structure. This is 2N/A * typically used when the size of an existing unit is changed. 2N/A /* allocate new unit structure and copy in old unit */ 2N/A /* update size and geometry information */ 2N/A /* update extent information */ 2N/A * FUNCTION: meta_get_sp() 2N/A * INPUT: sp - the set name for the device to get 2N/A * np - the name of the device to get 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: md_sp_t * - the XDR unit structure for the soft partition 2N/A * PURPOSE: interface to the rest of libmeta for fetching a unit structure 2N/A * for the named device. Just a wrapper for meta_get_sp_common(). 2N/A * FUNCTION: meta_get_sp_common() 2N/A * INPUT: sp - the set name for the device to get 2N/A * np - the name of the device to get 2N/A * fast - whether to use the cache or not (NOT IMPLEMENTED!) 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: md_sp_t * - the XDR unit structure for the soft partition, 2N/A * NULL if np is not a soft partition 2N/A * PURPOSE: common routine for fetching a soft partition unit structure 2N/A /* get miscname and unit */ 2N/A /* allocate soft partition */ 2N/A /* get the common information */ 2N/A /* get soft partition information */ 2N/A * Fill in the key and the start block. Note that the start 2N/A * block in the unit structure is 64 bits but the name pointer 2N/A * only supports 32 bits. 2N/A /* fill in status field */ 2N/A /* allocate the extents */ 2N/A /* do the extents for this soft partition */ 2N/A /* cleanup, return success */ 2N/A /* clean up and return error */ 2N/A * FUNCTION: meta_init_sp() 2N/A * INPUT: spp - the set name for the new device 2N/A * argc - the remaining argument count for the metainit cmdline 2N/A * argv - the remainder of the unparsed command line 2N/A * options - global options parsed by metainit 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - -1 failure, 0 success 2N/A * PURPOSE: provides the command line parsing and name management overhead 2N/A * for creating a new soft partition. Ultimately this calls 2N/A * meta_create_sp() which does the real work of allocating space 2N/A * for the new soft partition. 2N/A /* expect sp name, -p, optional -e, compname, and size parameters */ 2N/A /* grab soft partition name */ 2N/A /* see if it exists already */ 2N/A /* see if -e is there */ 2N/A /* use the whole disk */ 2N/A /* get component name */ 2N/A /* allocate the soft partition */ 2N/A * parse any other command line options, this includes 2N/A * the recovery options -o and -b. The special thing 2N/A * with these options is that the len needs to be 2N/A * kept track of otherwise when the geometry of the 2N/A * "device" is built it will create an invalid geometry 2N/A case 'A':
/* data alignment */ 2N/A case 'o':
/* offset in the partition */ 2N/A case 'b':
/* number of blocks */ 2N/A /* we have a pair of values */ 2N/A * Must have matching pairs of -o and -b flags 2N/A * Can't specify both layout (indicated indirectly by 2N/A * len being set by thye -o/-b cases above) AND 2N/A * sanity check the allocation list 2N/A /* we should be at the end */ 2N/A /* create soft partition */ 2N/A "%s: Soft Partition is setup\n"),
2N/A * FUNCTION: meta_free_sp() 2N/A * INPUT: msp - the soft partition unit to free 2N/A * PURPOSE: provides an interface from the rest of libmeta for freeing a 2N/A * soft partition unit 2N/A * FUNCTION: meta_sp_issp() 2N/A * INPUT: sp - the set name to check 2N/A * np - the name to check 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 means sp,np is a soft partition 2N/A * 1 means sp,np is not a soft partition 2N/A * PURPOSE: determines whether the given device is a soft partition 2N/A * device. This is called by other metadevice check routines. 2N/A * FUNCTION: meta_check_sp() 2N/A * INPUT: sp - the set name to check 2N/A * msp - the unit structure to check 2N/A * options - creation options 2N/A * OUTPUT: repart_options - options to be passed to 2N/A * meta_repartition_drive() 2N/A * ep - return error pointer 2N/A * RETURNS: int - 0 ok to create on this component 2N/A * -1 error or not ok to create on this component 2N/A * PURPOSE: Checks to determine whether the rules for creation of 2N/A * soft partitions allow creation of a soft partition on 2N/A * the device described by the mdname_t structure referred 2N/A * to by msp->compnamep. 2N/A * NOTE: Does NOT check to determine whether the extents 2N/A * described in the md_sp_t structure referred to by 2N/A * msp will fit on the device described by the mdname_t 2N/A * structure located at msp->compnamep. 2N/A /* make sure it is in the set */ 2N/A * check to make sure we can partition this drive. 2N/A * we cannot continue if any of the following are 2N/A * The drive is a metadevice. 2N/A * The drive contains a mounted slice. 2N/A * The drive contains a slice being swapped to. 2N/A * The drive contains slices which are part of other 2N/A * The drive contains a metadb. 2N/A * ensure that we have slice 0 since the disk will be 2N/A * repartitioned in the USE_WHOLE_DISK case. this check 2N/A * is redundant unless the user incorrectly specifies a 2N/A * a fully qualified drive AND slice name (i.e., 2N/A * recognized as a drive name by the metaname code. 2N/A /* only check if the slice really exists */ 2N/A /* check to ensure that it is not already in use */ 2N/A * Up to this point, tests are applied to all 2N/A * Tests inside the body of this 2N/A * conditional are applied only to 2N/A * For slice seven, a metadb is NOT an 2N/A * automatic failure. It merely means 2N/A * that we're not allowed to muck 2N/A * about with the partitioning of that 2N/A * slice. We indicate this by masking 2N/A * in the MD_REPART_LEAVE_REP flag. 2N/A * Skip the remaining tests for slice 2N/A * Tests below this point will be applied to 2N/A * all slices EXCEPT for the replica slice. 2N/A /* check if component is in a metadevice */ 2N/A /* check to see if component has a metadb */ 2N/A * This should be all of the testing necessary when 2N/A * the MDCMD_USE_WHOLE_DISK flag is set; the rest of 2N/A * meta_check_sp() is oriented towards component 2N/A * arguments instead of disks. 2N/A /* check to ensure that it is not already in use */ 2N/A * The component can have one or more soft partitions on it 2N/A * already, but can't be part of any other type of metadevice, 2N/A * so if it is used for a metadevice, but the metadevice 2N/A * isn't a soft partition, return failure. 2N/A }
else {
/* handle metadevices */ 2N/A /* get underlying unit & check capabilities */ 2N/A * FUNCTION: meta_create_sp() 2N/A * INPUT: sp - the set name to create in 2N/A * msp - the unit structure to create 2N/A * oblist - an optional list of requested extents (-o/-b options) 2N/A * options - creation options 2N/A * alignment - data alignment 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 success, -1 error 2N/A * PURPOSE: does most of the work for creating a soft partition. If 2N/A * metainit -p -e was used, first partition the drive. Then 2N/A * create an extent list based on the existing soft partitions 2N/A * and assume all space not used by them is free. Storage for 2N/A * the new soft partition is allocated from the free extents 2N/A * based on the length specified on the command line or the 2N/A * oblist passed in. The unit structure is then committed and 2N/A * the watermarks are updated. Finally, the status is changed to 2N/A * Okay and the process is complete. 2N/A /* validate soft partition */ 2N/A * If -n and -e are both specified, it doesn't make 2N/A * sense to continue without actually partitioning 2N/A /* populate the start_blk field of the component name */ 2N/A /* store name in namespace */ 2N/A * Get a list of the soft partitions that currently reside on 2N/A * the component. We should ALWAYS force reload the cache, 2N/A * because if this is a single creation, there will not BE a 2N/A * cached list, and if we're using the md.tab, we must rebuild 2N/A * the list because it won't contain the previous (if any) 2N/A * get the size of the underlying device. if the size is smaller 2N/A * than or equal to the watermark size, we know there isn't 2N/A * seed extlist with reserved space at the beginning of the volume and 2N/A * enough space for the end watermark. The end watermark always gets 2N/A * updated, but if the underlying device changes size it may not be 2N/A * pointed to until the extent before it is updated. Since the 2N/A * end of the reserved space is where the first watermark starts, 2N/A * the reserved extent should never be marked for updating. 2N/A /* get extent list from -o/-b options or from free space */ 2N/A /* create soft partition */ 2N/A /* if we're not doing anything (metainit -n), return success */ 2N/A * Check to see if we're trying to create a partition on a mirror. If so 2N/A * we may have to enforce an ownership change before writing the 2N/A * For a multi-node environment we have to ensure that the master 2N/A * node owns an underlying mirror before we issue the MD_IOCSET ioctl. 2N/A * If the master does not own the device we will deadlock as the 2N/A * ownership change that will block as the MD_IOCSET is still in 2N/A * progress. To close this window we force an owner change to occur 2N/A * before issuing the MD_IOCSET. We cannot simply open the device and 2N/A * write to it as this will only work for the first soft-partition 2N/A /* first phase of commit. */ 2N/A /* we've successfully committed the record */ 2N/A /* write watermarks */ 2N/A * Special-case for Multi-node sets. As we now have a distributed DRL 2N/A * update mechanism, we _will_ hit the ioctl-within-ioctl deadlock case 2N/A * unless we use a 'special' MN-capable ioctl to stage the watermark 2N/A * update. This only affects the master-node in an MN set. 2N/A /* second phase of commit, set status to MD_SP_OK */ 2N/A * ************************************************************************** 2N/A * Reset (metaclear) Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_reset_common() 2N/A * INPUT: sp - the set name of the device to reset 2N/A * np - the name of the device to reset 2N/A * msp - the unit structure to reset 2N/A * options - metaclear options 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 success, -1 error 2N/A * PURPOSE: "resets", or more accurately deletes, the soft partition 2N/A * specified. First the state is set to "deleting" and then the 2N/A * watermarks are all cleared out. Once the watermarks have been 2N/A * updated, the unit structure is deleted from the metadb. 2N/A /* make sure that nobody owns us */ 2N/A /* make sure that the soft partition isn't open */ 2N/A /* fill in reset params */ 2N/A * clear soft partition - phase one. 2N/A * place the soft partition into the "delete pending" state. 2N/A * Now clear the watermarks. If the force flag is specified, 2N/A * ignore any errors writing the watermarks and delete the unit 2N/A * structure anyway. An error may leave the on-disk format in a 2N/A * corrupt state. If force is not specified and we fail here, 2N/A * the soft partition will remain in the "delete pending" state. 2N/A * clear soft partition - phase two. 2N/A * the driver removes the soft partition from the metadb and 2N/A * zeros out incore version. 2N/A * Wait for the /dev to be cleaned up. Ignore the return 2N/A * value since there's not much we can do. 2N/A "%s: Soft Partition is cleared\n"),
2N/A * if told to recurse and on a metadevice, then attempt to 2N/A * clear the subdevices. Indicate failure if the clear fails. 2N/A * FUNCTION: meta_sp_reset() 2N/A * INPUT: sp - the set name of the device to reset 2N/A * np - the name of the device to reset 2N/A * options - metaclear options 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 success, -1 error 2N/A * PURPOSE: provides the entry point to the rest of libmeta for deleting a 2N/A * soft partition. If np is NULL, then soft partitions are 2N/A * all deleted at the current level and then recursively deleted. 2N/A * Otherwise, if a name is specified either directly or as a 2N/A * result of a recursive operation, it deletes only that name. 2N/A * Since something sitting under a soft partition may be parented 2N/A * to it, we have to reparent that other device to another soft 2N/A * partition on the same component if we're deleting the one it's 2N/A * meta_reset_all sets MDCMD_RECURSE, but this behavior 2N/A * is incorrect for soft partitions. We want to clear 2N/A * all soft partitions at a particular level in the 2N/A * metadevice stack before moving to the next level. 2N/A * Thus, we clear MDCMD_RECURSE from the options. 2N/A /* for each soft partition */ 2N/A * meta_reset_all calls us twice to get soft 2N/A * partitions at the top and bottom of the stack. 2N/A * thus, if we have a parent, we'll get deleted 2N/A * If this is a multi-node set, we send a series 2N/A * of individual metaclear commands. 2N/A /* cleanup return status */ 2N/A /* check the name */ 2N/A /* get the unit structure */ 2N/A /* clear out reset parameters */ 2N/A /* get sp's on this component */ 2N/A /* no sp's on this device. error! */ 2N/A /* last sp on this device, so we deparent */ 2N/A /* have to reparent this metadevice */ 2N/A * this isn't the softpart we are deleting, 2N/A * so use this device as the new parent. 2N/A * FUNCTION: meta_sp_reset_component() 2N/A * INPUT: sp - the set name of the device to reset 2N/A * name - the string name of the device to reset 2N/A * options - metaclear options 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 success, -1 error 2N/A * PURPOSE: provides the ability to delete all soft partitions on a 2N/A * specified device (metaclear -p). It first gets all of the 2N/A * soft partitions on the component and then deletes each one 2N/A /* If we're starting out with no soft partitions, it's an error */ 2N/A * clear all soft partitions on this component. 2N/A * NOTE: we reparent underlying metadevices as we go so that 2N/A * things stay sane. Also, if we encounter an error, we stop 2N/A * and go no further in case recovery might be needed. 2N/A /* clear out reset parameters */ 2N/A /* check the name */ 2N/A /* get the unit structure */ 2N/A /* clear soft partition */ 2N/A * ************************************************************************** 2N/A * Grow (metattach) Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_sp_attach() 2N/A * INPUT: sp - the set name of the device to attach to 2N/A * np - the name of the device to attach to 2N/A * addsize - the unparsed string holding the amount of space to add 2N/A * options - metattach options 2N/A * alignment - data alignment 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 success, -1 error 2N/A * PURPOSE: grows a soft partition by reading in the existing unit 2N/A * structure and setting its state to Growing, allocating more 2N/A * space (similar to meta_create_sp()), updating the watermarks, 2N/A * and then writing out the new unit structure in the Okay state. 2N/A /* should have the same set */ 2N/A /* make sure we don't have a parent */ 2N/A * NOTE: the fast option to metakeyname is 0 as opposed to 1 2N/A * If this was not the case we would suffer the following 2N/A * assertion failure: 2N/A * Assertion failed: type1 != MDT_FAST_META && type1 != MDT_FAST_COMP 2N/A * file meta_check.x, line 315 2N/A * I guess this is because we have not "seen" this drive before 2N/A * and hence hit the failure - this is of course the attach routine 2N/A /* metakeyname does not fill in the key. */ 2N/A /* work out the space on the component that we are dealing with */ 2N/A * see if the component has been soft partitioned yet, or if an 2N/A * seed extlist with reserved space at the beginning of the volume and 2N/A * enough space for the end watermark. The end watermark always gets 2N/A * updated, but if the underlying device changes size it may not be 2N/A * pointed to until the extent before it is updated. Since the 2N/A * end of the reserved space is where the first watermark starts, 2N/A * the reserved extent should never be marked for updating. 2N/A /* allocate new unit structure and copy in old unit */ 2N/A /* If running in dryrun mode (-n option), we're done here */ 2N/A "%s: Soft Partition would grow\n"),
2N/A /* update all watermarks */ 2N/A /* second phase of commit, set status to MD_SP_OK */ 2N/A "%s: Soft Partition has been grown\n"),
2N/A * ************************************************************************** 2N/A * Recovery (metarecover) Functions * 2N/A * ************************************************************************** 2N/A * FUNCTION: meta_recover_sp() 2N/A * INPUT: sp - the name of the set we are recovering on 2N/A * compnp - name pointer for device we are recovering on 2N/A * argc - argument count 2N/A * argv - left over arguments not parsed by metarecover command 2N/A * options - metarecover options 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: parse soft partitioning-specific metarecover options and 2N/A * dispatch to the appropriate function to handle recovery. 2N/A * For a MN set, this operation must be performed on the master 2N/A * as it is responsible for maintaining the watermarks 2N/A * if no additional arguments are passed, metarecover should 2N/A * validate both on-disk and metadb structures as well as 2N/A * checking that both are consistent with each other 2N/A * Ensure that there is no existing valid record for this 2N/A * soft-partition. If there is we have nothing to do. 2N/A /* validate and recover from on-disk structures */ 2N/A /* validate and recover from metadb structures */ 2N/A * FUNCTION: meta_sp_display_exthdr() 2N/A * PURPOSE: print header line for sp_ext_node_t information. to be used 2N/A * in conjunction with meta_sp_display_ext(). 2N/A * FUNCTION: meta_sp_display_ext() 2N/A * INPUT: ext - extent to display 2N/A * PURPOSE: print selected fields from sp_ext_node_t. 2N/A /* print extent information */ 2N/A * FUNCTION: meta_sp_checkseq() 2N/A * INPUT: extlist - list of extents to be checked 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: check soft partition sequence numbers. this function assumes 2N/A * that a list of extents representing 1 or more soft partitions 2N/A * is passed in sorted in sequence number order. within a 2N/A * single soft partition, there may not be any missing or 2N/A * duplicate sequence numbers. 2N/A "%s: sequence numbers are " 2N/A "incorrect: %d should be %d\n"),
2N/A * FUNCTION: meta_sp_resolve_name_conflict() 2N/A * INPUT: sp - name of set we're are recovering in. 2N/A * old_np - name pointer of soft partition we found on disk. 2N/A * OUTPUT: new_np - name pointer for new soft partition name. 2N/A * ep - error pointer returned. 2N/A * RETURNS: int - 0 - name not replace, 1 - name replaced, -1 - error 2N/A * PURPOSE: Check to see if the name of one of the soft partitions we found 2N/A * on disk already exists in the metadb. If so, prompt for a new 2N/A * name. In addition, we keep a static array of names that 2N/A * will be recovered from this device since these names don't 2N/A * exist in the configuration at this point but cannot be 2N/A * recovered more than once. 2N/A /* see if it exists already */ 2N/A /* name exists, ask the user for a new one */ 2N/A "WARNING: A soft partition named %s was found in the extent\n" 2N/A "headers, but this name already exists in the metadb " 2N/A "In order to continue recovery you must supply\n" 2N/A "Would you like to continue and supply a new name? (yes/no) "));
2N/A /* get the new name */ 2N/A "for this soft partition (dXXXX) "));
2N/A /* remove newline character */ 2N/A "Invalid metadevice name\n"));
2N/A "Invalid metadevice name\n"));
2N/A /* make sure the name isn't already being used */ 2N/A "That name already exists\n"));
2N/A /* got a new name, place in used array and return */ 2N/A * FUNCTION: meta_sp_validate_wm() 2N/A * INPUT: sp - set name we are recovering in 2N/A * compnp - name pointer for device we are recovering from 2N/A * options - metarecover options 2N/A * OUTPUT: ep - error pointer returned 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: validate and display watermark configuration. walk the 2N/A * on-disk watermark structures and validate the information 2N/A * found within. since a watermark configuration is 2N/A * "self-defining", the act of traversing the watermarks 2N/A * is part of the validation process. 2N/A "Verifying on-disk structures on %s.\n"),
2N/A * for each watermark, build an ext_node, place on list. 2N/A /* print out what we found */ 2N/A "No extent headers found on %s.\n"),
2N/A "The following extent headers were found on %s.\n"),
2N/A "%s: On-disk structures invalid or " 2N/A "no soft partitions found.\n"),
2N/A /* count number of soft partitions */ 2N/A /* check sequence numbers */ 2N/A "Checking sequence numbers.\n"));
2N/A * FUNCTION: meta_sp_validate_unit() 2N/A * INPUT: sp - name of set we are recovering in 2N/A * compnp - name of component we are recovering from 2N/A * options - metarecover options 2N/A * OUTPUT: ep - error pointer returned 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: validate and display metadb configuration. begin by getting 2N/A * all soft partitions built on the specified component. get 2N/A * the unit structure for each one and validate the fields within. 2N/A "%s: Validating soft partition metadb entries.\n"),
2N/A /* get all soft partitions on component */ 2N/A /* Now go through the soft partitions and check each one */ 2N/A /* get the unit structure */ 2N/A /* verify generic unit structure parameters */ 2N/A "\nVerifying device %s.\n"),
2N/A * MD_SP_LAST is an invalid state and is always the 2N/A "%s: status value %u is out of range.\n"),
2N/A "%s: Status \"%s\" is valid.\n"),
2N/A /* Now verify each extent */ 2N/A "%s: virtual offset for extent %u " 2N/A "is inconsistent, expected %llu, " 2N/A /* make sure extent does not drop off the end */ 2N/A "%s: extent %u at offset %llu, " 2N/A "length %llu exceeds the size of the " 2N/A "%s: Soft Partition metadb configuration is valid\n"),
2N/A * FUNCTION: meta_sp_validate_wm_and_unit() 2N/A * INPUT: sp - name of set we are recovering in 2N/A * compnp - name of device we are recovering from 2N/A * options - metarecover options 2N/A * OUTPUT: ep - error pointer returned 2N/A * RETURNS: int - 0 - success, -1 error 2N/A * PURPOSE: cross-validate and display watermarks and metadb records. 2N/A * get both the unit structures for the soft partitions built 2N/A * on the specified component and the watermarks found on that 2N/A * component and check to make sure they are consistent with 2N/A /* get unit structure list */ 2N/A * step through both lists and compare allocated nodes. Free 2N/A * nodes and end watermarks may differ between the two but 2N/A * that's generally ok, and if they're wrong will typically 2N/A * cause misplaced allocated extents. 2N/A "allocations match extent headers.\n"),
np->
cname);
2N/A /* find next allocated extents in each list */ 2N/A "Metadb extent:\n"));
2N/A "Extent header extent:\n"));
2N/A * if the offsets aren't equal, only increment the 2N/A * lowest one in hopes of getting the lists back in sync. 2N/A * if both lists aren't at the end then there are extra 2N/A * allocated nodes in one of them. 2N/A "%s: extent headers contain allocations not in " 2N/A "%s: metadb contains allocations not in the extent " 2N/A "%s: Soft Partition metadb matches extent " 2N/A "%s: Soft Partition metadb does not match extent " 2N/A * FUNCTION: meta_sp_validate_exts() 2N/A * INPUT: compnp - name pointer for device we are recovering from 2N/A * wmext - extent node representing watermark 2N/A * unitext - extent node from unit structure 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 - succes, mdmderror return code - error 2N/A * PURPOSE: Takes two extent nodes and checks them against each other. 2N/A * offset, length, sequence number, set, and name are compared. 2N/A "%s: unit structure and extent header offsets differ.\n"),
2N/A "%s: unit structure and extent header lengths differ.\n"),
2N/A "%s: unit structure and extent header sequence numbers " 2N/A "%s: unit structure and extent header types differ.\n"),
2N/A * If one has a set pointer and the other doesn't, error. 2N/A * If both extents have setnames, then make sure they match 2N/A * If both are NULL, it's ok, they match. 2N/A "%s: unit structure and extent header set values " 2N/A "%s: unit structure and extent header set names " 2N/A * If one has a name pointer and the other doesn't, error. 2N/A * If both extents have names, then make sure they match 2N/A * If both are NULL, it's ok, they match. 2N/A "%s: unit structure and extent header name values " 2N/A "%s: unit structure and extent header names " 2N/A * FUNCTION: update_sp_status() 2N/A * INPUT: sp - name of set we are recovering in 2N/A * minors - pointer to an array of soft partition minor numbers 2N/A * num_sps - number of minor numbers in array 2N/A * status - new status to be applied to all soft parts in array 2N/A * mn_set - set if current set is a multi-node set 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: update status of soft partitions to new status. minors is an 2N/A * array of minor numbers to apply the new status to. 2N/A * If mn_set is set, a message is sent to all nodes in the 2N/A * cluster to update the status locally. 2N/A "Error updating status on recovered soft " 2N/A * FUNCTION: meta_sp_recover_from_wm() 2N/A * INPUT: sp - name of set we are recovering in 2N/A * compnp - name pointer for component we are recovering from 2N/A * options - metarecover options 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: update metadb records to match watermarks. begin by getting 2N/A * an extlist representing all soft partitions on the component. 2N/A * then build a unit structure for each soft partition. 2N/A * notify user of changes, then commit each soft partition to 2N/A * the metadb one at a time in the "recovering" state. update 2N/A * any watermarks that may need it (to reflect possible name 2N/A * changes), and, finally, set the status of all recovered 2N/A * partitions to the "OK" state at once. 2N/A * if this component appears in another metadevice already, do 2N/A * NOT recover from it. 2N/A /* set flag if dealing with a MN set */ 2N/A * for each watermark, build an ext_node, place on list. 2N/A /* count number of soft partitions */ 2N/A /* allocate array of unit structure pointers */ 2N/A * build unit structures from list of ext_nodes. 2N/A * if we made it here, we are at a soft partition 2N/A * boundary in the list. 2N/A * insert into the update list for 2N/A /* store name in namespace */ 2N/A /* send message to all nodes to return key */ 2N/A /* create the unit structure */ 2N/A "printing newly created unit structure");
2N/A /* place in unit structure array */ 2N/A /* display configuration updates */ 2N/A "The following soft partitions were found and will be added to\n" 2N/A "your metadevice configuration.\n"));
2N/A /* ask user for confirmation */ 2N/A "WARNING: You are about to add one or more soft partition\n" 2N/A "metadevices to your metadevice configuration. If there\n" 2N/A "appears to be an error in the soft partition(s) displayed\n" 2N/A "above, do NOT proceed with this recovery operation.\n"));
2N/A "Are you sure you want to do this (yes/no)? "));
2N/A /* commit records one at a time */ 2N/A * If this is an MN set, send the MD_IOCSET ioctl to all nodes 2N/A * Calculate message size. md_mn_msg_iocset_t only 2N/A * contains one extent, so increment the size to 2N/A * include all extents 2N/A "%s: Error committing record to metadb.\n"),
2N/A /* note that we've committed a record */ 2N/A /* update any watermarks that need it */ 2N/A * Check to see if we're trying to create a partition 2N/A * on a mirror. If so we may have to enforce an 2N/A * ownership change before writing the watermark out. 2N/A * If this is a MN set and the component is a mirror, 2N/A * change ownership to this node in order to write the 2N/A "%s: Error updating extent headers.\n"),
2N/A "%s: Error updating extent headers " 2N/A * If we have changed ownership earlier and prevented any 2N/A * ownership changes, we can now allow ownership changes 2N/A /* update status of all soft partitions to OK */ 2N/A "Soft Partitions recovered from device.\n"),
2N/A * if we haven't committed any softparts, either because of an 2N/A * error or because the user decided not to proceed, delete 2N/A * namelist key for the component 2N/A "Soft Partitions NOT recovered from device.\n"),
2N/A * FUNCTION: meta_sp_recover_from_unit() 2N/A * INPUT: sp - name of set we are recovering in 2N/A * compnp - name of component we are recovering from 2N/A * options - metarecover options 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: update watermarks to match metadb records. begin by getting 2N/A * a namelist representing all soft partitions on the specified 2N/A * component. then, build an extlist representing the soft 2N/A * partitions, filling in the freespace extents. notify user 2N/A * of changes, place all soft partitions into the "recovering" 2N/A * state and update the watermarks. finally, return all soft 2N/A * partitions to the "OK" state. 2N/A /* set flag if dealing with a MN set */ 2N/A * Save the XDR unit structure for one of the soft partitions; 2N/A * we'll use this later to provide metadevice context to 2N/A * update the watermarks so the device can be resolved by 2N/A * devid instead of dev_t. 2N/A "Updating extent headers on device %s from metadb.\n\n"),
2N/A "The following extent headers will be written:\n"));
2N/A /* mark every node for updating except the reserved space */ 2N/A /* print extent information */ 2N/A /* request verification and then update all watermarks */ 2N/A "\nWARNING: You are about to overwrite portions of %s\n" 2N/A "with soft partition metadata. The extent headers will be\n" 2N/A "written to match the existing metadb configuration. If\n" 2N/A "the device was not previously setup with this\n" 2N/A "configuration, data loss may result.\n\n"),
2N/A "Are you sure you want to do this (yes/no)? "));
2N/A /* place soft partitions into recovering state */ 2N/A /* update the watermarks */ 2N/A "Soft Partitions recovered from metadb\n"),
2N/A /* return soft partitions to the OK state */ 2N/A "%s: Soft Partitions NOT recovered from metadb\n"),
2N/A * FUNCTION: meta_sp_update_abr() 2N/A * INPUT: sp - name of set we are recovering in 2N/A * OUTPUT: ep - return error pointer 2N/A * RETURNS: int - 0 - success, -1 - error 2N/A * PURPOSE: update the ABR state for all soft partitions in the set. This 2N/A * is called when joining a set. It sends a message to the master 2N/A * node for each soft partition to get the value of tstate and 2N/A * then sets ABR ,if required, by opening the sp, setting ABR 2N/A * and then closing the sp. This approach is taken rather that 2N/A * just issuing the MD_MN_SET_CAP ioctl, in order to deal with 2N/A * the case when we have another node simultaneously unsetting ABR. 2N/A /* Exit if no soft partitions in this set */ 2N/A /* For each soft partition */ 2N/A /* check if this is a top level metadevice */ 2N/A /* Get tstate from Master */ 2N/A /* If not set on the master, nothing to do */ 2N/A * FUNCTION: meta_mn_sp_update_abr() 2N/A * INPUT: arg - Given set. 2N/A * PURPOSE: update the ABR state for all soft partitions in the set by 2N/A * forking a process to call meta_sp_update_abr() 2N/A * This function is only called via rpc.metad when adding a node 2N/A * to a set, ie this node is beong joined to the set by another 2N/A /* should have a set */ 2N/A /* fork a process */ 2N/A * md_daemonize will fork off a process. The is the 2N/A * Child process should never return back to rpc.metad, but 2N/A * Flush all internally cached data inherited from parent process 2N/A * since cached data will be cleared when parent process RPC request 2N/A * has completed (which is possibly before this child process 2N/A * Child process can retrieve and cache its own copy of data from 2N/A * rpc.metad that won't be changed by the parent process. 2N/A * Reset md_in_daemon since this child will be a client of rpc.metad 2N/A * not part of the rpc.metad daemon itself. 2N/A * md_in_daemon is used by rpc.metad so that libmeta can tell if 2N/A * this thread is rpc.metad or any other thread. (If this thread 2N/A * was rpc.metad it could use some short circuit code to get data 2N/A * directly from rpc.metad instead of doing an RPC call to rpc.metad). 2N/A * Now get the data from the unit structure. The compnamep stuff 2N/A * contains the data from the namespace and we need the un_dev 2N/A * from the unit structure. 2N/A mgd.
cnt =
1;
/* sp's only have one subdevice */ 2N/A /* Get the devname from the name space. */ 2N/A * The minor numbers are different. Update the namespace 2N/A * with the information from the component.