/*
* 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
*/
/*
*/
/*
* Just in case we're not in a build environment, make sure that
* TEXT_DOMAIN gets set to something.
*/
#if !defined(TEXT_DOMAIN)
#endif
/*
* Metadevice database interfaces.
*/
#define MDDB
#include <meta.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
struct svm_daemon {
char *svmd_name;
char *svmd_kill_val;
};
/*
* This is a list of the daemons that are not stopped by the SVM smf(5)
* but no contract(4) is constructed and so it is not stopped by smf(5).
*/
{"mdmonitord", "HUP"},
{"mddoors", "KILL"},
};
/*
* Are the locator blocks for the replicas using devids
*/
static char *
struct mddb_config *c,
)
{
char *devid_str;
return (NULL);
}
c->c_locator.l_devid_flags =
} else {
goto out;
}
goto out;
}
goto out;
}
goto out;
}
if (meta_deviceid_to_nmlist("/dev/dsk",
goto out;
}
}
out:
return (diskname);
}
/*
* meta_get_lb_inittime sends a request for the lb_inittime to the kernel
*/
)
{
(void) memset(&c, 0, sizeof (c));
/* Fill in setno, setname, and sideno */
}
return (c.c_timestamp);
}
/*
* mkmasterblks writes out the master blocks of the mddb to the replica.
*
* In a MN diskset, this is called by the node that is adding this replica
* to the diskset.
*/
static int
int fd,
int dbsize,
)
{
int consecutive;
char *buffer;
int iosize;
int mn_set = 0;
int cnt;
if (! metaislocalset(sp)) {
return (-1);
if (MD_MNSET_DESC(sd)) {
}
}
/*
* chunks.
*
* A side-effect of this loop is to zero out the entire mddb region
*/
if (cnt > MDDB_VERIFY_SIZE)
else
consecutive = cnt;
}
}
}
}
startblk += consecutive;
}
}
/*
* If a MN diskset, set master block revision for a MN set.
* Even though the master block structure is no different
* for a MN set, setting the revision field to a different
* number keeps any pre-MN_diskset code from accessing
* this diskset. It also allows for an early determination
* of a MN diskset when reading in from disk so that the
* proper size locator block and locator names structure
* can be read in thus saving time on diskset startup.
*/
if (mn_set)
else
mb->mb_nextblk = 0;
if (! metaislocalset(sp)) {
}
/*
* We try to save the disks device ID into the remaining bytes in
* the master block. The saved devid is used to provide a mapping
* between this disk's devid and the devid stored into the master
* block. This allows the disk image to be self-identifying
* if it gets copied (e.g. SNDR, True Copy, etc.). This is used
* when we try to import these disks on the remote copied image.
* If we cannot save the disks device ID onto the master block that is
* ok. The disk is just not self-identifying and won't be importable
* in the remote copy scenario.
*/
/* there is enough space to store the devid */
}
}
(crc_skip_t *)NULL);
}
}
}
}
}
return (0);
}
void
int fd,
)
{
int mnset = 0;
/*
* No dummy master blocks are written for a MN diskset since devids
* are not supported in MN disksets.
*/
if (! metaislocalset(sp)) {
return;
if (MD_MNSET_DESC(sd))
mnset = 1;
}
return;
/*
* We try to save the disks device ID into the remaining bytes in
* the master block. This allows the disk image to be self-identifying
* if it gets copied (e.g. SNDR, True Copy, etc.). This is used
* when we try to import these disks on the remote copied image.
* If we cannot save the disks device ID onto the master block that is
* ok. The disk is just not self-identifying and won't be importable
* in the remote copy scenario.
*/
int len;
/* there is enough space to store the devid */
}
}
(crc_skip_t *)NULL);
/*
* If any of these operations fail, we need to inform the
* user that the disk won't be self identifying. When support
* for importing remotely replicated disksets is added, we
* want to add the error messages here.
*/
goto out;
goto out;
goto out;
goto out;
goto out;
out:
}
static int
{
int rval = 0;
int in_miniroot = 0;
/* get list of local replicas */
if (! metaislocalset(sp))
return (0);
return (-1);
/* open tempfile, copy permissions of original file */
/*
* If we get a EROFS error, we assume that we are in the
* miniroot.
*/
goto error;
in_miniroot = 1;
errno = 0;
/*
* If we are booted on a read-only root because
* of mddb quorum problems we don't want to emit
* any scary error messages.
*/
errno = 0;
goto out;
}
/* open tempfile, copy permissions of original file */
goto error;
}
goto error;
goto error;
}
/* print header */
goto error;
goto error;
"#driver\tminor_t\tdaddr_t\tdevice id\tchecksum\n") < 0)
goto error;
/* dump replicas */
int i;
char *devidp;
/* If devid code can't encode devidp - skip entry */
continue;
}
/* compute checksum */
for (i = 0; ((r->r_driver_name[i] != '\0') &&
(i < sizeof (r->r_driver_name))); i++) {
checksum -= r->r_driver_name[i];
}
}
/* print info */
goto error;
}
}
/* close and rename to real file */
goto error;
goto error;
goto error;
}
/*
* Renames don't work in the miniroot since tmpfiles are
*/
if (! in_miniroot) {
goto error;
} else {
goto error;
goto error;
goto error;
}
goto error;
goto error;
goto error;
}
/* delete the tempfile */
}
/* success */
rval = 0;
goto out;
/* tempfile error */
/* cleanup, return success */
out:
}
return (rval);
}
/*
* check replica for dev
*/
static int
)
{
/* should be in the same set */
/* if error in master block, assume whole partition */
if ((rep_sblk == MD_DISKADDR_ERROR) ||
(rep_nblks == MD_DISKADDR_ERROR)) {
rep_sblk = 0;
}
/* check overlap */
if (meta_check_overlap(
return (-1);
}
/* return success */
return (0);
}
/*
* check to see if we're in a replica
*/
int
)
{
int rval = 0;
/* should have a set */
/* for each replica */
return (-1);
/* check replica */
rval = -1;
break;
}
}
/* cleanup, return success */
return (rval);
}
/*
* check replica
*/
int
)
{
/* make sure we have a disk */
return (-1);
/* check to ensure that it is not already in use */
return (-1);
}
if (options & MDCHK_ALLOW_NODBS)
return (0);
if (options & MDCHK_DRVINSET)
return (0);
/* make sure it is in the set */
return (-1);
/* make sure its not in a metadevice */
return (-1);
/* return success */
return (0);
}
static int
int set_locked,
int force,
)
{
int i;
int rval = 0;
return (-1);
if (! set_locked) {
if (MD_MNSET_DESC(sd)) {
/* Make sure we are blocking all signals */
mdclrerror(&xep);
while (nd) {
mynode()) != 0) {
continue;
}
continue;
}
return (-1);
}
} else {
for (i = 0; i < MD_MAXSIDES; i++) {
/* Skip empty slots */
continue;
mynode()) != 0)
continue;
return (-1);
}
}
}
if (MD_MNSET_DESC(sd)) {
while (nd) {
continue;
}
continue;
}
== -1) {
rval = -1;
break;
}
}
} else {
for (i = 0; i < MD_MAXSIDES; i++) {
/* Skip empty slots */
continue;
continue;
== -1) {
rval = -1;
break;
}
}
}
if (! set_locked) {
if (MD_MNSET_DESC(sd)) {
while (nd) {
if (force &&
continue;
}
continue;
}
ep)) {
rval = -1;
break;
}
}
} else {
for (i = 0; i < MD_MAXSIDES; i++) {
/* Skip empty slots */
continue;
if (force &&
continue;
ep)) {
rval = -1;
break;
}
}
}
}
return (rval);
}
int
int bcast,
)
{
int done;
int rval = 0;
/*CONSTCOND*/
while (1) {
}
}
rval = -1;
break;
}
if (done == 0)
break;
if (! metaislocalset(sp)) {
rval = -1;
break;
}
}
/*
* Send addsidenms to all nodes using rpc.mdcommd if
* sidename is being added to MN diskset.
*
* It's ok to broadcast this call to other nodes.
*
* Note: The broadcast to other nodes isn't needed during
* the addition of the first mddbs to the set since the
* other nodes haven't been joined to the set yet. All
* nodes in a MN diskset are (implicitly) joined to the set
* on the addition of the first mddb.
*/
(bcast == DB_ADDSIDENMS_BCAST)) {
int send_rval;
/* Set devid to NULL until devids are supported */
/*
* If reconfig cycle has been started, this node is
* stuck in in the return step until this command has
* completed. If mdcommd is suspended, ask
* send_message to fail (instead of retrying)
* so that metaset can finish allowing the reconfig
* cycle to proceed.
*/
MD_MSGF_PANIC_WHEN_INCONSISTENT, 0, (char *)&db_ns,
sizeof (md_mn_msg_meta_db_newside_t),
if (send_rval != 0) {
rval = -1;
else {
(void) mdstealerror(ep,
}
}
break;
}
if (resultp)
} else {
/*
* Let this side's device name, minor # and driver name
* be known to the database replica.
*/
(void) memset(&c, 0, sizeof (c));
break;
}
/* Fill in setno, setname, and sideno */
sizeof (c.c_setname));
/*
* Don't need device id information from this ioctl
* Kernel determines device id from dev_t, which
* is just what this code would do.
*/
c.c_locator.l_devid_flags = 0;
break;
}
}
}
/* cleanup, return success */
}
}
return (rval);
}
int
)
{
if (! metaislocalset(sp)) {
return (-1);
}
/* Use rpc.mdcommd to delete mddb side from all nodes */
int send_rval;
/* Set devid to NULL until devids are supported */
/*
* If reconfig cycle has been started, this node is
* stuck in in the return step until this command has
* completed. If mdcommd is suspended, ask
* send_message to fail (instead of retrying)
* so that metaset can finish allowing the reconfig
* cycle to proceed.
*/
MD_MSGF_PANIC_WHEN_INCONSISTENT, 0, (char *)&db_ds,
if (send_rval != 0) {
else {
}
}
return (-1);
}
if (resultp)
} else {
/*
* Let this side's device name, minor # and driver name
* be known to the database replica.
*/
(void) memset(&c, 0, sizeof (c));
/* Fill in setno, setname, and sideno */
/*
* Don't need device id information from this ioctl
* Kernel determines device id from dev_t, which
* is just what this code would do.
*/
c.c_locator.l_devid_flags = 0;
}
return (0);
}
static int
{
}
}
return (0);
}
/*
* Return 1 if files are different, else return 0
*/
static int
{
return (1);
return (1);
return (1);
/* allocate memory and read both files into buffer */
goto out;
if (fd == -1)
goto out;
goto out;
if (fd == -1)
goto out;
goto out;
/* compare content */
out:
if (tbuf)
if (buf)
return (ret);
}
/*
* patch md.conf file with mddb locations
*/
int
char *sname, /* system file name */
int patch, /* patching locally */
)
{
/* check names */
if (patch)
else
}
cname = META_DBCONF;
/*
* edit file
*/
/*
* If we are booted on a read-only root because
* of mddb quorum problems we don't want to emit
* any scary error messages.
*/
mdclrerror(ep);
rval = 0;
}
goto out;
}
ep) != 0)
goto out;
/* if file content is identical, skip rename */
rval = 0;
goto out;
}
goto out;
}
/*
* rename file. If we get a Cross Device error then it
* is because we are in the miniroot.
*/
goto out;
}
goto out;
goto out;
goto out;
}
goto out;
goto out;
goto out;
}
}
rval = 0;
/* cleanup, return error */
out:
}
return (rval);
}
/*
* Add replicas to set. This happens as a result of:
* - metadb [-s set_name] -a
* - metaset -s set_name -a disk
* - metaset -s set_name -d disk (causes a rebalance of mddbs)
* - metaset -s set_name -b
*
* For a local set, this routine is run on the local set host.
*
* For a traditional diskset, this routine is run on the node that
* is running the metaset command.
*
* For a multinode diskset, this routine is run by the node that is
* running the metaset command. If this is the first mddb added to
* the MN diskset, then no communication is made to other nodes via commd
* since the other nodes will be in-sync with respect to the mddbs when
* those other nodes join the set and snarf in the newly created mddb.
* If this is not the first mddb added to the MN diskset, then this
* attach command is sent to all of the nodes using commd. This keeps
* the nodes in-sync.
*/
int
int dbcnt,
int dbsize,
char *sysfilename,
)
{
struct mddb_config c;
md_drive_desc *p;
int i;
int replicacount = 0;
int start_svmdaemons = 0;
int rval = 0;
int flags;
/*
* Error if we don't get some work to do.
*/
return (-1);
(void) memset(&c, 0, sizeof (c));
c.c_id = 0;
/* Don't need device id information from this ioctl */
c.c_locator.l_devid_flags = 0;
if (metaislocalset(sp)) {
mdclrerror(&c.c_mde);
(! (options & MDCHK_ALLOW_NODBS)))
} else {
}
mdclrerror(&c.c_mde);
}
/*
* Is current set STALE?
*/
if (c.c_flags & MDDB_C_STALE) {
stale_bool = TRUE;
}
/* if these are the first replicas then the SVM daemons need to run */
if (c.c_dbcnt == 0)
start_svmdaemons = 1;
/*
* check to see if we will go over the total possible number
* of data bases
*/
while (nlp) {
replicacount += dbcnt;
}
mdclrerror(&status);
}
}
/*
* go through and check to make sure all locations specified
* are legal also pick out driver name;
*/
if (! metaislocalset(sp)) {
/*
* make sure that non-local database replicas
* are always on the replica slice.
*/
if (meta_replicaslice(dnp,
&rep_partno, ep) != 0)
return (-1);
return (-1);
if (partno != rep_partno)
}
ep)) {
return (-1);
}
return (-1);
}
/*
* If first disk in set we don't have lb_inittime yet for use as
* mb_setcreatetime so don't go looking for it. WE'll come back
* later and update after the locator block has been created.
* If this isn't the first disk in the set, we have a locator
* block and thus we have lb_inittime. Set mb_setcreatetime to
* lb_inittime.
*/
if (! metaislocalset(sp)) {
if (c.c_dbcnt != 0) {
firstmddb = 0;
}
}
/*
* go through and write all master blocks
*/
int fd;
for (i = 0; i < dbcnt; i++) {
return (-1);
}
}
}
return (-1);
if (! metaislocalset(sp)) {
return (-1);
return (-1);
}
/*
* go through and tell kernel to add them
*/
rval = -1;
goto out;
}
/*
* If mddb is being added to MN diskset and there already
* exists a valid mddb in the set (which equates to this
* node being an owner of the set) then use rpc.mdcommd
* mechanism to add mddb(s) so that all nodes stay in sync.
* If set is stale, don't log the message since rpc.mdcommd
* can't write the message to the mddb.
*
* Otherwise, just add mddb to this node.
*/
int send_rval;
/*
* In a scenario where new replicas had been added on
* the master, and then all of the old replicas failed
* before the slaves had knowledge of the new replicas,
* the slaves are unable to re-parse in the mddb
* from the new replicas since the slaves have no
* knowledge of the new replicas. The following
* algorithm solves this problem:
* - META_DB_ATTACH message generates submsgs
* - BLOCK parse (master)
* - MDDB_ATTACH new replicas
* - UNBLOCK parse (master) causing parse
* information to be sent from master
* to slaves at a higher class than the
* unblock so the parse message will
* reach slaves before unblock message.
*/
/* Set devid to NULL until devids are supported */
/*
* If reconfig cycle has been started, this node is
* stuck in in the return step until this command has
* completed. If mdcommd is suspended, ask
* send_message to fail (instead of retrying)
* so that metaset can finish allowing the reconfig
* cycle to proceed.
*/
if (stale_bool == TRUE)
flags |= MD_MSGF_NO_LOG;
sizeof (md_mn_msg_meta_db_attach_t),
if (send_rval != 0) {
rval = -1;
else {
(void) mdstealerror(ep,
}
}
goto out;
}
if (resultp)
} else {
/* Adding mddb(s) to just this node */
for (i = 0; i < dbcnt; i++) {
(void) memset(&c, 0, sizeof (c));
FALSE) {
goto out;
}
/* Fill in setno, setname, and sideno */
if (! metaislocalset(sp)) {
if (MD_MNSET_DESC(sd)) {
c.c_multi_node = 1;
}
}
/*
* Don't need device id information from this
* ioctl Kernel determines device id from
* dev_t, which is just what this code would do.
*/
c.c_locator.l_devid_flags = 0;
c.c_timestamp = *timeval;
if (setup_med_cfg(sp, &c,
rval = -1;
goto out;
}
NULL) != 0) {
goto out;
}
/*
* This is either a traditional diskset OR this
* is the first replica added to a MN diskset.
* In either case, set broadcast to NO_BCAST so
* that message won't go through rpc.mdcommd.
* If this is a traditional diskset, the bcast
* flag is ignored since traditional disksets
* don't use the rpc.mdcommd.
*/
goto out;
}
}
if (! metaislocalset(sp)) {
/* update the dbcnt and size in dd */
break;
}
}
/*
* If this was the first addition of disks to the
* diskset you now need to update the mb_setcreatetime
* which needed lb_inittime which wasn't there until now.
*/
if (firstmddb) {
return (-1);
}
}
}
out:
if (metaislocalset(sp)) {
/* Don't mask any previous errors */
if (rval == 0)
return (rval);
}
/* Don't mask any previous errors */
if (rval == 0)
}
} else {
(options & MDCHK_SET_LOCKED),
(options & MDCHK_SET_FORCE),
&status)) {
/* Don't mask any previous errors */
if (rval == 0)
else
mdclrerror(&status);
}
}
/*
* For MN disksets that already had already had nodes joined
* before the attach of this mddb(s), the name invalidation is
* done by the commd handler routine. Otherwise, if this
* is the first attach of a MN diskset mddb, the invalidation
* must be done here since the first attach cannot be sent
* via the commd since there are no nodes joined to the set yet.
*/
(MD_MNSET_DESC(sd) &&
}
}
return (rval);
}
/*
* deletelist_length
*
* return the number of slices that have been specified for deletion
* on the metadb command line. This does not calculate the number
* of replicas because there may be multiple replicas per slice.
*/
static int
{
int list_length = 0;
list_length++;
}
return (list_length);
}
static int
{
int index = 0;
return (index);
index++;
}
return (-1);
}
/*
* Delete replicas from set. This happens as a result of:
* - metadb [-s set_name] -d
* - metaset -s set_name -a disk (causes a rebalance of mddbs)
* - metaset -s set_name -d disk
* - metaset -s set_name -b
*
* For a local set, this routine is run on the local set host.
*
* For a traditional diskset, this routine is run on the node that
* is running the metaset command.
*
* For a multinode diskset, this routine is run by the node that is
* running the metaset command. This detach routine is sent to all
* of the joined nodes in the diskset using commd. This keeps
* the nodes in-sync.
*/
int
char *sysfilename,
)
{
struct mddb_config c;
md_drive_desc *p;
int replicacount;
int replica_delete_count;
int nr_replica_slices;
int i;
int stop_svmdaemons = 0;
int rval = 0;
int index;
int valid_replicas_nottodelete = 0;
int invalid_replicas_nottodelete = 0;
int invalid_replicas_todelete = 0;
int errored = 0;
int *tag_array;
int flags;
/*
* Error if we don't get some work to do.
*/
return (-1);
(void) memset(&c, 0, sizeof (c));
c.c_id = 0;
/* Don't need device id information from this ioctl */
c.c_locator.l_devid_flags = 0;
/*
* Is current set STALE?
*/
if (c.c_flags & MDDB_C_STALE) {
stale_bool = TRUE;
}
replicacount = c.c_dbcnt;
/*
* go through and gather how many data bases are on each
* device specified.
*/
replica_delete_count = 0;
for (i = 0; i < replicacount; i++) {
char *devname;
int found = 0;
c.c_id = i;
/* Don't need device id information from this ioctl */
c.c_locator.l_devid_flags = 0;
return (-1);
}
}
found = 1;
}
/*
* There are four combinations of "errored" and "found"
* and they are used to find the number of
* list and are available in the system.
*/
else if (!found) /* !errored and !found */
else if (errored) /* errored and found */
/*
* else it is !errored and found. This means
* valid_replicas_todelete++; But this variable will not
* be used anywhere
*/
}
index = 0;
}
}
/* if all replicas are deleted stop mdmonitord */
if ((replicacount - replica_delete_count) == 0)
stop_svmdaemons = 1;
if (force_option & MDFORCE_NONE)
}
/*
* The following algorithms are followed to check for deletion:
* (a) If the delete list(db_nlp) has all invalid replicas and no valid
* replicas, then deletion should be allowed.
* (b) Deletion should be allowed only if valid replicas that are "not"
* to be deleted is always greater than the invalid replicas that
* are "not" to be deleted.
* (c) If the user uses -f option, then deletion should be allowed.
*/
if ((invalid_replicas_todelete != replica_delete_count) &&
(force_option != MDFORCE_LOCAL))
/*
* go through and tell kernel to delete them
*/
/* Don't need device id information from this ioctl */
c.c_locator.l_devid_flags = 0;
if (! metaislocalset(sp)) {
return (-1);
return (-1);
}
/*
* If mddb is being deleted from MN diskset and node is
* an owner of the diskset then use rpc.mdcommd
* mechanism to add mddb(s) so that all nodes stay in sync.
* If set is stale, don't log the message since rpc.mdcommd
* can't write the message to the mddb.
*
* When mddbs are first being added to set, a detach can
* be called before any node has joined the diskset, so
* must check to see if node is an owner of the diskset.
*
* Otherwise, just delete mddb from this node.
*/
int send_rval;
/*
* The following algorithm is used to detach replicas.
* - META_DB_DETACH message generates submsgs
* - BLOCK parse (master)
* - MDDB_DETACH replicas
* - UNBLOCK parse (master) causing parse
* information to be sent from master
* to slaves at a higher class than the
* unblock so the parse message will
* reach slaves before unblock message.
*/
/* Set devid to NULL until devids are supported */
/*
* If reconfig cycle has been started, this node is
* stuck in in the return step until this command has
* completed. If mdcommd is suspended, ask
* send_message to fail (instead of retrying)
* so that metaset can finish allowing the reconfig
* cycle to proceed.
*/
if (stale_bool == TRUE)
flags |= MD_MSGF_NO_LOG;
sizeof (md_mn_msg_meta_db_detach_t),
if (send_rval != 0) {
rval = -1;
else {
(void) mdstealerror(ep,
}
}
goto out;
}
if (resultp)
} else {
i = 0;
while (i < c.c_dbcnt) {
char *devname;
c.c_id = i;
/* Don't need devid info from this ioctl */
c.c_locator.l_devid_flags = 0;
if (metaioctl(MD_DB_GETDEV, &c,
goto out;
}
!= NULL) {
return (-1);
}
}
i++;
continue;
}
/* Don't need devid info from this ioctl */
c.c_locator.l_devid_flags = 0;
if (metaioctl(MD_DB_DELDEV, &c,
goto out;
}
/* Not incrementing "i" intentionally */
}
}
if (! metaislocalset(sp)) {
/* update the dbcnt and size in dd */
p->dd_dbcnt = 0;
p->dd_dbsize = 0;
break;
}
}
/*
* Slam a dummy master block and make it self
* identifying
*/
}
}
}
out:
if (metaislocalset(sp)) {
/*
* Stop all the daemons if there are
* no more replicas so that the module can be
* unloaded.
*/
int i;
for (i = 0; i < DAEMON_COUNT; i++) {
svmd_kill_list[i].svmd_name);
}
mdclrerror(&status);
}
}
/* Don't mask any previous errors */
if (rval == 0)
else
mdclrerror(&status);
return (rval);
}
/* Don't mask any previous errors */
if (rval == 0)
else
mdclrerror(&status);
}
} else {
((force_option & MDFORCE_LOCAL) |
/* Don't mask any previous errors */
if (rval == 0)
else
mdclrerror(&status);
}
}
}
}
return (rval);
}
static md_replica_t *
int flags,
struct mddb_config *c,
)
{
char *devname;
char *devid_str;
/* allocate replicaname */
/* get device name */
/*
* Check if the device has a long name (>40 characters) and
* if so then we have to use devids to get the device name.
* If this cannot be done then we have to fail the request.
*/
if (meta_deviceid_to_nmlist("/dev/dsk",
return (NULL);
}
} else {
return (NULL);
}
}
if (flags & PRINT_FAST) {
return (NULL);
}
} else {
return (NULL);
}
}
/* make sure it's OK */
if ((! (flags & MD_BASICNAME_OK)) &&
return (NULL);
}
(ddi_devid_t)NULL) {
return (NULL);
}
/* Overwrite dev derived from name with dev from devid */
}
if (c->c_dbend != 0)
/* return replica */
return (rp);
}
/*
* free replica list
*/
void
)
{
}
}
}
/*
* return list of all replicas in set
*/
int
int flags,
)
{
int count = 0;
struct mddb_config c;
int i;
char *devid;
/* for each replica */
i = 0;
do {
/* get next replica */
(void) memset(&c, 0, sizeof (c));
c.c_id = i;
mdclrerror(&c.c_mde);
break; /* handle none at all */
}
goto out;
}
goto out;
}
/*
* Turn on space and sz flags since 'sz' amount of
* space has been alloc'd.
*/
}
mdclrerror(&c.c_mde);
break; /* handle none at all */
}
goto out;
}
/*
* Paranoid check - shouldn't happen, but is left as
* a place holder for changes that will be needed after
* dynamic reconfiguration changes are added to SVM (to
* support movement of disks at any point in time).
*/
"Error: Relocation Information "
"(drvnm=%s, mnum=0x%lx) \n"
"relocation information size changed - \n"
"rerun command\n"),
goto out;
}
if (c.c_dbcnt == 0)
break; /* handle none at all */
/* get info */
goto out;
/* append to list */
++count;
c.c_locator.l_devid_flags = 0;
}
} while (++i < c.c_dbcnt);
}
/* return count */
return (count);
/* cleanup, return error */
out:
}
return (-1);
}
/*
* meta_sync_db_locations - get list of replicas from kernel and write
* the kernel with the replica list in the conf files.
*
*/
void
)
{
if (!metaislocalset(sp))
return;
/* Updates backup of configuration file (aka mddb.cf) */
return;
/* Updates system configuration file (aka md.conf) */
}
/*
* setup_db_locations - parse the mddb.cf file and
* tells the driver which db locations to use.
*/
int
)
{
char *buff;
uint_t i;
int rval = 0;
char *devidp;
int checksum;
/* do mddb.cf file */
(void) memset(&c, '\0', sizeof (c));
}
/* ignore comments */
if (*buff == '#')
continue;
/* parse locator */
(void) memset(&c, 0, sizeof (c));
c.c_setno = MD_LOCAL_SET;
buff += i;
/* parse out devid */
buff += 1;
devidp[i] = '\0';
&minor_name) == -1) {
continue;
}
/* Conf file must have minor name associated with devid */
if (minor_name == NULL) {
continue;
}
/* Copy to devid size buffer that ioctl expects */
}
(void *)devid_decode, sz);
}
buff += devid_size;
for (i = 0; i < devid_size; i++) {
}
if (checksum != 42) {
/* overwritten later for more serious problems */
continue;
}
/* use db location */
}
/* free up devid if in use */
c.c_locator.l_devid_flags = 0;
}
/* check for stale database */
(void) memset((char *)&c, 0, sizeof (struct mddb_config));
c.c_id = 0;
c.c_setno = MD_LOCAL_SET;
/*
* While we do not need the devid here we may need to
* know if devid's are being used by the kernel for
* the replicas. This is because under some circumstances
* we can only manipulate the SVM configuration if the
* kernel is using devid's.
*/
c.c_locator.l_devid_sz = 0;
mdclrerror(&c.c_mde);
}
if (c.c_flags & MDDB_C_STALE)
0, NULL));
if (c.c_locator.l_devid_sz != 0) {
/*
* Devid's are being used to track the replicas because
* there is space for a devid.
*/
devid_in_use = TRUE;
}
/* success */
return (rval);
}
/*
* meta_db_minreplica - returns the minimum size replica currently in use.
*/
)
{
md_replica_t *r;
return (-1);
return (-1);
/* find the smallest existing replica */
}
return (nblks);
}
/*
* meta_get_replica_names
* returns an mdnamelist_t of replica slices
*/
/*ARGSUSED*/
int
mdnamelist_t **nlpp,
int options,
)
{
int cnt = 0;
if (!metaislocalset(sp))
goto out;
/* get replicas */
cnt = -1;
goto out;
}
/* build name list */
/*
* Add the name struct to the end of the
* namelist but keep a pointer to the last
* element so that we don't incur the overhead
* of traversing the list each time
*/
++cnt;
}
/* cleanup, return count or error */
out:
return (cnt);
}