/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*/
/*
*/
#include <meta.h>
#include <metad.h>
#include <ctype.h>
#include <string.h>
/*
* Just in case we're not in a build environment, make sure that
* TEXT_DOMAIN gets set to something.
*/
#if !defined(TEXT_DOMAIN)
#endif
/*
* 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
extern char *getfullblkname();
/*
* caches
*/
/*
* Static definitions
*/
/*
* FUNCTION: meta_dsk_to_rdsk()
* INPUT: str - Fully qualified pathname of a block or character device
* RETURNS: char * - The pathname of the raw device
* PURPOSE: Allocation of a new string representing the character device
* associated with the input string. Note that no checking is
* done to verify the existence of this device file.
*/
static char *
{
/*
* If this is a malformed string, (i.e. containing neither
* "/rdsk/" nor "/dsk/") then check to see if the caller
* is passing old school device names like "/dev/[r]sd" or
* exotic hardware presenting "/dev/[r]dc" names.
*/
} else {
return (NULL);
}
}
dp++;
if (*dp == '\0')
return (NULL);
return (rdskp);
}
/*
* FUNCTION: rawname()
* INPUT: uname - Fully qualified pathname of a block or character device
* RETURNS: char * - The fully qualified character device pathname
* PURPOSE: Return the fully qualified pathname of the character device
* corresponding to the block or character device passed in.
*/
static char *
{
if (*uname != '/')
return (NULL);
return (NULL);
return (NULL);
}
}
return (new_path);
}
char *
char *uname
)
{
char *p;
return (NULL);
} else if (*p == '\0') {
Free(p);
return (NULL);
} else {
return (p);
}
}
/*
* FUNCTION: parse_device()
* INPUT: sp - pointer to setname struct
* uname - Name of either a hotspare pool or metadevice
* This can either be a fully qualified path or
* in the form [set name/]device
* OUTPUT: snamep - name of the set that uname is in
* fnamep - metadevice or hsp with path and set name info stripped
* This parameter is dynamically allocated and must be
* freed by the calling function.
* PURPOSE: Parse uname and sp into the set name and device name strings.
* If the set name is specified as part of uname then use that
* otherwise attempt to get the set name from sp.
*/
void
char *uname,
char **fnamep, /* dynamically alloced - caller must free */
char **snamep /* dynamically alloced - caller must free */
)
{
int len;
char *up;
char *tp;
/* Now copy uname to tname by throwing away any duplicate '/' */
if (lcws) {
if (*up == '/') {
continue;
} else {
lcws = 0;
}
}
if (*up == '/') {
lcws = 1;
}
}
*tp = '\0';
/* fully-qualified - local set */
return;
}
/* with setname specified - either fully qualified and relative spec */
return;
}
/* without setname specified */
else
}
/*
* check for "all"
*/
int
meta_is_all(char *s)
{
return (1);
return (0);
}
/*
* check for "none"
*/
int
meta_is_none(char *s)
{
return (1);
return (0);
}
static int
{
int i;
int uname_len;
return (0);
return (0);
/* 'all' and 'none' are reserved */
return (0);
for (i = 1; i < uname_len; i++) {
continue;
break;
}
if (i < uname_len)
return (0);
return (1);
}
/*
* canonicalize name
*/
char *
char *uname
)
{
char *cname;
/* return the dev name and set name */
if (!valid_name_syntax(tname)) {
return (NULL);
}
else {
(void) snprintf(
}
return (cname);
}
/*
* canonicalize name and check the set
*/
char *
mdsetname_t **spp,
char *uname,
)
{
char *cname;
/* return the dev name and set name */
if (!valid_name_syntax(tname)) {
return (NULL);
}
/* check the set name returned from the name for validity */
return (NULL);
}
else {
(void) snprintf(
}
return (cname);
}
/*
* Verify that the name is a valid hsp/metadevice name
*/
static int
{
int ret;
/* return the dev name and set name */
return (ret);
}
/*
* check that name is a metadevice
*/
int
char *uname
)
{
return (parse_meta_hsp_name(uname));
}
/*
* check that name is a hotspare pool
*/
int
char *uname
)
{
return (parse_meta_hsp_name(uname));
}
/*
* check to verify that name is an existing metadevice
*/
int
char *uname
)
{
char *raw_name;
char *set_name;
char *full_path;
int pathlen;
int retval = 0;
/*
* If it is an absolute name of a metadevice, then just call rawname
* on the input
*/
if (uname[0] == '/') {
return (1);
}
return (0);
}
/* create a fully specified path from the parsed string */
} else {
}
retval = 1;
}
return (retval);
}
/*
* check to verify that name is an existing hsp
*/
int
char *uname
)
{
else
cur_set = 0;
if (hsp == MD_HSP_NONE) {
mdclrerror(&status);
return (0);
}
return (1);
}
/*
* check to verify that name is an existing metadevice or hotspare pool
*/
int
char *uname
)
{
return (1);
return (0);
}
/*
* mdsetname_t stuff
*/
/*
* initialize setname
*/
static void
)
{
}
static void
{
if (MD_MNSET_DESC(sd)) {
while (nd) {
}
}
}
/*
* free allocated setname
*/
static void
)
{
}
/*
* flush the setname cache
*/
static void
{
mdsetnamelist_t *p, *n;
n = p->next;
metafreesetname(p->sp);
Free(p);
}
}
/*
* get set number
*/
static int
char *sname,
)
{
/* local set */
*setnop = 0;
return (0);
}
/* shared set */
char *p;
Free(p);
}
return (-1);
}
mdclrerror(ep);
return (0);
}
/*
* find setname from name
*/
char *sname,
)
{
/* look for cached value first */
return (sp);
}
}
/* setup set */
return (NULL);
/* allocate new list element and setname */
return (sp);
}
/*
* find setname from setno
*/
)
{
/* look for cached value first */
return (sp);
}
/* local set */
if (setno == MD_LOCAL_SET)
/* shared set */
return (NULL);
mdclrerror(ep);
return (sp);
}
char *sname
)
{
/* look for cached value first */
return (sp);
}
}
/* allocate new list element and setname */
return (sp);
}
/*
* setup set record (sr) and cache it in the mdsetname_t struct
*/
)
{
int i;
if (MD_MNSET_DESC(sd)) {
}
/*
* Get membershiplist from API routine. If there's
* an error, just use a NULL nodelist.
*/
nodecnt = 0; /* no nodes are alive */
}
nrcnt = 0;
/*
* Node descriptor node list must be built in
* ascending order of nodeid. The nodechain
* in the mnset record is in ascending order,
* so just make them the same.
*/
while (nr) {
if (nd_prev) {
} else {
}
sizeof (nd->nd_nodename));
}
}
/*
* If node is marked ALIVE, then set priv_ic
* from membership list. During the early part
* of a reconfig cycle, the membership list may
* have been changed, (a node entering or leaving
* the cluster), but rpc.metad hasn't flushed
* its data yet. So, if node is marked alive, but
* is no longer in the membership list (node has
* left the cluster) then just leave priv_ic to NULL.
*/
while (nl2) {
sizeof (nd->nd_priv_ic));
break;
}
}
}
nrcnt++;
}
if (nodecnt)
/* Just copying to keep consistent view between sr & sd */
} else {
for (i = 0; i < MD_MAXSIDES; i++)
}
return (sd);
}
)
{
mdclrerror(ep);
}
}
mdclrerror(ep);
}
}
return (NULL);
}
/*
* metapurgesetcache:
* -----------------
* Purge the application setlistp cache for the given set number.
* This means a subsequent call to metasetname() or metasetnosetname() will
* incur a disk access to read the replica set contents instead of
* short-circuiting and returning potentially stale cached data.
*/
static void
{
if (sp) {
} else {
}
return;
}
}
}
}
void
{
return;
return;
/*
* Purge the setlistp cache for this setno
*/
}
/*
* metaflushsetno:
* --------------
* Flush the setlistp cache for the given non-local setno.
*/
void
{
}
}
/*
* check for local set
*/
int
)
{
return (1);
} else {
return (0);
}
}
/*
* check for same set
*/
int
)
{
return (1);
} else {
return (0);
}
}
/*
* check to see if set changed
*/
static int
mdsetname_t **spp,
char *sname,
)
{
/* if we already have a set, make sure it's the same */
}
return (0);
}
/* otherwise store new set name and number */
return (-1);
}
/* return success */
return (0);
}
/*
* check to see if set changed from default
*/
static int
mdsetname_t **spp,
char *sname,
)
{
/* default to *spp's setname, or if that is NULL to MD_LOCAL_NAME */
if (*spp) {
return (0);
} else {
}
}
/* see if changed */
}
/*
* check setname from setno
*/
static int
mdsetname_t **spp,
)
{
int rval;
/* local set */
if (setno == 0)
/* shared set */
return (-1);
if (rval != -1)
mdclrerror(ep);
return (rval);
}
/*
* mddrivename_t stuff
*/
/*
* initialize name
*/
static void
)
{
}
/*
* free allocated name
*/
static void
)
{
}
/*
* initialize drive name
*/
static void
)
{
}
/*
* flush side names
*/
void
)
{
mdsidenames_t *p, *n;
n = p->next;
Free(p);
}
}
/*
* free drive name
*/
void
)
{
}
/*
* flush the drive name cache
*/
void
{
mddrivenamelist_t *p, *n;
n = p->next;
Free(p->drivenamep);
Free(p);
}
drivelistp = NULL;
}
/*
* peel off s%u from name
*/
char *
char *name
)
{
char *p, *e;
uint_t d = 0;
int l = 0;
/*
*/
}
/*
*/
}
/* gobble number and 's' */
for (; (p > name); --p) {
if (!isdigit(*p))
break;
}
if ((p == e) || (p <= name))
p--;
*(++p) = '\0';
*p = 's';
return (e);
}
/*
* free list of drivenames
*/
void
)
{
}
}
/*
* build list of drivenames
*/
int
mdsetname_t **spp,
int argc,
char *argv[],
)
{
int count = 0;
return (-1);
}
}
return (count);
}
/*
* append to end of drivename list
*/
)
{
/* run to end of list */
;
/* allocate new list element */
/* append drivename */
return (dnp);
}
/*
* FUNCTION: meta_drivenamelist_append_wrapper()
* INPUT: tailpp - pointer to the list tail pointer
* dnp - name node to be appended to list
* OUTPUT: none
* RETURNS: mddrivenamelist_t * - new tail of the list.
* PURPOSE: wrapper to meta_namelist_append for performance.
* metanamelist_append finds the tail each time which slows
* down long lists. By keeping track of the tail ourselves
* we can change metadrivenamelist_append into a
* constant time operation.
*/
)
{
/* If it's the first item in the list, return it instead of the next */
return (tailpp);
}
/*
* mdname_t stuff
*/
/*
* check set and get comparison name
*
* NOTE: This function has a side effect of setting *spp if the setname
* has been specified and *spp is not already set.
*/
char *
mdsetname_t **spp,
char *uname,
)
{
/*
* if the setname is specified in uname, *spp is set,
* and the set names don't agree then canonical name will be
* returned as NULL
*/
}
return (NULL);
}
/*
* FUNCTION: getrname()
* INPUT: spp - the setname struct
* uname - the possibly unqualified device name
* type - ptr to the device type of uname
* OUTPUT: ep - return error pointer
* RETURNS: char* - character string containing the fully
* qualified raw device name
* PURPOSE: Create the fully qualified raw name for the possibly
* unqualified device name. If uname is an absolute
* path the raw name is derived from the input string.
* Otherwise, an attempt is made to get the rawname by
* value of type is UNKNOWN and it can be successfully
* determined then update type to the correct value.
*/
static char *
{
char *rname;
char *fname;
int i;
int rname_cnt = 0;
/* if it is an absolute name then just call rawname on the input */
if (uname[0] == '/') {
/*
* If the returned rname does not match with
* the specified uname type, we'll return null.
*/
if (*type == LOGICAL_DEVICE) {
return (NULL);
}
*type = META_DEVICE;
} else {
if (*type == META_DEVICE) {
return (NULL);
}
*type = LOGICAL_DEVICE;
}
return (rname);
}
/* out of luck */
return (NULL);
}
/*
* Get device that matches the requested type. If
* a match is found, return immediately. If type is
* UNKNOWN, save all the found devices in rname_list
* so we can determine later whether the input uname
* is ambiguous.
*
* Check for metadevice before physical device.
* With the introduction of softpartitions it is more
* likely to be a metadevice.
*/
/* metadevice short form */
if (metaislocalset(*spp)) {
} else {
char *p;
++p;
} else {
p = uname;
}
}
if (*type == META_DEVICE) {
/*
* Handle the case where we have a new metadevice
* that does not yet exist in the name-space(e.g
* not yet created in the non-master nodes). In
* this case we return the constructed metadevice
* name as that will exist after the metainit call
* has created it.
*/
}
return (rname);
}
/* Save this result */
rname_cnt ++;
}
}
/* Simply return if a logical device was requested */
if (*type == LOGICAL_DEVICE) {
return (rname);
} else {
rname_cnt ++;
}
}
}
/*
* ./ for the specified device. rname_list contains all
* the matches we've found and rname_cnt is the number of
* matches.
*
* We know that either we don't have a match if a specific
* type was given, in which case we simply return NULL or
* we have an UNKNOWN device with 1-3 entries in rname_list.
*
* If we get 3 entries, rname_cnt == 3, it's ambiguous.
* If we only get 1 entry, rname_cnt == 1, return rname_list[0].
* If we get 2 entries that are not the same, it's ambigous.
*/
/* out of luck */
return (NULL);
} else {
if (rname_cnt == 3) {
"Error: ambiguous device name.\n%s %s %s\n\n"),
}
/* grab the type in case it is not ambiguous */
else
if (rname_cnt == 1) {
} else {
/*
* Prevent the case where the command is run in
* rname_list[0] and rname_list[1] are the same.
*/
if (rname_cnt != 3) {
/*
* For the rname_cnt == 3 case, the
* error was printed above.
*/
"Error: ambiguous device "
"name.\n%s %s\n\n"),
}
} else {
}
}
for (i = 0; i < rname_cnt; i++)
Free(rname_list[i]);
return (rname);
}
}
/*
* get raw slice and drive names
*/
static char *
mdsetname_t **spp,
char *uname,
char **dnamep,
)
{
/*
* Incorrect code path if type is HSP_DEVICE
*/
/* initialize */
/* get slice name */
return (rname);
}
/*
* If name cannot be found, if may be because is is not accessible.
* If it is an absolute name, try all possible disk name formats and
* Since the code below assumes logical devices, if the given
* uname_type is META_DEVICE, there's nothing to do.
*/
if (uname[0] == '/') {
/* Absolute name */
uint_t d = 0;
int l = 0;
/*
* Handle old style raw names
*/
mdclrerror(ep);
return (rname);
}
/*
* Handle old style block names
*/
return (rname);
}
/* /.../dsk/... or /.../rdsk/... */
mdclrerror(ep);
return (rname);
}
} else {
/*
* If it's not an absolute name but is a valid ctd name,
*/
uint_t s;
uname);
return (rname);
}
}
}
/* out of luck */
return (NULL);
}
/*
* get number of slices for name
*/
static int
char *rname,
char *dname,
)
{
char *srname;
size_t l = 0;
/*
* get our slice number - works only with names that end in s%u -
* all others return -1.
*/
(int)*slicep < 0) {
return (-1);
}
/*
* go find how many slices there really are
*/
/* build slice name */
/* see if it's there */
break;
}
}
/* Need to make sure that we at least have V_NUMPAR */
/* make sure we have at least our slice */
return (-1);
/* return number of slices */
return (nslice);
}
/*
* Attempt to parse the input string as a c[t]ds specifier
* The target can either be a SCSI target id or if the device
* is in a fabric configuration in a fibre channel setup then
* the target is a standard WWN (world wide name).
*
* if successful return 0
* if c[t]dp name return 1
* otherwise return -1
*/
int
char *uname,
{
char *partial_ctd_str;
char *target_str;
char *device_start_pos;
int l = -1;
/* pull off the channel spec and the 't' for the target */
/* check for cds style name */
return (-1);
} else {
l--; /* we want to be on the 'd' */
has_target = 0;
}
}
partial_ctd_str = uname + l;
/* find the beginning of the device specifier */
if (device_start_pos == NULL) {
return (-1);
}
/* check to see if it is a ctd with a WWN or SCSI target */
if (has_target) {
/* pull off the target and see if it is a WWN */
target_str_len - 2);
l != target_str_len) {
return (-1);
}
}
/* check the device and slice */
l != cl) {
/* check the device and partition */
== 2 && l == cl) {
return (1);
}
return (-1);
}
return (0);
}
/*
* get number of slices for name
*/
static int
char *uname,
)
{
uint_t c = 0, t = 0, d = 0;
int l = 0, cl = 0;
int fd;
char *p;
if (uname_type == META_DEVICE)
return (*slicep = 0);
p++;
else
p = uname;
return (*slicep);
l == cl)
return (*slicep);
return (*slicep);
/*
* If we can't get the slice from the name, then we have to do it the
* hard and expensive way.
*/
return (-1);
/* get controller info */
return (-1);
}
else
return (-1);
}
}
}
/*
* get partition info
*/
static int
char *rname,
char *dname,
)
{
int nparts;
/* metadevice */
if (uname_type == META_DEVICE) {
nparts = 1;
partno = 0;
goto gotit;
}
/* see how many partitions in drive, this is really tricky */
metainitname(&name);
/* partno already setup */
/* dname already setup */
goto gotit;
}
return (-1);
/* fallback and try and guess (used to check for just EACCES here) */
if (mdanysyserror(ep)) {
} else {
}
mdclrerror(ep);
/* nparts already setup */
/* partno already setup */
/* dname already setup */
goto gotit;
}
/* nothing worked */
if (mdanysyserror(ep)) {
} else {
}
mdclrerror(ep);
mdclrerror(ep);
partno = 0;
}
/* return success */
return (0);
}
/*
* get block name
*/
static int
)
{
char *bname;
/* fully qualified */
return (0);
}
/* out of luck */
}
static void
)
{
char *p;
/* regular device */
return;
}
return;
}
return;
}
/* anything else but metadevice */
return;
}
/* metadevice */
++p;
if (metaislocalset(sp)) {
} else {
}
}
/*
* get dev
*/
int
)
{
/* get dev */
/* check set */
/* return sucess */
return (0);
}
/*
* set up names for a slice
*/
static int
char *rname,
)
{
/* get names */
return (-1);
return (-1);
/* return success */
return (0);
}
/*
* fake up names for a slice
*/
static void
char *rname
)
{
char *p;
uint_t d = 0;
int l = 0;
/* fake names */
/*
* Fixup old style names
*/
/*
* Fixup new style names
*/
for (++p; (*(p + 1) != '\0'); ++p)
*p = *(p + 1);
*p = '\0';
}
}
static mdname_t *
char *uname,
char *rname,
char *dname,
)
{
/* must have a set */
if (rname)
else if (uname_type == META_DEVICE)
else {
uint_t d = 0;
/*
*/
'a' + partno);
'a' + partno);
} else {
/* build the slice that is wanted */
}
}
mdclrerror(ep);
if (mdanysyserror(ep)) {
} else {
}
mdclrerror(ep);
} else {
mdclrerror(ep);
goto fixup;
}
}
}
out:
/* return name */
return (np);
if (mdanysyserror(ep)) {
char *p;
mdclrerror(ep);
else
} else {
else
}
}
goto out;
}
/*
* flush the fast name cache
*/
static void
{
}
}
/*
* flush the fast name cache
*/
static void
{
mdnamelist_t *p, *n;
n = p->next;
metafreefastnm(&p->namep);
Free(p);
}
}
static char *
{
uint_t d = 0;
int l = 0;
char *rnm;
if (uname_type == META_DEVICE) {
/* fully qualified - local set */
return (rnm);
}
/* fully qualified - setname specified */
return (rnm);
}
/* Fully qualified path - error */
if (unm[0] == '/') {
return (NULL);
}
/* setname specified <setname>/<metadev> */
/* Not <setname>/<metadev> - error */
return (NULL);
}
return (rnm);
}
return (rnm);
}
/* NOT Fully qualified path, done */
if (unm[0] != '/') {
return (NULL);
}
/*
* Get slice information from old style names of the form
* devices, but after metadevices.
*/
}
}
/* /.../dsk/... or /.../rdsk/... */
return (rnm);
/*
* Shouldn't get here but if we do then we have an unrecognized
* fully qualified path - error
*/
return (NULL);
}
static mdname_t *
char *uname,
)
{
uint_t c = 0, t = 0, d = 0, s = 0;
int l = 0;
char *cname;
return (np);
}
/* Metadevices */
if (uname_type == META_DEVICE &&
goto done;
}
/* Others */
&s, &l) == 4 ||
&s, &l) == 4 ||
&s, &l) == 4 ||
&s, &l) == 4 ||
else
} else {
}
done:
/* Driver always gives us block names */
/* canonical disk name */
} else {
return (NULL);
}
/* cleanup, return success */
return (np);
}
/*
* set up names for a device
*/
static mdname_t *
mdsetname_t **spp,
char *uname,
int fast,
)
{
/* check setname */
return (NULL);
/* get raw name (rname) of the slice and drive (dname) we have */
return (NULL);
}
/* look in cache first */
/* check to see if the drive name is already in the cache */
return (NULL);
}
}
/*
* If a fast names is OK, then get one, and be done.
*/
if (fast) {
}
/* allocate new list element and drive */
/* get parts info */
goto out;
/*
* libmeta needs at least V_NUMPAR partitions.
* If we have an EFI partition with less than V_NUMPAR slices,
* we nevertheless reserve space for V_NUMPAR
*/
}
/* allocate and link in parts */
}
/* setup name_t (or slice) wanted */
goto out;
/* canonical disk name */
/* cleanup, return success */
return (np);
/* cleanup, return error */
out:
return (NULL);
}
/*
* metaname()
*
* Wrapper function for metaname_common()
* If the second arg is a metadevice name then it is important that this should
* case then a bad entry may be placed into the drivelistp cache.
*/
mdname_t *
mdsetname_t **spp,
char *uname,
)
{
}
mdname_t *
mdsetname_t **spp,
char *uname,
)
{
}
/*
* Get the dnp using the device id.
*
* We have the potential to have more than 1 dnp with the same disk name but
* have different device ids. This would happen in the case of a partial
* diskset. The unavailable disk name is relative to the prior host and could
* possibly be the same as a disk on this system. The only way to tell which
* dnp belongs with this disk is by searching by device id. We have the
* potential to have the case where 1) the disk who's device id we pass in is
* in the system. In this case the name and the device id are both valid for
* the disk. 2) The disk whose device id we've been passed is not in the
* system and no disk with the same name has a dnp on the list. And 3) The
* disk whose device id we've been passed is not on the system but there is
* a disk with the same name (different devid) that is on the system. Here's
* what we return for each of those cases:
* 1) If disk is in system:
* disk is found on drivelistp or we create a new drivename and it's
* fully populated as expected.
* 2) If disk not in system, no collision
* Disk with the same devid is not found on drivelistp, we create a new
* drivename structure and the dnp->devid is filled in not from getparts
* but from the devidp passed in. No other disk in the system has the
* same "name" or devid.
* This situation would be caused by the import of a partial diskset.
* 3) If disk not in system, collision
* Disk with the same devid is not found on the drivelistp, we create a
* new drivename struct but getparts will use the information from the
* name which is actually in reference to another disk of the same name
* in the system. getparts will fill in the dnp->devid with the value
* from the other disk and we overwrite this with the value of this disk.
* To get into this situation one of the disks is actually unavailable
* as in the case of a partial import.
*/
)
{
char *nm;
int ret;
/* look in the cache first */
continue;
continue;
if (ret != 0) {
/* unable to decode the devid */
return (NULL);
}
/* compare with the devid passed in. */
/* match! We have the same disk */
return (dnp);
}
}
/* drive not in the cache */
return (NULL);
}
/* get namespace info */
if (MD_MNSET_DESC(sd)) {
return (NULL);
} else {
return (NULL);
}
/* get raw name (rname) of the slice and drive name (dname) */
return (NULL);
}
/* allocate new list element and drive */
/* get parts info */
/*
* Note that if the disk is unavailable this name will point to
* either a nonexistent disk and thus the part info and devid will
* be empty or the name will point to the wrong disk and this
* information will be invalid. Because of this, we overwrite the
* dnp->devid with the correct one after getparts returns.
*/
goto out;
/*
* libmeta needs at least V_NUMPAR partitions.
* If we have an EFI partition with less than V_NUMPAR slices,
* we nevertheless reserve space for V_NUMPAR
*/
}
/* allocate and link in parts */
}
/* setup name_t (or slice) wanted */
goto out;
/* canonical disk name */
return (dnp);
out:
return (NULL);
}
/*
* Search the drivename list by devid instead of name. If you don't find
* an entry with the same device id, create one for the uname passed in.
*/
mdsetname_t **spp,
char *devid,
char *uname,
)
{
char *dname;
int ret;
/* look in the cache first */
continue;
/* decode the dnp devid */
if (ret != 0) {
/* unable to decode the devid */
return (NULL);
}
/* decode the passed in devid */
if (ret != 0) {
/* unable to decode the devid */
return (NULL);
}
/* compare with the devids */
/* match! We have the same disk */
return (dnp);
}
}
/* not in the cache */
/* get raw name (rname) of the slice and drive (dname) we have */
return (NULL);
}
/* allocate new list element and drive */
/* get parts info */
goto out;
/*
* libmeta needs at least V_NUMPAR partitions.
* If we have an EFI partition with less than V_NUMPAR slices,
* we nevertheless reserve space for V_NUMPAR
*/
}
/* allocate and link in parts */
}
/* setup name_t (or slice) wanted */
goto out;
/* canonical disk name */
/* cleanup, return success */
return (dnp);
/* cleanup, return error */
out:
return (NULL);
}
/*
* set up names for a drive
*/
mdsetname_t **spp,
char *uname,
)
{
char *slicename;
char *dname;
int i;
int mplen;
return (NULL);
}
/* look in cache first */
return (dnp);
}
}
/* Check each possible slice name based on MD_MAX_PARTS. */
/*
* Figure out how much string space to reserve to fit
* (MD_MAX_PARTS - 1) into the name string; the loop will
* increment the mplen counter once for each decimal digit in
* (MD_MAX_PARTS - 1).
*/
;
/* Check for each slice in turn until we find one */
}
}
return (NULL);
}
return (np->drivenamep);
}
/*
* FUNCTION: metaslicename_type()
* INPUT: dnp - the drivename structure
* sliceno - the slice on the drive to return
* type - LOGICAL_DEVICE or META_DEVICE
* OUTPUT: ep - return error pointer
* RETURNS: mdname_t- pointer the the slice name structure
* PURPOSE: interface to the parts struct in the drive name struct
* Since there is no guarantee that the slice name
* structures are populated users should call this
* function rather than accessing the structure directly
* since it will populate the structure values if they
* haven't already been populated before returning.
*/
mdname_t *
)
{
return (NULL);
}
/* check to see if the struct is already populated */
return (np);
}
return (NULL);
return (np);
}
/*
* FUNCTION: metaslicename()
* INPUT: dnp - the drivename structure
* sliceno - the slice on the drive to return
* OUTPUT: ep - return error pointer
* RETURNS: mdname_t- pointer the the slice name structure
* PURPOSE: interface to the parts struct in the drive name struct
* Since there is no guarantee that the slice name
* structures are populated users should call this
* function rather than accessing the structure directly
* since it will populate the structure values if they
* haven't already been populated before returning.
*/
mdname_t *
)
{
}
/*
* set up metadevice name from id
*/
mdname_t *
mdsetname_t **spp,
int fast,
)
{
char *uname;
/* check set first */
return (NULL);
/* get corresponding device name */
return (NULL);
/* setup name */
if (fast) {
if (np) {
}
} else
return (np);
}
/*
* return metadevice name
*/
char *
)
{
/* get name */
return (NULL);
}
/* return name */
}
/*
* check for device type
*/
int
)
{
}
int
)
{
if (! metaismeta(np)) {
}
return (0);
}
int
)
{
case MDT_ACCES:
case MDT_UNKNOWN:
default:
assert(0);
}
}
return (0);
}
int
)
{
if (metaismeta(np)) {
}
}
/*
* free list of names
*/
void
)
{
}
}
/*
* build list of names
*/
int
mdsetname_t **spp,
mdnamelist_t **nlpp,
int argc,
char *argv[],
)
{
int count = 0;
return (-1);
}
}
return (count);
}
/*
* append to end of name list
*/
mdname_t *
mdnamelist_t **nlpp,
)
{
/* run to end of list */
;
/* allocate new list element */
/* append name */
return (np);
}
/*
* FUNCTION: meta_namelist_append_wrapper()
* INPUT: tailpp - pointer to the list tail pointer
* np - name node to be appended to list
* OUTPUT: none
* RETURNS: mdnamelist_t * - new tail of the list.
* PURPOSE: wrapper to meta_namelist_append for performance.
* metanamelist_append finds the tail each time which slows
* down long lists. By keeping track of the tail ourselves
* we can change metanamelist_append into a constant time
* operation.
*/
mdnamelist_t **
)
{
/* If it's the first item in the list, return it instead of the next */
return (tailpp);
}
/*
* mdhspname_t stuff
*/
/*
* initialize hspname
*/
static void
)
{
}
/*
* free allocated hspname
*/
static void
)
{
}
/*
* clear the hspname cache
*/
static void
{
mdhspnamelist_t *p, *n;
n = p->next;
metafreehspname(p->hspnamep);
Free(p);
}
}
/*
* check set and get comparison name
*/
static char *
mdsetname_t **spp,
char *uname,
)
{
return (NULL);
}
return (cname);
}
/*
* set up a hotspare pool name structure using both the name
* and the self id
*/
static mdhspname_t *
mdsetname_t **spp,
char *uname,
)
{
char *cname;
/* check setname */
return (NULL);
/* look in cache first */
/* if the hsp value has not been set then set it now */
return (hspnp);
}
}
/* if the hsp number isn't specified then attempt to get it */
/*
* If the error is ENOENT, then we will continue on,
* because the device does not yet exist.
* For other types of errors, however, we'll bail out.
*/
return (NULL);
}
mdclrerror(ep);
}
}
/* allocate new list element and hspname */
/* save hspname and number */
/* success */
return (hspnp);
}
/*
* set up names for a hotspare pool
*/
mdsetname_t **spp,
char *uname,
)
{
}
/*
* set up hotspare pool name from key
*/
mdsetname_t **spp,
)
{
char *uname;
/* check set first */
return (NULL);
/* get corresponding hotspare pool name */
return (NULL);
/* setup name */
return (hspnp);
}
/*
* return hotspare pool name
*/
char *
{
/* get name */
mdclrerror(&status);
return (NULL);
}
/* return name */
}
/*
* free hotspare pool list
*/
void
{
}
}
/*
* build list of hotspare pool names
*/
int
mdsetname_t **spp,
int argc,
char *argv[],
)
{
int count = 0;
return (-1);
}
}
return (count);
}
/*
* append to end of hotspare pool list
*/
{
/* run to end of list */
;
/* allocate new list element */
/* append hotspare pool name */
return (hspnp);
}
/*
* get name from dev
*/
mdname_t *
mdsetname_t **spp,
md_error_t *ep)
{
char *device_name;
/* short circuit metadevices */
if (meta_dev_ismeta(dev))
/* create local set, if necessary */
return (NULL);
}
/* get name from namespace */
return (NULL);
}
return (namep);
}
/*
* return cached name from md_dev64_t
*/
static char *
{
/* look in cache */
uint_t i;
}
}
/* not found */
return (NULL);
}
/*
* Ask the driver for the name, which has been stored in the
* metadevice state database (on behalf of the utilities).
* (by devno)
*/
char *
{
/* get name */
if ((setno == MD_SET_BAD) ||
mdclrerror(&status);
return (metadevtocachename(dev));
}
/* return name */
}
/*
* get name from key
*/
mdname_t *
mdsetname_t **spp,
int fast,
)
{
char *device_name;
/* create local set, if necessary */
return (NULL);
}
/* get name from namespace */
return (NULL);
}
if (fast)
else
if (namep)
return (namep);
}
/*
*/
void
{
}
/*
* completely flush the caches
*/
void
{
if (flush_sr_cache)
sr_cache_flush(0);
}
/*
* meta_get_hotspare_names
* returns an mdnamelist_t of hot spare names
*/
int
mdnamelist_t **nlpp,
int options,
)
{
int cnt = 0;
/* get hotspare names */
cnt = -1;
goto out;
}
/* build name list */
int i;
cnt = -1;
goto out;
}
++cnt;
}
}
/* cleanup and return count or error */
out:
/*
* At least try to give some sort of meaningful error
*/
}
return (cnt);
}
/*
* meta_create_non_dup_list
* INPUT: mdnp mdname_t pointer to add to the list if a new name
* ldevidp list of non-duplicate names.
* OUTPUT: ldevidp list of non-duplicate names.
* meta_create_non_dup_list will take a mdname_t pointer and if the device
* is not in the list (ldevidp) will add it to the list.
* User needs to free allocated memory.
*/
void
)
{
char *lcname;
return;
/*
* Grab the name of the device and strip off slice information
*/
return;
}
else
*slice = '\0';
/* first item in list */
} else {
/* already there so just return */
return;
}
lastdevidp = tmp;
}
}
}