/*
* 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 <dlfcn.h>
#include <meta.h>
#include <metadyn.h>
#include <ctype.h>
#include <dirent.h>
#include <devid.h>
#include <sys/efi_partition.h>
typedef struct ctlr_cache {
char *ctlr_nm;
int ctlr_ty;
} ctlr_cache_t;
/*
* return set for a device
*/
int bypass_daemon,
)
{
/* metadevice */
if (metaismeta(np))
ep));
/* regular device */
ep) != 0)
return (NULL);
return (sp);
}
/*
* convert system to md types
*/
static void
)
{
}
/*
* convert efi to md types
*/
static void
{
/*
* Should always get geom from metadevice unit if metadevice.
* If metadevice is built on top of efi disks then it will
* have MD_EFI_FG_ values, otherwise it will have geom from
* the first component.
*/
if (mdev) {
} else {
/ (MD_EFI_FG_HEADS * MD_EFI_FG_SECTORS);
}
}
static void
{
uint_t i;
return;
for (i = 0; (i < gpt->efi_nparts); ++i) {
/*
* It is possible to present an efi label but be using vtoc
* disks to create a > 1 TB metadevice. In case the first
* disk in the underlying metadevice is a vtoc disk and starts
* at the beginning of the disk it is necessary to convey this
* information to the user.
*/
}
/*
* Due to the lack of a label for the entire partition table,
* we use p_name of the reserved partition
*/
/* Stop at first (if any) space or tab */
}
}
}
static void
{
uint_t i;
/* first we count how many partitions we have to send */
for (i = 0; i < MD_MAX_PARTS; i++) {
continue;
}
/* if we are here, we know the partition is really used */
lastpart = i;
}
for (i = 0; (i < (*gpt)->efi_nparts); ++i) {
/*
* Due to the lack of a label for the entire partition table,
* we use p_name of the reserved partition
*/
}
}
}
void
{
return;
}
int
{
return (-1);
}
void
metaflushctlrcache(void)
{
}
ctlr_cache = NULL;
}
/*
* getdrvnode -- return the driver name based on mdname_t->bname
* Need to free pointer when finished.
*/
char *
{
char *devicespath;
char *drvnode;
char *cp;
return (NULL);
/*
* At this point devicespath should be like the following
* "/devices/<unknow_and_dont_care>/xxxx@vvvv"
*
* There's a couple of 'if' statements below which could
* return an error condition, but I've decide to allow
* a more open approach regarding the mapping so as to
* not restrict possible future projects.
*/
/*
* drvnode now just "xxxx@vvvv"
*/
drvnode++;
/*
* Now drvnode is just the driver name "xxxx"
*/
*cp = '\0';
return (cp);
}
/*
* meta_load_dl -- open dynamic library using LDLIBRARYPATH, a debug
* environment variable METALDPATH, or the default location.
*/
static void *
{
char *drvnode;
char *p;
void *cookie;
/*
* Library seach algorithm:
* 1) Use LDLIBRARYPATH which is implied when a non-absolute
* path name is passed to dlopen()
* 2) Use the value of METALDPATH as the directory. Mainly
* used for debugging
*/
drvnode);
p = METALDPATH_DEFAULT;
/*
* Common failure here would be failing to
* Some controllers will not have a library
* because there's no enclosure or name
* translation required.
*/
return (cookie);
}
} else {
return (cookie);
}
}
return (NULL);
}
/*
* meta_match_names -- possibly convert the driver names returned by CINFO
*/
static void
md_error_t *ep)
{
void *cookie;
md_error_t *));
}
}
/*
* meta_match_enclosure -- return any enclosure info if found
*/
int
{
md_error_t *));
void *cookie;
switch (e) {
case Enclosure_Error:
/*
* Looks like this library wanted to handle
* our device and had an internal error.
*/
return (1);
case Enclosure_Okay:
/*
* Found a library to handle the request so
* just return with data provided.
*/
return (0);
case Enclosure_Noop:
/*
* Need to continue the search
*/
break;
}
}
}
return (0);
}
static int
md_error_t *ep)
{
/* default */
/*
* See if the driver name returned from DKIOCINFO
* is valid or not. In somecases, such as the ap_dmd
* driver, we need to modify the name that's return
* for everything to work.
*/
return (-1);
/* return success */
return (0);
}
static void
)
{
uint_t i;
sizeof (vp->v_asciilabel));
typename[i] = '\0';
break;
}
}
}
}
/*
* free allocations in vtoc
*/
void
)
{
}
/*
* return md types
*/
mdvtoc_t *
int nocache,
)
{
int fd;
int partno;
char *p;
/* short circuit */
/*
* the following assigment works because the
* mdname_t structs are always created as part
* of the drivenamep struct. When a user
* creates an mdname_t struct it either
* uses an existing drivenamep struct or creates
* a new one and then adds the mdname_t struct
* as part of its parts_val array. So what is
* being computed below is the slice offset in
* the parts_val array.
*/
}
}
/* can't get vtoc */
if (! nocache) {
case MDT_ACCES:
case MDT_UNKNOWN:
return (NULL);
}
}
/* get all the info */
return (NULL);
}
/*
* The disk is open so this is a good point to get the devid
* otherwise it will need to be done at another time which
* means reopening it.
*/
/* there is no devid for the disk */
}
} else {
/*
* The minor name could be NULL if the underlying
* device driver does not support 'minor names'.
* This means we do not use devid's for this device.
* SunCluster did driver does not support minor names.
*/
if (minor_name != NULL) {
} else {
"%s no minor name (no devid)\n"),
}
}
}
/*
* if our drivenamep points to a device not supporting DKIOCGGEOM,
* it's likely to have an EFI label.
*/
return (NULL);
return (NULL);
}
}
/*
* If we are here, there was either no failure on DKIOCGGEOM or
* the failure was ENOTSUP
*/
/* DKIOCGGEOM yielded ENOTSUP => try efi_alloc_and_read */
int save_errno;
/* this also sets errno */
save_errno = errno;
if (partno < 0) {
return (NULL);
}
rname);
return (NULL);
}
/* convert to our format */
rname);
return (NULL);
}
/*
* 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
*/
}
/*
* Is np a metadevice?
*/
if (metaismeta(np)) {
NULL) {
return (NULL);
}
}
} else {
/* no error on DKIOCGGEOM, try meta_getvtoc */
return (NULL);
}
/* convert to our format */
}
/* fix up any drives which are now accessible */
}
/* save partno */
/* return info */
}
static void
)
{
uint_t i;
}
}
/*
* Set the vtoc, but use the cached copy to get the info from.
* We write np->drivenamep->vtoc to disk.
* Before we can do this we read the vtoc in.
* if we're dealing with a metadevice and this metadevice is a 64 bit device
* we can use meta_getmdvtoc/meta_setmdvtoc
* else
* we use meta_getvtoc/meta_setvtoc but than we first have to convert
* dnp->vtoc (actually being a mdvtoc_t) into a vtoc_t
*/
int
)
{
int fd;
int err;
int save_errno;
save_errno = errno;
if (err == 0) {
return (-1);
}
return (-1);
}
} else if (save_errno == ENOTSUP) {
int ret;
/* allocation of gpt is done in meta_mdvtoc_to_efi */
save_errno = errno;
if (ret != 0) {
} else {
return (0);
}
} else {
}
return (0);
}
mdgeom_t *
)
{
return (NULL);
}
)
{
int fd;
/* short circuit */
/* get controller info */
return (NULL);
}
} else {
}
return (NULL);
}
/* convert to our format */
return (NULL);
/* return info */
}
/*
* get partition number
*/
int
)
{
return (-1);
return (partno);
}
/*
* get size of device
*/
)
{
return (MD_DISKADDR_ERROR);
}
/*
* get label of device
*/
)
{
return (MD_DISKADDR_ERROR);
}
/*
* find out where database replicas end
*/
static int
)
{
/* make sure we have a component */
*endblkp = 0;
if (metaismeta(np))
return (0);
/* get replicas, quit if none */
return (-1);
mdclrerror(ep);
return (0);
return (0);
/* go through all the replicas */
continue;
}
/* cleanup, return success */
return (0);
}
/*
* return cached start block
*/
static diskaddr_t
)
{
/* short circuit */
/* look for database locations */
return (MD_DISKADDR_ERROR);
/* success */
return (end_blk);
}
/*
* does device have a metadb
*/
int
)
{
return (-1);
return (1);
else
return (0);
}
/*
* return cached start block
*/
)
{
/* short circuit */
/* look for database locations */
return (MD_DISKADDR_ERROR);
/* check for label */
if (start_blk == 0) {
if (start_blk == MD_DISKADDR_ERROR) {
return (MD_DISKADDR_ERROR);
}
}
/* roundup to next cylinder */
if (start_blk != 0) {
return (MD_DISKADDR_ERROR);
}
/* success */
return (start_blk);
}
/*
* return cached devices name
*/
char *
)
{
int len;
/* short circuit */
return (np->devicesname);
/* follow symlink */
return (NULL);
return (NULL);
}
return (NULL);
}
/* return name */
return (np->devicesname);
}
/*
* get metadevice misc name
*/
char *
)
{
/* short circuit */
return (NULL);
/* get misc module from driver */
return (NULL);
}
/* return miscname */
}
/*
* get unit structure from driver
*/
)
{
/* should have a set */
/* get size of unit structure */
return (NULL);
return (NULL);
return (NULL);
}
/* get actual unit structure */
return (NULL);
}
}
/*
* free metadevice unit
*/
void
)
{
case MD_DEVICE:
break;
case MD_METAMIRROR:
break;
case MD_METATRANS:
break;
case MD_METARAID:
break;
case MD_METASP:
break;
default:
assert(0);
break;
}
}
}
/*
* free metadevice name info
*/
void
)
{
/* get rid of cached name info */
}
/* get rid of cached drivename info */
}
}
/*
* get metadevice unit
*/
)
{
char *miscname;
/* short circuit */
return (NULL);
/* dispatch */
return (NULL);
else {
return (NULL);
}
}
int
md_error_t *ep,
)
{
md_isopen_t d;
return (-1);
(void) memset(&d, '\0', sizeof (d));
/*
* shortcut: if the device is open, no need to check on other nodes,
* even in case of a mn metadevice
* Also return in case we're told not to check on other nodes.
*/
return (d.isopen);
}
/*
* If the device is closed locally, but it's a mn device,
* check on all other nodes, too
*/
int err = 0;
/*
* This message is never directly issued.
* So we launch it with a suspend override flag.
* If the commd is suspended, and this message comes
* along it must be sent due to replaying a metainit or
* similar. In that case we don't want this message to
* be blocked.
* If the commd is not suspended, the flag does no harm.
* Additionally we don't want the result of the message
* cached in the MCT, because we want uptodate results,
* and the message doesn't need being logged either.
* Hence NO_LOG and NO_MCT
*/
MD_MSGF_OVERRIDE_SUSPEND, 0, (char *)&d,
if (err == 0) {
} else {
/*
* in case some error occurred,
* we better say the device is open
*/
d.isopen = 1;
}
}
}
}
return (d.isopen);
}
/*
* Return the minor name associated with a given disk slice
*/
char *
char *devname,
)
{
return (NULL);
return (NULL);
}
}
return (ret_minor_name);
}