/*
* 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
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Just in case we're not in a build environment, make sure that
* TEXT_DOMAIN gets set to something.
*/
#if !defined(TEXT_DOMAIN)
#endif
/*
* Mediator functions
*/
#include <meta.h>
#include <metamed.h>
#include <dlfcn.h>
#include <sdssc.h>
/*
* There are too many external factors that affect the timing of the
* operations, so we set the timeout to a very large value, in this
* case 1 day, which should handle HW timeouts, large configurations,
* and other potential delays.
*/
/*
* RPC handle
*/
typedef struct {
char *hostname;
} med_handle_t;
/*
* Data to be sent from med_clnt_create_timed to med_create_helper via
* meta_client_create_retry.
*/
typedef struct {
/*
* Perform the work of actually doing the clnt_create for
* meta_client_create_retry.
*/
static CLIENT *
{
}
static
char *hostname,
char *nettype,
const md_timeval32_t *tp
)
{
}
/*
* Set the timeout value for this client handle.
*/
static int
char *hostname,
long time_out,
)
{
return (0);
}
/*
* close RPC connection
*/
static void
)
{
}
}
}
/*
* open RPC connection to rpc.medd
*/
static med_handle_t *
char *hostname,
long time_out,
)
{
/* default to local host */
/* open RPC connection */
"medd med_clnt_create_timed");
return (NULL);
} else {
}
return (NULL);
/* return connection */
return (hp);
}
/*
* steal and convert med_err_t
*/
int
md_error_t *ep,
)
{
char *p = buf;
char *emsg;
/* no error */
/* assert(medep->name == NULL); */
rval = 0;
goto out;
}
/* steal error */
}
}
else
} else {
else
}
/* cleanup, return success */
out:
return (rval);
}
static med_handle_t *
long time_out,
)
{
int i;
char *hnm;
/* Loop through the hosts listed */
for (; i >= 0; i--) {
if (mdanyrpcerror(ep) && i != 0) {
mdclrerror(ep);
continue;
}
}
return (hp);
}
return (NULL);
}
static int
{
int i;
int err = 0;
goto out;
}
goto out;
goto out;
}
goto out;
}
for (i = 0; i < tp->med_tp_nents; i++) {
md_perror("setup_med_transtab(): stat():");
} else {
}
}
out:
return (err);
}
/*
* Externals
*/
/*
* NULLPROC - just returns a response
*/
int
char *hostname,
)
{
/* initialize */
mdclrerror(ep);
/* do it */
return (-1);
close_medd(hp);
return (-1);
return (0);
}
/*
* Update the mediator information on the mediator.
* This function does the same functionality as
* clnt_med_upd_data() except that it takes different
* argument so that host which is just a mediator, can
* still update its mediator record.
*/
int
char *setname,
)
{
/* Initialize */
mdclrerror(ep);
/* Build args */
if (obandiskset)
else
return (-1);
else
close_medd(hp);
return (-1);
return (0);
}
/*
* Get the mediator information from the client.
* The code does same functinality as clnt_med_get_data()
* except that it takes different arguments so that
* host which doesn't have set information, can still
* get access to mediator information
*/
int
char *setname,
)
{
/* Initialize */
mdclrerror(ep);
/* Build args */
if (obandiskset)
else
return (-1);
else
close_medd(hp);
/* copy the mediator data in meddp */
rval = 0;
}
return (rval);
}
/*
* Update the mediator information on the mediator.
* *** This is not normally called from user code, the kernel does this! ***
*/
int
)
{
/* initialize */
mdclrerror(ep);
/* build args */
return (-1);
if (MD_MNSET_DESC(sd))
/*
* In the MN diskset, use a generic nodename, multiowner, as
* the node initiating the RPC request. This allows
* any node to access mediator information.
*
* MN diskset reconfig cycle forces consistent
* in the MN diskset. This allows the relaxation of
* node name checking in rpc.metamedd for MN disksets.
*
* In the traditional diskset, only a calling node that is
* in the mediator record's diskset nodelist can access
* mediator data.
*/
else
/* do it */
return (-1);
else
close_medd(hp);
return (-1);
return (0);
}
/*
* Get the mediator data for this client from the mediator
*/
int
)
{
/* initialize */
mdclrerror(ep);
/* build args */
return (-1);
if (MD_MNSET_DESC(sd))
/*
* In the MN diskset, use a generic nodename, multiowner, as
* the node initiating the RPC request. This allows
* any node to access mediator information.
*
* MN diskset reconfig cycle forces consistent
* in the MN diskset. This allows the relaxation of
* node name checking in rpc.metamedd for MN disksets.
*
* In the traditional diskset, only a calling node that is
* in the mediator record's diskset nodelist can access
* mediator data.
*/
else
/* do it */
return (-1);
else
close_medd(hp);
/* do something with the results */
rval = 0;
}
return (rval);
}
/*
* Update the mediator record on the mediator.
*/
int
)
{
/* initialize */
mdclrerror(ep);
/* build args */
return (-1);
if (MD_MNSET_DESC(sd))
/*
* In the MN diskset, use a generic nodename, multiowner, as
* the node initiating the RPC request. This allows
* any node to access mediator information.
*
* MN diskset reconfig cycle forces consistent
* in the MN diskset. This allows the relaxation of
* node name checking in rpc.metamedd for MN disksets.
*
* In the traditional diskset, only a calling node that is
* in the mediator record's diskset nodelist can access
* mediator data.
*/
else
/* do it */
return (-1);
else
close_medd(hp);
return (-1);
return (0);
}
/*
* Get the mediator record for this client from the mediator
*/
int
)
{
/* initialize */
mdclrerror(ep);
/* build args */
return (-1);
if (MD_MNSET_DESC(sd))
/*
* In the MN diskset, use a generic nodename, multiowner, as
* the node initiating the RPC request. This allows
* any node to access mediator information.
*
* MN diskset reconfig cycle forces consistent
* in the MN diskset. This allows the relaxation of
* node name checking in rpc.metamedd for MN disksets.
*
* In the traditional diskset, only a calling node that is
* in the mediator record's diskset nodelist can access
* mediator data.
*/
else
/* do it */
return (-1);
else
close_medd(hp);
/* do something with the results */
rval = 0;
}
return (rval);
}
/*
* Get the name of the host from the mediator daemon.
*/
int
char *hostname,
char **ret_hostname,
)
{
/* initialize */
mdclrerror(ep);
/* No args */
/* do it */
return (-1);
else
close_medd(hp);
/* do something with the results */
rval = 0;
if (ret_hostname != NULL)
}
return (rval);
}
int
{
int i, j;
int max_meds;
return (-1);
for (i = 0; i < max_meds; i++) {
/* See if this is the local host */
/*
* Cluster nodename support
*
* See if the clustering code can give us an IP addr
* for the stored name. If not, find it the old way
* which will use the public interface.
*/
SDSSC_OKAY) {
hnm));
/* We only do INET addresses */
hnm));
/* We take the first address only */
if (*hp->h_addr_list) {
*hp->h_addr_list,
sizeof (struct in_addr));
} else
hnm));
}
}
}
return (0);
}
int
{
int i, j;
int max_meds;
return (-1);
for (i = 0; i < max_meds; i++) {
continue;
}
return (0);
}
int
{
int i, j;
int max_meds;
return (-1);
for (i = 0; i < max_meds; i++) {
continue;
}
return (0);
}
int
int force,
)
{
int i;
int max_meds;
if (metaislocalset(sp))
return (0);
return (-1);
if (setup_med_transtab(ep))
return (-1);
return (-1);
/* Make sure the ip addresses are current */
return (-1);
if (force)
return (0);
return (-1);
/* Make sure metamedd still running on host - only chk nodename */
for (i = 0; i < max_meds; i++) {
char *hostname;
char *hnm;
continue;
}
return (0);
}
/*
* This is a general routine to get mediator information from
* routine to get mediator information from all mediator hosts or update
* its mediator record respectively.
*/
int
{
uint_t c;
int i;
int j;
int fd;
int rec_size;
char *setname;
int retval = 0;
int medok = 0;
int golden = 0;
int isSetFound = 0;
/* Open the meddb file */
/*
* During the start up of the SVM services, this function
* will be called with an empty sname. In that case it is
* entirely possible for the MED_DB_FILE not to exist.
* If so, then no need to report an error.
*/
"Error in opening meddb file"));
return (1);
}
return (0);
}
/* Initialize rec_size */
/* Allocate a record buffer */
"Error in allocating memory"));
goto out;
}
/* read the file header */
"Error in reading mediator record"));
goto out;
}
/* Number of records in the mediator file */
c = dbhbr->med_dbh_nm;
for (i = 0; i < c; i++) {
"Error in reading mediator record"));
goto out;
}
/*
* For oban diskset first entry in the rec_nodes field is
* "multiowner" and all other entries are empty.
* Check if this is really multiowner diskset.
*/
obandiskset = TRUE;
else
obandiskset = FALSE;
/*
* Continue if the set name is not in our interest.
* This is required when this routine is called
* from medstat
*/
continue;
}
if (verbose)
(void) printf("%8.8s\t\t%6.6s\t%6.6s\n",
gettext("Golden"));
isSetFound = 1;
} else {
}
latest_med_dat_cc = 0;
for (j = 0; j < MED_MAX_HOSTS; j++) {
/*
* It is possible for the n_lst[j] slot to be empty
* if the mediator node has already been removed so
* go to the next slot.
*/
continue;
(void) printf("%-17.17s\t",
continue;
} else {
if (mdanyrpcerror(ep)) {
if (verbose)
(void) printf("%s\n",
gettext("Unreach"
"able"));
continue;
MDE_MED_ERROR)) {
if (verbose)
(void) printf("%s\n",
gettext("Bad"));
} else {
if (verbose)
(void) printf("%s\n",
gettext("Fatal"));
}
continue;
goto out;
}
} else {
/*
* Make sure this node has the correct value
* for the mediator record. If not we want the
* highest value from the other nodes. Save it
* for updating once the loop through all the
* mediator nodes has completed.
*/
if (latest_med_dat_cc <
medd.med_dat_cc) {
sizeof (medd));
}
} else {
if (verbose)
(void) printf("%s",
gettext("Ok"));
if (verbose)
(void) printf("\t%s",
gettext("Yes"));
golden++;
} else {
if (verbose)
(void) printf("\t%s",
gettext("No"));
}
if (verbose)
(void) printf("\n");
medok++;
}
}
}
/*
* Mediators only become active when there are
* replica updates to the sets and this can only
* occur when there is a disk in the set.
* If there are no disks found then the save_medd
* structure will be empty. If save_medd is empty,
* do not update the set.
*/
if (save_medd.med_dat_sn == 0)
continue;
/*
* Update the latest mediator information
* on this node
*/
/*
* We had some errors while updaing the
* record. This means this metaset is
* not updated with latest mediator
* information.
*/
}
} else {
if (golden) {
retval = 0;
goto out;
}
retval = 1;
}
}
out:
retval = 1;
}
"Error in closing meddb file"));
return (1);
}
return (retval);
}