2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A/*
2N/A * Just in case we're not in a build environment, make sure that
2N/A * TEXT_DOMAIN gets set to something.
2N/A */
2N/A#if !defined(TEXT_DOMAIN)
2N/A#define TEXT_DOMAIN "SYS_TEST"
2N/A#endif
2N/A
2N/A#include <meta.h>
2N/A#include <metad.h>
2N/A#include <devid.h>
2N/A
2N/Astatic md_setkey_t *my_cl_sk = NULL;
2N/A
2N/A#define CL_DEF_TMO 30L
2N/A
2N/A/*
2N/A * Convert an old style mddrivename_t into a new style
2N/A * mddrivename_t. Meant to be used *ONLY* by rpc.metad
2N/A */
2N/Avoid
2N/Ameta_conv_drvname_old2new(
2N/A o_mddrivename_t *v1_dp,
2N/A mddrivename_t *v2_dp
2N/A)
2N/A{
2N/A int sliceno;
2N/A o_mdname_t *v1_np;
2N/A mdname_t *v2_np;
2N/A
2N/A /* fields that haven't changed */
2N/A v2_dp->cname = v1_dp->cname;
2N/A v2_dp->rname = v1_dp->rname;
2N/A v2_dp->type = v1_dp->type;
2N/A v2_dp->errnum = v1_dp->errnum;
2N/A
2N/A /* geometry information */
2N/A v2_dp->geom.ncyl = v1_dp->geom.ncyl;
2N/A v2_dp->geom.nhead = v1_dp->geom.nhead;
2N/A v2_dp->geom.nsect = v1_dp->geom.nsect;
2N/A v2_dp->geom.rpm = v1_dp->geom.rpm;
2N/A v2_dp->geom.write_reinstruct = v1_dp->geom.write_reinstruct;
2N/A v2_dp->geom.read_reinstruct = v1_dp->geom.read_reinstruct;
2N/A v2_dp->geom.blk_sz = 0;
2N/A
2N/A /* controller information */
2N/A v2_dp->cinfo = v1_dp->cinfo;
2N/A
2N/A /* vtoc information */
2N/A v2_dp->vtoc.nparts = v1_dp->vtoc.nparts;
2N/A v2_dp->vtoc.first_lba = 0;
2N/A v2_dp->vtoc.last_lba = 0;
2N/A v2_dp->vtoc.lbasize = 0;
2N/A
2N/A for (sliceno = 0; sliceno < (MD_MAX_PARTS - 1); sliceno++) {
2N/A v2_dp->vtoc.parts[sliceno].start =
2N/A (diskaddr_t)v1_dp->vtoc.parts[sliceno].start;
2N/A v2_dp->vtoc.parts[sliceno].size =
2N/A (diskaddr_t)v1_dp->vtoc.parts[sliceno].size;
2N/A v2_dp->vtoc.parts[sliceno].tag =
2N/A v1_dp->vtoc.parts[sliceno].tag;
2N/A v2_dp->vtoc.parts[sliceno].flag =
2N/A v1_dp->vtoc.parts[sliceno].flag;
2N/A v2_dp->vtoc.parts[sliceno].label =
2N/A (diskaddr_t)v1_dp->vtoc.parts[sliceno].label;
2N/A }
2N/A
2N/A /* The new style vtoc has 17 partitions */
2N/A v2_dp->vtoc.parts[MD_MAX_PARTS - 1].start = 0;
2N/A v2_dp->vtoc.parts[MD_MAX_PARTS - 1].size = 0;
2N/A v2_dp->vtoc.parts[MD_MAX_PARTS - 1].tag = 0;
2N/A v2_dp->vtoc.parts[MD_MAX_PARTS - 1].flag = 0;
2N/A v2_dp->vtoc.parts[MD_MAX_PARTS - 1].label = 0;
2N/A
2N/A v2_dp->vtoc.typename = v1_dp->vtoc.typename;
2N/A
2N/A /* partition information */
2N/A v2_dp->parts.parts_len = v1_dp->parts.parts_len;
2N/A for (sliceno = 0; sliceno < v1_dp->parts.parts_len; sliceno++) {
2N/A v1_np = &v1_dp->parts.parts_val[sliceno];
2N/A v2_np = &v2_dp->parts.parts_val[sliceno];
2N/A
2N/A /*
2N/A * We speculate that if cname for a particular
2N/A * partition does not exist, the other fields
2N/A * don't exist either. In such a case, we don't
2N/A * need to do anything for that partition.
2N/A */
2N/A if (v1_np->cname != NULL) {
2N/A v2_np->cname = v1_np->cname;
2N/A v2_np->bname = v1_np->bname;
2N/A v2_np->rname = v1_np->rname;
2N/A v2_np->devicesname = v1_np->devicesname;
2N/A v2_np->dev = meta_expldev(v1_np->dev);
2N/A v2_np->key = v1_np->key;
2N/A v2_np->end_blk = (diskaddr_t)v1_np->end_blk;
2N/A v2_np->start_blk = (diskaddr_t)v1_np->start_blk;
2N/A }
2N/A v2_np->drivenamep = v2_dp;
2N/A }
2N/A
2N/A /* We don't care about the rest of the fields */
2N/A v2_dp->side_names = v1_dp->side_names;
2N/A v2_dp->side_names_key = v1_dp->side_names_key;
2N/A v2_dp->miscname = v1_dp->miscname;
2N/A}
2N/A
2N/A/*
2N/A * Convert a new style mddrivename_t into an old style
2N/A * mddrivename_t. Meant to be used *ONLY* by rpc.metad
2N/A */
2N/Avoid
2N/Ameta_conv_drvname_new2old(
2N/A o_mddrivename_t *v1_dp,
2N/A mddrivename_t *v2_dp
2N/A)
2N/A{
2N/A int sliceno;
2N/A o_mdname_t *v1_np;
2N/A mdname_t *v2_np;
2N/A
2N/A /* fields that haven't changed */
2N/A v1_dp->cname = v2_dp->cname;
2N/A v1_dp->rname = v2_dp->rname;
2N/A v1_dp->type = v2_dp->type;
2N/A v1_dp->errnum = v2_dp->errnum;
2N/A
2N/A /* geometry information */
2N/A v1_dp->geom.ncyl = v2_dp->geom.ncyl;
2N/A v1_dp->geom.nhead = v2_dp->geom.nhead;
2N/A v1_dp->geom.nsect = v2_dp->geom.nsect;
2N/A v1_dp->geom.rpm = v2_dp->geom.rpm;
2N/A v1_dp->geom.write_reinstruct = v2_dp->geom.write_reinstruct;
2N/A v1_dp->geom.read_reinstruct = v2_dp->geom.read_reinstruct;
2N/A
2N/A /* controller information */
2N/A v1_dp->cinfo = v2_dp->cinfo;
2N/A
2N/A /* vtoc information */
2N/A v1_dp->vtoc.typename = v2_dp->vtoc.typename;
2N/A v1_dp->vtoc.nparts = v2_dp->vtoc.nparts;
2N/A
2N/A for (sliceno = 0; sliceno < (MD_MAX_PARTS - 1); sliceno++) {
2N/A v1_dp->vtoc.parts[sliceno].start =
2N/A (daddr_t)v2_dp->vtoc.parts[sliceno].start;
2N/A v1_dp->vtoc.parts[sliceno].size =
2N/A (daddr_t)v2_dp->vtoc.parts[sliceno].size;
2N/A v1_dp->vtoc.parts[sliceno].tag =
2N/A v2_dp->vtoc.parts[sliceno].tag;
2N/A v1_dp->vtoc.parts[sliceno].flag =
2N/A v2_dp->vtoc.parts[sliceno].flag;
2N/A v1_dp->vtoc.parts[sliceno].label =
2N/A (daddr_t)v2_dp->vtoc.parts[sliceno].label;
2N/A }
2N/A
2N/A /* partition information */
2N/A v1_dp->parts.parts_len = v2_dp->parts.parts_len;
2N/A
2N/A for (sliceno = 0; sliceno < v2_dp->parts.parts_len; sliceno++) {
2N/A v1_np = &v1_dp->parts.parts_val[sliceno];
2N/A v2_np = &v2_dp->parts.parts_val[sliceno];
2N/A
2N/A /*
2N/A * We speculate that if cname for a particular
2N/A * partition does not exist then the rest of
2N/A * the fields a partition don't exist either.
2N/A * In such a case, we don't need to do anything
2N/A * for that partition.
2N/A */
2N/A if (v2_np->cname != NULL) {
2N/A v1_np->cname = v2_np->cname;
2N/A v1_np->bname = v2_np->bname;
2N/A v1_np->rname = v2_np->rname;
2N/A v1_np->devicesname = v2_np->devicesname;
2N/A v1_np->dev = meta_cmpldev(v2_np->dev);
2N/A v1_np->key = v2_np->key;
2N/A v1_np->end_blk = (daddr_t)v2_np->end_blk;
2N/A v1_np->start_blk = (daddr_t)v2_np->start_blk;
2N/A }
2N/A v1_np->drivenamep = v1_dp;
2N/A }
2N/A
2N/A /* We don't care about the rest of the fields */
2N/A v1_dp->side_names = v2_dp->side_names;
2N/A v1_dp->side_names_key = v2_dp->side_names_key;
2N/A v1_dp->miscname = v2_dp->miscname;
2N/A}
2N/A
2N/A/*
2N/A * Convert an old style md_drive_desc_t into a new style
2N/A * md_drive_desc_t. Meant to be used *ONLY* by rpc.metad
2N/A */
2N/Avoid
2N/Ameta_conv_drvdesc_old2new(
2N/A o_md_drive_desc *v1_dd,
2N/A md_drive_desc *v2_dd
2N/A)
2N/A{
2N/A md_drive_desc *dd;
2N/A o_md_drive_desc *o_dd;
2N/A
2N/A dd = v2_dd;
2N/A
2N/A for (o_dd = v1_dd; o_dd != NULL; o_dd = o_dd->dd_next) {
2N/A dd->dd_ctime = o_dd->dd_ctime;
2N/A dd->dd_genid = o_dd->dd_genid;
2N/A dd->dd_flags = o_dd->dd_flags;
2N/A meta_conv_drvname_old2new(o_dd->dd_dnp, dd->dd_dnp);
2N/A dd->dd_dbcnt = o_dd->dd_dbcnt;
2N/A dd->dd_dbsize = o_dd->dd_dbsize;
2N/A dd = dd->dd_next;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Convert an new style md_drive_desc_t into a old style
2N/A * md_drive_desc_t. Meant to be used *ONLY* by rpc.metad
2N/A */
2N/Avoid
2N/Ameta_conv_drvdesc_new2old(
2N/A o_md_drive_desc *v1_dd,
2N/A md_drive_desc *v2_dd
2N/A)
2N/A{
2N/A md_drive_desc *dd;
2N/A o_md_drive_desc *o_dd;
2N/A
2N/A o_dd = v1_dd;
2N/A
2N/A for (dd = v2_dd; dd != NULL; dd = dd->dd_next) {
2N/A o_dd->dd_ctime = dd->dd_ctime;
2N/A o_dd->dd_genid = dd->dd_genid;
2N/A o_dd->dd_flags = dd->dd_flags;
2N/A meta_conv_drvname_new2old(o_dd->dd_dnp, dd->dd_dnp);
2N/A o_dd->dd_dbcnt = dd->dd_dbcnt;
2N/A o_dd->dd_dbsize = dd->dd_dbsize;
2N/A o_dd = o_dd->dd_next;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Allocate memory for v1 drive descriptor
2N/A * depending upon the number of drives in the
2N/A * v2 drive descriptor
2N/A */
2N/Avoid
2N/Aalloc_olddrvdesc(
2N/A o_md_drive_desc **v1_dd,
2N/A md_drive_desc *v2_dd
2N/A)
2N/A{
2N/A md_drive_desc *dd;
2N/A o_md_drive_desc *new, *head;
2N/A
2N/A head = NULL;
2N/A
2N/A for (dd = v2_dd; dd != NULL; dd = dd->dd_next) {
2N/A new = Zalloc(sizeof (o_md_drive_desc));
2N/A new->dd_dnp = Zalloc(sizeof (o_mddrivename_t));
2N/A new->dd_dnp->parts.parts_val = Zalloc(sizeof (o_mdname_t) *
2N/A dd->dd_dnp->parts.parts_len);
2N/A new->dd_next = head;
2N/A head = new;
2N/A }
2N/A *v1_dd = head;
2N/A}
2N/A
2N/A/*
2N/A * Allocate memory for v2 drive descriptor
2N/A * depending upon the number of drives in the
2N/A * v1 drive descriptor
2N/A */
2N/Avoid
2N/Aalloc_newdrvdesc(
2N/A o_md_drive_desc *v1_dd,
2N/A md_drive_desc **v2_dd
2N/A)
2N/A{
2N/A md_drive_desc *new, *head;
2N/A o_md_drive_desc *o_dd;
2N/A
2N/A head = NULL;
2N/A
2N/A for (o_dd = v1_dd; o_dd != NULL; o_dd = o_dd->dd_next) {
2N/A new = Zalloc(sizeof (md_drive_desc));
2N/A new->dd_dnp = Zalloc(sizeof (mddrivename_t));
2N/A new->dd_dnp->parts.parts_val = Zalloc(sizeof (mdname_t) *
2N/A o_dd->dd_dnp->parts.parts_len);
2N/A new->dd_next = head;
2N/A head = new;
2N/A }
2N/A *v2_dd = head;
2N/A}
2N/A
2N/Avoid
2N/Afree_olddrvdesc(
2N/A o_md_drive_desc *v1_dd
2N/A)
2N/A{
2N/A o_md_drive_desc *o_dd, *head;
2N/A
2N/A head = v1_dd;
2N/A
2N/A while (head != NULL) {
2N/A o_dd = head;
2N/A head = head->dd_next;
2N/A free(o_dd->dd_dnp->parts.parts_val);
2N/A free(o_dd->dd_dnp);
2N/A free(o_dd);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Afree_newdrvdesc(
2N/A md_drive_desc *v2_dd
2N/A)
2N/A{
2N/A md_drive_desc *dd, *head;
2N/A
2N/A head = v2_dd;
2N/A
2N/A while (head != NULL) {
2N/A dd = head;
2N/A head = head->dd_next;
2N/A free(dd->dd_dnp->parts.parts_val);
2N/A free(dd->dd_dnp);
2N/A free(dd);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Return the device id for a given device
2N/A */
2N/Achar *
2N/Ameta_get_devid(
2N/A char *rname
2N/A)
2N/A{
2N/A ddi_devid_t devid;
2N/A int fd;
2N/A char *enc_devid, *dup_enc_devid = NULL;
2N/A
2N/A if ((fd = open(rname, O_RDWR | O_NDELAY, 0)) < 0)
2N/A return (NULL);
2N/A
2N/A if (devid_get(fd, &devid) == -1) {
2N/A (void) close(fd);
2N/A return (NULL);
2N/A }
2N/A (void) close(fd);
2N/A
2N/A enc_devid = devid_str_encode(devid, NULL);
2N/A devid_free(devid);
2N/A
2N/A if (enc_devid != NULL) {
2N/A dup_enc_devid = strdup(enc_devid);
2N/A devid_str_free(enc_devid);
2N/A }
2N/A
2N/A return (dup_enc_devid);
2N/A}
2N/A
2N/A/*
2N/A * Add side names for the diskset drive records
2N/A * NOTE: these go into the local set's namespace.
2N/A */
2N/Aint
2N/Aclnt_add_drv_sidenms(
2N/A char *hostname,
2N/A char *this_host,
2N/A mdsetname_t *sp,
2N/A md_set_desc *sd,
2N/A int node_c,
2N/A char **node_v,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_drv_sidenm_args v1_args;
2N/A mdrpc_drv_sidenm_2_args v2_args;
2N/A mdrpc_drv_sidenm_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A int i, j;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v1_args, 0, sizeof (v1_args));
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_drv_sidenm_2_args_u.rev1;
2N/A v21_args->hostname = this_host;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->sp = sp;
2N/A v21_args->sd = sd;
2N/A v21_args->node_v.node_v_len = node_c;
2N/A v21_args->node_v.node_v_val = node_v;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure
2N/A */
2N/A bool = mdrpc_add_drv_sidenms_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A
2N/A v1_args.sd = Zalloc(sizeof (o_md_set_desc));
2N/A alloc_olddrvdesc(&v1_args.sd->sd_drvs, sd->sd_drvs);
2N/A
2N/A /* build args */
2N/A v1_args.hostname = this_host;
2N/A v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v1_args.sp = sp;
2N/A /* set descriptor */
2N/A v1_args.sd->sd_ctime = sd->sd_ctime;
2N/A v1_args.sd->sd_genid = sd->sd_genid;
2N/A v1_args.sd->sd_setno = sd->sd_setno;
2N/A v1_args.sd->sd_flags = sd->sd_flags;
2N/A for (i = 0; i < MD_MAXSIDES; i++) {
2N/A v1_args.sd->sd_isown[i] = sd->sd_isown[i];
2N/A
2N/A for (j = 0; j < MD_MAX_NODENAME_PLUS_1; j ++)
2N/A v1_args.sd->sd_nodes[i][j] =
2N/A sd->sd_nodes[i][j];
2N/A }
2N/A v1_args.sd->sd_med = sd->sd_med;
2N/A meta_conv_drvdesc_new2old(v1_args.sd->sd_drvs,
2N/A sd->sd_drvs);
2N/A v1_args.node_v.node_v_len = node_c;
2N/A v1_args.node_v.node_v_val = node_v;
2N/A
2N/A rval = mdrpc_add_drv_sidenms_1(&v1_args, &res, clntp);
2N/A
2N/A free_olddrvdesc(v1_args.sd->sd_drvs);
2N/A free(v1_args.sd);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad add drive sidenames"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_add_drv_sidenms_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad add drive sidenames"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Adding drives via metaimport to disksets. Some of the drives may
2N/A * not be available so we need more information than the basic clnt_adddrvs
2N/A * offers us.
2N/A */
2N/Aint
2N/Aclnt_imp_adddrvs(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_drive_desc *dd,
2N/A md_timeval32_t timestamp,
2N/A ulong_t genid,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_drives_2_args v2_args;
2N/A mdrpc_drives_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->drivedescs = dd;
2N/A v21_args->timestamp = timestamp;
2N/A v21_args->genid = genid;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v1 procedure
2N/A */
2N/A bool = mdrpc_imp_adddrvs_2(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, NULL);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A rval = mdrpc_imp_adddrvs_2(&v2_args, &res, clntp);
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad imp add drives"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Add drives to disksets.
2N/A */
2N/Aint
2N/Aclnt_adddrvs(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_drive_desc *dd,
2N/A md_timeval32_t timestamp,
2N/A ulong_t genid,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_drives_args v1_args;
2N/A mdrpc_drives_2_args v2_args;
2N/A mdrpc_drives_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v1_args, 0, sizeof (v1_args));
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->drivedescs = dd;
2N/A v21_args->timestamp = timestamp;
2N/A v21_args->genid = genid;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure
2N/A */
2N/A bool = mdrpc_adddrvs_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A
2N/A alloc_olddrvdesc(&v1_args.drivedescs, dd);
2N/A
2N/A /* build args */
2N/A v1_args.sp = sp;
2N/A v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
2N/A v1_args.timestamp = timestamp;
2N/A v1_args.genid = genid;
2N/A
2N/A rval = mdrpc_adddrvs_1(&v1_args, &res, clntp);
2N/A
2N/A free_olddrvdesc(v1_args.drivedescs);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad add drives"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_adddrvs_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad add drives"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Add hosts to disksets.
2N/A */
2N/Aint
2N/Aclnt_addhosts(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A int node_c,
2N/A char **node_v,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_host_args *args;
2N/A mdrpc_host_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_host_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->hosts.hosts_len = node_c;
2N/A args->hosts.hosts_val = node_v;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_addhosts_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version and invoke
2N/A * the appropriate version of the remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_addhosts_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad add hosts"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_addhosts_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad add hosts"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Create disksets.
2N/A */
2N/Aint
2N/Aclnt_createset(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_node_nm_arr_t nodes,
2N/A md_timeval32_t timestamp,
2N/A ulong_t genid,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_createset_args *args;
2N/A mdrpc_createset_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int i;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_createset_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->timestamp = timestamp;
2N/A args->genid = genid;
2N/A for (i = 0; i < MD_MAXSIDES; i++)
2N/A (void) strcpy(args->nodes[i], nodes[i]);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_createset_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version and invoke
2N/A * the appropriate version of the remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_createset_1(args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad create set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_createset_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad create set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Create MN disksets.
2N/A */
2N/Aint
2N/Aclnt_mncreateset(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_mnnode_desc *nodelist,
2N/A md_timeval32_t timestamp,
2N/A ulong_t genid,
2N/A md_node_nm_t master_nodenm,
2N/A int master_nodeid,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_mncreateset_args *args;
2N/A mdrpc_mncreateset_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_mncreateset_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->timestamp = timestamp;
2N/A args->genid = genid;
2N/A (void) strlcpy(args->master_nodenm, master_nodenm, MD_MAX_NODENAME);
2N/A args->master_nodeid = master_nodeid;
2N/A args->nodelist = nodelist;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_mncreateset_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_mncreateset_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad mncreate set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Join MN set
2N/A */
2N/Aint
2N/Aclnt_joinset(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A int flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_flags_args *args;
2N/A mdrpc_sp_flags_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_flags_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->flags = flags;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_joinset_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_joinset_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad join set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Withdraw from MN set
2N/A */
2N/Aint
2N/Aclnt_withdrawset(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_args *args;
2N/A mdrpc_sp_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_withdrawset_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_withdrawset_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad withdraw set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Delete side names for the diskset drive records
2N/A * NOTE: these are removed from the local set's namespace.
2N/A */
2N/Aint
2N/Aclnt_del_drv_sidenms(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_args *args;
2N/A mdrpc_sp_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_del_drv_sidenms_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A if (metaget_setdesc(sp, ep) == NULL) {
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A /*
2N/A * Check the client handle for the version and invoke
2N/A * the appropriate version of the remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_del_drv_sidenms_1(args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad delete drive sidenames"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_del_drv_sidenms_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad delete drive sidenames"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * delete drives from the set
2N/A */
2N/Aint
2N/Aclnt_deldrvs(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_drive_desc *dd,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_drives_args v1_args;
2N/A mdrpc_drives_2_args v2_args;
2N/A mdrpc_drives_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v1_args, 0, sizeof (v1_args));
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->drivedescs = dd;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure
2N/A */
2N/A bool = mdrpc_deldrvs_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A
2N/A alloc_olddrvdesc(&v1_args.drivedescs, dd);
2N/A
2N/A /* build args */
2N/A v1_args.sp = sp;
2N/A v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
2N/A
2N/A rval = mdrpc_deldrvs_1(&v1_args, &res, clntp);
2N/A
2N/A free_olddrvdesc(v1_args.drivedescs);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad delete drives"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_deldrvs_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad delete drives"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * delete host(s) from a set.
2N/A */
2N/Aint
2N/Aclnt_delhosts(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A int node_c,
2N/A char **node_v,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_host_args *args;
2N/A mdrpc_host_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_host_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->hosts.hosts_len = node_c;
2N/A args->hosts.hosts_val = node_v;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_delhosts_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_delhosts_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad delete hosts"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_delhosts_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad delete hosts"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Delete diskset.
2N/A */
2N/Aint
2N/Aclnt_delset(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_args *args;
2N/A mdrpc_sp_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_delset_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_delset_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad delete set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_delset_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad delete set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * return remote device info
2N/A */
2N/Aint
2N/Aclnt_devinfo(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A mddrivename_t *dp,
2N/A md_dev64_t *ret_dev,
2N/A time_t *ret_timestamp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_devinfo_args v1_args;
2N/A mdrpc_devinfo_2_args v2_args;
2N/A mdrpc_devinfo_2_args_r1 *v21_args;
2N/A mdrpc_devinfo_res v1_res;
2N/A mdrpc_devinfo_2_res v2_res;
2N/A int rval, version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v1_args, 0, sizeof (v1_args));
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&v1_res, 0, sizeof (v1_res));
2N/A (void) memset(&v2_res, 0, sizeof (v2_res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_devinfo_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->drivenamep = dp;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure.
2N/A */
2N/A bool = mdrpc_devinfo_2_svc(&v2_args, &v2_res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &v1_res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of
2N/A * the remote procedure.
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A v1_args.drivenamep =
2N/A Zalloc(sizeof (o_mddrivename_t));
2N/A v1_args.drivenamep->parts.parts_val =
2N/A Zalloc((sizeof (o_mdname_t)) *
2N/A dp->parts.parts_len);
2N/A
2N/A /* build args */
2N/A v1_args.sp = sp;
2N/A v1_args.cl_sk = cl_get_setkey(sp->setno,
2N/A sp->setname);
2N/A
2N/A /*
2N/A * Convert v2 arguments to v1 arguments
2N/A * before sending over the wire.
2N/A */
2N/A meta_conv_drvname_new2old(v1_args.drivenamep,
2N/A v21_args->drivenamep);
2N/A
2N/A rval = mdrpc_devinfo_1(&v1_args, &v1_res, clntp);
2N/A
2N/A free(v1_args.drivenamep->parts.parts_val);
2N/A free(v1_args.drivenamep);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad device info"));
2N/A else
2N/A (void) mdstealerror(ep, &v1_res.status);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_devinfo_2(&v2_args, &v2_res, clntp);
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad device info"));
2N/A else
2N/A (void) mdstealerror(ep, &v2_res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A if (ret_dev != NULL) {
2N/A if (version == METAD_VERSION)
2N/A *ret_dev = meta_expldev(v1_res.dev);
2N/A else
2N/A *ret_dev = v2_res.dev;
2N/A }
2N/A
2N/A if (ret_timestamp != NULL) {
2N/A if (version == METAD_VERSION)
2N/A *ret_timestamp = v1_res.vtime;
2N/A else
2N/A *ret_timestamp = v2_res.vtime;
2N/A }
2N/A }
2N/A
2N/A if (version == METAD_VERSION)
2N/A xdr_free(xdr_mdrpc_devinfo_res, (char *)&v1_res);
2N/A else
2N/A xdr_free(xdr_mdrpc_devinfo_2_res, (char *)&v2_res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * return remote device info
2N/A */
2N/Aint
2N/Aclnt_devid(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A mddrivename_t *dp,
2N/A char **ret_encdevid,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_devid_args *args;
2N/A mdrpc_devid_2_args v2_args;
2N/A mdrpc_devid_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_devid_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->drivenamep = dp;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure.
2N/A */
2N/A bool = mdrpc_devid_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_DRIVENOTONHOST, sp->setno,
2N/A hostname, dp->cname, sp->setname);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_devid_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad devid info"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A if (ret_encdevid != NULL)
2N/A *ret_encdevid = strdup(res.enc_devid);
2N/A
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_devid_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Get the device information of a disk on a remote host. The information
2N/A * retrieved is the device's name, the associated driver and the dev_t.
2N/A * The lookup is performed by using the devid of the disk as this is
2N/A * unique to the disk. The device name on the originating node is passed
2N/A * in. If that devname is found when doing the devid to namelist translation
2N/A * then that value is used to make the device names as consistent as possible
2N/A * across the nodes.
2N/A *
2N/A * An attempt is made to retrieve this information by calling
2N/A * mdrpc_devinfo_by_devid_name_2_svc. Locally this call should always
2N/A * succeed. In the case where a call is made through a CLIENT handle,
2N/A * it is possible that the function hasn't been implemented on the called
2N/A * node. If this is the case fall back to mdrpc_devinfo_by_devidstr_2_svc.
2N/A *
2N/A * Returns:
2N/A * -1 Error
2N/A * ENOTSUP Operation not supported i.e. procedure not supported on
2N/A * the remote node
2N/A * 0 Success
2N/A */
2N/Aint
2N/Aclnt_devinfo_by_devid(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A char *devidstr,
2N/A md_dev64_t *ret_dev,
2N/A char *orig_devname,
2N/A char **ret_devname,
2N/A char **ret_driver,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_devidstr_args devid_args;
2N/A mdrpc_devid_name_args *args;
2N/A mdrpc_devid_name_2_args v2_args;
2N/A mdrpc_devinfo_2_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_devid_name_2_args_u.rev1;
2N/A args->enc_devid = devidstr;
2N/A args->orig_devname = orig_devname;
2N/A args->sp = sp;
2N/A
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * We are calling this locally so call the function
2N/A * directly.
2N/A */
2N/A bool = mdrpc_devinfo_by_devid_name_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A
2N/A /* open connection */
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) {
2N/A return (-1);
2N/A }
2N/A
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* Version 1 */
2N/A metarpcclose(clntp);
2N/A return (ENOTSUP);
2N/A }
2N/A
2N/A rval = mdrpc_devinfo_by_devid_name_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS) {
2N/A /* try falling back to devidstr_2_svc */
2N/A (void) memset(&devid_args, 0, sizeof (devid_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A devid_args.enc_devid = devidstr;
2N/A devid_args.sp = sp;
2N/A
2N/A rval = mdrpc_devinfo_by_devid_2(
2N/A &devid_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS) {
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad devinfo by devid"));
2N/A } else {
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A } else {
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A rval = 0;
2N/A if (ret_dev != NULL)
2N/A *ret_dev = res.dev;
2N/A
2N/A if (ret_devname != NULL && res.devname != NULL)
2N/A *ret_devname = Strdup(res.devname);
2N/A
2N/A if (ret_driver != NULL && res.drivername != NULL)
2N/A *ret_driver = Strdup(res.drivername);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_devinfo_2_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A
2N/A}
2N/A
2N/A
2N/A/*
2N/A * return status of whether driver is used, mount
2N/A */
2N/Aint
2N/Aclnt_drvused(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A mddrivename_t *dp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_drvused_args v1_args;
2N/A mdrpc_drvused_2_args v2_args;
2N/A mdrpc_drvused_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v1_args, 0, sizeof (v1_args));
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_drvused_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->drivenamep = dp;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure
2N/A */
2N/A bool = mdrpc_drvused_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A /* open connection */
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A v1_args.drivenamep =
2N/A Zalloc(sizeof (o_mddrivename_t));
2N/A v1_args.drivenamep->parts.parts_val =
2N/A Zalloc((sizeof (o_mdname_t)) *
2N/A dp->parts.parts_len);
2N/A
2N/A /* build args */
2N/A v1_args.sp = sp;
2N/A v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* Convert v2 args to v1 args */
2N/A meta_conv_drvname_new2old(v1_args.drivenamep,
2N/A v21_args->drivenamep);
2N/A
2N/A rval = mdrpc_drvused_1(&v1_args, &res, clntp);
2N/A
2N/A free(v1_args.drivenamep->parts.parts_val);
2N/A free(v1_args.drivenamep);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad drive used"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_drvused_2(&v2_args, &res, clntp);
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad drive used"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Avoid
2N/Afree_sr(md_set_record *sr)
2N/A{
2N/A mdrpc_getset_res res;
2N/A mdrpc_mngetset_res mnres;
2N/A
2N/A if (md_in_daemon)
2N/A return;
2N/A
2N/A /*
2N/A * dummy up a result struct, to do a deep free of the (mn)sr.
2N/A * (A deep free means that the xdr_free code will free the
2N/A * linked list of drive records for the sr and will also free
2N/A * the linked list of node records for the mnsr.)
2N/A */
2N/A if (MD_MNSET_REC(sr)) {
2N/A (void) memset(&mnres, 0, sizeof (mnres));
2N/A mnres.mnsr = (struct md_mnset_record *)sr;
2N/A xdr_free(xdr_mdrpc_mngetset_res, (char *)&mnres);
2N/A } else {
2N/A (void) memset(&res, 0, sizeof (res));
2N/A res.sr = sr;
2N/A xdr_free(xdr_mdrpc_getset_res, (char *)&res);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Ashort_circuit_getset(
2N/A mdrpc_getset_args *args,
2N/A mdrpc_getset_res *res
2N/A)
2N/A{
2N/A if (args->setname != NULL)
2N/A res->sr = metad_getsetbyname(args->setname, &res->status);
2N/A else
2N/A res->sr = metad_getsetbynum(args->setno, &res->status);
2N/A}
2N/A
2N/Avoid
2N/Ashort_circuit_mngetset(
2N/A mdrpc_getset_args *args,
2N/A mdrpc_mngetset_res *res
2N/A)
2N/A{
2N/A md_set_record *sr;
2N/A if (args->setname != NULL)
2N/A sr = metad_getsetbyname(args->setname, &res->status);
2N/A else
2N/A sr = metad_getsetbynum(args->setno, &res->status);
2N/A
2N/A if (MD_MNSET_REC(sr)) {
2N/A res->mnsr = (struct md_mnset_record *)sr;
2N/A } else {
2N/A res->mnsr = NULL;
2N/A }
2N/A}
2N/A
2N/Astatic int
2N/Ais_auto_take_set(char *setname, set_t setno)
2N/A{
2N/A if (setname != NULL)
2N/A return (metad_isautotakebyname(setname));
2N/A else
2N/A return (metad_isautotakebynum(setno));
2N/A}
2N/A
2N/A/*
2N/A * return the diskset record, and drive records.
2N/A * If record is a MNdiskset record, then only the first md_set_record
2N/A * bytes were copied from the daemon.
2N/A */
2N/Aint
2N/Aclnt_getset(
2N/A char *hostname,
2N/A char *setname,
2N/A set_t setno,
2N/A md_set_record **ret_sr,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_getset_args *args;
2N/A mdrpc_getset_2_args v2_args;
2N/A mdrpc_getset_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_getset_2_args_u.rev1;
2N/A args->setname = setname;
2N/A args->setno = setno;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A short_circuit_getset(args, &res);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) {
2N/A /*
2N/A * This has to work during the boot up before the rpc.metad can
2N/A * run. Check to see if we can handle this as a strictly local
2N/A * diskset.
2N/A */
2N/A if (is_auto_take_set(setname, setno)) {
2N/A mdclrerror(ep);
2N/A short_circuit_getset(args, &res);
2N/A res.sr = setdup(res.sr);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A return (-1);
2N/A }
2N/A } else {
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_getset_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad get set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_getset_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad get set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A rval = 0;
2N/A if (ret_sr != NULL)
2N/A *ret_sr = res.sr;
2N/A else
2N/A if (! md_in_daemon)
2N/A xdr_free(xdr_mdrpc_getset_res, (char *)&res);
2N/A }
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * return the multi-node diskset record, drive records and node records.
2N/A */
2N/Aint
2N/Aclnt_mngetset(
2N/A char *hostname,
2N/A char *setname,
2N/A set_t setno,
2N/A md_mnset_record **ret_mnsr,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_getset_args *args;
2N/A mdrpc_getset_2_args v2_args;
2N/A mdrpc_mngetset_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_getset_2_args_u.rev1;
2N/A args->setname = setname;
2N/A args->setno = setno;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A short_circuit_mngetset(args, &res);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A setno, hostname, NULL, setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_mngetset_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad mn get set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A /* If no ep error and no version mismatch - rpc call worked ok */
2N/A if (mdisok(ep)) {
2N/A rval = 0;
2N/A if (ret_mnsr != NULL)
2N/A *ret_mnsr = res.mnsr;
2N/A else
2N/A if (! md_in_daemon)
2N/A xdr_free(xdr_mdrpc_mngetset_res, (char *)&res);
2N/A }
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Set master nodeid and nodename in multi-node set record.
2N/A */
2N/Aint
2N/Aclnt_mnsetmaster(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_node_nm_t master_nodenm,
2N/A int master_nodeid,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_mnsetmaster_args *args;
2N/A mdrpc_mnsetmaster_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_mnsetmaster_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A (void) strlcpy(args->master_nodenm, master_nodenm, MD_MAX_NODENAME);
2N/A args->master_nodeid = master_nodeid;
2N/A
2N/A /* do it */
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_mnsetmaster_2(&v2_args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad multi-owner set master"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Get the MH timeout values.
2N/A */
2N/Aint
2N/Aclnt_gtimeout(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A mhd_mhiargs_t *ret_mhiargs,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_args *args;
2N/A mdrpc_sp_2_args v2_args;
2N/A mdrpc_gtimeout_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_gtimeout_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_gtimeout_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad get timeout"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_gtimeout_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad get timeout"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A /* copy md_mhiargs_t */
2N/A if (ret_mhiargs != NULL)
2N/A *ret_mhiargs = *res.mhiargsp;
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_gtimeout_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * get real hostname from remote host
2N/A */
2N/Aint
2N/Aclnt_hostname(
2N/A char *hostname,
2N/A char **ret_hostname,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_null_args args;
2N/A mdrpc_hostname_res res;
2N/A int rval = -1;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&args, 0, sizeof (args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A args.cl_sk = NULL;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_hostname_1_svc(&args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A if (mdrpc_hostname_1(&args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad hostname"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A if (ret_hostname != NULL)
2N/A *ret_hostname = Strdup(res.hostname);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_hostname_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * NULLPROC - just returns a response
2N/A */
2N/Aint
2N/Aclnt_nullproc(
2N/A char *hostname,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_nullproc_1_svc(NULL, ep, NULL);
2N/A assert(bool == TRUE);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_DEF_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A if (mdrpc_nullproc_1(NULL, ep, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad nullproc"));
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * does host own the set?
2N/A */
2N/Aint
2N/Aclnt_ownset(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A int *ret_bool,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_args *args;
2N/A mdrpc_sp_2_args v2_args;
2N/A mdrpc_bool_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_ownset_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) {
2N/A /*
2N/A * This has to work in the code path from libpreen which is
2N/A * running within fsck before the rpc.metad can run. Check
2N/A * to see if we should handle this as an auto-take diskset.
2N/A */
2N/A if (is_auto_take_set(sp->setname, sp->setno)) {
2N/A /* Can't call mdrpc_ownset_2_svc since not in daemon */
2N/A mdclrerror(ep);
2N/A if (s_ownset(sp->setno, ep))
2N/A res.value = TRUE;
2N/A else
2N/A res.value = FALSE;
2N/A } else {
2N/A return (-1);
2N/A }
2N/A
2N/A } else {
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_ownset_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad own set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_ownset_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad own set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A if (ret_bool != NULL)
2N/A *ret_bool = res.value;
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_bool_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Valid set name.
2N/A */
2N/Aint
2N/Aclnt_setnameok(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A int *ret_bool,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_args *args;
2N/A mdrpc_sp_2_args v2_args;
2N/A mdrpc_bool_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_setnameok_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_setnameok_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad setname ok"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_setnameok_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad setname ok"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A if (ret_bool != NULL)
2N/A *ret_bool = res.value;
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_bool_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Is set number in-use?
2N/A */
2N/Aint
2N/Aclnt_setnumbusy(
2N/A char *hostname,
2N/A set_t setno,
2N/A int *ret_bool,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_setno_args *args;
2N/A mdrpc_setno_2_args v2_args;
2N/A mdrpc_bool_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_setno_2_args_u.rev1;
2N/A args->setno = setno;
2N/A args->cl_sk = NULL;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_setnumbusy_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_setnumbusy_1(args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad setnumber busy"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_setnumbusy_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad setnumber busy"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A if (ret_bool != NULL)
2N/A *ret_bool = res.value;
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_bool_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Set the timeout values used into the drive records.
2N/A */
2N/Aint
2N/Aclnt_stimeout(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A mhd_mhiargs_t *mhiargsp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_stimeout_args *args;
2N/A mdrpc_stimeout_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_stimeout_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->mhiargsp = mhiargsp;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_stimeout_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_stimeout_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad set timeout"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_stimeout_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad set timeout"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * update drive records
2N/A */
2N/Aint
2N/Aclnt_upd_dr_dbinfo(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_drive_desc *dd,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_drives_args v1_args;
2N/A mdrpc_drives_2_args v2_args;
2N/A mdrpc_drives_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v1_args, 0, sizeof (v1_args));
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_drives_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->drivedescs = dd;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure
2N/A */
2N/A bool = mdrpc_upd_dr_dbinfo_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A
2N/A alloc_olddrvdesc(&v1_args.drivedescs, dd);
2N/A
2N/A /* build args */
2N/A v1_args.sp = sp;
2N/A v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
2N/A
2N/A rval = mdrpc_upd_dr_dbinfo_1(&v1_args, &res, clntp);
2N/A
2N/A free_olddrvdesc(v1_args.drivedescs);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad update drive dbinfo"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_upd_dr_dbinfo_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad update drive dbinfo"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * update dr_flags field of drive record.
2N/A */
2N/Aint
2N/Aclnt_upd_dr_flags(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_drive_desc *dd,
2N/A uint_t new_flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_upd_dr_flags_args v1_args;
2N/A mdrpc_upd_dr_flags_2_args v2_args;
2N/A mdrpc_upd_dr_flags_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v1_args, 0, sizeof (v1_args));
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_upd_dr_flags_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A v21_args->drivedescs = dd;
2N/A v21_args->new_flags = new_flags;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure
2N/A */
2N/A bool = mdrpc_upd_dr_flags_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A
2N/A alloc_olddrvdesc(&v1_args.drivedescs, dd);
2N/A
2N/A /* build args */
2N/A v1_args.sp = sp;
2N/A v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A meta_conv_drvdesc_new2old(v1_args.drivedescs, dd);
2N/A v1_args.new_flags = new_flags;
2N/A
2N/A rval = mdrpc_upd_dr_flags_1(&v1_args, &res, clntp);
2N/A
2N/A free_olddrvdesc(v1_args.drivedescs);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad update drive flags"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else { /* version 2 */
2N/A rval = mdrpc_upd_dr_flags_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad update drive flags"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * update set record flags
2N/A * This replaces all of the sr_flags with the new_flags. It relies on the
2N/A * caller to "do the right thing" to preserve the existing flags that should
2N/A * not be reset.
2N/A */
2N/Astatic int
2N/Aupd_sr_flags_common(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A uint_t new_flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_upd_sr_flags_args *args;
2N/A mdrpc_upd_sr_flags_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_upd_sr_flags_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A args->new_flags = new_flags;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_upd_sr_flags_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_upd_sr_flags_1(args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad update set flags"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_upd_sr_flags_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad update set flags"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Enable bits in the set record flags field. This just turns on the specified
2N/A * bits and leaves the other bits alone.
2N/A */
2N/Aint
2N/Aclnt_enable_sr_flags(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A uint_t flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A uint_t new_flags;
2N/A md_set_desc *sd;
2N/A
2N/A mdclrerror(ep);
2N/A
2N/A /* Get the flags from the current set */
2N/A if ((sd = metaget_setdesc(sp, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /* Turn on the specified bits */
2N/A new_flags = (sd->sd_flags | flags);
2N/A
2N/A /* do it */
2N/A return (upd_sr_flags_common(hostname, sp, new_flags, ep));
2N/A}
2N/A
2N/A/*
2N/A * Disable bits in the set record flags field. This just turns off the
2N/A * specified bits and leaves the other bits alone.
2N/A */
2N/Aint
2N/Aclnt_disable_sr_flags(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A uint_t flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A uint_t new_flags;
2N/A md_set_desc *sd;
2N/A
2N/A mdclrerror(ep);
2N/A
2N/A /* Get the flags from the current set */
2N/A if ((sd = metaget_setdesc(sp, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /* Turn off the specified bits */
2N/A new_flags = (sd->sd_flags & ~flags);
2N/A
2N/A /* do it */
2N/A return (upd_sr_flags_common(hostname, sp, new_flags, ep));
2N/A}
2N/A
2N/A/*
2N/A * Assign the flags as the new value(s) for the MD_SR_STATE_FLAGS within the
2N/A * set record flags field. This actually can set any bits but only clears
2N/A * the bits within the MD_SR_STATE_FLAGS subfield and leaves any other
2N/A * bits turned on. It can be used to clear (state) and set bits all in one
2N/A * rpc call.
2N/A */
2N/Aint
2N/Aclnt_upd_sr_flags(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A uint_t flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A uint_t new_flags;
2N/A md_set_desc *sd;
2N/A
2N/A mdclrerror(ep);
2N/A
2N/A /* Get the flags from the current set */
2N/A if ((sd = metaget_setdesc(sp, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /* clear the existing state flags */
2N/A sd->sd_flags &= ~MD_SR_STATE_FLAGS;
2N/A
2N/A /* Or in the new value */
2N/A new_flags = (sd->sd_flags | flags);
2N/A
2N/A /* do it */
2N/A return (upd_sr_flags_common(hostname, sp, new_flags, ep));
2N/A}
2N/A
2N/Amd_setkey_t *
2N/Acl_get_setkey(set_t setno, char *setname)
2N/A{
2N/A
2N/A if (my_cl_sk == NULL) {
2N/A my_cl_sk = Zalloc(sizeof (md_setkey_t));
2N/A my_cl_sk->sk_setno = setno;
2N/A my_cl_sk->sk_setname = Strdup(setname);
2N/A my_cl_sk->sk_host = Strdup(mynode());
2N/A } else {
2N/A my_cl_sk->sk_setno = setno;
2N/A if (my_cl_sk->sk_setname != NULL)
2N/A Free(my_cl_sk->sk_setname);
2N/A my_cl_sk->sk_setname = Strdup(setname);
2N/A }
2N/A
2N/A return (my_cl_sk);
2N/A}
2N/A
2N/Avoid
2N/Acl_set_setkey(md_setkey_t *cl_sk)
2N/A{
2N/A if ((cl_sk != NULL) && (my_cl_sk != NULL)) {
2N/A assert(my_cl_sk->sk_setno == cl_sk->sk_setno);
2N/A assert(strcmp(my_cl_sk->sk_setname, cl_sk->sk_setname) == 0);
2N/A assert(strcmp(my_cl_sk->sk_host, cl_sk->sk_host) == 0);
2N/A my_cl_sk->sk_key = cl_sk->sk_key;
2N/A return;
2N/A }
2N/A
2N/A if (my_cl_sk != NULL) {
2N/A if (my_cl_sk->sk_setname != NULL)
2N/A Free(my_cl_sk->sk_setname);
2N/A if (my_cl_sk->sk_host != NULL)
2N/A Free(my_cl_sk->sk_host);
2N/A Free(my_cl_sk);
2N/A }
2N/A
2N/A my_cl_sk = NULL;
2N/A
2N/A /* get here, if set called before get */
2N/A if (cl_sk != NULL) {
2N/A my_cl_sk = Zalloc(sizeof (md_setkey_t));
2N/A my_cl_sk->sk_host = Strdup(cl_sk->sk_host);
2N/A my_cl_sk->sk_setno = cl_sk->sk_setno;
2N/A my_cl_sk->sk_setname = Strdup(cl_sk->sk_setname);
2N/A my_cl_sk->sk_key = cl_sk->sk_key;
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Unlock the set after operation is complete.
2N/A */
2N/Aint
2N/Aclnt_unlock_set(
2N/A char *hostname,
2N/A md_setkey_t *cl_sk,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_null_args args;
2N/A mdrpc_setlock_res res;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&args, 0, sizeof (args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A args.cl_sk = cl_sk;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_unlock_set_1_svc(&args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A if (mdrpc_unlock_set_1(&args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad unlock set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_setlock_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Lock set so that only operators with valid keys are allowed in the daemon.
2N/A */
2N/Aint
2N/Aclnt_lock_set(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_null_args args;
2N/A mdrpc_setlock_res res;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&args, 0, sizeof (args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A args.cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_lock_set_1_svc(&args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A if (mdrpc_lock_set_1(&args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad lock set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep))
2N/A cl_set_setkey(res.cl_sk);
2N/A
2N/A xdr_free(xdr_mdrpc_setlock_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Add mediator hosts to disksets.
2N/A */
2N/Aint
2N/Aclnt_updmeds(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_h_arr_t *medp,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_updmeds_args *args;
2N/A mdrpc_updmeds_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_updmeds_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->meds = *medp; /* structure assignment */
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_updmeds_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A if (mdrpc_updmeds_1(args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad add hosts"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if (mdrpc_updmeds_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad add hosts"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * update nr_flags field of node records based
2N/A * on given action.
2N/A */
2N/Aint
2N/Aclnt_upd_nr_flags(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_mnnode_desc *nd,
2N/A uint_t flag_action,
2N/A uint_t flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_upd_nr_flags_args *args;
2N/A mdrpc_upd_nr_flags_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_upd_nr_flags_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->nodedescs = nd;
2N/A args->flag_action = flag_action;
2N/A args->flags = flags;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_upd_nr_flags_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_upd_nr_flags_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad set node flags"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Clear set locks for all MN disksets.
2N/A * Used during reconfig cycle to recover from failed nodes.
2N/A */
2N/Aint
2N/Aclnt_clr_mnsetlock(
2N/A char *hostname,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_null_args args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&args, 0, sizeof (args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* do it */
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A NULL, hostname, NULL, NULL);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_clr_mnsetlock_2(&args, &res, clntp) != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad clr mnsetlock"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Calls to suspend, resume or reinit the rpc.mdcommd daemon.
2N/A * This allows a node to remotely suspend, reinit and resume the
2N/A * rpc.mdcommd daemon on the given hostname node. Used by libmeta
2N/A * to lock out class 1 messages (metainit, etc) on all nodes when running
2N/A * metaset and metadb commands on this node.
2N/A *
2N/A * When suspending the commd, the suspend request will fail until all
2N/A * messages have been drained from the rpc.mdcommd. This routine will
2N/A * spin sending the suspend request until the rpc.mdcommd is drained
2N/A * or until rpc.mdcommd returns a failure other than MDMNE_SET_NOT_DRAINED.
2N/A *
2N/A * Also used to send the rpc.mdcommd daemon a new nodelist by draining all
2N/A * messages from the mdcommd and sending a reinit command to have mdcommd
2N/A * get the new nodelist from rpc.metad. Used when nodelist is changed
2N/A * during:
2N/A * - addition or deletion of host from diskset
2N/A * - join or withdrawal of host from diskset
2N/A * - addition of first disk to diskset (joins all nodes)
2N/A * - removal of last disk from diskset (withdraws all nodes)
2N/A */
2N/Aint
2N/Aclnt_mdcommdctl(
2N/A char *hostname,
2N/A int flag_action,
2N/A mdsetname_t *sp,
2N/A md_mn_msgclass_t class,
2N/A uint_t flags,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_mdcommdctl_args *args;
2N/A mdrpc_mdcommdctl_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A int suspend_spin = 0;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_mdcommdctl_2_args_u.rev1;
2N/A args->flag_action = flag_action;
2N/A args->setno = sp->setno;
2N/A args->class = class;
2N/A args->flags = flags;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A /*
2N/A * Call v2 procedure directly if rpc.metad on this node is
2N/A * sending message to itself.
2N/A */
2N/A if (flag_action == COMMDCTL_SUSPEND) {
2N/A suspend_spin = 1;
2N/A while (suspend_spin) {
2N/A suspend_spin = 0;
2N/A bool = mdrpc_mdcommdctl_2_svc(&v2_args, &res,
2N/A NULL);
2N/A assert(bool == TRUE);
2N/A /*
2N/A * If set not yet drained, wait a second
2N/A * and try again.
2N/A */
2N/A if (mdisdserror(&(res.status),
2N/A MDE_DS_COMMDCTL_SUSPEND_NYD)) {
2N/A /* Wait a second and try again */
2N/A mdclrerror(&(res.status));
2N/A (void) sleep(1);
2N/A suspend_spin = 1;
2N/A }
2N/A }
2N/A } else {
2N/A bool = mdrpc_mdcommdctl_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A }
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A }
2N/A
2N/A if (flag_action == COMMDCTL_SUSPEND) {
2N/A suspend_spin = 1;
2N/A while (suspend_spin) {
2N/A suspend_spin = 0;
2N/A if (mdrpc_mdcommdctl_2(&v2_args, &res,
2N/A clntp) != RPC_SUCCESS) {
2N/A (void) mdrpcerror(ep, clntp,
2N/A hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad commd control"));
2N/A } else {
2N/A /*
2N/A * If set not yet drained,
2N/A * wait a second and
2N/A * and try again.
2N/A */
2N/A if (mdisdserror(&(res.status),
2N/A MDE_DS_COMMDCTL_SUSPEND_NYD)) {
2N/A mdclrerror(&(res.status));
2N/A (void) sleep(1);
2N/A suspend_spin = 1;
2N/A } else {
2N/A (void) mdstealerror(ep,
2N/A &res.status);
2N/A }
2N/A }
2N/A }
2N/A } else {
2N/A if (mdrpc_mdcommdctl_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad commd control"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Is owner node stale?
2N/A */
2N/Aint
2N/Aclnt_mn_is_stale(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A int *ret_bool,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_setno_args *args;
2N/A mdrpc_setno_2_args v2_args;
2N/A mdrpc_bool_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_setno_2_args_u.rev1;
2N/A args->setno = sp->setno;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A /*
2N/A * Call v2 procedure directly if rpc.metad on this node is
2N/A * sending message to itself.
2N/A */
2N/A bool = mdrpc_mn_is_stale_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_mn_is_stale_2(&v2_args, &res, clntp) !=
2N/A RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad mn is stale"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A if (mdisok(ep)) {
2N/A /* do something with the results */
2N/A rval = 0;
2N/A
2N/A if (ret_bool != NULL)
2N/A *ret_bool = res.value;
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_bool_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Free md_drive_desc linked list of drive descriptors that was alloc'd
2N/A * from a call to the RPC routine clnt_getdrivedesc. Drive descriptors
2N/A * are from another node.
2N/A */
2N/Avoid
2N/Afree_rem_dd(md_drive_desc *dd)
2N/A{
2N/A mdrpc_getdrivedesc_res res;
2N/A
2N/A /*
2N/A * dummy up a result struct, to do a deep free of the dd.
2N/A * (A deep free means that the xdr_free code will free the
2N/A * linked list of drive descs.)
2N/A */
2N/A (void) memset(&res, 0, sizeof (res));
2N/A res.dd = (struct md_drive_desc *)dd;
2N/A xdr_free(xdr_mdrpc_getdrivedesc_res, (char *)&res);
2N/A}
2N/A
2N/A/*
2N/A * Get a partially filled in drive desc from remote node. Used in MN
2N/A * disksets during the reconfig cycle to get the diskset drive
2N/A * information from another host in order to sync up all nodes.
2N/A * Used when the drive record information isn't good enough
2N/A * since the drive record doesn't give the name of
2N/A * the drive, but just a key into that other node's nodespace.
2N/A * Returned drive desc has the drive name filled in but no other strings
2N/A * in the drivename structure.
2N/A *
2N/A * Returns a 0 if RPC was successful, 1 otherwise.
2N/A */
2N/Aint
2N/Aclnt_getdrivedesc(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_drive_desc **ret_dd,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_sp_args *args;
2N/A mdrpc_sp_2_args v2_args;
2N/A mdrpc_getdrivedesc_res res;
2N/A int version;
2N/A int rval = -1;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_sp_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_getdrivedesc_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_getdrivedesc_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad get drive desc set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A /* If no ep error and no version mismatch - rpc call worked ok */
2N/A if (mdisok(ep)) {
2N/A rval = 0;
2N/A if (ret_dd != NULL)
2N/A *ret_dd = res.dd;
2N/A else
2N/A xdr_free(xdr_mdrpc_getdrivedesc_res, (char *)&res);
2N/A }
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * update dr_flags field of drive record.
2N/A * Also sync up genid of drive descriptors and make set
2N/A * record and node records match the genid.
2N/A *
2N/A * Returns a 0 if RPC was successful, 1 otherwise.
2N/A */
2N/Aint
2N/Aclnt_upd_dr_reconfig(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A md_drive_desc *dd,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_upd_dr_flags_2_args v2_args;
2N/A mdrpc_upd_dr_flags_2_args_r1 *v21_args;
2N/A mdrpc_generic_res res;
2N/A int rval;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A v21_args = &v2_args.mdrpc_upd_dr_flags_2_args_u.rev1;
2N/A v21_args->sp = sp;
2N/A v21_args->drivedescs = dd;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A
2N/A /*
2N/A * If the server is local, we call the v2 procedure
2N/A */
2N/A bool = mdrpc_upd_dr_reconfig_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A rval = mdrpc_upd_dr_reconfig_2(&v2_args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad update drive reconfig"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Reset mirror owner(s) if mirror owner(s) is in the list of
2N/A * node's specified in the array of nodeids.
2N/A * This is called when a node has been deleted or withdrawn
2N/A * from the diskset.
2N/A */
2N/Aint
2N/Aclnt_reset_mirror_owner(
2N/A char *hostname,
2N/A mdsetname_t *sp,
2N/A int node_c,
2N/A int node_id[],
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_nodeid_args *args;
2N/A mdrpc_nodeid_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_nodeid_2_args_u.rev1;
2N/A args->sp = sp;
2N/A args->cl_sk = cl_get_setkey(sp->setno, sp->setname);
2N/A args->nodeid.nodeid_len = node_c;
2N/A args->nodeid.nodeid_val = &node_id[0];
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A bool = mdrpc_reset_mirror_owner_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A * and invoke the appropriate version of the
2N/A * remote procedure
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A sp->setno, hostname, NULL, sp->setname);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_reset_mirror_owner_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad reset mirror owner"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep))
2N/A return (-1);
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Call to suspend and resume I/O for given diskset(s).
2N/A * This allows a node to remotely suspend and resume I/O on
2N/A * a MN diskset. A diskset number of 0 represents all MN disksets.
2N/A */
2N/Aint
2N/Aclnt_mn_susp_res_io(
2N/A char *hostname,
2N/A set_t setno,
2N/A int cmd,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_mn_susp_res_io_args *args;
2N/A mdrpc_mn_susp_res_io_2_args v2_args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&v2_args, 0, sizeof (v2_args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A v2_args.rev = MD_METAD_ARGS_REV_1;
2N/A args = &v2_args.mdrpc_mn_susp_res_io_2_args_u.rev1;
2N/A args->susp_res_cmd = cmd;
2N/A args->susp_res_setno = setno;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A /*
2N/A * Call v2 procedure directly if rpc.metad on this node is
2N/A * sending message to itself.
2N/A */
2N/A bool = mdrpc_mn_susp_res_io_2_svc(&v2_args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A setno, hostname, NULL, NULL);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_mn_susp_res_io_2(&v2_args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad mn_susp_res_io control"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Resnarf the set after the set has been imported
2N/A *
2N/A * We should never be making this procedure call
2N/A * over the wire, it's sole purpose is to snarf
2N/A * the imported set on the localhost.
2N/A */
2N/Aint
2N/Aclnt_resnarf_set(
2N/A char *hostname,
2N/A set_t setno,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_setno_2_args args;
2N/A mdrpc_generic_res res;
2N/A int rval = -1;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&args, 0, sizeof (args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A args.rev = MD_METAD_ARGS_REV_1;
2N/A args.mdrpc_setno_2_args_u.rev1.setno = setno;
2N/A args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL;
2N/A
2N/A /* do it */
2N/A if (strcmp(mynode(), hostname) == 0) {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /* Check the client handle for the version */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /* If the client is version 1, return error */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_CANTRESNARF, MD_SET_BAD,
2N/A mynode(), NULL, NULL);
2N/A } else {
2N/A rval = mdrpc_resnarf_set_2(&args, &res, clntp);
2N/A
2N/A if (rval != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN, "metad resnarf set"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A
2N/A } else {
2N/A (void) mddserror(ep, MDE_DS_CANTRESNARF, MD_SET_BAD,
2N/A mynode(), NULL, NULL);
2N/A }
2N/A
2N/A if (mdisok(ep))
2N/A rval = 0;
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A return (rval);
2N/A}
2N/A
2N/A/*
2N/A * Call to start a resync for a given diskset.
2N/A * Used when a node has been added to a diskset.
2N/A * Should be called after rpc.mdcommd is resumed.
2N/A */
2N/Aint
2N/Aclnt_mn_mirror_resync_all(
2N/A char *hostname,
2N/A set_t setno,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_setno_2_args args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&args, 0, sizeof (args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A args.rev = MD_METAD_ARGS_REV_1;
2N/A args.mdrpc_setno_2_args_u.rev1.setno = setno;
2N/A args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL;
2N/A
2N/A /* do it */
2N/A if (md_in_daemon && strcmp(mynode(), hostname) == 0) {
2N/A int bool;
2N/A /*
2N/A * Call v2 procedure directly if rpc.metad on this node is
2N/A * sending message to itself.
2N/A */
2N/A bool = mdrpc_mn_mirror_resync_all_2_svc(&args, &res, NULL);
2N/A assert(bool == TRUE);
2N/A (void) mdstealerror(ep, &res.status);
2N/A } else {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A setno, hostname, NULL, NULL);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_mn_mirror_resync_all_2(&args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad mn_mirror_resync_all"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A if (strcmp(mynode(), hostname) == 0)
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * Call to update the ABR state for all soft partitions.
2N/A * Used when a node has been added to a diskset.
2N/A * Should be called after rpc.mdcommd is resumed.
2N/A */
2N/Aint
2N/Aclnt_mn_sp_update_abr(
2N/A char *hostname,
2N/A set_t setno,
2N/A md_error_t *ep
2N/A)
2N/A{
2N/A CLIENT *clntp;
2N/A mdrpc_setno_2_args args;
2N/A mdrpc_generic_res res;
2N/A int version;
2N/A
2N/A /* initialize */
2N/A mdclrerror(ep);
2N/A (void) memset(&args, 0, sizeof (args));
2N/A (void) memset(&res, 0, sizeof (res));
2N/A
2N/A /* build args */
2N/A args.rev = MD_METAD_ARGS_REV_1;
2N/A args.mdrpc_setno_2_args_u.rev1.setno = setno;
2N/A args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL;
2N/A
2N/A /*
2N/A * No need to call function if adding local node as ABR cannot
2N/A * be set.
2N/A */
2N/A if (strcmp(mynode(), hostname) != 0) {
2N/A if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL)
2N/A return (-1);
2N/A
2N/A /*
2N/A * Check the client handle for the version
2N/A */
2N/A CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version);
2N/A
2N/A /*
2N/A * If the client is version 1, return error
2N/A * otherwise, make the remote procedure call.
2N/A */
2N/A if (version == METAD_VERSION) { /* version 1 */
2N/A (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH,
2N/A setno, hostname, NULL, NULL);
2N/A metarpcclose(clntp);
2N/A return (-1);
2N/A } else {
2N/A if (mdrpc_mn_sp_update_abr_2(&args, &res, clntp)
2N/A != RPC_SUCCESS)
2N/A (void) mdrpcerror(ep, clntp, hostname,
2N/A dgettext(TEXT_DOMAIN,
2N/A "metad mn_sp_update_abr"));
2N/A else
2N/A (void) mdstealerror(ep, &res.status);
2N/A }
2N/A
2N/A metarpcclose(clntp);
2N/A }
2N/A
2N/A xdr_free(xdr_mdrpc_generic_res, (char *)&res);
2N/A
2N/A if (! mdisok(ep)) {
2N/A if (! mdanyrpcerror(ep))
2N/A return (-1);
2N/A mdclrerror(ep);
2N/A }
2N/A
2N/A return (0);
2N/A}