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