summaryrefslogtreecommitdiff
path: root/usr/src/lib/lvm/libmeta/common
diff options
context:
space:
mode:
authormk117520 <none@none>2008-07-07 11:40:07 -0700
committermk117520 <none@none>2008-07-07 11:40:07 -0700
commitf3e56050555d3d1ae673b32c5815b57e97db899a (patch)
treeb2d8f9bd19df2277740bf94596801050f09ff87d /usr/src/lib/lvm/libmeta/common
parent913f2d80f883f1c81cd35aa675de9c1df0447724 (diff)
downloadillumos-joyent-f3e56050555d3d1ae673b32c5815b57e97db899a.tar.gz
4849644 rfe for 3-node mediators for campus clusters
Diffstat (limited to 'usr/src/lib/lvm/libmeta/common')
-rw-r--r--usr/src/lib/lvm/libmeta/common/mapfile-vers3
-rw-r--r--usr/src/lib/lvm/libmeta/common/meta_med.c326
2 files changed, 328 insertions, 1 deletions
diff --git a/usr/src/lib/lvm/libmeta/common/mapfile-vers b/usr/src/lib/lvm/libmeta/common/mapfile-vers
index 4990ec5375..960a5fe5a4 100644
--- a/usr/src/lib/lvm/libmeta/common/mapfile-vers
+++ b/usr/src/lib/lvm/libmeta/common/mapfile-vers
@@ -82,6 +82,8 @@ SUNWprivate_1.1 {
clnt_updmeds;
clnt_upd_nr_flags;
clnt_upd_sr_flags;
+ clnt_user_med_get_data;
+ clnt_user_med_upd_data;
close_admin;
close_mnttab;
cl_set_setkey;
@@ -483,6 +485,7 @@ SUNWprivate_1.1 {
meta_match_enclosure;
meta_mc_log;
meta_med_hnm2ip;
+ meta_mediator_info_from_file;
meta_mirror_anycomp_is_err;
meta_mirror_attach;
meta_mirror_detach;
diff --git a/usr/src/lib/lvm/libmeta/common/meta_med.c b/usr/src/lib/lvm/libmeta/common/meta_med.c
index b11f86a0c1..38d74e2e16 100644
--- a/usr/src/lib/lvm/libmeta/common/meta_med.c
+++ b/usr/src/lib/lvm/libmeta/common/meta_med.c
@@ -19,8 +19,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -377,6 +378,122 @@ clnt_med_null(
/*
* 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
+clnt_user_med_upd_data(
+ md_h_t *mdhp,
+ bool_t obandiskset,
+ char *setname,
+ uint_t setnum,
+ med_data_t *meddp,
+ md_error_t *ep
+)
+{
+ med_handle_t *hp;
+ med_upd_data_args_t args;
+ med_err_t res;
+
+ /* Initialize */
+ mdclrerror(ep);
+ (void) memset(&args, 0, sizeof (args));
+ (void) memset(&res, 0, sizeof (res));
+
+ /* Build args */
+ if (obandiskset)
+ args.med.med_caller = Strdup(MED_MN_CALLER);
+ else
+ args.med.med_caller = Strdup(mynode());
+
+ args.med.med_setname = Strdup(setname);
+ args.med.med_setno = setnum;
+ args.med_data = *meddp;
+
+ if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
+ return (-1);
+
+ if (med_upd_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
+ (void) mdrpcerror(ep, hp->clntp, hp->hostname,
+ dgettext(TEXT_DOMAIN, "medd get record"));
+ else
+ (void) meddstealerror(ep, &res);
+
+ close_medd(hp);
+
+ xdr_free(xdr_med_upd_data_args_t, (char *)&args);
+ xdr_free(xdr_med_err_t, (char *)&res);
+
+ if (! mdisok(ep))
+ 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
+clnt_user_med_get_data(
+ md_h_t *mdhp,
+ bool_t obandiskset,
+ char *setname,
+ uint_t setnum,
+ med_data_t *meddp,
+ md_error_t *ep
+)
+{
+ int rval = -1;
+ med_handle_t *hp;
+ med_args_t args;
+ med_get_data_res_t res;
+
+ /* Initialize */
+ mdclrerror(ep);
+ (void) memset(&args, 0, sizeof (args));
+ (void) memset(&res, 0, sizeof (res));
+
+ /* Build args */
+ if (obandiskset)
+ args.med.med_caller = Strdup(MED_MN_CALLER);
+ else
+ args.med.med_caller = Strdup(mynode());
+
+ args.med.med_setname = Strdup(setname);
+ args.med.med_setno = setnum;
+
+ if ((hp = open_medd_wrap(mdhp, CL_DEF_TMO, ep)) == NULL)
+ return (-1);
+
+ if (med_get_data_1(&args, &res, hp->clntp) != RPC_SUCCESS)
+ (void) mdrpcerror(ep, hp->clntp, hp->hostname,
+ dgettext(TEXT_DOMAIN, "medd get record"));
+ else
+ (void) meddstealerror(ep, &res.med_status);
+
+ close_medd(hp);
+
+ if (mdisok(ep)) {
+ /* copy the mediator data in meddp */
+ (void) memmove(meddp, &res.med_data, sizeof (med_data_t));
+ rval = 0;
+ }
+
+ xdr_free(xdr_med_args_t, (char *)&args);
+ xdr_free(xdr_med_get_data_res_t, (char *)&res);
+
+ return (rval);
+}
+
+
+/*
+ * Update the mediator information on the mediator.
* *** This is not normally called from user code, the kernel does this! ***
*/
int
@@ -849,3 +966,210 @@ setup_med_cfg(
}
return (0);
}
+
+/*
+ * This is a general routine to get mediator information from
+ * file /etc/lvm/meddb. Commands medstat and metainit use this
+ * routine to get mediator information from all mediator hosts or update
+ * its mediator record respectively.
+ */
+int
+meta_mediator_info_from_file(char *sname, int verbose, md_error_t *ep)
+{
+ uint_t c;
+ int i;
+ int j;
+ int fd;
+ int rec_size;
+ char *setname;
+ uint_t setnum;
+ med_rec_t *rec_buf = NULL;
+ med_db_hdr_t *dbhbr;
+ med_rec_t *medrecp;
+ med_data_t medd;
+ med_data_t *save_medd;
+ md_h_t mdh;
+ uint_t latest_med_dat_cc = 0;
+ int retval;
+ int medok = 0;
+ int golden = 0;
+ bool_t obandiskset;
+
+ /* Open the meddb file */
+ if ((fd = open(MED_DB_FILE, O_RDONLY, 0)) == -1) {
+ mde_perror(ep, "Error in opening meddb file");
+ return (1);
+ }
+
+ /* Initialize rec_size */
+ rec_size = roundup(sizeof (med_rec_t), DEV_BSIZE);
+
+ /* Allocate a record buffer */
+ if ((rec_buf = malloc(rec_size)) == NULL) {
+ mde_perror(ep, "Error in allocating memory");
+ goto out;
+ }
+
+ /* read the file header */
+ if ((read(fd, rec_buf, rec_size)) != rec_size) {
+ mde_perror(ep, "Error in reading mediator record");
+ goto out;
+ }
+
+ dbhbr = (med_db_hdr_t *)rec_buf;
+
+ /* Number of records in the mediator file */
+ c = dbhbr->med_dbh_nm;
+
+ for (i = 0; i < c; i++) {
+ (void) memset(rec_buf, 0, rec_size);
+
+ if (read(fd, rec_buf, rec_size) == -1) {
+ mde_perror(ep, "Error in reading mediator record");
+ goto out;
+ }
+
+ medrecp = (med_rec_t *)rec_buf;
+
+ /*
+ * For oban diskset first entry in the rec_nodes field is
+ * "multiowner" and all other entries are null
+ * Check if this is really multiowner diskset.
+ */
+
+ if ((strcmp(medrecp->med_rec_nodes[0], MED_MN_CALLER) == 0) &&
+ (medrecp->med_rec_nodes[1] == NULL))
+ obandiskset = TRUE;
+ else
+ obandiskset = FALSE;
+
+ if (sname != NULL) {
+ /*
+ * Continue if the set name is not in our interest.
+ * This is required when this routine is called
+ * from medstat
+ */
+
+ if (strcmp(sname, medrecp->med_rec_snm) != 0) {
+ continue;
+ }
+
+ if (verbose)
+ (void) printf("%8.8s\t\t%6.6s\t%6.6s\n",
+ gettext("Mediator"), gettext("Status"),
+ gettext("Golden"));
+
+ if (medrecp->med_rec_meds.n_cnt == 0) {
+ if (verbose)
+ (void) printf(gettext(
+ "No mediator hosts configured for"
+ " set \"%s\".\n"),
+ sname);
+ goto out;
+ }
+ setname = sname;
+ } else {
+ setname = medrecp->med_rec_snm;
+ }
+ setnum = medrecp->med_rec_sn;
+
+ for (j = 0; j < medrecp->med_rec_meds.n_cnt; j ++) {
+ (void) memset(&medd, 0, sizeof (medd));
+ (void) memset(&mdh, 0, sizeof (mdh));
+ mdh = medrecp->med_rec_meds.n_lst[j];
+
+ if ((sname != NULL) && (verbose))
+ (void) printf("%-17.17s\t",
+ medrecp->med_rec_meds.n_lst[j].a_nm[0]);
+
+ if (clnt_user_med_get_data(&mdh, obandiskset,
+ setname, setnum, &medd, ep) == -1) {
+ if (sname == NULL) {
+ continue;
+ } else {
+ if (mdanyrpcerror(ep)) {
+ if (verbose)
+ (void) printf("%s\n",
+ gettext("Unreach"
+ "able"));
+ continue;
+ } else if (mdiserror(ep,
+ MDE_MED_ERROR)) {
+ if (verbose)
+ (void) printf("%s\n",
+ gettext("Bad"));
+ } else {
+ if (verbose)
+ (void) printf("%s\n",
+ gettext("Fatal"));
+ }
+ mde_perror(ep, "");
+ if (mdiserror(ep, MDE_MED_ERROR))
+ continue;
+ goto out;
+ }
+ } else {
+ if (sname == NULL) {
+ if (latest_med_dat_cc <
+ medd.med_dat_cc) {
+ latest_med_dat_cc =
+ medd.med_dat_cc;
+ save_medd = &medd;
+ }
+ } else {
+ if (verbose)
+ (void) printf("%s",
+ gettext("Ok"));
+ if (medd.med_dat_fl & MED_DFL_GOLDEN) {
+ if (verbose)
+ (void) printf("\t%s",
+ gettext("Yes"));
+ golden++;
+ } else {
+ if (verbose)
+ (void) printf("\t%s",
+ gettext("No"));
+ }
+ if (verbose)
+ (void) printf("\n");
+ medok++;
+ }
+ }
+ }
+ if (sname == NULL) {
+ /*
+ * Update the latest mediator information
+ * on this node
+ */
+ (void) strlcpy(mdh.a_nm[0], mynode(),
+ sizeof (mdh.a_nm[0]));
+ if (clnt_user_med_upd_data(&mdh, obandiskset,
+ setname, setnum, save_medd, ep) == -1) {
+ /*
+ * We had some errors while updaing the
+ * record. This means this metaset is
+ * not updated with latest mediator
+ * information.
+ */
+ mde_perror(ep, "");
+ continue;
+ }
+ } else {
+ if (golden) {
+ retval = 0;
+ goto out;
+ }
+ if (medok < ((medrecp->med_rec_meds.n_cnt / 2) + 1))
+ retval = 1;
+ }
+ }
+
+out:
+ if (rec_buf != NULL)
+ Free(rec_buf);
+ if (close(fd) < 0) {
+ mde_perror(ep, "Error in closing meddb file");
+ return (1);
+ }
+ return (retval);
+}