/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <meta.h>
#include <libdiskmgt.h>
#include "meta_repartition.h"
#define _LAYOUT_DEVICE_UTIL_C
#include "volume_dlist.h"
#include "volume_error.h"
#include "volume_output.h"
#include "volume_nvpair.h"
#include "layout_device_cache.h"
#include "layout_device_util.h"
#include "layout_discovery.h"
#include "layout_dlist_util.h"
#include "layout_slice.h"
/*
* Macros to produce a quoted string containing the value of a
* preprocessor macro. For example, if SIZE is defined to be 256,
* VAL2STR(SIZE) is "256". This is used to construct format
* strings for scanf-family functions below.
*/
#define QUOTE(x) #x
/* private utilities for disks */
static int disk_get_uint64_attribute(
char *attr,
static int disk_get_boolean_attribute(
char *attr,
boolean_t *bool);
static int disk_get_rpm(
static int disk_get_sync_speed(
static int disk_has_virtual_slices(
boolean_t *bool);
static int disk_get_virtual_slices(
static int disk_get_reserved_indexes(
static int disk_get_associated_desc(
char *assoc_type_str,
/* utilities for slices */
static int slice_get_uint64_attribute(
char *attr,
static int slice_set_attribute(
char *attr,
/*
* Virtual slices are created to represent slices that will be
* on the system after disks have been added to the destination
* diskset. For the purposes of layout, these slices must
* look & function just as real slices that are currently on
* the system.
*/
/* temporary implementation */
static int virtual_repartition_drive(
static int disk_add_virtual_slice(
static int virtual_slice_get_disk(
/*
* attribute names for layout private information stored in
* device nvpair attribute lists.
*/
/*
* FUNCTION: is_ctd_like_slice_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name follows an alternate slice
* naming scheme similar to CTD
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is of the form XXXsNNN
* (e.g., whizzy0s1)
*/
char *name)
{
uint_t s = 0;
uint_t d = 0;
int l = 0;
/* The format strings below match and discard the non-numeric part. */
}
return (is);
}
/*
* FUNCTION: is_bsd_like_slice_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name follows an alternate slice
* BSD-like naming scheme
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is of the form XXXNNN[a-h]
* (e.g., whizzy0a)
*/
char *name)
{
uint_t d = 0;
int l = 0;
/* The format strings below match and discard the non-numeric part. */
}
return (is);
}
/*
* FUNCTION: is_did_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name is from the DID namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is from the DID namespace.
*/
char *name)
{
}
/*
* FUNCTION: is_did_slice_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name represents a slice from the DID
* namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is a slice from the DID namespace.
*/
char *name)
{
uint_t d = 0, s = 0;
int l = 0;
}
return (is);
}
/*
* FUNCTION: is_did_disk_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name represents a disk from the DID
* namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is a disk from the DID namespace.
*/
char *name)
{
uint_t d = 0;
int l = 0;
}
return (is);
}
/*
* FUNCTION: is_ctd_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name is from the CTD namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is from the CTD namespace.
*
*/
char *name)
{
}
/*
* FUNCTION: is_ctd_slice_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name represents a slice from the CTD
* namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is a slice name from the
* CTD namespace.
*
*/
char *name)
{
uint_t c = 0, t = 0, d = 0, s = 0;
int l = 0;
} else if (
&c, buf, &l) == 2 ||
&c, buf, &l) == 2 ||
char *dev_pos;
/* see if buf ends with "dXsX" */
/* buf ends with "dXsX", truncate at the 'd' */
*dev_pos = '\0';
/* prepend "0X" to remainder and try to scan as a hex WWN */
}
}
}
return (is);
}
/*
* FUNCTION: is_ctd_disk_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name represents a disk from the CTD
* namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is a disk name from the
* CTD namespace.
*
*/
char *name)
{
uint_t c = 0, t = 0, d = 0;
int l = 0;
&c, buf, &l) == 2 ||
&c, buf, &l) == 2 ||
char *dev_pos;
/* see if buf ends with "dX" */
/* buf ends with "dX", truncate at the 'd' */
*dev_pos = '\0';
/* prepend "0X" to remainder and try to scan as a hex WWN */
}
}
}
return (is);
}
/*
* FUNCTION: is_ctd_disk_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name represents a target from the CTD
* namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is a target name from the
* CTD namespace.
*
*/
char *name)
{
uint_t c = 0, t = 0;
int l = 0;
} else if (
&c, buf, &l) == 2 ||
&c, buf, &l) == 2 ||
/* prepend "0X" to buf and try to scan as a hex WWN */
}
}
return (is);
}
/*
* FUNCTION: is_ctd_ctrl_name(char *name)
* INPUT: name - a char *
*
* RETURNS: boolean_t - B_TRUE - if name represents a controller/hba
* from the CTD namespace
* B_FALSE - otherwise
*
* PURPOSE: Determines if the input name is an HBA name from the
* CTD namespace.
*
*/
char *name)
{
uint_t c = 0;
int l = 0;
}
return (is);
}
/*
* FUNCTION: set_display_name(dm_descriptor_t desc, char *name)
* get_display_name(dm_descriptor_t desc, char **name)
*
* INPUT: desc - a dm_descriptor_t handle for a device
* name - a char * name
*
* OUTPUT: **name - a pointer to a char * to hold the display
* name associated with the input descriptor.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
*
* Only slices, disks and HBAs should have display names.
*
* The attribute is only set in the cached copy of
* the device's nvpair attribute list. This function
* does not affect the underlying physical device.
*
* An entry is added in the name->descriptor cache
* so the descriptor can be found by name quickly.
*/
int
char *name)
{
int error = 0;
return (error);
}
int
char **name)
{
int error = 0;
return (error);
}
/*
* FUNCTION: disk_get_slices(dm_descriptor_t disk, dlist_t **list)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: *list - a pointer to list to hold the results.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Collect all of the known slices for the input disk.
*
* These slices may be actual slices which currently exist
* on the disk, or virtual slices which will exist when the
* disk is added to the destination diskset.
*/
int
{
int i = 0;
int error = 0;
*list = 0;
return (error);
}
}
/* add real slices from disk's media... */
(void) add_descriptors_to_free(media);
if (error == 0) {
/* if there's no media, this is a removeable drive */
/* examine media's slices... */
(void) add_descriptors_to_free(slices);
if (error != 0) {
} else {
} else {
}
}
}
}
} else {
}
return (error);
}
int
{
*list = _virtual_slices;
return (0);
}
/*
* FUNCTION: virtual_repartition_drive(dm_descriptor_t disk,
* mdvtoc_t *vtocp)
*
* INPUT: disk - the disk to be virtually repartitioned
*
* OUTPUT: vtocp - a poitner to a mdvtoc struct to hold the results
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which emulates the repartitioning that is done
* when a disk is added to a diskset.
*
* Modified version of meta_partition_drive which uses info
* from libdiskmgt to accomplish the repartitioning.
*
* This exists to allow the layout module to run with a
* simulated hardware environment.
*
* XXX This method absolutely does not produce the exact
* same result as meta_repartition_drive: only information
* required by the layout code is returned. Basically,
* a slice 7 (or 6 on EFI labelled disks) is created and
* sized, the remained of the available cylinders are put
* into slice 0.
*
* XXX2 This method is required until there is resolution
* on whether metassist testing will be done using the
* hardware simulation mechanism libdiskmgt provides.
* Doing so will also require parts of libmeta to be
* simulated as well. Some research has been done into
* building an alternate libmeta.so containing
* implementations of the functions used by metassist
* that are compatible with the simulated hardware.
* Actual work is currently on hold.
*/
static int
{
unsigned long long cylsize;
unsigned long long drvsize;
unsigned long long ressize;
int error = 0;
/*
* At this point, ressize is used as a minimum value. Later it
* will be rounded up to a cylinder boundary. ressize is in
* units of disk sectors.
*/
if (error != 0) {
return (error);
}
if (efi) {
replicaslice = 6;
}
/*
* Both cylsize and drvsize are in units of disk sectors.
*
* The intended results are of type unsigned long long. Since
* each operand of the first multiplication is of type
* unsigned int, we risk overflow by multiplying and then
* converting the result. Therefore we explicitly cast (at
* least) one of the operands, forcing conversion BEFORE
* multiplication, and avoiding overflow. The second
* assignment is OK, since one of the operands is already of
* the desired type.
*/
/*
* How many cylinders must we reserve for slice seven to
* ensure that it meets the previously calculated minimum
* size?
*/
/*
* It seems unlikely that someone would pass us too small a
* disk, but it's still worth checking for...
*/
if (reservedcyl >= ncyls) {
gettext("disk is too small to hold a metadb replica"));
return (-1);
}
replica_start = 0;
/*
* fill in the proposed VTOC information.
*/
/* We need at least replicaslice partitions in the proposed vtoc */
return (0);
}
/*
* FUNCTION: create_virtual_slices(dlist_t *disks)
*
* INPUT: possibles - a list of dm_descriptor_t disk handles for
* disks known to be available for use by layout.
*
* SIDEEFFECT: populates the private of virtual slices.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which creates virtual slices for each disk which
* could be added to a diskset if necessary...
*
* Iterate the input list of available disks and see what the
* slicing would be if the disk were added to a diskset.
*
* For the resulting slices, create virtual slice descriptors
* and attributes for these slices and add them to the list of
* available slices.
*/
int
{
int error = 0;
/* see what slices each of the disks will have when added to a set */
char *dname;
int i = 0;
break;
}
/* sim disabled: use meta_repartition_drive() */
/* disk is in the local set */
error = -1;
break;
}
error = -1;
break;
}
gettext("failed to repartition disk %s\n"),
dname);
error = -1;
break;
}
} else {
/* sim enabled: use faked repartition code */
gettext("failed simulated repartition of %s\n"),
dname);
error = -1;
break;
}
}
/* BEGIN CSTYLED */
/*
* get the existing slices on the disk, if the repartition
* was successful, these slices need to have their size, start
* blk and size in blks set to 0
*/
/* END CSTYLED */
}
}
/* scan VTOC, find slice with the free space */
/* non-replica slice with free space */
(uint32_t)i,
disk)) != 0) {
break;
}
/* skip EFI reserved slice */
continue;
/* BEGIN CSTYLED */
/*
* Make the replica slice 0 sized -- this will
* force the disk to be repartitioned by
* metaset when it is added to the disk set.
*
* XXX this is a temporary workaround until
* 4712873 is integrated...
*/
/* BEGIN CSTYLED */
add_slice_to_remove(buf, i);
/* replica slice, stop here */
break;
}
}
}
return (error);
}
/*
* FUNCTION: add_virtual_slice(char *name, uint32_t index,
* uint64_t startblk, uint64_t sizeblks,
* dm_descriptor_t disk)
*
* INPUT: name - the name of the new virtual slice
* index - the VTOC index ...
* startblk - the start block ...
* sizeblks - the size in blocks ...
* disk - the parent disk ...
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which adds the appropriate data structures to
* represent a new virtual slice.
*
* allocates a new descriptor
* adds entries to name->desc and desc->name caches
* allocates an attribute nvpair list
* fills in the relevant attributes for the slice
* associates the slice with its parent disk
* adds an entry to the list of all virtual slices
* generates aliases if the associated disk has aliases.
*/
int
char *name,
{
char *sname;
int error = 0;
return (error);
}
/* create descriptor */
/* cache name for the descriptor */
/* cache descriptor for the name */
/* fill in attributes */
/* add attributes to the cache */
/* connect slice to disk */
if (error != 0) {
return (error);
}
/* generate slice's aliases if the disk has aliases */
}
}
return (ENOMEM);
}
gettext(" created virtual slice %s start: %llu, size: %llu\n"),
return (error);
}
/*
* FUNCTION: release_virtual_slices()
*
* PURPOSE: Helper which cleans up the module private list of virtual
* slices.
*
* The descriptors for the virtual slices are cleaned up
* in device_cache_util.free_cached_descriptors
*/
void
{
}
/*
* FUNCTION: disk_add_virtual_slice(dm_descriptor_t disk,
* dm_descriptor_t slice)
*
* INPUT: disk - a dm_descriptor_t disk handle
* slice - a dm_descriptor_t virtual slice handle
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Helper which adds a virtual slice to the input disk's
* list of virtual slices.
*
* The disk's virtual slice dm_descriptor_t handles are
* stored in the disk's nvpair attribute list.
*/
static int
{
int i = 0;
int error = 0;
return (error);
}
if ((error = get_uint64_array(
return (error);
}
error = 0;
}
/* make a new array */
if (new_slices != NULL) {
for (i = 0; i < nelem; i++) {
new_slices[i] = old_slices[i];
}
new_slices[i] = slice;
} else {
}
return (error);
}
/*
* FUNCTION: disk_has_virtual_slices(dm_descriptor_t disk, boolean_t *bool)
*
* INPUT: disk - a dm_descriptor_t disk handle
*
* OUTPUT: bool - B_TRUE - if the disk has virtual slices
* B_FALSE - otherwise
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Helper which determines if the input disk has virtual slices.
*
* If a disk has virtual slices, their dm_descriptor_t handles
* will be stored in the disk's nvpair attribute list.
*/
static int
boolean_t *bool)
{
int error = 0;
*bool = B_FALSE;
return (error);
}
if ((error = get_uint64_array(
error = 0;
nelem = 0;
} else {
/* count actual number of elements */
int i = 0;
while (i < nelem) {
if (slices[i] != -1) {
++i;
}
}
nelem = i;
}
}
*bool = (nelem != 0);
return (error);
}
/*
* FUNCTION: disk_get_virtual_slices(dm_descriptor_t disk, boolean_t *bool)
*
* INPUT: disk - a dm_descriptor_t disk handle
*
* OUTPUT: list - a dlist_t list of dm_descriptor_t handles for the
* disk's virtual slices.
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Helper which retrieves a list of the input disk's virtual
* slices.
*
* If a disk has virtual slices, their dm_descriptor_t handles
* will be stored in the disk's nvpair attribute list.
*/
static int
{
int error = 0;
int i = 0;
return (error);
}
if ((error = get_uint64_array(
return (error);
}
return (0);
}
break;
}
}
return (error);
}
/*
* FUNCTION: is_virtual_slice(dm_descriptor_t desc)
*
* INPUT: desc - a dm_descriptor_t handle
*
* RETURNS: boolean_t - B_TRUE if the input descriptor is for
* a virtual slice.
* B_FALSE otherwise
*
* PURPOSE: Helper which determines whether the input descriptor
* corresponds to a virtual slice.
*
* All virtual slices are stored in a module private list.
* This list is iterated to see if it contains the input
* descriptor.
*/
{
return (dlist_contains(_virtual_slices,
}
/*
* FUNCTION: disk_get_available_slice_index(dm_descriptor_t disk,
* uint32_t *newindex)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: *newindex - a pointer to a uint32_t to hold the available
* index. If no index is available, the value pointed
* to is not modified.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: examine the input disk's list of slices and find an unused
* slice index. The replica slice (index 7 or 6) is always
* off-limits -- it shows up as in use. Slice 0 should only
* be used as a last resort.
*
* If an available index is found, it is stored into newindex.
* Otherwise, newindex is unchanged. This allows the caller to
* pass in an index and check if it has been modified on return.
*
* V_NUMPAR is used as the number of available slices,
* SPARC systems have V_NUMPAR == 8, X86 have V_NUMPAR == 16.
*
* EFI disks have only 7.
*/
int
{
int error = 0;
int i = 0;
return (error);
}
/* limit possible indexes to 7 for EFI */
nslices = 7;
}
gettext("failed allocating slice index array\n"),
NULL);
return (ENOMEM);
}
/* eliminate indexes that are reserved */
return (error);
}
for (i = 0; i < nslices; i++) {
if (reserved[i] == 1) {
}
}
}
/* eliminate slices that are in use (have a size > 0) */
/* 0 sized slices unused slices */
if (error != 0) {
return (error);
}
if (size > 0) {
}
}
for (i = 0; i < nslices; i++) {
/* skip the index passed in */
if (i == *newindex) {
continue;
}
index = i;
break;
}
}
if (i != nslices) {
/* return unused slice index */
}
return (0);
}
/*
* FUNCTION: disk_get_media_type(dm_descriptor_t slice, uint32_t *type)
*
* INPUT: slice - a dm_descriptor_t handle for a disk
*
* OUTPUT: *type - a pointer to a uint32_t to hold the
* current type value for the media on which
* the input slice resides.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Retrieves the media type for the disk.
*
* Get the media associate with the input disk descriptor
* and determine its type.
*/
int
{
int error = 0;
(void) add_descriptors_to_free(mdp);
if (error != 0) {
} else {
/* disk should have exactly 1 media */
}
}
/* no media: removeable drive */
}
}
return (error);
}
/*
* FUNCTION: disk_get_rpm(dm_descriptor_t disk, uint32_t *val)
* disk_get_sync_speed(dm_descriptor_t disk, uint32_t *val)
* disk_get_size_in_blocks(dm_descriptor_t disk, uint64_t *val)
* disk_get_blocksize(dm_descriptor_t disk, uint64_t *val)
* disk_get_ncylinders(dm_descriptor_t disk, uint64_t *val)
* disk_get_nheads(dm_descriptor_t disk, uint64_t *val)
* disk_get_nsectors(dm_descriptor_t disk, uint64_t *val)
* disk_get_is_efi(dm_descriptor_t disk, boolean_t *val)
* disk_get_is_online(dm_descriptor_t disk, boolean_t *val)
* disk_get_media_type(dm_descriptor_t disk, uint32_t *type)
* disk_get_has_fdisk(dm_descriptor_t disk, boolean_t *val)
* disk_get_start_block(dm_descriptor_t disk, uint64_t *val)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: *bool - a pointer to a variable of the appropriate
* type to hold the current value for the attribute
* of interest.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Wrappers around disk_get_XXX_attribute that know
* which attribute needs to be retrieved and also handle
* any necesasry type or units conversions.
*/
static int
{
int error = 0;
if ((error = disk_get_uint64_attribute(
return (error);
}
return (error);
}
int
{
int error = 0;
if ((error = disk_get_uint64_attribute(
return (error);
}
return (error);
}
static int
{
int error = 0;
if ((error = disk_get_uint64_attribute(
return (error);
}
return (error);
}
/* returns number of usable blocks */
int
{
}
/* returns first usable block on disk */
int
{
}
int
{
}
int
{
}
int
{
}
int
{
}
/*
* FUNCTION: disk_get_is_online(dm_descriptor_t disk, boolean_t *val)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: *bool - a pointer to a boolean_t to hold the result.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Determine if the input disk is "online".
*
* Check the status bit of the drive, if it is 1 the drive
* is online, if it is 0 the drive is offline.
*/
int
{
int error = 0;
if (error == 0) {
}
return (error);
}
/*
* FUNCTION: disk_get_is_efi(dm_descriptor_t disk, boolean_t *bool)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: *bool - a pointer to a boolean_t to hold the result.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Determine if the input disk is labeled with an EFI label.
*
* The label type is actually a property of the media
* associated with the disk, so retrieve the media and
* check if it is EFI labeled.
*/
int
boolean_t *bool)
{
}
/*
* FUNCTION: disk_get_has_fdisk(dm_descriptor_t disk, boolean_t *bool)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: *bool - a pointer to a boolean_t to hold the result.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Determine if the input disk has an FDISK partition.
*/
int
boolean_t *bool)
{
}
/*
* FUNCTION: disk_get_has_solaris_partition(dm_descriptor_t disk, boolean_t *bool)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: *bool - a pointer to a boolean_t to hold the result.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Determine if the input disk has a Solaris FDISK partition.
*/
int
boolean_t *bool)
{
int error = 0;
return (error);
}
*bool = B_FALSE;
/* get disk's media */
(void) add_descriptors_to_free(media);
if (error != 0) {
/* get media's partitions */
(void) add_descriptors_to_free(parts);
if (error != 0) {
} else {
/* search partitions for one with type Solaris */
int i = 0;
if ((error == 0) &&
*bool = B_TRUE;
}
}
}
}
}
/* if there was no media, it was a removeable drive */
}
return (error);
}
static int
char *attr,
boolean_t *bool)
{
int error = 0;
*bool = B_FALSE;
/*
* these attributes are actually on the media,
* not the disk... so get the media descriptor
* for this disk
*/
(void) add_descriptors_to_free(media);
if (error != 0) {
/* if there's no media, it is a removeable drive */
}
} else {
if (error != 0) {
}
}
if (error != 0) {
return (error);
}
*bool = B_TRUE;
}
return (error);
}
static int
char *attr,
{
int error = 0;
/*
* these attributes are actually on the media,
* not the disk... so get the media descriptor
* for this disk
*/
(void) add_descriptors_to_free(media);
if (error != 0) {
error = -1;
} else {
}
} else {
if (error != 0) {
}
}
if (error != 0) {
return (error);
}
}
return (error);
}
/*
* FUNCTION: group_similar_hbas(dlist_t *hbas, dlist_t **list)
*
* INPUT: hbas - a list of HBA dm_descriptor_t handles.
*
* OUTPUT: **list - a pointer to a list to hold the lists of HBAs
* grouped by characteristics.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Examine the input HBAs and collate them into separate
* lists, grouped by their type and the protocols they
* support.
*
* The returned list of list is arranged in decreasing order
* of preference, "better" HBAs come first.
*
* find all MPXIO controllers
* find all similar FC HBAs
* find all similar SCSI HBAs
* fast{wide}80
* fast{wide}40
* fast{wide}20
* clock uint32 ??
* find all similar USB HBAs
*/
int
{
/* preference order of HBAs */
enum {
HBA_FIBRE_MPXIO = 0,
};
int error = 0;
int i = 0;
/* if item doesn't go into a list it must be freed */
continue;
}
continue;
}
if (ismpxio) {
} else {
}
} else {
}
/* determine subtype */
if (error == 0) {
if (ismpxio) {
} else if (is80) {
if (iswide) {
} else {
}
} else if (is40) {
if (iswide) {
} else {
}
} else if (is20) {
if (iswide) {
} else {
}
} else {
}
} else {
}
gettext("found an HBA with unknown type\n"));
}
}
if (error == 0) {
/* collect individual lists into a list of lists */
} else {
}
}
}
}
if (error != 0) {
for (i = 0; i < HBA_LAST; i++) {
}
}
}
return (error);
}
/*
* FUNCTION: hba_group_usable_disks(dm_descriptor_t hba, dlist_t **list)
*
* INPUT: hba - a dm_descriptor_t handle for a slice
*
* OUTPUT: **list - a pointer to a list to hold the lists of disks
* grouped by characteristics.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Examine the disks assocated with the HBA and collates them
* into separate lists, grouped by similar characteristics.
*
* get disks on HBA
* check disks against _usable_disks list
* group disks by similarities:
* sync-speed uint32
* wide boolean
* rpm uint32
*
* XXX this function is currently unused. At some point,
* it may be useful to group disks by performance
* characteristics and use "better" disks before others.
*/
int
{
int i = 0;
int error = 0;
(void) add_descriptors_to_free(disk);
if (error != 0) {
return (error);
error = -1;
}
/* ignore non fixed media drives */
(dtype != DM_DT_FIXED)) {
continue;
}
compare_descriptor_names) == B_TRUE) {
if (error != 0) {
continue;
}
gettext("found an available disk: %s\n\t"
"sync_speed = %u, rpm = %u, "
"nsect = %llu, blksiz = %llu\n"),
/* add to the appropriate list */
}
}
}
return (error);
}
/*
* FUNCTION: hba_get_n_avail_disks(dm_descriptor_t hba, uint16_t *val)
* hba_set_n_avail_disks(dm_descriptor_t hba, uint16_t val)
*
* INPUT: hba - a dm_descriptor_t handle for a slice
*
* OUTPUT: *val - a pointer to a uint16_t to hold the current number
* of available disks for the input HBA.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*/
int
{
int error = 0;
return (error);
}
int
{
int error = 0;
*val = 0;
return (error);
}
/*
* FUNCTION: hba_get_type(dm_descriptor_t hba, char **type)
*
* INPUT: hba - a dm_descriptor_t handle for a HBA
*
* OUTPUT: **type - a char * to hold the current type value for
* the HBA.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Retrieves the type attribute for the HBA.
*/
int
char **type)
{
int error = 0;
return (error);
}
/*
* FUNCTION: hba_is_fast(dm_descriptor_t hba, boolean_t *bool)
* hba_is_fast20(dm_descriptor_t hba, boolean_t *bool)
* hba_is_fast40(dm_descriptor_t hba, boolean_t *bool)
* hba_is_fast80(dm_descriptor_t hba, boolean_t *bool)
* hba_is_multiplex(dm_descriptor_t hba, boolean_t *bool)
* hba_is_wide(dm_descriptor_t hba, boolean_t *bool)
*
* INPUT: hba - a dm_descriptor_t handle for a HBA
*
* OUTPUT: *bool - a pointer to a boolean_t to hold the
* boolean value of the predicate.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Wrappers around hba_supports_protocol which determines
* if the input HBA supports the protocol of interest.
*/
int
boolean_t *bool)
{
}
int
boolean_t *bool)
{
}
int
boolean_t *bool)
{
}
int
boolean_t *bool)
{
}
int
boolean_t *bool)
{
}
int
boolean_t *bool)
{
int error = 0;
*bool = B_FALSE;
return (error);
}
return (error);
}
/*
* FUNCTION: hba_supports_protocol(dm_descriptor_t hba, char *attr,
* boolean_t *bool)
*
* INPUT: hba - a dm_descriptor_t handle for a HBA
* attr - a protocol "name"
*
* OUTPUT: *bool - a pointer to a boolean_t to hold the
* boolean value of the predicate.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Checks the HBAs attributes to see if it is known to
* support the protocol of interest.
*
* If the protocol is supported, it will have an entry
* in the nvpair attribute list that can be retrieved.
*
* If the entry cannot be retrieved, the protocol is not
* supported.
*/
int
char *attr,
boolean_t *bool)
{
int error = 0;
*bool = B_FALSE;
return (error);
}
return (error);
}
/*
* FUNCTION: slice_set_size(dm_descriptor_t slice, uint64_t size)
*
* INPUT: slice - a dm_descriptor_t handle for a slice
*
* OUTPUT: size - a uint64_t value representing the size of the
* slice.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Wrapper around slice_set_uint64_attribute which converts
* the input size in bytes to blocks prior to storing it.
*
* This function is used when an existing slice gets resized
* to provide space for a new slice. It is necessary to update
* the slice's size so that it is accurate.
*/
int
{
int error = 0;
return (error);
}
/*
* FUNCTION: slice_set_size_in_blocks(dm_descriptor_t slice, uint64_t size)
*
* INPUT: slice - a dm_descriptor_t handle for a slice
*
* OUTPUT: size - a uint64_t value representing the size of the
* slice.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Wrapper around slice_set_uint64_attribute to set the slice
* size.
*
* This function is used when an existing slice gets resized
* to provide space for a new slice. It is necessary to update
* the slice's size so that it is accurate.
*/
int
{
}
/*
* FUNCTION: slice_set_start_block(dm_descriptor_t slice, uint64_t start)
*
* INPUT: slice - a dm_descriptor_t handle for a slice
*
* OUTPUT: size - a uint64_t value representing the start block of the
* slice.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Wrapper around slice_set_attribute.
*
* This function is used when an existing slice gets adjusted
* due to being resized or combined with another slice.
*/
int
{
}
/*
* FUNCTION: slice_get_start_block(dm_descriptor_t slice, uint64_t *val)
* slice_get_size_in_blocks(dm_descriptor_t slice, uint64_t *val)
* slice_get_start(dm_descriptor_t slice, uint64_t *val)
* slice_get_size(dm_descriptor_t slice, uint64_t *val)
* slice_get_index(dm_descriptor_t slice, uint64_t *val)
*
* INPUT: slice - a dm_descriptor_t handle for a slice
*
* OUTPUT: *val - a pointer to a uint64_t to hold the
* current value of the desired attribute.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Wrappers around slice_get_uint64_attribute which retrieve
* specific attribute values.
*/
int
{
}
int
{
}
int
{
int error = 0;
if (error == 0) {
}
return (error);
}
int
{
int error = 0;
*val = 0;
if (error == 0) {
}
return (error);
}
int
{
int error = 0;
if ((error = slice_get_uint64_attribute(
return (error);
}
return (0);
}
/*
* FUNCTION: slice_set_uint64_attribute(dm_descriptor_t slice,
* char *attr, uint64_t val)
* slice_get_uint64_attribute(dm_descriptor_t slice,
* char *attr, uint64_t *val)
*
* INPUT: slice - a dm_descriptor_t handle for a slice
* attr - a char * attribute name
* val - auint64_t value
*
* OUTPUT: *val - a pointer to a uint64_t to hold the
* current value of the named attribute.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
*
* attributes. Some attributes are actually stored as
* uint32_t or uint16_t values, these functions mask
* the type conversions.
*/
static int
char *attr,
{
int error = 0;
return (error);
}
}
if (error != 0) {
}
return (error);
}
/*
* Set a slice attribute. The attribute is only set in the cached
* copy of the slice's nvpair attribute list. This function does
* NOT affect the underlying physical device.
*/
static int
char *attr,
{
int error = 0;
return (error);
}
}
if (error != 0) {
}
return (error);
}
/*
* FUNCTION: virtual_slice_get_disk(dm_descriptor_t slice,
* dm_descriptor_t *diskp)
*
* INPUT: slice - a dm_descriptor_t virtual slice handle
* diskp - pointer to a dm_descriptor_t disk handle
* to return the slice's disk
*
* OUTPUT: the disk associated with the virtual slice.
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Helper which determines the disk that the input virtual
* slice "belongs" to.
*
* The virtual slice's disk is stored in the slice's nvpair
* attribute list when the slice gets created.
*/
static int
{
int error = 0;
if ((error = slice_get_uint64_attribute(
return (error);
}
if (disk == 0) {
return (-1);
}
return (0);
}
/*
* FUNCTION: slice_get_disk(dm_descriptor_t disk, dm_descriptor_t *diskp)
*
* INPUT: slice - a dm_descriptor_t handle for a slice
*
* OUTPUT: diskp - a pointer to a dm_descriptor_t to hold the
* disk associated with the input slice
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which retrieves the disk for a slice device.
*
* A slice is actually connected to its disk thru an intermediate
* device known as the "media". The media concept exists to
* model drives with removeable disk media. For the purposes
* of layout, such devices aren't relevant and the intermediate
* media can mostly be ignored.
*/
int
{
int i = 0;
int error = 0;
*diskp = 0;
if (is_virtual_slice(slice)) {
}
(void) add_descriptors_to_free(media);
if (error != 0) {
error = -1;
}
if (error != 0) {
return (error);
}
/* slice should have exactly 1 media */
/* get disk from media */
(void) add_descriptors_to_free(disks);
}
}
}
if (*diskp == 0) {
error = -1;
}
return (error);
}
/*
* FUNCTION: slice_get_hbas(dm_descriptor_t slice, dlist_t **list)
*
* INPUT: slice - a dm_descriptor_t handle for a slice
*
* OUTPUT: list - a pointer to a dlist_t list to hold the
* HBAs associated with the input slice
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which retrieves the known HBAs for a slice device.
*
*/
int
{
int error = 0;
error = -1;
}
return (error);
}
/*
* FUNCTION: disk_get_associated_desc(dm_descriptor_t disk,
* dm_desc_type_t assoc_type, char *assoc_type_str,
* dlist_t **list)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
* assoc_type - the type of associated object to get
* assoc_type_str - a char * string for the associated type
*
* OUTPUT: list - a pointer to a dlist_t list to hold the
* objects associated with the input disk
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which retrieves the associated objects of the
* requested type for a disk device.
*/
static int
char *assoc_type_str,
{
int i = 0;
int error = 0;
(void) add_descriptors_to_free(assoc);
if (error == 0) {
for (i = 0;
i++) {
} else {
}
}
} else {
}
}
if (error != 0) {
}
return (error);
}
/*
* FUNCTION: disk_get_hbas(dm_descriptor_t disk, dlist_t **list)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: list - a pointer to a dlist_t list to hold the
* HBAs associated with the input disk
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which retrieves the known HBAs for a disk device.
*
*/
int
{
}
/*
* FUNCTION: disk_get_paths(dm_descriptor_t disk, dlist_t **list)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: list - a pointer to a dlist_t list to hold the
* paths associated with the input disk
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which retrieves the known paths for a disk device.
*
* Paths are managed by the MPXIO driver, they represent hardware
* paths to the disk drive managed by the MPXIO and not visible
* externally, unlike aliases which are.
*/
int
{
}
/*
* FUNCTION: disk_get_aliases(dm_descriptor_t disk, dlist_t **list)
*
* INPUT: disk - a dm_descriptor_t handle for a disk
*
* OUTPUT: list - a pointer to a dlist_t list to hold the
* alias descriptors associated with the input disk
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which retrieves the known aliases for a disk device.
*
* Aliases are the different CTD names for the disk drive when
* MPXIO is not enabled for multipathed drives.
*/
int
{
}
/*
* FUNCTION: compare_string_to_desc_name_or_alias(
* void *str, void *desc)
*
* INPUT: str - opaque pointer
* descr - opaque pointer
*
* RETURNS: int - <0 - if str < desc.name
* 0 - if str == desc.name
* >0 - if str > desc.name
*
* PURPOSE: dlist_t helper which compares a string to the name
* and aliases associated with the input dm_descriptor_t
* handle.
*
* Comparison is done via compare_device_names.
*/
static int
void *str,
void *desc)
{
/* try name first, then aliases */
result = 0;
}
}
return (result);
}
/*
* FUNCTION: hba_get_by_name(char *name, dm_descriptor_t *hba)
*
* INPUT: name - a char * disk name
*
* OUTPUT: hba - a pointer to a dm_descriptor_t to hold the
* HBA corresponding to the input name, if found
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Helper which iterates the known HBAs, searching for
* the one matching name.
*
* If no HBA matches the name, 0 is returned and the
* value of 'hba' will be (dm_descriptor_t)0;
*/
int
char *name,
{
int error = 0;
*hba = (dm_descriptor_t)0;
return (0);
}
return (error);
}
}
return (error);
}
/*
* FUNCTION: disk_get_by_name(char *name, dm_descriptor_t *disk)
*
* INPUT: name - a char * disk name
*
* OUTPUT: disk - a pointer to a dm_descriptor_t to hold the
* disk corresponding to the input name, if found
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which retrieves a dm_descriptor_t disk handle
* by name.
*
* If no disk is found for the input name, variations of
* the name are tried.
*
* If the input name is unqualified, an appropriate leading
* path is prepended.
*
* If the input name is qualified, the leading path is
* removed.
*
* If no disk is found for the variations, 0 is returned
* and the value of 'disk' will be (dm_descriptor_t)0;
*/
int
char *name,
{
if (*disk == (dm_descriptor_t)0) {
if (name[0] == '/') {
/* fully qualified, try unqualified */
}
} else {
/* unqualified, try fully qualified */
if (is_ctd_disk_name(name)) {
} else if (is_did_disk_name(name)) {
}
}
}
/*
* since the descriptor cache includes HBAs, disks and slices,
* what gets returned may not be a disk... make sure it is
*/
if (*disk != (dm_descriptor_t)0) {
*disk = (dm_descriptor_t)0;
}
}
return (0);
}
/*
* FUNCTION: slice_get_by_name(char *name, dm_descriptor_t *slice)
*
* INPUT: name - a char * slice name
*
* OUTPUT: slice - a pointer to a dm_descriptor_t to hold the
* slice corresponding to the input name, if found.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which iterates the known slices, searching for
* the one matching name.
*
* If no slice is found for the input name, variations of
* the name are tried.
*
* If the input name is unqualified, an appropriate leading
* path is prepended.
*
* If the input name is qualified, the leading path is
* removed.
*
* If no slice matches the variations, 0 is returned and the
* value of 'slice' will be (dm_descriptor_t)0;
*/
int
char *name,
{
if (*slice == (dm_descriptor_t)0) {
if (name[0] == '/') {
/* fully qualified, try unqualified */
}
} else {
/* unqualified, try fully qualified */
} else if (is_did_slice_name(name)) {
}
}
}
/*
* since the descriptor cache includes HBAs, disks and slices,
* what gets returned may not be a slice... make sure it is
*/
if (*slice != (dm_descriptor_t)0) {
*slice = (dm_descriptor_t)0;
}
}
return (0);
}
/*
* FUNCTION: extract_hbaname(char *name, char **hbaname)
*
* INPUT: slicename - a char * device name
*
* OUTPUT: hbaname - a pointer to a char * to hold the hbaname derived
* from the input name.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which extracts the HBA name from the input name.
*
* If the input name is in ctd form, extracts just the cX part,
* by truncating everything following the last 't'.
*
* Of course on X86, with IDE drives, there is no 't' in the
* ctd name, so start by truncating everything following 'd'
* and then look for 't'.
*
* The returned string must be passed to free().
*/
int
char *name,
char **hbaname)
{
char *cp;
if (is_ctd_name(name)) {
return (ENOMEM);
}
*cp = '\0';
}
*cp = '\0';
}
}
return (0);
}
/*
* FUNCTION: extract_diskname(char *slicename, char **diskname)
*
* INPUT: slicename - a char * slice name
*
* OUTPUT: diskname - a pointer to a char * to hold the diskname derived
* from the input slicename.
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which extracts the disk's name from a slice name.
*
* Checks to see if the input slicename is in ctd or did form,
* and if so, truncates everything following the last 's'.
*
* If the input slicename is BSD-like, truncate the last
* character (a-h).
*
* The returned string must be passed to free().
*/
int
char *slicename,
char **diskname)
{
char *cp;
return (ENOMEM);
}
*cp = '\0';
}
} else if (is_bsd_like_slice_name(slicename)) {
return (ENOMEM);
}
}
return (0);
}
/*
* FUNCTION: get_disk_for_named_slice(char *slicename,
* dm_descriptor_t disk)
*
* INPUT: slicename - a char * slice name
*
* OUTPUT: disk - a pointer to a dm_descriptor_t to hold the
* disk corresponding to the input name, if found
*
* RETURNS: int - 0 on success
* !0 otherwise.
*
* PURPOSE: Helper which locates the disk dm_descriptor_t handle for
* the input slice name.
*
* If no disk matches the name, 0 is returned and the
* value of 'disk' will be (dm_descriptor_t)0;
*/
int
char *slicename,
{
int error = 0;
/* find disk for slice */
if (slice != (dm_descriptor_t)0) {
} else {
/* named slice was created by layout: */
/* need to find disk by name */
char *dname;
if (error == 0) {
}
}
}
return (error);
}
/*
* FUNCTION: disk_get_reserved_indexes(dm_descriptor_t disk,
* uint16_t **array)
*
* INPUT: disk - a dm_descriptor_t disk handle
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Retrieves the input disk's list of reserved slice indices.
*
* The list of reserved indices is stored as an array in
* the disk's nvpair attribute list.
*/
static int
{
int error = 0;
return (error);
}
if ((error = get_uint16_array(
/* no reserved indices yet */
error = 0;
}
}
return (error);
}
/*
* FUNCTION: disk_reserve_index(dm_descriptor_t disk, uint16_t index)
*
* INPUT: disk - a disk dm_descirptor_t handle
* undex - a VTOC slice index
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Reserves the input VTOC slice index for the input disk.
*
* The list of reserved indices is stored as an array in
* the disk's nvpair attribute list.
*/
int
{
int error = 0;
int i = 0;
return (error);
}
if ((error = get_uint16_array(
return (error);
}
/* no reserved indices yet */
error = 0;
}
/* add new index */
if (newindexes != NULL) {
for (i = 0; i < nelem; i++) {
newindexes[i] = oldindexes[i];
}
} else {
}
return (error);
}
/*
* FUNCTION: disk_release_index(dm_descriptor_t disk, uint16_t index)
*
* INPUT: disk - a disk dm_descirptor_t handle
* undex - a VTOC slice index
*
* RETURNS: int - 0 on success
* !0 otherwise
*
* PURPOSE: Releases the input VTOC slice index for the input disk.
* The index was previously reserved by disk_reserve_index()
*/
int
{
int error = 0;
int i = 0;
return (error);
}
if ((error = get_uint16_array(
return (error);
}
error = 0;
}
if (newindexes != NULL) {
for (i = 0; i < nelem; i++) {
newindexes[i] = oldindexes[i];
}
/* release index */
newindexes[(int)index] = 0;
} else {
}
return (error);
}
/*
* FUNCTION: print_get_assoc_desc_error(dm_descriptor_t desc, char *which,
* int error)
*
* INPUT: desc - a dm_descriptor_t handle
* which - a char * indicating which association
* error - an integer error value
*
* PURPOSE: Utility function to print an error message for a failed
* call to dm_get_associated_descriptors().
*
* Extracts the device's CTD name and formats an error message.
*/
void
char *which,
int error)
{
gettext("dm_get_associated_descriptors(%s) for "
"'%s' failed: %d\n"),
gettext("Unexpected error getting associated "
"descriptors for '%s'"),
name);
}
/*
* FUNCTION: print_get_desc_attr_error(dm_descriptor_t desc,
* char *devtype, char *attr, int error)
*
* INPUT: desc - a dm_descriptor_t handle
* devtype - a char * device type that's being accessed
* attr - a char * attribute name
* error - an integer error value
*
* PURPOSE: Shared utility function to print an error message for a failed
* call to retrieve an attribute for a descriptor.
*
* Extracts the device's CTD name and formats an error message.
*/
void
char *devtype,
char *attr,
int error)
{
gettext("'%s' get attribute (%s.%s) error: %d\n"),
gettext("Unexpected error getting attribute '%s.%s' for '%s'"),
}
/*
* FUNCTION: print_set_desc_attr_error(dm_descriptor_t desc,
* char *devtype, char *attr, int error)
*
* INPUT: desc - a dm_descriptor_t handle
* devtype - a char * device type that's being accessed
* attr - a char * attribute name
* error - an integer error value
*
* PURPOSE: Shared utility function to print an error message for a failed
* call to set an attribute for a descriptor.
*
* Extracts the device's CTD name and formats an error message.
*/
void
char *devtype,
char *attr,
int error)
{
gettext("'%s' set attribute (%s.%s) error: %d\n"),
gettext("Unexpected error setting attribute '%s.%s' for '%s'"),
}