1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Just in case we're not in a build environment, make sure that 30 * TEXT_DOMAIN gets set to something. 31 */ 32 #if !defined(TEXT_DOMAIN) 33 #define TEXT_DOMAIN "SYS_TEST" 34 #endif 35 36 #include <meta.h> 37 #include <metad.h> 38 #include <devid.h> 39 40 static md_setkey_t *my_cl_sk = NULL; 41 42 #define CL_DEF_TMO 30L 43 44 /* 45 * Convert an old style mddrivename_t into a new style 46 * mddrivename_t. Meant to be used *ONLY* by rpc.metad 47 */ 48 void 49 meta_conv_drvname_old2new( 50 o_mddrivename_t *v1_dp, 51 mddrivename_t *v2_dp 52 ) 53 { 54 int sliceno; 55 o_mdname_t *v1_np; 56 mdname_t *v2_np; 57 58 /* fields that haven't changed */ 59 v2_dp->cname = v1_dp->cname; 60 v2_dp->rname = v1_dp->rname; 61 v2_dp->type = v1_dp->type; 62 v2_dp->errnum = v1_dp->errnum; 63 64 /* geometry information */ 65 v2_dp->geom.ncyl = v1_dp->geom.ncyl; 66 v2_dp->geom.nhead = v1_dp->geom.nhead; 67 v2_dp->geom.nsect = v1_dp->geom.nsect; 68 v2_dp->geom.rpm = v1_dp->geom.rpm; 69 v2_dp->geom.write_reinstruct = v1_dp->geom.write_reinstruct; 70 v2_dp->geom.read_reinstruct = v1_dp->geom.read_reinstruct; 71 v2_dp->geom.blk_sz = 0; 72 73 /* controller information */ 74 v2_dp->cinfo = v1_dp->cinfo; 75 76 /* vtoc information */ 77 v2_dp->vtoc.nparts = v1_dp->vtoc.nparts; 78 v2_dp->vtoc.first_lba = 0; 79 v2_dp->vtoc.last_lba = 0; 80 v2_dp->vtoc.lbasize = 0; 81 82 for (sliceno = 0; sliceno < (MD_MAX_PARTS - 1); sliceno++) { 83 v2_dp->vtoc.parts[sliceno].start = 84 (diskaddr_t)v1_dp->vtoc.parts[sliceno].start; 85 v2_dp->vtoc.parts[sliceno].size = 86 (diskaddr_t)v1_dp->vtoc.parts[sliceno].size; 87 v2_dp->vtoc.parts[sliceno].tag = 88 v1_dp->vtoc.parts[sliceno].tag; 89 v2_dp->vtoc.parts[sliceno].flag = 90 v1_dp->vtoc.parts[sliceno].flag; 91 v2_dp->vtoc.parts[sliceno].label = 92 (diskaddr_t)v1_dp->vtoc.parts[sliceno].label; 93 } 94 95 /* The new style vtoc has 17 partitions */ 96 v2_dp->vtoc.parts[MD_MAX_PARTS - 1].start = 0; 97 v2_dp->vtoc.parts[MD_MAX_PARTS - 1].size = 0; 98 v2_dp->vtoc.parts[MD_MAX_PARTS - 1].tag = 0; 99 v2_dp->vtoc.parts[MD_MAX_PARTS - 1].flag = 0; 100 v2_dp->vtoc.parts[MD_MAX_PARTS - 1].label = 0; 101 102 v2_dp->vtoc.typename = v1_dp->vtoc.typename; 103 104 /* partition information */ 105 v2_dp->parts.parts_len = v1_dp->parts.parts_len; 106 for (sliceno = 0; sliceno < v1_dp->parts.parts_len; sliceno++) { 107 v1_np = &v1_dp->parts.parts_val[sliceno]; 108 v2_np = &v2_dp->parts.parts_val[sliceno]; 109 110 /* 111 * We speculate that if cname for a particular 112 * partition does not exist, the other fields 113 * don't exist either. In such a case, we don't 114 * need to do anything for that partition. 115 */ 116 if (v1_np->cname != NULL) { 117 v2_np->cname = v1_np->cname; 118 v2_np->bname = v1_np->bname; 119 v2_np->rname = v1_np->rname; 120 v2_np->devicesname = v1_np->devicesname; 121 v2_np->dev = meta_expldev(v1_np->dev); 122 v2_np->key = v1_np->key; 123 v2_np->end_blk = (diskaddr_t)v1_np->end_blk; 124 v2_np->start_blk = (diskaddr_t)v1_np->start_blk; 125 } 126 v2_np->drivenamep = v2_dp; 127 } 128 129 /* We don't care about the rest of the fields */ 130 v2_dp->side_names = v1_dp->side_names; 131 v2_dp->side_names_key = v1_dp->side_names_key; 132 v2_dp->miscname = v1_dp->miscname; 133 } 134 135 /* 136 * Convert a new style mddrivename_t into an old style 137 * mddrivename_t. Meant to be used *ONLY* by rpc.metad 138 */ 139 void 140 meta_conv_drvname_new2old( 141 o_mddrivename_t *v1_dp, 142 mddrivename_t *v2_dp 143 ) 144 { 145 int sliceno; 146 o_mdname_t *v1_np; 147 mdname_t *v2_np; 148 149 /* fields that haven't changed */ 150 v1_dp->cname = v2_dp->cname; 151 v1_dp->rname = v2_dp->rname; 152 v1_dp->type = v2_dp->type; 153 v1_dp->errnum = v2_dp->errnum; 154 155 /* geometry information */ 156 v1_dp->geom.ncyl = v2_dp->geom.ncyl; 157 v1_dp->geom.nhead = v2_dp->geom.nhead; 158 v1_dp->geom.nsect = v2_dp->geom.nsect; 159 v1_dp->geom.rpm = v2_dp->geom.rpm; 160 v1_dp->geom.write_reinstruct = v2_dp->geom.write_reinstruct; 161 v1_dp->geom.read_reinstruct = v2_dp->geom.read_reinstruct; 162 163 /* controller information */ 164 v1_dp->cinfo = v2_dp->cinfo; 165 166 /* vtoc information */ 167 v1_dp->vtoc.typename = v2_dp->vtoc.typename; 168 v1_dp->vtoc.nparts = v2_dp->vtoc.nparts; 169 170 for (sliceno = 0; sliceno < (MD_MAX_PARTS - 1); sliceno++) { 171 v1_dp->vtoc.parts[sliceno].start = 172 (daddr_t)v2_dp->vtoc.parts[sliceno].start; 173 v1_dp->vtoc.parts[sliceno].size = 174 (daddr_t)v2_dp->vtoc.parts[sliceno].size; 175 v1_dp->vtoc.parts[sliceno].tag = 176 v2_dp->vtoc.parts[sliceno].tag; 177 v1_dp->vtoc.parts[sliceno].flag = 178 v2_dp->vtoc.parts[sliceno].flag; 179 v1_dp->vtoc.parts[sliceno].label = 180 (daddr_t)v2_dp->vtoc.parts[sliceno].label; 181 } 182 183 /* partition information */ 184 v1_dp->parts.parts_len = v2_dp->parts.parts_len; 185 186 for (sliceno = 0; sliceno < v2_dp->parts.parts_len; sliceno++) { 187 v1_np = &v1_dp->parts.parts_val[sliceno]; 188 v2_np = &v2_dp->parts.parts_val[sliceno]; 189 190 /* 191 * We speculate that if cname for a particular 192 * partition does not exist then the rest of 193 * the fields a partition don't exist either. 194 * In such a case, we don't need to do anything 195 * for that partition. 196 */ 197 if (v2_np->cname != NULL) { 198 v1_np->cname = v2_np->cname; 199 v1_np->bname = v2_np->bname; 200 v1_np->rname = v2_np->rname; 201 v1_np->devicesname = v2_np->devicesname; 202 v1_np->dev = meta_cmpldev(v2_np->dev); 203 v1_np->key = v2_np->key; 204 v1_np->end_blk = (daddr_t)v2_np->end_blk; 205 v1_np->start_blk = (daddr_t)v2_np->start_blk; 206 } 207 v1_np->drivenamep = v1_dp; 208 } 209 210 /* We don't care about the rest of the fields */ 211 v1_dp->side_names = v2_dp->side_names; 212 v1_dp->side_names_key = v2_dp->side_names_key; 213 v1_dp->miscname = v2_dp->miscname; 214 } 215 216 /* 217 * Convert an old style md_drive_desc_t into a new style 218 * md_drive_desc_t. Meant to be used *ONLY* by rpc.metad 219 */ 220 void 221 meta_conv_drvdesc_old2new( 222 o_md_drive_desc *v1_dd, 223 md_drive_desc *v2_dd 224 ) 225 { 226 md_drive_desc *dd; 227 o_md_drive_desc *o_dd; 228 229 dd = v2_dd; 230 231 for (o_dd = v1_dd; o_dd != NULL; o_dd = o_dd->dd_next) { 232 dd->dd_ctime = o_dd->dd_ctime; 233 dd->dd_genid = o_dd->dd_genid; 234 dd->dd_flags = o_dd->dd_flags; 235 meta_conv_drvname_old2new(o_dd->dd_dnp, dd->dd_dnp); 236 dd->dd_dbcnt = o_dd->dd_dbcnt; 237 dd->dd_dbsize = o_dd->dd_dbsize; 238 dd = dd->dd_next; 239 } 240 } 241 242 /* 243 * Convert an new style md_drive_desc_t into a old style 244 * md_drive_desc_t. Meant to be used *ONLY* by rpc.metad 245 */ 246 void 247 meta_conv_drvdesc_new2old( 248 o_md_drive_desc *v1_dd, 249 md_drive_desc *v2_dd 250 ) 251 { 252 md_drive_desc *dd; 253 o_md_drive_desc *o_dd; 254 255 o_dd = v1_dd; 256 257 for (dd = v2_dd; dd != NULL; dd = dd->dd_next) { 258 o_dd->dd_ctime = dd->dd_ctime; 259 o_dd->dd_genid = dd->dd_genid; 260 o_dd->dd_flags = dd->dd_flags; 261 meta_conv_drvname_new2old(o_dd->dd_dnp, dd->dd_dnp); 262 o_dd->dd_dbcnt = dd->dd_dbcnt; 263 o_dd->dd_dbsize = dd->dd_dbsize; 264 o_dd = o_dd->dd_next; 265 } 266 } 267 268 /* 269 * Allocate memory for v1 drive descriptor 270 * depending upon the number of drives in the 271 * v2 drive descriptor 272 */ 273 void 274 alloc_olddrvdesc( 275 o_md_drive_desc **v1_dd, 276 md_drive_desc *v2_dd 277 ) 278 { 279 md_drive_desc *dd; 280 o_md_drive_desc *new, *head; 281 282 head = NULL; 283 284 for (dd = v2_dd; dd != NULL; dd = dd->dd_next) { 285 new = Zalloc(sizeof (o_md_drive_desc)); 286 new->dd_dnp = Zalloc(sizeof (o_mddrivename_t)); 287 new->dd_dnp->parts.parts_val = Zalloc(sizeof (o_mdname_t) * 288 dd->dd_dnp->parts.parts_len); 289 new->dd_next = head; 290 head = new; 291 } 292 *v1_dd = head; 293 } 294 295 /* 296 * Allocate memory for v2 drive descriptor 297 * depending upon the number of drives in the 298 * v1 drive descriptor 299 */ 300 void 301 alloc_newdrvdesc( 302 o_md_drive_desc *v1_dd, 303 md_drive_desc **v2_dd 304 ) 305 { 306 md_drive_desc *new, *head; 307 o_md_drive_desc *o_dd; 308 309 head = NULL; 310 311 for (o_dd = v1_dd; o_dd != NULL; o_dd = o_dd->dd_next) { 312 new = Zalloc(sizeof (md_drive_desc)); 313 new->dd_dnp = Zalloc(sizeof (mddrivename_t)); 314 new->dd_dnp->parts.parts_val = Zalloc(sizeof (mdname_t) * 315 o_dd->dd_dnp->parts.parts_len); 316 new->dd_next = head; 317 head = new; 318 } 319 *v2_dd = head; 320 } 321 322 void 323 free_olddrvdesc( 324 o_md_drive_desc *v1_dd 325 ) 326 { 327 o_md_drive_desc *o_dd, *head; 328 329 head = v1_dd; 330 331 while (head != NULL) { 332 o_dd = head; 333 head = head->dd_next; 334 free(o_dd->dd_dnp->parts.parts_val); 335 free(o_dd->dd_dnp); 336 free(o_dd); 337 } 338 } 339 340 void 341 free_newdrvdesc( 342 md_drive_desc *v2_dd 343 ) 344 { 345 md_drive_desc *dd, *head; 346 347 head = v2_dd; 348 349 while (head != NULL) { 350 dd = head; 351 head = head->dd_next; 352 free(dd->dd_dnp->parts.parts_val); 353 free(dd->dd_dnp); 354 free(dd); 355 } 356 } 357 358 /* 359 * Return the device id for a given device 360 */ 361 char * 362 meta_get_devid( 363 char *rname 364 ) 365 { 366 ddi_devid_t devid; 367 int fd; 368 char *enc_devid, *dup_enc_devid = NULL; 369 370 if ((fd = open(rname, O_RDWR | O_NDELAY, 0)) < 0) 371 return (NULL); 372 373 if (devid_get(fd, &devid) == -1) { 374 (void) close(fd); 375 return (NULL); 376 } 377 (void) close(fd); 378 379 enc_devid = devid_str_encode(devid, NULL); 380 devid_free(devid); 381 382 if (enc_devid != NULL) { 383 dup_enc_devid = strdup(enc_devid); 384 devid_str_free(enc_devid); 385 } 386 387 return (dup_enc_devid); 388 } 389 390 /* 391 * Add side names for the diskset drive records 392 * NOTE: these go into the local set's namespace. 393 */ 394 int 395 clnt_add_drv_sidenms( 396 char *hostname, 397 char *this_host, 398 mdsetname_t *sp, 399 md_set_desc *sd, 400 int node_c, 401 char **node_v, 402 md_error_t *ep 403 ) 404 { 405 CLIENT *clntp; 406 mdrpc_drv_sidenm_args v1_args; 407 mdrpc_drv_sidenm_2_args v2_args; 408 mdrpc_drv_sidenm_2_args_r1 *v21_args; 409 mdrpc_generic_res res; 410 int rval; 411 int version; 412 int i, j; 413 414 /* initialize */ 415 mdclrerror(ep); 416 (void) memset(&v1_args, 0, sizeof (v1_args)); 417 (void) memset(&v2_args, 0, sizeof (v2_args)); 418 (void) memset(&res, 0, sizeof (res)); 419 420 /* build args */ 421 v2_args.rev = MD_METAD_ARGS_REV_1; 422 v21_args = &v2_args.mdrpc_drv_sidenm_2_args_u.rev1; 423 v21_args->hostname = this_host; 424 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 425 v21_args->sp = sp; 426 v21_args->sd = sd; 427 v21_args->node_v.node_v_len = node_c; 428 v21_args->node_v.node_v_val = node_v; 429 430 /* do it */ 431 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 432 int bool; 433 434 /* 435 * If the server is local, we call the v2 procedure 436 */ 437 bool = mdrpc_add_drv_sidenms_2_svc(&v2_args, &res, NULL); 438 assert(bool == TRUE); 439 (void) mdstealerror(ep, &res.status); 440 } else { 441 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 442 return (-1); 443 444 /* 445 * Check the client handle for the version 446 * and invoke the appropriate version of the 447 * remote procedure 448 */ 449 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 450 451 if (version == METAD_VERSION) { /* version 1 */ 452 453 v1_args.sd = Zalloc(sizeof (o_md_set_desc)); 454 alloc_olddrvdesc(&v1_args.sd->sd_drvs, sd->sd_drvs); 455 456 /* build args */ 457 v1_args.hostname = this_host; 458 v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname); 459 v1_args.sp = sp; 460 /* set descriptor */ 461 v1_args.sd->sd_ctime = sd->sd_ctime; 462 v1_args.sd->sd_genid = sd->sd_genid; 463 v1_args.sd->sd_setno = sd->sd_setno; 464 v1_args.sd->sd_flags = sd->sd_flags; 465 for (i = 0; i < MD_MAXSIDES; i++) { 466 v1_args.sd->sd_isown[i] = sd->sd_isown[i]; 467 468 for (j = 0; j < MD_MAX_NODENAME_PLUS_1; j ++) 469 v1_args.sd->sd_nodes[i][j] = 470 sd->sd_nodes[i][j]; 471 } 472 v1_args.sd->sd_med = sd->sd_med; 473 meta_conv_drvdesc_new2old(v1_args.sd->sd_drvs, 474 sd->sd_drvs); 475 v1_args.node_v.node_v_len = node_c; 476 v1_args.node_v.node_v_val = node_v; 477 478 rval = mdrpc_add_drv_sidenms_1(&v1_args, &res, clntp); 479 480 free_olddrvdesc(v1_args.sd->sd_drvs); 481 free(v1_args.sd); 482 483 if (rval != RPC_SUCCESS) 484 (void) mdrpcerror(ep, clntp, hostname, 485 dgettext(TEXT_DOMAIN, 486 "metad add drive sidenames")); 487 else 488 (void) mdstealerror(ep, &res.status); 489 } else { /* version 2 */ 490 rval = mdrpc_add_drv_sidenms_2(&v2_args, &res, clntp); 491 492 if (rval != RPC_SUCCESS) 493 (void) mdrpcerror(ep, clntp, hostname, 494 dgettext(TEXT_DOMAIN, 495 "metad add drive sidenames")); 496 else 497 (void) mdstealerror(ep, &res.status); 498 } 499 500 metarpcclose(clntp); 501 } 502 503 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 504 505 if (! mdisok(ep)) 506 return (-1); 507 508 return (0); 509 } 510 511 /* 512 * Adding drives via metaimport to disksets. Some of the drives may 513 * not be available so we need more information than the basic clnt_adddrvs 514 * offers us. 515 */ 516 int 517 clnt_imp_adddrvs( 518 char *hostname, 519 mdsetname_t *sp, 520 md_drive_desc *dd, 521 md_timeval32_t timestamp, 522 ulong_t genid, 523 md_error_t *ep 524 ) 525 { 526 CLIENT *clntp; 527 mdrpc_drives_2_args v2_args; 528 mdrpc_drives_2_args_r1 *v21_args; 529 mdrpc_generic_res res; 530 int rval; 531 int version; 532 533 /* initialize */ 534 mdclrerror(ep); 535 (void) memset(&v2_args, 0, sizeof (v2_args)); 536 (void) memset(&res, 0, sizeof (res)); 537 538 /* build args */ 539 v2_args.rev = MD_METAD_ARGS_REV_1; 540 v21_args = &v2_args.mdrpc_drives_2_args_u.rev1; 541 v21_args->sp = sp; 542 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 543 v21_args->drivedescs = dd; 544 v21_args->timestamp = timestamp; 545 v21_args->genid = genid; 546 547 /* do it */ 548 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 549 int bool; 550 551 /* 552 * If the server is local, we call the v1 procedure 553 */ 554 bool = mdrpc_imp_adddrvs_2(&v2_args, &res, NULL); 555 assert(bool == TRUE); 556 (void) mdstealerror(ep, &res.status); 557 } else { 558 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 559 return (-1); 560 561 /* 562 * Check the client handle for the version 563 * and invoke the appropriate version of the 564 * remote procedure 565 */ 566 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 567 568 /* 569 * If the client is version 1, return error 570 * otherwise, make the remote procedure call. 571 */ 572 if (version == METAD_VERSION) { /* version 1 */ 573 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 574 sp->setno, hostname, NULL, NULL); 575 metarpcclose(clntp); 576 return (-1); 577 } else { 578 rval = mdrpc_imp_adddrvs_2(&v2_args, &res, clntp); 579 if (rval != RPC_SUCCESS) 580 (void) mdrpcerror(ep, clntp, hostname, 581 dgettext(TEXT_DOMAIN, 582 "metad imp add drives")); 583 else 584 (void) mdstealerror(ep, &res.status); 585 } 586 587 metarpcclose(clntp); 588 } 589 590 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 591 592 if (! mdisok(ep)) 593 return (-1); 594 595 return (0); 596 } 597 598 599 /* 600 * Add drives to disksets. 601 */ 602 int 603 clnt_adddrvs( 604 char *hostname, 605 mdsetname_t *sp, 606 md_drive_desc *dd, 607 md_timeval32_t timestamp, 608 ulong_t genid, 609 md_error_t *ep 610 ) 611 { 612 CLIENT *clntp; 613 mdrpc_drives_args v1_args; 614 mdrpc_drives_2_args v2_args; 615 mdrpc_drives_2_args_r1 *v21_args; 616 mdrpc_generic_res res; 617 int rval; 618 int version; 619 620 /* initialize */ 621 mdclrerror(ep); 622 (void) memset(&v1_args, 0, sizeof (v1_args)); 623 (void) memset(&v2_args, 0, sizeof (v2_args)); 624 (void) memset(&res, 0, sizeof (res)); 625 626 /* build args */ 627 v2_args.rev = MD_METAD_ARGS_REV_1; 628 v21_args = &v2_args.mdrpc_drives_2_args_u.rev1; 629 v21_args->sp = sp; 630 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 631 v21_args->drivedescs = dd; 632 v21_args->timestamp = timestamp; 633 v21_args->genid = genid; 634 635 /* do it */ 636 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 637 int bool; 638 639 /* 640 * If the server is local, we call the v2 procedure 641 */ 642 bool = mdrpc_adddrvs_2_svc(&v2_args, &res, NULL); 643 assert(bool == TRUE); 644 (void) mdstealerror(ep, &res.status); 645 } else { 646 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 647 return (-1); 648 649 /* 650 * Check the client handle for the version 651 * and invoke the appropriate version of the 652 * remote procedure 653 */ 654 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 655 656 if (version == METAD_VERSION) { /* version 1 */ 657 658 alloc_olddrvdesc(&v1_args.drivedescs, dd); 659 660 /* build args */ 661 v1_args.sp = sp; 662 v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname); 663 meta_conv_drvdesc_new2old(v1_args.drivedescs, dd); 664 v1_args.timestamp = timestamp; 665 v1_args.genid = genid; 666 667 rval = mdrpc_adddrvs_1(&v1_args, &res, clntp); 668 669 free_olddrvdesc(v1_args.drivedescs); 670 671 if (rval != RPC_SUCCESS) 672 (void) mdrpcerror(ep, clntp, hostname, 673 dgettext(TEXT_DOMAIN, "metad add drives")); 674 else 675 (void) mdstealerror(ep, &res.status); 676 } else { /* version 2 */ 677 rval = mdrpc_adddrvs_2(&v2_args, &res, clntp); 678 679 if (rval != RPC_SUCCESS) 680 (void) mdrpcerror(ep, clntp, hostname, 681 dgettext(TEXT_DOMAIN, "metad add drives")); 682 else 683 (void) mdstealerror(ep, &res.status); 684 } 685 686 metarpcclose(clntp); 687 } 688 689 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 690 691 if (! mdisok(ep)) 692 return (-1); 693 694 return (0); 695 } 696 697 /* 698 * Add hosts to disksets. 699 */ 700 int 701 clnt_addhosts( 702 char *hostname, 703 mdsetname_t *sp, 704 int node_c, 705 char **node_v, 706 md_error_t *ep 707 ) 708 { 709 CLIENT *clntp; 710 mdrpc_host_args *args; 711 mdrpc_host_2_args v2_args; 712 mdrpc_generic_res res; 713 int version; 714 715 /* initialize */ 716 mdclrerror(ep); 717 (void) memset(&v2_args, 0, sizeof (v2_args)); 718 (void) memset(&res, 0, sizeof (res)); 719 720 /* build args */ 721 v2_args.rev = MD_METAD_ARGS_REV_1; 722 args = &v2_args.mdrpc_host_2_args_u.rev1; 723 args->sp = sp; 724 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 725 args->hosts.hosts_len = node_c; 726 args->hosts.hosts_val = node_v; 727 728 /* do it */ 729 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 730 int bool; 731 bool = mdrpc_addhosts_2_svc(&v2_args, &res, NULL); 732 assert(bool == TRUE); 733 (void) mdstealerror(ep, &res.status); 734 } else { 735 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 736 return (-1); 737 738 /* 739 * Check the client handle for the version and invoke 740 * the appropriate version of the remote procedure 741 */ 742 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 743 744 if (version == METAD_VERSION) { /* version 1 */ 745 if (mdrpc_addhosts_1(args, &res, clntp) != RPC_SUCCESS) 746 (void) mdrpcerror(ep, clntp, hostname, 747 dgettext(TEXT_DOMAIN, "metad add hosts")); 748 else 749 (void) mdstealerror(ep, &res.status); 750 } else { 751 if (mdrpc_addhosts_2(&v2_args, &res, clntp) != 752 RPC_SUCCESS) 753 (void) mdrpcerror(ep, clntp, hostname, 754 dgettext(TEXT_DOMAIN, "metad add hosts")); 755 else 756 (void) mdstealerror(ep, &res.status); 757 } 758 759 metarpcclose(clntp); 760 } 761 762 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 763 764 if (! mdisok(ep)) 765 return (-1); 766 767 return (0); 768 } 769 770 /* 771 * Create disksets. 772 */ 773 int 774 clnt_createset( 775 char *hostname, 776 mdsetname_t *sp, 777 md_node_nm_arr_t nodes, 778 md_timeval32_t timestamp, 779 ulong_t genid, 780 md_error_t *ep 781 ) 782 { 783 CLIENT *clntp; 784 mdrpc_createset_args *args; 785 mdrpc_createset_2_args v2_args; 786 mdrpc_generic_res res; 787 int i; 788 int version; 789 790 /* initialize */ 791 mdclrerror(ep); 792 (void) memset(&v2_args, 0, sizeof (v2_args)); 793 (void) memset(&res, 0, sizeof (res)); 794 795 /* build args */ 796 v2_args.rev = MD_METAD_ARGS_REV_1; 797 args = &v2_args.mdrpc_createset_2_args_u.rev1; 798 args->sp = sp; 799 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 800 args->timestamp = timestamp; 801 args->genid = genid; 802 for (i = 0; i < MD_MAXSIDES; i++) 803 (void) strcpy(args->nodes[i], nodes[i]); 804 805 /* do it */ 806 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 807 int bool; 808 bool = mdrpc_createset_2_svc(&v2_args, &res, NULL); 809 assert(bool == TRUE); 810 (void) mdstealerror(ep, &res.status); 811 } else { 812 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 813 return (-1); 814 815 /* 816 * Check the client handle for the version and invoke 817 * the appropriate version of the remote procedure 818 */ 819 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 820 821 if (version == METAD_VERSION) { /* version 1 */ 822 if (mdrpc_createset_1(args, &res, clntp) != 823 RPC_SUCCESS) 824 (void) mdrpcerror(ep, clntp, hostname, 825 dgettext(TEXT_DOMAIN, "metad create set")); 826 else 827 (void) mdstealerror(ep, &res.status); 828 } else { 829 if (mdrpc_createset_2(&v2_args, &res, clntp) != 830 RPC_SUCCESS) 831 (void) mdrpcerror(ep, clntp, hostname, 832 dgettext(TEXT_DOMAIN, "metad create set")); 833 else 834 (void) mdstealerror(ep, &res.status); 835 } 836 837 metarpcclose(clntp); 838 } 839 840 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 841 842 if (! mdisok(ep)) 843 return (-1); 844 845 return (0); 846 } 847 848 /* 849 * Create MN disksets. 850 */ 851 int 852 clnt_mncreateset( 853 char *hostname, 854 mdsetname_t *sp, 855 md_mnnode_desc *nodelist, 856 md_timeval32_t timestamp, 857 ulong_t genid, 858 md_node_nm_t master_nodenm, 859 int master_nodeid, 860 md_error_t *ep 861 ) 862 { 863 CLIENT *clntp; 864 mdrpc_mncreateset_args *args; 865 mdrpc_mncreateset_2_args v2_args; 866 mdrpc_generic_res res; 867 int version; 868 869 /* initialize */ 870 mdclrerror(ep); 871 (void) memset(&v2_args, 0, sizeof (v2_args)); 872 (void) memset(&res, 0, sizeof (res)); 873 874 /* build args */ 875 v2_args.rev = MD_METAD_ARGS_REV_1; 876 args = &v2_args.mdrpc_mncreateset_2_args_u.rev1; 877 args->sp = sp; 878 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 879 args->timestamp = timestamp; 880 args->genid = genid; 881 (void) strlcpy(args->master_nodenm, master_nodenm, MD_MAX_NODENAME); 882 args->master_nodeid = master_nodeid; 883 args->nodelist = nodelist; 884 885 /* do it */ 886 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 887 int bool; 888 bool = mdrpc_mncreateset_2_svc(&v2_args, &res, NULL); 889 assert(bool == TRUE); 890 (void) mdstealerror(ep, &res.status); 891 } else { 892 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 893 return (-1); 894 895 /* 896 * Check the client handle for the version 897 */ 898 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 899 900 /* 901 * If the client is version 1, return error 902 * otherwise, make the remote procedure call. 903 */ 904 if (version == METAD_VERSION) { /* version 1 */ 905 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 906 sp->setno, hostname, NULL, sp->setname); 907 metarpcclose(clntp); 908 return (-1); 909 } else { 910 if (mdrpc_mncreateset_2(&v2_args, &res, clntp) 911 != RPC_SUCCESS) 912 (void) mdrpcerror(ep, clntp, hostname, 913 dgettext(TEXT_DOMAIN, "metad mncreate set")); 914 else 915 (void) mdstealerror(ep, &res.status); 916 } 917 918 metarpcclose(clntp); 919 } 920 921 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 922 923 if (! mdisok(ep)) 924 return (-1); 925 926 return (0); 927 } 928 929 /* 930 * Join MN set 931 */ 932 int 933 clnt_joinset( 934 char *hostname, 935 mdsetname_t *sp, 936 int flags, 937 md_error_t *ep 938 ) 939 { 940 CLIENT *clntp; 941 mdrpc_sp_flags_args *args; 942 mdrpc_sp_flags_2_args v2_args; 943 mdrpc_generic_res res; 944 int version; 945 946 /* initialize */ 947 mdclrerror(ep); 948 (void) memset(&v2_args, 0, sizeof (v2_args)); 949 (void) memset(&res, 0, sizeof (res)); 950 951 /* build args */ 952 v2_args.rev = MD_METAD_ARGS_REV_1; 953 args = &v2_args.mdrpc_sp_flags_2_args_u.rev1; 954 args->sp = sp; 955 args->flags = flags; 956 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 957 958 /* do it */ 959 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 960 int bool; 961 bool = mdrpc_joinset_2_svc(&v2_args, &res, NULL); 962 assert(bool == TRUE); 963 (void) mdstealerror(ep, &res.status); 964 } else { 965 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 966 return (-1); 967 968 /* 969 * Check the client handle for the version 970 */ 971 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 972 973 /* 974 * If the client is version 1, return error 975 * otherwise, make the remote procedure call. 976 */ 977 if (version == METAD_VERSION) { /* version 1 */ 978 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 979 sp->setno, hostname, NULL, sp->setname); 980 metarpcclose(clntp); 981 return (-1); 982 } else { 983 if (mdrpc_joinset_2(&v2_args, &res, clntp) 984 != RPC_SUCCESS) 985 (void) mdrpcerror(ep, clntp, hostname, 986 dgettext(TEXT_DOMAIN, "metad join set")); 987 else 988 (void) mdstealerror(ep, &res.status); 989 } 990 991 metarpcclose(clntp); 992 } 993 994 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 995 996 if (! mdisok(ep)) 997 return (-1); 998 999 return (0); 1000 } 1001 1002 /* 1003 * Withdraw from MN set 1004 */ 1005 int 1006 clnt_withdrawset( 1007 char *hostname, 1008 mdsetname_t *sp, 1009 md_error_t *ep 1010 ) 1011 { 1012 CLIENT *clntp; 1013 mdrpc_sp_args *args; 1014 mdrpc_sp_2_args v2_args; 1015 mdrpc_generic_res res; 1016 int version; 1017 1018 /* initialize */ 1019 mdclrerror(ep); 1020 (void) memset(&v2_args, 0, sizeof (v2_args)); 1021 (void) memset(&res, 0, sizeof (res)); 1022 1023 /* build args */ 1024 v2_args.rev = MD_METAD_ARGS_REV_1; 1025 args = &v2_args.mdrpc_sp_2_args_u.rev1; 1026 args->sp = sp; 1027 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1028 1029 /* do it */ 1030 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1031 int bool; 1032 bool = mdrpc_withdrawset_2_svc(&v2_args, &res, NULL); 1033 assert(bool == TRUE); 1034 (void) mdstealerror(ep, &res.status); 1035 } else { 1036 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1037 return (-1); 1038 1039 /* 1040 * Check the client handle for the version 1041 */ 1042 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1043 1044 /* 1045 * If the client is version 1, return error 1046 * otherwise, make the remote procedure call. 1047 */ 1048 if (version == METAD_VERSION) { /* version 1 */ 1049 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 1050 sp->setno, hostname, NULL, sp->setname); 1051 metarpcclose(clntp); 1052 return (-1); 1053 } else { 1054 if (mdrpc_withdrawset_2(&v2_args, &res, clntp) 1055 != RPC_SUCCESS) 1056 (void) mdrpcerror(ep, clntp, hostname, 1057 dgettext(TEXT_DOMAIN, 1058 "metad withdraw set")); 1059 else 1060 (void) mdstealerror(ep, &res.status); 1061 } 1062 1063 metarpcclose(clntp); 1064 } 1065 1066 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 1067 1068 if (! mdisok(ep)) 1069 return (-1); 1070 1071 return (0); 1072 } 1073 1074 /* 1075 * Delete side names for the diskset drive records 1076 * NOTE: these are removed from the local set's namespace. 1077 */ 1078 int 1079 clnt_del_drv_sidenms( 1080 char *hostname, 1081 mdsetname_t *sp, 1082 md_error_t *ep 1083 ) 1084 { 1085 CLIENT *clntp; 1086 mdrpc_sp_args *args; 1087 mdrpc_sp_2_args v2_args; 1088 mdrpc_generic_res res; 1089 int version; 1090 1091 /* initialize */ 1092 mdclrerror(ep); 1093 (void) memset(&v2_args, 0, sizeof (v2_args)); 1094 (void) memset(&res, 0, sizeof (res)); 1095 1096 /* build args */ 1097 v2_args.rev = MD_METAD_ARGS_REV_1; 1098 args = &v2_args.mdrpc_sp_2_args_u.rev1; 1099 args->sp = sp; 1100 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1101 1102 /* do it */ 1103 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1104 int bool; 1105 bool = mdrpc_del_drv_sidenms_2_svc(&v2_args, &res, NULL); 1106 assert(bool == TRUE); 1107 (void) mdstealerror(ep, &res.status); 1108 } else { 1109 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1110 return (-1); 1111 1112 if (metaget_setdesc(sp, ep) == NULL) { 1113 if (! mdisok(ep)) 1114 return (-1); 1115 mdclrerror(ep); 1116 } 1117 1118 /* 1119 * Check the client handle for the version and invoke 1120 * the appropriate version of the remote procedure 1121 */ 1122 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1123 1124 if (version == METAD_VERSION) { /* version 1 */ 1125 if (mdrpc_del_drv_sidenms_1(args, &res, clntp) != 1126 RPC_SUCCESS) 1127 (void) mdrpcerror(ep, clntp, hostname, 1128 dgettext(TEXT_DOMAIN, 1129 "metad delete drive sidenames")); 1130 else 1131 (void) mdstealerror(ep, &res.status); 1132 } else { 1133 if (mdrpc_del_drv_sidenms_2(&v2_args, &res, clntp) != 1134 RPC_SUCCESS) 1135 (void) mdrpcerror(ep, clntp, hostname, 1136 dgettext(TEXT_DOMAIN, 1137 "metad delete drive sidenames")); 1138 else 1139 (void) mdstealerror(ep, &res.status); 1140 } 1141 1142 metarpcclose(clntp); 1143 } 1144 1145 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 1146 1147 if (! mdisok(ep)) 1148 return (-1); 1149 1150 return (0); 1151 } 1152 1153 /* 1154 * delete drives from the set 1155 */ 1156 int 1157 clnt_deldrvs( 1158 char *hostname, 1159 mdsetname_t *sp, 1160 md_drive_desc *dd, 1161 md_error_t *ep 1162 ) 1163 { 1164 CLIENT *clntp; 1165 mdrpc_drives_args v1_args; 1166 mdrpc_drives_2_args v2_args; 1167 mdrpc_drives_2_args_r1 *v21_args; 1168 mdrpc_generic_res res; 1169 int rval; 1170 int version; 1171 1172 /* initialize */ 1173 mdclrerror(ep); 1174 (void) memset(&v1_args, 0, sizeof (v1_args)); 1175 (void) memset(&v2_args, 0, sizeof (v2_args)); 1176 (void) memset(&res, 0, sizeof (res)); 1177 1178 /* build args */ 1179 v2_args.rev = MD_METAD_ARGS_REV_1; 1180 v21_args = &v2_args.mdrpc_drives_2_args_u.rev1; 1181 v21_args->sp = sp; 1182 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1183 v21_args->drivedescs = dd; 1184 1185 /* do it */ 1186 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1187 int bool; 1188 1189 /* 1190 * If the server is local, we call the v2 procedure 1191 */ 1192 bool = mdrpc_deldrvs_2_svc(&v2_args, &res, NULL); 1193 assert(bool == TRUE); 1194 (void) mdstealerror(ep, &res.status); 1195 } else { 1196 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1197 return (-1); 1198 1199 /* 1200 * Check the client handle for the version 1201 * and invoke the appropriate version of the 1202 * remote procedure 1203 */ 1204 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1205 1206 if (version == METAD_VERSION) { /* version 1 */ 1207 1208 alloc_olddrvdesc(&v1_args.drivedescs, dd); 1209 1210 /* build args */ 1211 v1_args.sp = sp; 1212 v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname); 1213 meta_conv_drvdesc_new2old(v1_args.drivedescs, dd); 1214 1215 rval = mdrpc_deldrvs_1(&v1_args, &res, clntp); 1216 1217 free_olddrvdesc(v1_args.drivedescs); 1218 1219 if (rval != RPC_SUCCESS) 1220 (void) mdrpcerror(ep, clntp, hostname, 1221 dgettext(TEXT_DOMAIN, 1222 "metad delete drives")); 1223 else 1224 (void) mdstealerror(ep, &res.status); 1225 } else { /* version 2 */ 1226 rval = mdrpc_deldrvs_2(&v2_args, &res, clntp); 1227 1228 if (rval != RPC_SUCCESS) 1229 (void) mdrpcerror(ep, clntp, hostname, 1230 dgettext(TEXT_DOMAIN, 1231 "metad delete drives")); 1232 else 1233 (void) mdstealerror(ep, &res.status); 1234 } 1235 1236 metarpcclose(clntp); 1237 } 1238 1239 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 1240 1241 if (! mdisok(ep)) 1242 return (-1); 1243 1244 return (0); 1245 } 1246 1247 /* 1248 * delete host(s) from a set. 1249 */ 1250 int 1251 clnt_delhosts( 1252 char *hostname, 1253 mdsetname_t *sp, 1254 int node_c, 1255 char **node_v, 1256 md_error_t *ep 1257 ) 1258 { 1259 CLIENT *clntp; 1260 mdrpc_host_args *args; 1261 mdrpc_host_2_args v2_args; 1262 mdrpc_generic_res res; 1263 int version; 1264 1265 /* initialize */ 1266 mdclrerror(ep); 1267 (void) memset(&v2_args, 0, sizeof (v2_args)); 1268 (void) memset(&res, 0, sizeof (res)); 1269 1270 /* build args */ 1271 v2_args.rev = MD_METAD_ARGS_REV_1; 1272 args = &v2_args.mdrpc_host_2_args_u.rev1; 1273 args->sp = sp; 1274 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1275 args->hosts.hosts_len = node_c; 1276 args->hosts.hosts_val = node_v; 1277 1278 /* do it */ 1279 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1280 int bool; 1281 bool = mdrpc_delhosts_2_svc(&v2_args, &res, NULL); 1282 assert(bool == TRUE); 1283 (void) mdstealerror(ep, &res.status); 1284 } else { 1285 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1286 return (-1); 1287 1288 /* 1289 * Check the client handle for the version 1290 * and invoke the appropriate version of the 1291 * remote procedure 1292 */ 1293 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1294 1295 if (version == METAD_VERSION) { /* version 1 */ 1296 if (mdrpc_delhosts_1(args, &res, clntp) != RPC_SUCCESS) 1297 (void) mdrpcerror(ep, clntp, hostname, 1298 dgettext(TEXT_DOMAIN, "metad delete hosts")); 1299 else 1300 (void) mdstealerror(ep, &res.status); 1301 } else { 1302 if (mdrpc_delhosts_2(&v2_args, &res, clntp) != 1303 RPC_SUCCESS) 1304 (void) mdrpcerror(ep, clntp, hostname, 1305 dgettext(TEXT_DOMAIN, "metad delete hosts")); 1306 else 1307 (void) mdstealerror(ep, &res.status); 1308 } 1309 1310 metarpcclose(clntp); 1311 } 1312 1313 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 1314 1315 if (! mdisok(ep)) 1316 return (-1); 1317 1318 return (0); 1319 } 1320 1321 /* 1322 * Delete diskset. 1323 */ 1324 int 1325 clnt_delset( 1326 char *hostname, 1327 mdsetname_t *sp, 1328 md_error_t *ep 1329 ) 1330 { 1331 CLIENT *clntp; 1332 mdrpc_sp_args *args; 1333 mdrpc_sp_2_args v2_args; 1334 mdrpc_generic_res res; 1335 int version; 1336 1337 /* initialize */ 1338 mdclrerror(ep); 1339 (void) memset(&v2_args, 0, sizeof (v2_args)); 1340 (void) memset(&res, 0, sizeof (res)); 1341 1342 /* build args */ 1343 v2_args.rev = MD_METAD_ARGS_REV_1; 1344 args = &v2_args.mdrpc_sp_2_args_u.rev1; 1345 args->sp = sp; 1346 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1347 1348 /* do it */ 1349 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1350 int bool; 1351 bool = mdrpc_delset_2_svc(&v2_args, &res, NULL); 1352 assert(bool == TRUE); 1353 (void) mdstealerror(ep, &res.status); 1354 } else { 1355 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1356 return (-1); 1357 1358 /* 1359 * Check the client handle for the version 1360 * and invoke the appropriate version of the 1361 * remote procedure 1362 */ 1363 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1364 1365 if (version == METAD_VERSION) { /* version 1 */ 1366 if (mdrpc_delset_1(args, &res, clntp) != RPC_SUCCESS) 1367 (void) mdrpcerror(ep, clntp, hostname, 1368 dgettext(TEXT_DOMAIN, "metad delete set")); 1369 else 1370 (void) mdstealerror(ep, &res.status); 1371 } else { 1372 if (mdrpc_delset_2(&v2_args, &res, clntp) != 1373 RPC_SUCCESS) 1374 (void) mdrpcerror(ep, clntp, hostname, 1375 dgettext(TEXT_DOMAIN, "metad delete set")); 1376 else 1377 (void) mdstealerror(ep, &res.status); 1378 } 1379 1380 metarpcclose(clntp); 1381 } 1382 1383 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 1384 1385 if (! mdisok(ep)) 1386 return (-1); 1387 1388 return (0); 1389 } 1390 1391 /* 1392 * return remote device info 1393 */ 1394 int 1395 clnt_devinfo( 1396 char *hostname, 1397 mdsetname_t *sp, 1398 mddrivename_t *dp, 1399 md_dev64_t *ret_dev, 1400 time_t *ret_timestamp, 1401 md_error_t *ep 1402 ) 1403 { 1404 CLIENT *clntp; 1405 mdrpc_devinfo_args v1_args; 1406 mdrpc_devinfo_2_args v2_args; 1407 mdrpc_devinfo_2_args_r1 *v21_args; 1408 mdrpc_devinfo_res v1_res; 1409 mdrpc_devinfo_2_res v2_res; 1410 int rval, version; 1411 1412 /* initialize */ 1413 mdclrerror(ep); 1414 (void) memset(&v1_args, 0, sizeof (v1_args)); 1415 (void) memset(&v2_args, 0, sizeof (v2_args)); 1416 (void) memset(&v1_res, 0, sizeof (v1_res)); 1417 (void) memset(&v2_res, 0, sizeof (v2_res)); 1418 1419 /* build args */ 1420 v2_args.rev = MD_METAD_ARGS_REV_1; 1421 v21_args = &v2_args.mdrpc_devinfo_2_args_u.rev1; 1422 v21_args->sp = sp; 1423 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1424 v21_args->drivenamep = dp; 1425 1426 /* do it */ 1427 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1428 int bool; 1429 1430 /* 1431 * If the server is local, we call the v2 procedure. 1432 */ 1433 bool = mdrpc_devinfo_2_svc(&v2_args, &v2_res, NULL); 1434 assert(bool == TRUE); 1435 (void) mdstealerror(ep, &v1_res.status); 1436 } else { 1437 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1438 return (-1); 1439 1440 /* 1441 * Check the client handle for the version 1442 * and invoke the appropriate version of 1443 * the remote procedure. 1444 */ 1445 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1446 1447 if (version == METAD_VERSION) { /* version 1 */ 1448 v1_args.drivenamep = 1449 Zalloc(sizeof (o_mddrivename_t)); 1450 v1_args.drivenamep->parts.parts_val = 1451 Zalloc((sizeof (o_mdname_t)) * 1452 dp->parts.parts_len); 1453 1454 /* build args */ 1455 v1_args.sp = sp; 1456 v1_args.cl_sk = cl_get_setkey(sp->setno, 1457 sp->setname); 1458 1459 /* 1460 * Convert v2 arguments to v1 arguments 1461 * before sending over the wire. 1462 */ 1463 meta_conv_drvname_new2old(v1_args.drivenamep, 1464 v21_args->drivenamep); 1465 1466 rval = mdrpc_devinfo_1(&v1_args, &v1_res, clntp); 1467 1468 free(v1_args.drivenamep->parts.parts_val); 1469 free(v1_args.drivenamep); 1470 1471 if (rval != RPC_SUCCESS) 1472 (void) mdrpcerror(ep, clntp, hostname, 1473 dgettext(TEXT_DOMAIN, "metad device info")); 1474 else 1475 (void) mdstealerror(ep, &v1_res.status); 1476 } else { /* version 2 */ 1477 rval = mdrpc_devinfo_2(&v2_args, &v2_res, clntp); 1478 if (rval != RPC_SUCCESS) 1479 (void) mdrpcerror(ep, clntp, hostname, 1480 dgettext(TEXT_DOMAIN, "metad device info")); 1481 else 1482 (void) mdstealerror(ep, &v2_res.status); 1483 } 1484 1485 metarpcclose(clntp); 1486 } 1487 1488 if (mdisok(ep)) { 1489 /* do something with the results */ 1490 rval = 0; 1491 1492 if (ret_dev != NULL) { 1493 if (version == METAD_VERSION) 1494 *ret_dev = meta_expldev(v1_res.dev); 1495 else 1496 *ret_dev = v2_res.dev; 1497 } 1498 1499 if (ret_timestamp != NULL) { 1500 if (version == METAD_VERSION) 1501 *ret_timestamp = v1_res.vtime; 1502 else 1503 *ret_timestamp = v2_res.vtime; 1504 } 1505 } 1506 1507 if (version == METAD_VERSION) 1508 xdr_free(xdr_mdrpc_devinfo_res, (char *)&v1_res); 1509 else 1510 xdr_free(xdr_mdrpc_devinfo_2_res, (char *)&v2_res); 1511 1512 return (rval); 1513 } 1514 1515 /* 1516 * return remote device info 1517 */ 1518 int 1519 clnt_devid( 1520 char *hostname, 1521 mdsetname_t *sp, 1522 mddrivename_t *dp, 1523 char **ret_encdevid, 1524 md_error_t *ep 1525 ) 1526 { 1527 CLIENT *clntp; 1528 mdrpc_devid_args *args; 1529 mdrpc_devid_2_args v2_args; 1530 mdrpc_devid_res res; 1531 int rval; 1532 int version; 1533 1534 /* initialize */ 1535 mdclrerror(ep); 1536 (void) memset(&v2_args, 0, sizeof (v2_args)); 1537 (void) memset(&res, 0, sizeof (res)); 1538 1539 /* build args */ 1540 v2_args.rev = MD_METAD_ARGS_REV_1; 1541 args = &v2_args.mdrpc_devid_2_args_u.rev1; 1542 args->sp = sp; 1543 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1544 args->drivenamep = dp; 1545 1546 /* do it */ 1547 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1548 int bool; 1549 1550 /* 1551 * If the server is local, we call the v2 procedure. 1552 */ 1553 bool = mdrpc_devid_2_svc(&v2_args, &res, NULL); 1554 assert(bool == TRUE); 1555 (void) mdstealerror(ep, &res.status); 1556 } else { 1557 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1558 return (-1); 1559 1560 /* 1561 * Check the client handle for the version 1562 */ 1563 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1564 1565 /* 1566 * If the client is version 1, return error 1567 * otherwise, make the remote procedure call. 1568 */ 1569 if (version == METAD_VERSION) { /* version 1 */ 1570 (void) mddserror(ep, MDE_DS_DRIVENOTONHOST, sp->setno, 1571 hostname, dp->cname, sp->setname); 1572 } else { /* version 2 */ 1573 rval = mdrpc_devid_2(&v2_args, &res, clntp); 1574 1575 if (rval != RPC_SUCCESS) 1576 (void) mdrpcerror(ep, clntp, hostname, 1577 dgettext(TEXT_DOMAIN, "metad devid info")); 1578 else 1579 (void) mdstealerror(ep, &res.status); 1580 } 1581 1582 metarpcclose(clntp); 1583 } 1584 1585 if (mdisok(ep)) { 1586 /* do something with the results */ 1587 rval = 0; 1588 1589 if (ret_encdevid != NULL) 1590 *ret_encdevid = strdup(res.enc_devid); 1591 1592 } 1593 1594 xdr_free(xdr_mdrpc_devid_res, (char *)&res); 1595 1596 return (rval); 1597 } 1598 1599 /* 1600 * Get the device information of a disk on a remote host. The information 1601 * retrieved is the device's name, the associated driver and the dev_t. 1602 * The lookup is performed by using the devid of the disk as this is 1603 * unique to the disk. The device name on the originating node is passed 1604 * in. If that devname is found when doing the devid to namelist translation 1605 * then that value is used to make the device names as consistent as possible 1606 * across the nodes. 1607 * 1608 * An attempt is made to retrieve this information by calling 1609 * mdrpc_devinfo_by_devid_name_2_svc. Locally this call should always 1610 * succeed. In the case where a call is made through a CLIENT handle, 1611 * it is possible that the function hasn't been implemented on the called 1612 * node. If this is the case fall back to mdrpc_devinfo_by_devidstr_2_svc. 1613 * 1614 * Returns: 1615 * -1 Error 1616 * ENOTSUP Operation not supported i.e. procedure not supported on 1617 * the remote node 1618 * 0 Success 1619 */ 1620 int 1621 clnt_devinfo_by_devid( 1622 char *hostname, 1623 mdsetname_t *sp, 1624 char *devidstr, 1625 md_dev64_t *ret_dev, 1626 char *orig_devname, 1627 char **ret_devname, 1628 char **ret_driver, 1629 md_error_t *ep 1630 ) 1631 { 1632 CLIENT *clntp; 1633 mdrpc_devidstr_args devid_args; 1634 mdrpc_devid_name_args *args; 1635 mdrpc_devid_name_2_args v2_args; 1636 mdrpc_devinfo_2_res res; 1637 int rval; 1638 int version; 1639 1640 /* initialize */ 1641 mdclrerror(ep); 1642 (void) memset(&v2_args, 0, sizeof (v2_args)); 1643 (void) memset(&res, 0, sizeof (res)); 1644 1645 /* build args */ 1646 v2_args.rev = MD_METAD_ARGS_REV_1; 1647 args = &v2_args.mdrpc_devid_name_2_args_u.rev1; 1648 args->enc_devid = devidstr; 1649 args->orig_devname = orig_devname; 1650 args->sp = sp; 1651 1652 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1653 int bool; 1654 1655 /* 1656 * We are calling this locally so call the function 1657 * directly. 1658 */ 1659 bool = mdrpc_devinfo_by_devid_name_2_svc(&v2_args, &res, NULL); 1660 assert(bool == TRUE); 1661 (void) mdstealerror(ep, &res.status); 1662 } else { 1663 1664 /* open connection */ 1665 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) { 1666 return (-1); 1667 } 1668 1669 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1670 1671 if (version == METAD_VERSION) { /* Version 1 */ 1672 metarpcclose(clntp); 1673 return (ENOTSUP); 1674 } 1675 1676 rval = mdrpc_devinfo_by_devid_name_2(&v2_args, &res, clntp); 1677 1678 if (rval != RPC_SUCCESS) { 1679 /* try falling back to devidstr_2_svc */ 1680 (void) memset(&devid_args, 0, sizeof (devid_args)); 1681 (void) memset(&res, 0, sizeof (res)); 1682 1683 devid_args.enc_devid = devidstr; 1684 devid_args.sp = sp; 1685 1686 rval = mdrpc_devinfo_by_devid_2( 1687 &devid_args, &res, clntp); 1688 1689 if (rval != RPC_SUCCESS) { 1690 (void) mdrpcerror(ep, clntp, hostname, 1691 dgettext(TEXT_DOMAIN, 1692 "metad devinfo by devid")); 1693 } else { 1694 (void) mdstealerror(ep, &res.status); 1695 } 1696 } else { 1697 (void) mdstealerror(ep, &res.status); 1698 } 1699 metarpcclose(clntp); 1700 } 1701 1702 if (mdisok(ep)) { 1703 rval = 0; 1704 if (ret_dev != NULL) 1705 *ret_dev = res.dev; 1706 1707 if (ret_devname != NULL && res.devname != NULL) 1708 *ret_devname = Strdup(res.devname); 1709 1710 if (ret_driver != NULL && res.drivername != NULL) 1711 *ret_driver = Strdup(res.drivername); 1712 } 1713 1714 xdr_free(xdr_mdrpc_devinfo_2_res, (char *)&res); 1715 1716 if (! mdisok(ep)) 1717 return (-1); 1718 1719 return (0); 1720 1721 } 1722 1723 1724 /* 1725 * return status of whether driver is used, mount 1726 */ 1727 int 1728 clnt_drvused( 1729 char *hostname, 1730 mdsetname_t *sp, 1731 mddrivename_t *dp, 1732 md_error_t *ep 1733 ) 1734 { 1735 CLIENT *clntp; 1736 mdrpc_drvused_args v1_args; 1737 mdrpc_drvused_2_args v2_args; 1738 mdrpc_drvused_2_args_r1 *v21_args; 1739 mdrpc_generic_res res; 1740 int rval; 1741 int version; 1742 1743 /* initialize */ 1744 mdclrerror(ep); 1745 (void) memset(&v1_args, 0, sizeof (v1_args)); 1746 (void) memset(&v2_args, 0, sizeof (v2_args)); 1747 (void) memset(&res, 0, sizeof (res)); 1748 1749 /* build args */ 1750 v2_args.rev = MD_METAD_ARGS_REV_1; 1751 v21_args = &v2_args.mdrpc_drvused_2_args_u.rev1; 1752 v21_args->sp = sp; 1753 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 1754 v21_args->drivenamep = dp; 1755 1756 /* do it */ 1757 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1758 int bool; 1759 1760 /* 1761 * If the server is local, we call the v2 procedure 1762 */ 1763 bool = mdrpc_drvused_2_svc(&v2_args, &res, NULL); 1764 assert(bool == TRUE); 1765 (void) mdstealerror(ep, &res.status); 1766 } else { 1767 /* open connection */ 1768 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 1769 return (-1); 1770 1771 /* 1772 * Check the client handle for the version 1773 * and invoke the appropriate version of the 1774 * remote procedure 1775 */ 1776 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1777 1778 if (version == METAD_VERSION) { /* version 1 */ 1779 v1_args.drivenamep = 1780 Zalloc(sizeof (o_mddrivename_t)); 1781 v1_args.drivenamep->parts.parts_val = 1782 Zalloc((sizeof (o_mdname_t)) * 1783 dp->parts.parts_len); 1784 1785 /* build args */ 1786 v1_args.sp = sp; 1787 v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname); 1788 1789 /* Convert v2 args to v1 args */ 1790 meta_conv_drvname_new2old(v1_args.drivenamep, 1791 v21_args->drivenamep); 1792 1793 rval = mdrpc_drvused_1(&v1_args, &res, clntp); 1794 1795 free(v1_args.drivenamep->parts.parts_val); 1796 free(v1_args.drivenamep); 1797 1798 if (rval != RPC_SUCCESS) 1799 (void) mdrpcerror(ep, clntp, hostname, 1800 dgettext(TEXT_DOMAIN, "metad drive used")); 1801 else 1802 (void) mdstealerror(ep, &res.status); 1803 } else { /* version 2 */ 1804 rval = mdrpc_drvused_2(&v2_args, &res, clntp); 1805 if (rval != RPC_SUCCESS) 1806 (void) mdrpcerror(ep, clntp, hostname, 1807 dgettext(TEXT_DOMAIN, "metad drive used")); 1808 else 1809 (void) mdstealerror(ep, &res.status); 1810 } 1811 1812 metarpcclose(clntp); 1813 } 1814 1815 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 1816 1817 if (! mdisok(ep)) 1818 return (-1); 1819 1820 return (0); 1821 } 1822 1823 void 1824 free_sr(md_set_record *sr) 1825 { 1826 mdrpc_getset_res res; 1827 mdrpc_mngetset_res mnres; 1828 1829 if (md_in_daemon) 1830 return; 1831 1832 /* 1833 * dummy up a result struct, to do a deep free of the (mn)sr. 1834 * (A deep free means that the xdr_free code will free the 1835 * linked list of drive records for the sr and will also free 1836 * the linked list of node records for the mnsr.) 1837 */ 1838 if (MD_MNSET_REC(sr)) { 1839 (void) memset(&mnres, 0, sizeof (mnres)); 1840 mnres.mnsr = (struct md_mnset_record *)sr; 1841 xdr_free(xdr_mdrpc_mngetset_res, (char *)&mnres); 1842 } else { 1843 (void) memset(&res, 0, sizeof (res)); 1844 res.sr = sr; 1845 xdr_free(xdr_mdrpc_getset_res, (char *)&res); 1846 } 1847 } 1848 1849 void 1850 short_circuit_getset( 1851 mdrpc_getset_args *args, 1852 mdrpc_getset_res *res 1853 ) 1854 { 1855 if (args->setname != NULL) 1856 res->sr = metad_getsetbyname(args->setname, &res->status); 1857 else 1858 res->sr = metad_getsetbynum(args->setno, &res->status); 1859 } 1860 1861 void 1862 short_circuit_mngetset( 1863 mdrpc_getset_args *args, 1864 mdrpc_mngetset_res *res 1865 ) 1866 { 1867 md_set_record *sr; 1868 if (args->setname != NULL) 1869 sr = metad_getsetbyname(args->setname, &res->status); 1870 else 1871 sr = metad_getsetbynum(args->setno, &res->status); 1872 1873 if (MD_MNSET_REC(sr)) { 1874 res->mnsr = (struct md_mnset_record *)sr; 1875 } else { 1876 res->mnsr = NULL; 1877 } 1878 } 1879 1880 static int 1881 is_auto_take_set(char *setname, set_t setno) 1882 { 1883 if (setname != NULL) 1884 return (metad_isautotakebyname(setname)); 1885 else 1886 return (metad_isautotakebynum(setno)); 1887 } 1888 1889 /* 1890 * return the diskset record, and drive records. 1891 * If record is a MNdiskset record, then only the first md_set_record 1892 * bytes were copied from the daemon. 1893 */ 1894 int 1895 clnt_getset( 1896 char *hostname, 1897 char *setname, 1898 set_t setno, 1899 md_set_record **ret_sr, 1900 md_error_t *ep 1901 ) 1902 { 1903 CLIENT *clntp; 1904 mdrpc_getset_args *args; 1905 mdrpc_getset_2_args v2_args; 1906 mdrpc_getset_res res; 1907 int rval = -1; 1908 int version; 1909 1910 /* initialize */ 1911 mdclrerror(ep); 1912 (void) memset(&v2_args, 0, sizeof (v2_args)); 1913 (void) memset(&res, 0, sizeof (res)); 1914 1915 /* build args */ 1916 v2_args.rev = MD_METAD_ARGS_REV_1; 1917 args = &v2_args.mdrpc_getset_2_args_u.rev1; 1918 args->setname = setname; 1919 args->setno = setno; 1920 1921 /* do it */ 1922 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 1923 short_circuit_getset(args, &res); 1924 (void) mdstealerror(ep, &res.status); 1925 } else { 1926 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) { 1927 /* 1928 * This has to work during the boot up before the rpc.metad can 1929 * run. Check to see if we can handle this as a strictly local 1930 * diskset. 1931 */ 1932 if (is_auto_take_set(setname, setno)) { 1933 mdclrerror(ep); 1934 short_circuit_getset(args, &res); 1935 res.sr = setdup(res.sr); 1936 (void) mdstealerror(ep, &res.status); 1937 } else { 1938 return (-1); 1939 } 1940 } else { 1941 1942 /* 1943 * Check the client handle for the version 1944 * and invoke the appropriate version of the 1945 * remote procedure 1946 */ 1947 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 1948 1949 if (version == METAD_VERSION) { /* version 1 */ 1950 if (mdrpc_getset_1(args, &res, clntp) != RPC_SUCCESS) 1951 (void) mdrpcerror(ep, clntp, hostname, 1952 dgettext(TEXT_DOMAIN, "metad get set")); 1953 else 1954 (void) mdstealerror(ep, &res.status); 1955 } else { 1956 if (mdrpc_getset_2(&v2_args, &res, clntp) != 1957 RPC_SUCCESS) 1958 (void) mdrpcerror(ep, clntp, hostname, 1959 dgettext(TEXT_DOMAIN, "metad get set")); 1960 else 1961 (void) mdstealerror(ep, &res.status); 1962 } 1963 1964 metarpcclose(clntp); 1965 } 1966 } 1967 1968 if (mdisok(ep)) { 1969 rval = 0; 1970 if (ret_sr != NULL) 1971 *ret_sr = res.sr; 1972 else 1973 if (! md_in_daemon) 1974 xdr_free(xdr_mdrpc_getset_res, (char *)&res); 1975 } 1976 1977 return (rval); 1978 } 1979 1980 /* 1981 * return the multi-node diskset record, drive records and node records. 1982 */ 1983 int 1984 clnt_mngetset( 1985 char *hostname, 1986 char *setname, 1987 set_t setno, 1988 md_mnset_record **ret_mnsr, 1989 md_error_t *ep 1990 ) 1991 { 1992 CLIENT *clntp; 1993 mdrpc_getset_args *args; 1994 mdrpc_getset_2_args v2_args; 1995 mdrpc_mngetset_res res; 1996 int rval = -1; 1997 int version; 1998 1999 /* initialize */ 2000 mdclrerror(ep); 2001 (void) memset(&v2_args, 0, sizeof (v2_args)); 2002 (void) memset(&res, 0, sizeof (res)); 2003 2004 /* build args */ 2005 v2_args.rev = MD_METAD_ARGS_REV_1; 2006 args = &v2_args.mdrpc_getset_2_args_u.rev1; 2007 args->setname = setname; 2008 args->setno = setno; 2009 2010 /* do it */ 2011 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2012 short_circuit_mngetset(args, &res); 2013 (void) mdstealerror(ep, &res.status); 2014 } else { 2015 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2016 return (-1); 2017 2018 /* 2019 * Check the client handle for the version 2020 */ 2021 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2022 2023 /* 2024 * If the client is version 1, return error 2025 * otherwise, make the remote procedure call. 2026 */ 2027 if (version == METAD_VERSION) { /* version 1 */ 2028 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 2029 setno, hostname, NULL, setname); 2030 metarpcclose(clntp); 2031 return (-1); 2032 } else { 2033 if (mdrpc_mngetset_2(&v2_args, &res, clntp) 2034 != RPC_SUCCESS) 2035 (void) mdrpcerror(ep, clntp, hostname, 2036 dgettext(TEXT_DOMAIN, "metad mn get set")); 2037 else 2038 (void) mdstealerror(ep, &res.status); 2039 } 2040 2041 metarpcclose(clntp); 2042 } 2043 2044 /* If no ep error and no version mismatch - rpc call worked ok */ 2045 if (mdisok(ep)) { 2046 rval = 0; 2047 if (ret_mnsr != NULL) 2048 *ret_mnsr = res.mnsr; 2049 else 2050 if (! md_in_daemon) 2051 xdr_free(xdr_mdrpc_mngetset_res, (char *)&res); 2052 } 2053 2054 return (rval); 2055 } 2056 2057 /* 2058 * Set master nodeid and nodename in multi-node set record. 2059 */ 2060 int 2061 clnt_mnsetmaster( 2062 char *hostname, 2063 mdsetname_t *sp, 2064 md_node_nm_t master_nodenm, 2065 int master_nodeid, 2066 md_error_t *ep 2067 ) 2068 { 2069 CLIENT *clntp; 2070 mdrpc_mnsetmaster_args *args; 2071 mdrpc_mnsetmaster_2_args v2_args; 2072 mdrpc_generic_res res; 2073 int version; 2074 2075 /* initialize */ 2076 mdclrerror(ep); 2077 (void) memset(&v2_args, 0, sizeof (v2_args)); 2078 (void) memset(&res, 0, sizeof (res)); 2079 2080 /* build args */ 2081 v2_args.rev = MD_METAD_ARGS_REV_1; 2082 args = &v2_args.mdrpc_mnsetmaster_2_args_u.rev1; 2083 args->sp = sp; 2084 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2085 (void) strlcpy(args->master_nodenm, master_nodenm, MD_MAX_NODENAME); 2086 args->master_nodeid = master_nodeid; 2087 2088 /* do it */ 2089 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2090 return (-1); 2091 2092 /* 2093 * Check the client handle for the version 2094 */ 2095 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2096 2097 /* 2098 * If the client is version 1, return error 2099 * otherwise, make the remote procedure call. 2100 */ 2101 if (version == METAD_VERSION) { /* version 1 */ 2102 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 2103 sp->setno, hostname, NULL, sp->setname); 2104 metarpcclose(clntp); 2105 return (-1); 2106 } else { 2107 if (mdrpc_mnsetmaster_2(&v2_args, &res, clntp) != RPC_SUCCESS) 2108 (void) mdrpcerror(ep, clntp, hostname, 2109 dgettext(TEXT_DOMAIN, "metad multi-owner set master")); 2110 else 2111 (void) mdstealerror(ep, &res.status); 2112 } 2113 2114 metarpcclose(clntp); 2115 2116 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 2117 2118 if (! mdisok(ep)) 2119 return (-1); 2120 2121 return (0); 2122 } 2123 2124 /* 2125 * Get the MH timeout values. 2126 */ 2127 int 2128 clnt_gtimeout( 2129 char *hostname, 2130 mdsetname_t *sp, 2131 mhd_mhiargs_t *ret_mhiargs, 2132 md_error_t *ep 2133 ) 2134 { 2135 CLIENT *clntp; 2136 mdrpc_sp_args *args; 2137 mdrpc_sp_2_args v2_args; 2138 mdrpc_gtimeout_res res; 2139 int rval = -1; 2140 int version; 2141 2142 /* initialize */ 2143 mdclrerror(ep); 2144 (void) memset(&v2_args, 0, sizeof (v2_args)); 2145 (void) memset(&res, 0, sizeof (res)); 2146 2147 /* build args */ 2148 v2_args.rev = MD_METAD_ARGS_REV_1; 2149 args = &v2_args.mdrpc_sp_2_args_u.rev1; 2150 args->sp = sp; 2151 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2152 2153 /* do it */ 2154 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2155 int bool; 2156 bool = mdrpc_gtimeout_2_svc(&v2_args, &res, NULL); 2157 assert(bool == TRUE); 2158 (void) mdstealerror(ep, &res.status); 2159 } else { 2160 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2161 return (-1); 2162 2163 /* 2164 * Check the client handle for the version 2165 * and invoke the appropriate version of the 2166 * remote procedure 2167 */ 2168 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2169 2170 if (version == METAD_VERSION) { /* version 1 */ 2171 if (mdrpc_gtimeout_1(args, &res, clntp) != RPC_SUCCESS) 2172 (void) mdrpcerror(ep, clntp, hostname, 2173 dgettext(TEXT_DOMAIN, "metad get timeout")); 2174 else 2175 (void) mdstealerror(ep, &res.status); 2176 } else { 2177 if (mdrpc_gtimeout_2(&v2_args, &res, clntp) != 2178 RPC_SUCCESS) 2179 (void) mdrpcerror(ep, clntp, hostname, 2180 dgettext(TEXT_DOMAIN, "metad get timeout")); 2181 else 2182 (void) mdstealerror(ep, &res.status); 2183 } 2184 2185 metarpcclose(clntp); 2186 } 2187 2188 if (mdisok(ep)) { 2189 2190 /* do something with the results */ 2191 rval = 0; 2192 2193 /* copy md_mhiargs_t */ 2194 if (ret_mhiargs != NULL) 2195 *ret_mhiargs = *res.mhiargsp; 2196 } 2197 2198 xdr_free(xdr_mdrpc_gtimeout_res, (char *)&res); 2199 2200 return (rval); 2201 } 2202 2203 /* 2204 * get real hostname from remote host 2205 */ 2206 int 2207 clnt_hostname( 2208 char *hostname, 2209 char **ret_hostname, 2210 md_error_t *ep 2211 ) 2212 { 2213 CLIENT *clntp; 2214 mdrpc_null_args args; 2215 mdrpc_hostname_res res; 2216 int rval = -1; 2217 2218 /* initialize */ 2219 mdclrerror(ep); 2220 (void) memset(&args, 0, sizeof (args)); 2221 (void) memset(&res, 0, sizeof (res)); 2222 2223 /* build args */ 2224 args.cl_sk = NULL; 2225 2226 /* do it */ 2227 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2228 int bool; 2229 bool = mdrpc_hostname_1_svc(&args, &res, NULL); 2230 assert(bool == TRUE); 2231 (void) mdstealerror(ep, &res.status); 2232 } else { 2233 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2234 return (-1); 2235 2236 if (mdrpc_hostname_1(&args, &res, clntp) != RPC_SUCCESS) 2237 (void) mdrpcerror(ep, clntp, hostname, 2238 dgettext(TEXT_DOMAIN, "metad hostname")); 2239 else 2240 (void) mdstealerror(ep, &res.status); 2241 2242 metarpcclose(clntp); 2243 } 2244 2245 if (mdisok(ep)) { 2246 /* do something with the results */ 2247 rval = 0; 2248 2249 if (ret_hostname != NULL) 2250 *ret_hostname = Strdup(res.hostname); 2251 } 2252 2253 xdr_free(xdr_mdrpc_hostname_res, (char *)&res); 2254 2255 return (rval); 2256 } 2257 2258 /* 2259 * NULLPROC - just returns a response 2260 */ 2261 int 2262 clnt_nullproc( 2263 char *hostname, 2264 md_error_t *ep 2265 ) 2266 { 2267 CLIENT *clntp; 2268 2269 /* initialize */ 2270 mdclrerror(ep); 2271 2272 /* do it */ 2273 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2274 int bool; 2275 bool = mdrpc_nullproc_1_svc(NULL, ep, NULL); 2276 assert(bool == TRUE); 2277 } else { 2278 if ((clntp = metarpcopen(hostname, CL_DEF_TMO, ep)) == NULL) 2279 return (-1); 2280 2281 if (mdrpc_nullproc_1(NULL, ep, clntp) != RPC_SUCCESS) 2282 (void) mdrpcerror(ep, clntp, hostname, 2283 dgettext(TEXT_DOMAIN, "metad nullproc")); 2284 2285 metarpcclose(clntp); 2286 } 2287 2288 if (! mdisok(ep)) 2289 return (-1); 2290 2291 return (0); 2292 } 2293 2294 /* 2295 * does host own the set? 2296 */ 2297 int 2298 clnt_ownset( 2299 char *hostname, 2300 mdsetname_t *sp, 2301 int *ret_bool, 2302 md_error_t *ep 2303 ) 2304 { 2305 CLIENT *clntp; 2306 mdrpc_sp_args *args; 2307 mdrpc_sp_2_args v2_args; 2308 mdrpc_bool_res res; 2309 int rval = -1; 2310 int version; 2311 2312 /* initialize */ 2313 mdclrerror(ep); 2314 (void) memset(&v2_args, 0, sizeof (v2_args)); 2315 (void) memset(&res, 0, sizeof (res)); 2316 2317 /* build args */ 2318 v2_args.rev = MD_METAD_ARGS_REV_1; 2319 args = &v2_args.mdrpc_sp_2_args_u.rev1; 2320 args->sp = sp; 2321 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2322 2323 /* do it */ 2324 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2325 int bool; 2326 bool = mdrpc_ownset_2_svc(&v2_args, &res, NULL); 2327 assert(bool == TRUE); 2328 (void) mdstealerror(ep, &res.status); 2329 } else { 2330 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) { 2331 /* 2332 * This has to work in the code path from libpreen which is 2333 * running within fsck before the rpc.metad can run. Check 2334 * to see if we should handle this as an auto-take diskset. 2335 */ 2336 if (is_auto_take_set(sp->setname, sp->setno)) { 2337 /* Can't call mdrpc_ownset_2_svc since not in daemon */ 2338 mdclrerror(ep); 2339 if (s_ownset(sp->setno, ep)) 2340 res.value = TRUE; 2341 else 2342 res.value = FALSE; 2343 } else { 2344 return (-1); 2345 } 2346 2347 } else { 2348 2349 /* 2350 * Check the client handle for the version 2351 * and invoke the appropriate version of the 2352 * remote procedure 2353 */ 2354 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2355 2356 if (version == METAD_VERSION) { /* version 1 */ 2357 if (mdrpc_ownset_1(args, &res, clntp) != RPC_SUCCESS) 2358 (void) mdrpcerror(ep, clntp, hostname, 2359 dgettext(TEXT_DOMAIN, "metad own set")); 2360 else 2361 (void) mdstealerror(ep, &res.status); 2362 } else { 2363 if (mdrpc_ownset_2(&v2_args, &res, clntp) != 2364 RPC_SUCCESS) 2365 (void) mdrpcerror(ep, clntp, hostname, 2366 dgettext(TEXT_DOMAIN, "metad own set")); 2367 else 2368 (void) mdstealerror(ep, &res.status); 2369 } 2370 2371 metarpcclose(clntp); 2372 } 2373 } 2374 2375 if (mdisok(ep)) { 2376 /* do something with the results */ 2377 rval = 0; 2378 2379 if (ret_bool != NULL) 2380 *ret_bool = res.value; 2381 } 2382 2383 xdr_free(xdr_mdrpc_bool_res, (char *)&res); 2384 2385 return (rval); 2386 } 2387 2388 /* 2389 * Valid set name. 2390 */ 2391 int 2392 clnt_setnameok( 2393 char *hostname, 2394 mdsetname_t *sp, 2395 int *ret_bool, 2396 md_error_t *ep 2397 ) 2398 { 2399 CLIENT *clntp; 2400 mdrpc_sp_args *args; 2401 mdrpc_sp_2_args v2_args; 2402 mdrpc_bool_res res; 2403 int rval = -1; 2404 int version; 2405 2406 /* initialize */ 2407 mdclrerror(ep); 2408 (void) memset(&v2_args, 0, sizeof (v2_args)); 2409 (void) memset(&res, 0, sizeof (res)); 2410 2411 /* build args */ 2412 v2_args.rev = MD_METAD_ARGS_REV_1; 2413 args = &v2_args.mdrpc_sp_2_args_u.rev1; 2414 args->sp = sp; 2415 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2416 2417 /* do it */ 2418 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2419 int bool; 2420 bool = mdrpc_setnameok_2_svc(&v2_args, &res, NULL); 2421 assert(bool == TRUE); 2422 (void) mdstealerror(ep, &res.status); 2423 } else { 2424 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2425 return (-1); 2426 2427 /* 2428 * Check the client handle for the version 2429 * and invoke the appropriate version of the 2430 * remote procedure 2431 */ 2432 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2433 2434 if (version == METAD_VERSION) { /* version 1 */ 2435 if (mdrpc_setnameok_1(args, &res, clntp) != RPC_SUCCESS) 2436 (void) mdrpcerror(ep, clntp, hostname, 2437 dgettext(TEXT_DOMAIN, "metad setname ok")); 2438 else 2439 (void) mdstealerror(ep, &res.status); 2440 } else { 2441 if (mdrpc_setnameok_2(&v2_args, &res, clntp) != 2442 RPC_SUCCESS) 2443 (void) mdrpcerror(ep, clntp, hostname, 2444 dgettext(TEXT_DOMAIN, "metad setname ok")); 2445 else 2446 (void) mdstealerror(ep, &res.status); 2447 } 2448 2449 metarpcclose(clntp); 2450 } 2451 2452 if (mdisok(ep)) { 2453 /* do something with the results */ 2454 rval = 0; 2455 2456 if (ret_bool != NULL) 2457 *ret_bool = res.value; 2458 } 2459 2460 xdr_free(xdr_mdrpc_bool_res, (char *)&res); 2461 2462 return (rval); 2463 } 2464 2465 /* 2466 * Is set number in-use? 2467 */ 2468 int 2469 clnt_setnumbusy( 2470 char *hostname, 2471 set_t setno, 2472 int *ret_bool, 2473 md_error_t *ep 2474 ) 2475 { 2476 CLIENT *clntp; 2477 mdrpc_setno_args *args; 2478 mdrpc_setno_2_args v2_args; 2479 mdrpc_bool_res res; 2480 int rval = -1; 2481 int version; 2482 2483 /* initialize */ 2484 mdclrerror(ep); 2485 (void) memset(&v2_args, 0, sizeof (v2_args)); 2486 (void) memset(&res, 0, sizeof (res)); 2487 2488 /* build args */ 2489 v2_args.rev = MD_METAD_ARGS_REV_1; 2490 args = &v2_args.mdrpc_setno_2_args_u.rev1; 2491 args->setno = setno; 2492 args->cl_sk = NULL; 2493 2494 /* do it */ 2495 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2496 int bool; 2497 bool = mdrpc_setnumbusy_2_svc(&v2_args, &res, NULL); 2498 assert(bool == TRUE); 2499 (void) mdstealerror(ep, &res.status); 2500 } else { 2501 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2502 return (-1); 2503 2504 /* 2505 * Check the client handle for the version 2506 * and invoke the appropriate version of the 2507 * remote procedure 2508 */ 2509 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2510 2511 if (version == METAD_VERSION) { /* version 1 */ 2512 if (mdrpc_setnumbusy_1(args, &res, clntp) != 2513 RPC_SUCCESS) 2514 (void) mdrpcerror(ep, clntp, hostname, 2515 dgettext(TEXT_DOMAIN, "metad setnumber busy")); 2516 else 2517 (void) mdstealerror(ep, &res.status); 2518 } else { 2519 if (mdrpc_setnumbusy_2(&v2_args, &res, clntp) != 2520 RPC_SUCCESS) 2521 (void) mdrpcerror(ep, clntp, hostname, 2522 dgettext(TEXT_DOMAIN, "metad setnumber busy")); 2523 else 2524 (void) mdstealerror(ep, &res.status); 2525 } 2526 2527 metarpcclose(clntp); 2528 } 2529 2530 if (mdisok(ep)) { 2531 /* do something with the results */ 2532 rval = 0; 2533 2534 if (ret_bool != NULL) 2535 *ret_bool = res.value; 2536 } 2537 2538 xdr_free(xdr_mdrpc_bool_res, (char *)&res); 2539 2540 return (rval); 2541 } 2542 2543 /* 2544 * Set the timeout values used into the drive records. 2545 */ 2546 int 2547 clnt_stimeout( 2548 char *hostname, 2549 mdsetname_t *sp, 2550 mhd_mhiargs_t *mhiargsp, 2551 md_error_t *ep 2552 ) 2553 { 2554 CLIENT *clntp; 2555 mdrpc_stimeout_args *args; 2556 mdrpc_stimeout_2_args v2_args; 2557 mdrpc_generic_res res; 2558 int version; 2559 2560 /* initialize */ 2561 mdclrerror(ep); 2562 (void) memset(&v2_args, 0, sizeof (v2_args)); 2563 (void) memset(&res, 0, sizeof (res)); 2564 2565 /* build args */ 2566 v2_args.rev = MD_METAD_ARGS_REV_1; 2567 args = &v2_args.mdrpc_stimeout_2_args_u.rev1; 2568 args->sp = sp; 2569 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2570 args->mhiargsp = mhiargsp; 2571 2572 /* do it */ 2573 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2574 int bool; 2575 bool = mdrpc_stimeout_2_svc(&v2_args, &res, NULL); 2576 assert(bool == TRUE); 2577 (void) mdstealerror(ep, &res.status); 2578 } else { 2579 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2580 return (-1); 2581 2582 /* 2583 * Check the client handle for the version 2584 * and invoke the appropriate version of the 2585 * remote procedure 2586 */ 2587 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2588 2589 if (version == METAD_VERSION) { /* version 1 */ 2590 if (mdrpc_stimeout_1(args, &res, clntp) != RPC_SUCCESS) 2591 (void) mdrpcerror(ep, clntp, hostname, 2592 dgettext(TEXT_DOMAIN, "metad set timeout")); 2593 else 2594 (void) mdstealerror(ep, &res.status); 2595 } else { 2596 if (mdrpc_stimeout_2(&v2_args, &res, clntp) != 2597 RPC_SUCCESS) 2598 (void) mdrpcerror(ep, clntp, hostname, 2599 dgettext(TEXT_DOMAIN, "metad set timeout")); 2600 else 2601 (void) mdstealerror(ep, &res.status); 2602 } 2603 2604 metarpcclose(clntp); 2605 } 2606 2607 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 2608 2609 if (! mdisok(ep)) 2610 return (-1); 2611 2612 return (0); 2613 } 2614 2615 /* 2616 * update drive records 2617 */ 2618 int 2619 clnt_upd_dr_dbinfo( 2620 char *hostname, 2621 mdsetname_t *sp, 2622 md_drive_desc *dd, 2623 md_error_t *ep 2624 ) 2625 { 2626 CLIENT *clntp; 2627 mdrpc_drives_args v1_args; 2628 mdrpc_drives_2_args v2_args; 2629 mdrpc_drives_2_args_r1 *v21_args; 2630 mdrpc_generic_res res; 2631 int rval; 2632 int version; 2633 2634 /* initialize */ 2635 mdclrerror(ep); 2636 (void) memset(&v1_args, 0, sizeof (v1_args)); 2637 (void) memset(&v2_args, 0, sizeof (v2_args)); 2638 (void) memset(&res, 0, sizeof (res)); 2639 2640 /* build args */ 2641 v2_args.rev = MD_METAD_ARGS_REV_1; 2642 v21_args = &v2_args.mdrpc_drives_2_args_u.rev1; 2643 v21_args->sp = sp; 2644 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2645 v21_args->drivedescs = dd; 2646 2647 /* do it */ 2648 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2649 int bool; 2650 2651 /* 2652 * If the server is local, we call the v2 procedure 2653 */ 2654 bool = mdrpc_upd_dr_dbinfo_2_svc(&v2_args, &res, NULL); 2655 assert(bool == TRUE); 2656 (void) mdstealerror(ep, &res.status); 2657 } else { 2658 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2659 return (-1); 2660 2661 /* 2662 * Check the client handle for the version 2663 * and invoke the appropriate version of the 2664 * remote procedure 2665 */ 2666 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2667 2668 if (version == METAD_VERSION) { /* version 1 */ 2669 2670 alloc_olddrvdesc(&v1_args.drivedescs, dd); 2671 2672 /* build args */ 2673 v1_args.sp = sp; 2674 v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname); 2675 meta_conv_drvdesc_new2old(v1_args.drivedescs, dd); 2676 2677 rval = mdrpc_upd_dr_dbinfo_1(&v1_args, &res, clntp); 2678 2679 free_olddrvdesc(v1_args.drivedescs); 2680 2681 if (rval != RPC_SUCCESS) 2682 (void) mdrpcerror(ep, clntp, hostname, 2683 dgettext(TEXT_DOMAIN, 2684 "metad update drive dbinfo")); 2685 else 2686 (void) mdstealerror(ep, &res.status); 2687 } else { /* version 2 */ 2688 rval = mdrpc_upd_dr_dbinfo_2(&v2_args, &res, clntp); 2689 2690 if (rval != RPC_SUCCESS) 2691 (void) mdrpcerror(ep, clntp, hostname, 2692 dgettext(TEXT_DOMAIN, 2693 "metad update drive dbinfo")); 2694 else 2695 (void) mdstealerror(ep, &res.status); 2696 } 2697 2698 metarpcclose(clntp); 2699 } 2700 2701 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 2702 2703 if (! mdisok(ep)) 2704 return (-1); 2705 2706 return (0); 2707 } 2708 2709 /* 2710 * update dr_flags field of drive record. 2711 */ 2712 int 2713 clnt_upd_dr_flags( 2714 char *hostname, 2715 mdsetname_t *sp, 2716 md_drive_desc *dd, 2717 uint_t new_flags, 2718 md_error_t *ep 2719 ) 2720 { 2721 CLIENT *clntp; 2722 mdrpc_upd_dr_flags_args v1_args; 2723 mdrpc_upd_dr_flags_2_args v2_args; 2724 mdrpc_upd_dr_flags_2_args_r1 *v21_args; 2725 mdrpc_generic_res res; 2726 int rval; 2727 int version; 2728 2729 /* initialize */ 2730 mdclrerror(ep); 2731 (void) memset(&v1_args, 0, sizeof (v1_args)); 2732 (void) memset(&v2_args, 0, sizeof (v2_args)); 2733 (void) memset(&res, 0, sizeof (res)); 2734 2735 /* build args */ 2736 v2_args.rev = MD_METAD_ARGS_REV_1; 2737 v21_args = &v2_args.mdrpc_upd_dr_flags_2_args_u.rev1; 2738 v21_args->sp = sp; 2739 v21_args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2740 v21_args->drivedescs = dd; 2741 v21_args->new_flags = new_flags; 2742 2743 /* do it */ 2744 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2745 int bool; 2746 2747 /* 2748 * If the server is local, we call the v2 procedure 2749 */ 2750 bool = mdrpc_upd_dr_flags_2_svc(&v2_args, &res, NULL); 2751 assert(bool == TRUE); 2752 (void) mdstealerror(ep, &res.status); 2753 } else { 2754 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2755 return (-1); 2756 2757 /* 2758 * Check the client handle for the version 2759 * and invoke the appropriate version of the 2760 * remote procedure 2761 */ 2762 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2763 2764 if (version == METAD_VERSION) { /* version 1 */ 2765 2766 alloc_olddrvdesc(&v1_args.drivedescs, dd); 2767 2768 /* build args */ 2769 v1_args.sp = sp; 2770 v1_args.cl_sk = cl_get_setkey(sp->setno, sp->setname); 2771 meta_conv_drvdesc_new2old(v1_args.drivedescs, dd); 2772 v1_args.new_flags = new_flags; 2773 2774 rval = mdrpc_upd_dr_flags_1(&v1_args, &res, clntp); 2775 2776 free_olddrvdesc(v1_args.drivedescs); 2777 2778 if (rval != RPC_SUCCESS) 2779 (void) mdrpcerror(ep, clntp, hostname, 2780 dgettext(TEXT_DOMAIN, 2781 "metad update drive flags")); 2782 else 2783 (void) mdstealerror(ep, &res.status); 2784 } else { /* version 2 */ 2785 rval = mdrpc_upd_dr_flags_2(&v2_args, &res, clntp); 2786 2787 if (rval != RPC_SUCCESS) 2788 (void) mdrpcerror(ep, clntp, hostname, 2789 dgettext(TEXT_DOMAIN, 2790 "metad update drive flags")); 2791 else 2792 (void) mdstealerror(ep, &res.status); 2793 } 2794 2795 metarpcclose(clntp); 2796 } 2797 2798 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 2799 2800 if (! mdisok(ep)) { 2801 if (! mdanyrpcerror(ep)) 2802 return (-1); 2803 if (strcmp(mynode(), hostname) == 0) 2804 return (-1); 2805 mdclrerror(ep); 2806 } 2807 2808 return (0); 2809 } 2810 2811 /* 2812 * update set record flags 2813 * This replaces all of the sr_flags with the new_flags. It relies on the 2814 * caller to "do the right thing" to preserve the existing flags that should 2815 * not be reset. 2816 */ 2817 static int 2818 upd_sr_flags_common( 2819 char *hostname, 2820 mdsetname_t *sp, 2821 uint_t new_flags, 2822 md_error_t *ep 2823 ) 2824 { 2825 CLIENT *clntp; 2826 mdrpc_upd_sr_flags_args *args; 2827 mdrpc_upd_sr_flags_2_args v2_args; 2828 mdrpc_generic_res res; 2829 int version; 2830 2831 /* initialize */ 2832 mdclrerror(ep); 2833 (void) memset(&v2_args, 0, sizeof (v2_args)); 2834 (void) memset(&res, 0, sizeof (res)); 2835 2836 /* build args */ 2837 v2_args.rev = MD_METAD_ARGS_REV_1; 2838 args = &v2_args.mdrpc_upd_sr_flags_2_args_u.rev1; 2839 args->sp = sp; 2840 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 2841 2842 args->new_flags = new_flags; 2843 2844 /* do it */ 2845 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 2846 int bool; 2847 bool = mdrpc_upd_sr_flags_2_svc(&v2_args, &res, NULL); 2848 assert(bool == TRUE); 2849 (void) mdstealerror(ep, &res.status); 2850 } else { 2851 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 2852 return (-1); 2853 2854 /* 2855 * Check the client handle for the version 2856 * and invoke the appropriate version of the 2857 * remote procedure 2858 */ 2859 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 2860 2861 if (version == METAD_VERSION) { /* version 1 */ 2862 if (mdrpc_upd_sr_flags_1(args, &res, clntp) != 2863 RPC_SUCCESS) 2864 (void) mdrpcerror(ep, clntp, hostname, 2865 dgettext(TEXT_DOMAIN, "metad update set flags")); 2866 else 2867 (void) mdstealerror(ep, &res.status); 2868 } else { 2869 if (mdrpc_upd_sr_flags_2(&v2_args, &res, clntp) != 2870 RPC_SUCCESS) 2871 (void) mdrpcerror(ep, clntp, hostname, 2872 dgettext(TEXT_DOMAIN, "metad update set flags")); 2873 else 2874 (void) mdstealerror(ep, &res.status); 2875 } 2876 2877 metarpcclose(clntp); 2878 } 2879 2880 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 2881 2882 if (! mdisok(ep)) { 2883 if (! mdanyrpcerror(ep)) 2884 return (-1); 2885 if (strcmp(mynode(), hostname) == 0) 2886 return (-1); 2887 mdclrerror(ep); 2888 } 2889 2890 return (0); 2891 } 2892 2893 /* 2894 * Enable bits in the set record flags field. This just turns on the specified 2895 * bits and leaves the other bits alone. 2896 */ 2897 int 2898 clnt_enable_sr_flags( 2899 char *hostname, 2900 mdsetname_t *sp, 2901 uint_t flags, 2902 md_error_t *ep 2903 ) 2904 { 2905 uint_t new_flags; 2906 md_set_desc *sd; 2907 2908 mdclrerror(ep); 2909 2910 /* Get the flags from the current set */ 2911 if ((sd = metaget_setdesc(sp, ep)) == NULL) 2912 return (-1); 2913 2914 /* Turn on the specified bits */ 2915 new_flags = (sd->sd_flags | flags); 2916 2917 /* do it */ 2918 return (upd_sr_flags_common(hostname, sp, new_flags, ep)); 2919 } 2920 2921 /* 2922 * Disable bits in the set record flags field. This just turns off the 2923 * specified bits and leaves the other bits alone. 2924 */ 2925 int 2926 clnt_disable_sr_flags( 2927 char *hostname, 2928 mdsetname_t *sp, 2929 uint_t flags, 2930 md_error_t *ep 2931 ) 2932 { 2933 uint_t new_flags; 2934 md_set_desc *sd; 2935 2936 mdclrerror(ep); 2937 2938 /* Get the flags from the current set */ 2939 if ((sd = metaget_setdesc(sp, ep)) == NULL) 2940 return (-1); 2941 2942 /* Turn off the specified bits */ 2943 new_flags = (sd->sd_flags & ~flags); 2944 2945 /* do it */ 2946 return (upd_sr_flags_common(hostname, sp, new_flags, ep)); 2947 } 2948 2949 /* 2950 * Assign the flags as the new value(s) for the MD_SR_STATE_FLAGS within the 2951 * set record flags field. This actually can set any bits but only clears 2952 * the bits within the MD_SR_STATE_FLAGS subfield and leaves any other 2953 * bits turned on. It can be used to clear (state) and set bits all in one 2954 * rpc call. 2955 */ 2956 int 2957 clnt_upd_sr_flags( 2958 char *hostname, 2959 mdsetname_t *sp, 2960 uint_t flags, 2961 md_error_t *ep 2962 ) 2963 { 2964 uint_t new_flags; 2965 md_set_desc *sd; 2966 2967 mdclrerror(ep); 2968 2969 /* Get the flags from the current set */ 2970 if ((sd = metaget_setdesc(sp, ep)) == NULL) 2971 return (-1); 2972 2973 /* clear the existing state flags */ 2974 sd->sd_flags &= ~MD_SR_STATE_FLAGS; 2975 2976 /* Or in the new value */ 2977 new_flags = (sd->sd_flags | flags); 2978 2979 /* do it */ 2980 return (upd_sr_flags_common(hostname, sp, new_flags, ep)); 2981 } 2982 2983 md_setkey_t * 2984 cl_get_setkey(set_t setno, char *setname) 2985 { 2986 2987 if (my_cl_sk == NULL) { 2988 my_cl_sk = Zalloc(sizeof (md_setkey_t)); 2989 my_cl_sk->sk_setno = setno; 2990 my_cl_sk->sk_setname = Strdup(setname); 2991 my_cl_sk->sk_host = Strdup(mynode()); 2992 } else { 2993 my_cl_sk->sk_setno = setno; 2994 if (my_cl_sk->sk_setname != NULL) 2995 Free(my_cl_sk->sk_setname); 2996 my_cl_sk->sk_setname = Strdup(setname); 2997 } 2998 2999 return (my_cl_sk); 3000 } 3001 3002 void 3003 cl_set_setkey(md_setkey_t *cl_sk) 3004 { 3005 if ((cl_sk != NULL) && (my_cl_sk != NULL)) { 3006 assert(my_cl_sk->sk_setno == cl_sk->sk_setno); 3007 assert(strcmp(my_cl_sk->sk_setname, cl_sk->sk_setname) == 0); 3008 assert(strcmp(my_cl_sk->sk_host, cl_sk->sk_host) == 0); 3009 my_cl_sk->sk_key = cl_sk->sk_key; 3010 return; 3011 } 3012 3013 if (my_cl_sk != NULL) { 3014 if (my_cl_sk->sk_setname != NULL) 3015 Free(my_cl_sk->sk_setname); 3016 if (my_cl_sk->sk_host != NULL) 3017 Free(my_cl_sk->sk_host); 3018 Free(my_cl_sk); 3019 } 3020 3021 my_cl_sk = NULL; 3022 3023 /* get here, if set called before get */ 3024 if (cl_sk != NULL) { 3025 my_cl_sk = Zalloc(sizeof (md_setkey_t)); 3026 my_cl_sk->sk_host = Strdup(cl_sk->sk_host); 3027 my_cl_sk->sk_setno = cl_sk->sk_setno; 3028 my_cl_sk->sk_setname = Strdup(cl_sk->sk_setname); 3029 my_cl_sk->sk_key = cl_sk->sk_key; 3030 } 3031 } 3032 3033 /* 3034 * Unlock the set after operation is complete. 3035 */ 3036 int 3037 clnt_unlock_set( 3038 char *hostname, 3039 md_setkey_t *cl_sk, 3040 md_error_t *ep 3041 ) 3042 { 3043 CLIENT *clntp; 3044 mdrpc_null_args args; 3045 mdrpc_setlock_res res; 3046 3047 /* initialize */ 3048 mdclrerror(ep); 3049 (void) memset(&args, 0, sizeof (args)); 3050 (void) memset(&res, 0, sizeof (res)); 3051 3052 /* build args */ 3053 args.cl_sk = cl_sk; 3054 3055 /* do it */ 3056 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3057 int bool; 3058 bool = mdrpc_unlock_set_1_svc(&args, &res, NULL); 3059 assert(bool == TRUE); 3060 (void) mdstealerror(ep, &res.status); 3061 } else { 3062 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3063 return (-1); 3064 3065 if (mdrpc_unlock_set_1(&args, &res, clntp) != RPC_SUCCESS) 3066 (void) mdrpcerror(ep, clntp, hostname, 3067 dgettext(TEXT_DOMAIN, "metad unlock set")); 3068 else 3069 (void) mdstealerror(ep, &res.status); 3070 3071 metarpcclose(clntp); 3072 } 3073 3074 xdr_free(xdr_mdrpc_setlock_res, (char *)&res); 3075 3076 if (! mdisok(ep)) { 3077 if (! mdanyrpcerror(ep)) 3078 return (-1); 3079 if (strcmp(mynode(), hostname) == 0) 3080 return (-1); 3081 mdclrerror(ep); 3082 } 3083 3084 return (0); 3085 } 3086 3087 /* 3088 * Lock set so that only operators with valid keys are allowed in the daemon. 3089 */ 3090 int 3091 clnt_lock_set( 3092 char *hostname, 3093 mdsetname_t *sp, 3094 md_error_t *ep 3095 ) 3096 { 3097 CLIENT *clntp; 3098 mdrpc_null_args args; 3099 mdrpc_setlock_res res; 3100 3101 /* initialize */ 3102 mdclrerror(ep); 3103 (void) memset(&args, 0, sizeof (args)); 3104 (void) memset(&res, 0, sizeof (res)); 3105 3106 /* build args */ 3107 args.cl_sk = cl_get_setkey(sp->setno, sp->setname); 3108 3109 /* do it */ 3110 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3111 int bool; 3112 bool = mdrpc_lock_set_1_svc(&args, &res, NULL); 3113 assert(bool == TRUE); 3114 (void) mdstealerror(ep, &res.status); 3115 } else { 3116 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3117 return (-1); 3118 3119 if (mdrpc_lock_set_1(&args, &res, clntp) != RPC_SUCCESS) 3120 (void) mdrpcerror(ep, clntp, hostname, 3121 dgettext(TEXT_DOMAIN, "metad lock set")); 3122 else 3123 (void) mdstealerror(ep, &res.status); 3124 3125 metarpcclose(clntp); 3126 } 3127 3128 if (mdisok(ep)) 3129 cl_set_setkey(res.cl_sk); 3130 3131 xdr_free(xdr_mdrpc_setlock_res, (char *)&res); 3132 3133 if (! mdisok(ep)) { 3134 if (! mdanyrpcerror(ep)) 3135 return (-1); 3136 if (strcmp(mynode(), hostname) == 0) 3137 return (-1); 3138 mdclrerror(ep); 3139 } 3140 3141 return (0); 3142 } 3143 3144 /* 3145 * Add mediator hosts to disksets. 3146 */ 3147 int 3148 clnt_updmeds( 3149 char *hostname, 3150 mdsetname_t *sp, 3151 md_h_arr_t *medp, 3152 md_error_t *ep 3153 ) 3154 { 3155 CLIENT *clntp; 3156 mdrpc_updmeds_args *args; 3157 mdrpc_updmeds_2_args v2_args; 3158 mdrpc_generic_res res; 3159 int version; 3160 3161 /* initialize */ 3162 mdclrerror(ep); 3163 (void) memset(&v2_args, 0, sizeof (v2_args)); 3164 (void) memset(&res, 0, sizeof (res)); 3165 3166 /* build args */ 3167 v2_args.rev = MD_METAD_ARGS_REV_1; 3168 args = &v2_args.mdrpc_updmeds_2_args_u.rev1; 3169 args->sp = sp; 3170 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 3171 args->meds = *medp; /* structure assignment */ 3172 3173 /* do it */ 3174 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3175 int bool; 3176 bool = mdrpc_updmeds_2_svc(&v2_args, &res, NULL); 3177 assert(bool == TRUE); 3178 (void) mdstealerror(ep, &res.status); 3179 } else { 3180 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3181 return (-1); 3182 3183 /* 3184 * Check the client handle for the version 3185 * and invoke the appropriate version of the 3186 * remote procedure 3187 */ 3188 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3189 3190 if (version == METAD_VERSION) { /* version 1 */ 3191 if (mdrpc_updmeds_1(args, &res, clntp) != RPC_SUCCESS) 3192 (void) mdrpcerror(ep, clntp, hostname, 3193 dgettext(TEXT_DOMAIN, "metad add hosts")); 3194 else 3195 (void) mdstealerror(ep, &res.status); 3196 } else { 3197 if (mdrpc_updmeds_2(&v2_args, &res, clntp) != 3198 RPC_SUCCESS) 3199 (void) mdrpcerror(ep, clntp, hostname, 3200 dgettext(TEXT_DOMAIN, "metad add hosts")); 3201 else 3202 (void) mdstealerror(ep, &res.status); 3203 } 3204 3205 metarpcclose(clntp); 3206 } 3207 3208 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 3209 3210 if (! mdisok(ep)) 3211 return (-1); 3212 3213 return (0); 3214 } 3215 3216 /* 3217 * update nr_flags field of node records based 3218 * on given action. 3219 */ 3220 int 3221 clnt_upd_nr_flags( 3222 char *hostname, 3223 mdsetname_t *sp, 3224 md_mnnode_desc *nd, 3225 uint_t flag_action, 3226 uint_t flags, 3227 md_error_t *ep 3228 ) 3229 { 3230 CLIENT *clntp; 3231 mdrpc_upd_nr_flags_args *args; 3232 mdrpc_upd_nr_flags_2_args v2_args; 3233 mdrpc_generic_res res; 3234 int version; 3235 3236 /* initialize */ 3237 mdclrerror(ep); 3238 (void) memset(&v2_args, 0, sizeof (v2_args)); 3239 (void) memset(&res, 0, sizeof (res)); 3240 3241 /* build args */ 3242 v2_args.rev = MD_METAD_ARGS_REV_1; 3243 args = &v2_args.mdrpc_upd_nr_flags_2_args_u.rev1; 3244 args->sp = sp; 3245 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 3246 args->nodedescs = nd; 3247 args->flag_action = flag_action; 3248 args->flags = flags; 3249 3250 /* do it */ 3251 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3252 int bool; 3253 bool = mdrpc_upd_nr_flags_2_svc(&v2_args, &res, NULL); 3254 assert(bool == TRUE); 3255 (void) mdstealerror(ep, &res.status); 3256 } else { 3257 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3258 return (-1); 3259 3260 /* 3261 * Check the client handle for the version 3262 */ 3263 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3264 3265 /* 3266 * If the client is version 1, return error 3267 * otherwise, make the remote procedure call. 3268 */ 3269 if (version == METAD_VERSION) { /* version 1 */ 3270 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3271 sp->setno, hostname, NULL, sp->setname); 3272 metarpcclose(clntp); 3273 return (-1); 3274 } else { 3275 if (mdrpc_upd_nr_flags_2(&v2_args, &res, clntp) 3276 != RPC_SUCCESS) 3277 (void) mdrpcerror(ep, clntp, hostname, 3278 dgettext(TEXT_DOMAIN, 3279 "metad set node flags")); 3280 else 3281 (void) mdstealerror(ep, &res.status); 3282 } 3283 3284 metarpcclose(clntp); 3285 } 3286 3287 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 3288 3289 if (! mdisok(ep)) { 3290 if (! mdanyrpcerror(ep)) 3291 return (-1); 3292 if (strcmp(mynode(), hostname) == 0) 3293 return (-1); 3294 mdclrerror(ep); 3295 } 3296 3297 return (0); 3298 } 3299 3300 /* 3301 * Clear set locks for all MN disksets. 3302 * Used during reconfig cycle to recover from failed nodes. 3303 */ 3304 int 3305 clnt_clr_mnsetlock( 3306 char *hostname, 3307 md_error_t *ep 3308 ) 3309 { 3310 CLIENT *clntp; 3311 mdrpc_null_args args; 3312 mdrpc_generic_res res; 3313 int version; 3314 3315 /* initialize */ 3316 mdclrerror(ep); 3317 (void) memset(&args, 0, sizeof (args)); 3318 (void) memset(&res, 0, sizeof (res)); 3319 3320 /* do it */ 3321 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3322 return (-1); 3323 3324 /* 3325 * Check the client handle for the version 3326 */ 3327 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3328 3329 /* 3330 * If the client is version 1, return error 3331 * otherwise, make the remote procedure call. 3332 */ 3333 if (version == METAD_VERSION) { /* version 1 */ 3334 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3335 NULL, hostname, NULL, NULL); 3336 metarpcclose(clntp); 3337 return (-1); 3338 } else { 3339 if (mdrpc_clr_mnsetlock_2(&args, &res, clntp) != RPC_SUCCESS) 3340 (void) mdrpcerror(ep, clntp, hostname, 3341 dgettext(TEXT_DOMAIN, "metad clr mnsetlock")); 3342 else 3343 (void) mdstealerror(ep, &res.status); 3344 } 3345 3346 metarpcclose(clntp); 3347 3348 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 3349 3350 if (! mdisok(ep)) 3351 return (-1); 3352 3353 return (0); 3354 } 3355 3356 /* 3357 * Calls to suspend, resume or reinit the rpc.mdcommd daemon. 3358 * This allows a node to remotely suspend, reinit and resume the 3359 * rpc.mdcommd daemon on the given hostname node. Used by libmeta 3360 * to lock out class 1 messages (metainit, etc) on all nodes when running 3361 * metaset and metadb commands on this node. 3362 * 3363 * When suspending the commd, the suspend request will fail until all 3364 * messages have been drained from the rpc.mdcommd. This routine will 3365 * spin sending the suspend request until the rpc.mdcommd is drained 3366 * or until rpc.mdcommd returns a failure other than MDMNE_SET_NOT_DRAINED. 3367 * 3368 * Also used to send the rpc.mdcommd daemon a new nodelist by draining all 3369 * messages from the mdcommd and sending a reinit command to have mdcommd 3370 * get the new nodelist from rpc.metad. Used when nodelist is changed 3371 * during: 3372 * - addition or deletion of host from diskset 3373 * - join or withdrawal of host from diskset 3374 * - addition of first disk to diskset (joins all nodes) 3375 * - removal of last disk from diskset (withdraws all nodes) 3376 */ 3377 int 3378 clnt_mdcommdctl( 3379 char *hostname, 3380 int flag_action, 3381 mdsetname_t *sp, 3382 md_mn_msgclass_t class, 3383 uint_t flags, 3384 md_error_t *ep 3385 ) 3386 { 3387 CLIENT *clntp; 3388 mdrpc_mdcommdctl_args *args; 3389 mdrpc_mdcommdctl_2_args v2_args; 3390 mdrpc_generic_res res; 3391 int version; 3392 int suspend_spin = 0; 3393 3394 /* initialize */ 3395 mdclrerror(ep); 3396 (void) memset(&v2_args, 0, sizeof (v2_args)); 3397 (void) memset(&res, 0, sizeof (res)); 3398 3399 /* build args */ 3400 v2_args.rev = MD_METAD_ARGS_REV_1; 3401 args = &v2_args.mdrpc_mdcommdctl_2_args_u.rev1; 3402 args->flag_action = flag_action; 3403 args->setno = sp->setno; 3404 args->class = class; 3405 args->flags = flags; 3406 3407 /* do it */ 3408 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3409 int bool; 3410 /* 3411 * Call v2 procedure directly if rpc.metad on this node is 3412 * sending message to itself. 3413 */ 3414 if (flag_action == COMMDCTL_SUSPEND) { 3415 suspend_spin = 1; 3416 while (suspend_spin) { 3417 suspend_spin = 0; 3418 bool = mdrpc_mdcommdctl_2_svc(&v2_args, &res, 3419 NULL); 3420 assert(bool == TRUE); 3421 /* 3422 * If set not yet drained, wait a second 3423 * and try again. 3424 */ 3425 if (mdisdserror(&(res.status), 3426 MDE_DS_COMMDCTL_SUSPEND_NYD)) { 3427 /* Wait a second and try again */ 3428 mdclrerror(&(res.status)); 3429 (void) sleep(1); 3430 suspend_spin = 1; 3431 } 3432 } 3433 } else { 3434 bool = mdrpc_mdcommdctl_2_svc(&v2_args, &res, NULL); 3435 assert(bool == TRUE); 3436 } 3437 (void) mdstealerror(ep, &res.status); 3438 } else { 3439 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3440 return (-1); 3441 3442 /* 3443 * Check the client handle for the version 3444 */ 3445 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3446 3447 /* 3448 * If the client is version 1, return error 3449 * otherwise, make the remote procedure call. 3450 */ 3451 if (version == METAD_VERSION) { /* version 1 */ 3452 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3453 sp->setno, hostname, NULL, sp->setname); 3454 metarpcclose(clntp); 3455 return (-1); 3456 } 3457 3458 if (flag_action == COMMDCTL_SUSPEND) { 3459 suspend_spin = 1; 3460 while (suspend_spin) { 3461 suspend_spin = 0; 3462 if (mdrpc_mdcommdctl_2(&v2_args, &res, 3463 clntp) != RPC_SUCCESS) { 3464 (void) mdrpcerror(ep, clntp, 3465 hostname, 3466 dgettext(TEXT_DOMAIN, 3467 "metad commd control")); 3468 } else { 3469 /* 3470 * If set not yet drained, 3471 * wait a second and 3472 * and try again. 3473 */ 3474 if (mdisdserror(&(res.status), 3475 MDE_DS_COMMDCTL_SUSPEND_NYD)) { 3476 mdclrerror(&(res.status)); 3477 (void) sleep(1); 3478 suspend_spin = 1; 3479 } else { 3480 (void) mdstealerror(ep, 3481 &res.status); 3482 } 3483 } 3484 } 3485 } else { 3486 if (mdrpc_mdcommdctl_2(&v2_args, &res, clntp) 3487 != RPC_SUCCESS) 3488 (void) mdrpcerror(ep, clntp, hostname, 3489 dgettext(TEXT_DOMAIN, 3490 "metad commd control")); 3491 else 3492 (void) mdstealerror(ep, &res.status); 3493 } 3494 metarpcclose(clntp); 3495 } 3496 3497 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 3498 3499 if (! mdisok(ep)) { 3500 if (! mdanyrpcerror(ep)) 3501 return (-1); 3502 if (strcmp(mynode(), hostname) == 0) 3503 return (-1); 3504 mdclrerror(ep); 3505 } 3506 3507 return (0); 3508 } 3509 3510 /* 3511 * Is owner node stale? 3512 */ 3513 int 3514 clnt_mn_is_stale( 3515 char *hostname, 3516 mdsetname_t *sp, 3517 int *ret_bool, 3518 md_error_t *ep 3519 ) 3520 { 3521 CLIENT *clntp; 3522 mdrpc_setno_args *args; 3523 mdrpc_setno_2_args v2_args; 3524 mdrpc_bool_res res; 3525 int rval = -1; 3526 int version; 3527 3528 /* initialize */ 3529 mdclrerror(ep); 3530 (void) memset(&v2_args, 0, sizeof (v2_args)); 3531 (void) memset(&res, 0, sizeof (res)); 3532 3533 /* build args */ 3534 v2_args.rev = MD_METAD_ARGS_REV_1; 3535 args = &v2_args.mdrpc_setno_2_args_u.rev1; 3536 args->setno = sp->setno; 3537 3538 /* do it */ 3539 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3540 int bool; 3541 /* 3542 * Call v2 procedure directly if rpc.metad on this node is 3543 * sending message to itself. 3544 */ 3545 bool = mdrpc_mn_is_stale_2_svc(&v2_args, &res, NULL); 3546 assert(bool == TRUE); 3547 (void) mdstealerror(ep, &res.status); 3548 } else { 3549 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3550 return (-1); 3551 3552 /* 3553 * Check the client handle for the version 3554 * and invoke the appropriate version of the 3555 * remote procedure 3556 */ 3557 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3558 3559 /* 3560 * If the client is version 1, return error 3561 * otherwise, make the remote procedure call. 3562 */ 3563 if (version == METAD_VERSION) { /* version 1 */ 3564 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3565 sp->setno, hostname, NULL, sp->setname); 3566 metarpcclose(clntp); 3567 return (-1); 3568 } else { 3569 if (mdrpc_mn_is_stale_2(&v2_args, &res, clntp) != 3570 RPC_SUCCESS) 3571 (void) mdrpcerror(ep, clntp, hostname, 3572 dgettext(TEXT_DOMAIN, "metad mn is stale")); 3573 else 3574 (void) mdstealerror(ep, &res.status); 3575 } 3576 3577 metarpcclose(clntp); 3578 } 3579 3580 if (mdisok(ep)) { 3581 /* do something with the results */ 3582 rval = 0; 3583 3584 if (ret_bool != NULL) 3585 *ret_bool = res.value; 3586 } 3587 3588 xdr_free(xdr_mdrpc_bool_res, (char *)&res); 3589 3590 return (rval); 3591 } 3592 3593 /* 3594 * Free md_drive_desc linked list of drive descriptors that was alloc'd 3595 * from a call to the RPC routine clnt_getdrivedesc. Drive descriptors 3596 * are from another node. 3597 */ 3598 void 3599 free_rem_dd(md_drive_desc *dd) 3600 { 3601 mdrpc_getdrivedesc_res res; 3602 3603 /* 3604 * dummy up a result struct, to do a deep free of the dd. 3605 * (A deep free means that the xdr_free code will free the 3606 * linked list of drive descs.) 3607 */ 3608 (void) memset(&res, 0, sizeof (res)); 3609 res.dd = (struct md_drive_desc *)dd; 3610 xdr_free(xdr_mdrpc_getdrivedesc_res, (char *)&res); 3611 } 3612 3613 /* 3614 * Get a partially filled in drive desc from remote node. Used in MN 3615 * disksets during the reconfig cycle to get the diskset drive 3616 * information from another host in order to sync up all nodes. 3617 * Used when the drive record information isn't good enough 3618 * since the drive record doesn't give the name of 3619 * the drive, but just a key into that other node's nodespace. 3620 * Returned drive desc has the drive name filled in but no other strings 3621 * in the drivename structure. 3622 * 3623 * Returns a 0 if RPC was successful, 1 otherwise. 3624 */ 3625 int 3626 clnt_getdrivedesc( 3627 char *hostname, 3628 mdsetname_t *sp, 3629 md_drive_desc **ret_dd, 3630 md_error_t *ep 3631 ) 3632 { 3633 CLIENT *clntp; 3634 mdrpc_sp_args *args; 3635 mdrpc_sp_2_args v2_args; 3636 mdrpc_getdrivedesc_res res; 3637 int version; 3638 int rval = -1; 3639 3640 /* initialize */ 3641 mdclrerror(ep); 3642 (void) memset(&v2_args, 0, sizeof (v2_args)); 3643 (void) memset(&res, 0, sizeof (res)); 3644 3645 /* build args */ 3646 v2_args.rev = MD_METAD_ARGS_REV_1; 3647 args = &v2_args.mdrpc_sp_2_args_u.rev1; 3648 args->sp = sp; 3649 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 3650 3651 /* do it */ 3652 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3653 int bool; 3654 bool = mdrpc_getdrivedesc_2_svc(&v2_args, &res, NULL); 3655 assert(bool == TRUE); 3656 (void) mdstealerror(ep, &res.status); 3657 } else { 3658 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3659 return (-1); 3660 3661 /* 3662 * Check the client handle for the version 3663 */ 3664 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3665 3666 /* 3667 * If the client is version 1, return error 3668 * otherwise, make the remote procedure call. 3669 */ 3670 if (version == METAD_VERSION) { /* version 1 */ 3671 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3672 sp->setno, hostname, NULL, sp->setname); 3673 metarpcclose(clntp); 3674 return (-1); 3675 } else { 3676 if (mdrpc_getdrivedesc_2(&v2_args, &res, clntp) 3677 != RPC_SUCCESS) 3678 (void) mdrpcerror(ep, clntp, hostname, 3679 dgettext(TEXT_DOMAIN, 3680 "metad get drive desc set")); 3681 else 3682 (void) mdstealerror(ep, &res.status); 3683 } 3684 3685 metarpcclose(clntp); 3686 } 3687 3688 /* If no ep error and no version mismatch - rpc call worked ok */ 3689 if (mdisok(ep)) { 3690 rval = 0; 3691 if (ret_dd != NULL) 3692 *ret_dd = res.dd; 3693 else 3694 xdr_free(xdr_mdrpc_getdrivedesc_res, (char *)&res); 3695 } 3696 3697 return (rval); 3698 } 3699 3700 /* 3701 * update dr_flags field of drive record. 3702 * Also sync up genid of drive descriptors and make set 3703 * record and node records match the genid. 3704 * 3705 * Returns a 0 if RPC was successful, 1 otherwise. 3706 */ 3707 int 3708 clnt_upd_dr_reconfig( 3709 char *hostname, 3710 mdsetname_t *sp, 3711 md_drive_desc *dd, 3712 md_error_t *ep 3713 ) 3714 { 3715 CLIENT *clntp; 3716 mdrpc_upd_dr_flags_2_args v2_args; 3717 mdrpc_upd_dr_flags_2_args_r1 *v21_args; 3718 mdrpc_generic_res res; 3719 int rval; 3720 int version; 3721 3722 /* initialize */ 3723 mdclrerror(ep); 3724 (void) memset(&v2_args, 0, sizeof (v2_args)); 3725 (void) memset(&res, 0, sizeof (res)); 3726 3727 /* build args */ 3728 v2_args.rev = MD_METAD_ARGS_REV_1; 3729 v21_args = &v2_args.mdrpc_upd_dr_flags_2_args_u.rev1; 3730 v21_args->sp = sp; 3731 v21_args->drivedescs = dd; 3732 3733 /* do it */ 3734 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3735 int bool; 3736 3737 /* 3738 * If the server is local, we call the v2 procedure 3739 */ 3740 bool = mdrpc_upd_dr_reconfig_2_svc(&v2_args, &res, NULL); 3741 assert(bool == TRUE); 3742 (void) mdstealerror(ep, &res.status); 3743 } else { 3744 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3745 return (-1); 3746 3747 /* 3748 * Check the client handle for the version 3749 */ 3750 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3751 /* 3752 * If the client is version 1, return error 3753 * otherwise, make the remote procedure call. 3754 */ 3755 if (version == METAD_VERSION) { /* version 1 */ 3756 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3757 sp->setno, hostname, NULL, sp->setname); 3758 metarpcclose(clntp); 3759 return (-1); 3760 } else { 3761 rval = mdrpc_upd_dr_reconfig_2(&v2_args, &res, clntp); 3762 3763 if (rval != RPC_SUCCESS) 3764 (void) mdrpcerror(ep, clntp, hostname, 3765 dgettext(TEXT_DOMAIN, 3766 "metad update drive reconfig")); 3767 else 3768 (void) mdstealerror(ep, &res.status); 3769 } 3770 3771 metarpcclose(clntp); 3772 } 3773 3774 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 3775 3776 if (! mdisok(ep)) { 3777 if (! mdanyrpcerror(ep)) 3778 return (-1); 3779 if (strcmp(mynode(), hostname) == 0) 3780 return (-1); 3781 mdclrerror(ep); 3782 } 3783 3784 return (0); 3785 } 3786 3787 /* 3788 * Reset mirror owner(s) if mirror owner(s) is in the list of 3789 * node's specified in the array of nodeids. 3790 * This is called when a node has been deleted or withdrawn 3791 * from the diskset. 3792 */ 3793 int 3794 clnt_reset_mirror_owner( 3795 char *hostname, 3796 mdsetname_t *sp, 3797 int node_c, 3798 int node_id[], 3799 md_error_t *ep 3800 ) 3801 { 3802 CLIENT *clntp; 3803 mdrpc_nodeid_args *args; 3804 mdrpc_nodeid_2_args v2_args; 3805 mdrpc_generic_res res; 3806 int version; 3807 3808 /* initialize */ 3809 mdclrerror(ep); 3810 (void) memset(&v2_args, 0, sizeof (v2_args)); 3811 (void) memset(&res, 0, sizeof (res)); 3812 3813 /* build args */ 3814 v2_args.rev = MD_METAD_ARGS_REV_1; 3815 args = &v2_args.mdrpc_nodeid_2_args_u.rev1; 3816 args->sp = sp; 3817 args->cl_sk = cl_get_setkey(sp->setno, sp->setname); 3818 args->nodeid.nodeid_len = node_c; 3819 args->nodeid.nodeid_val = &node_id[0]; 3820 3821 /* do it */ 3822 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3823 int bool; 3824 bool = mdrpc_reset_mirror_owner_2_svc(&v2_args, &res, NULL); 3825 assert(bool == TRUE); 3826 (void) mdstealerror(ep, &res.status); 3827 } else { 3828 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3829 return (-1); 3830 3831 /* 3832 * Check the client handle for the version 3833 * and invoke the appropriate version of the 3834 * remote procedure 3835 */ 3836 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3837 3838 /* 3839 * If the client is version 1, return error 3840 * otherwise, make the remote procedure call. 3841 */ 3842 if (version == METAD_VERSION) { /* version 1 */ 3843 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3844 sp->setno, hostname, NULL, sp->setname); 3845 metarpcclose(clntp); 3846 return (-1); 3847 } else { 3848 if (mdrpc_reset_mirror_owner_2(&v2_args, &res, clntp) 3849 != RPC_SUCCESS) 3850 (void) mdrpcerror(ep, clntp, hostname, 3851 dgettext(TEXT_DOMAIN, 3852 "metad reset mirror owner")); 3853 else 3854 (void) mdstealerror(ep, &res.status); 3855 } 3856 3857 metarpcclose(clntp); 3858 } 3859 3860 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 3861 3862 if (! mdisok(ep)) 3863 return (-1); 3864 3865 return (0); 3866 } 3867 3868 /* 3869 * Call to suspend and resume I/O for given diskset(s). 3870 * This allows a node to remotely suspend and resume I/O on 3871 * a MN diskset. A diskset number of 0 represents all MN disksets. 3872 */ 3873 int 3874 clnt_mn_susp_res_io( 3875 char *hostname, 3876 set_t setno, 3877 int cmd, 3878 md_error_t *ep 3879 ) 3880 { 3881 CLIENT *clntp; 3882 mdrpc_mn_susp_res_io_args *args; 3883 mdrpc_mn_susp_res_io_2_args v2_args; 3884 mdrpc_generic_res res; 3885 int version; 3886 3887 /* initialize */ 3888 mdclrerror(ep); 3889 (void) memset(&v2_args, 0, sizeof (v2_args)); 3890 (void) memset(&res, 0, sizeof (res)); 3891 3892 /* build args */ 3893 v2_args.rev = MD_METAD_ARGS_REV_1; 3894 args = &v2_args.mdrpc_mn_susp_res_io_2_args_u.rev1; 3895 args->susp_res_cmd = cmd; 3896 args->susp_res_setno = setno; 3897 3898 /* do it */ 3899 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 3900 int bool; 3901 /* 3902 * Call v2 procedure directly if rpc.metad on this node is 3903 * sending message to itself. 3904 */ 3905 bool = mdrpc_mn_susp_res_io_2_svc(&v2_args, &res, NULL); 3906 assert(bool == TRUE); 3907 (void) mdstealerror(ep, &res.status); 3908 } else { 3909 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3910 return (-1); 3911 3912 /* 3913 * Check the client handle for the version 3914 */ 3915 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3916 3917 /* 3918 * If the client is version 1, return error 3919 * otherwise, make the remote procedure call. 3920 */ 3921 if (version == METAD_VERSION) { /* version 1 */ 3922 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 3923 setno, hostname, NULL, NULL); 3924 metarpcclose(clntp); 3925 return (-1); 3926 } else { 3927 if (mdrpc_mn_susp_res_io_2(&v2_args, &res, clntp) 3928 != RPC_SUCCESS) 3929 (void) mdrpcerror(ep, clntp, hostname, 3930 dgettext(TEXT_DOMAIN, 3931 "metad mn_susp_res_io control")); 3932 else 3933 (void) mdstealerror(ep, &res.status); 3934 } 3935 3936 metarpcclose(clntp); 3937 } 3938 3939 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 3940 3941 if (! mdisok(ep)) { 3942 if (! mdanyrpcerror(ep)) 3943 return (-1); 3944 if (strcmp(mynode(), hostname) == 0) 3945 return (-1); 3946 mdclrerror(ep); 3947 } 3948 3949 return (0); 3950 } 3951 3952 /* 3953 * Resnarf the set after the set has been imported 3954 * 3955 * We should never be making this procedure call 3956 * over the wire, it's sole purpose is to snarf 3957 * the imported set on the localhost. 3958 */ 3959 int 3960 clnt_resnarf_set( 3961 char *hostname, 3962 set_t setno, 3963 md_error_t *ep 3964 ) 3965 { 3966 CLIENT *clntp; 3967 mdrpc_setno_2_args args; 3968 mdrpc_generic_res res; 3969 int rval = -1; 3970 int version; 3971 3972 /* initialize */ 3973 mdclrerror(ep); 3974 (void) memset(&args, 0, sizeof (args)); 3975 (void) memset(&res, 0, sizeof (res)); 3976 3977 /* build args */ 3978 args.rev = MD_METAD_ARGS_REV_1; 3979 args.mdrpc_setno_2_args_u.rev1.setno = setno; 3980 args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL; 3981 3982 /* do it */ 3983 if (strcmp(mynode(), hostname) == 0) { 3984 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 3985 return (-1); 3986 3987 /* Check the client handle for the version */ 3988 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 3989 3990 /* If the client is version 1, return error */ 3991 if (version == METAD_VERSION) { /* version 1 */ 3992 (void) mddserror(ep, MDE_DS_CANTRESNARF, MD_SET_BAD, 3993 mynode(), NULL, NULL); 3994 } else { 3995 rval = mdrpc_resnarf_set_2(&args, &res, clntp); 3996 3997 if (rval != RPC_SUCCESS) 3998 (void) mdrpcerror(ep, clntp, hostname, 3999 dgettext(TEXT_DOMAIN, "metad resnarf set")); 4000 else 4001 (void) mdstealerror(ep, &res.status); 4002 } 4003 4004 metarpcclose(clntp); 4005 4006 } else { 4007 (void) mddserror(ep, MDE_DS_CANTRESNARF, MD_SET_BAD, 4008 mynode(), NULL, NULL); 4009 } 4010 4011 if (mdisok(ep)) 4012 rval = 0; 4013 4014 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 4015 4016 return (rval); 4017 } 4018 4019 /* 4020 * Call to start a resync for a given diskset. 4021 * Used when a node has been added to a diskset. 4022 * Should be called after rpc.mdcommd is resumed. 4023 */ 4024 int 4025 clnt_mn_mirror_resync_all( 4026 char *hostname, 4027 set_t setno, 4028 md_error_t *ep 4029 ) 4030 { 4031 CLIENT *clntp; 4032 mdrpc_setno_2_args args; 4033 mdrpc_generic_res res; 4034 int version; 4035 4036 /* initialize */ 4037 mdclrerror(ep); 4038 (void) memset(&args, 0, sizeof (args)); 4039 (void) memset(&res, 0, sizeof (res)); 4040 4041 /* build args */ 4042 args.rev = MD_METAD_ARGS_REV_1; 4043 args.mdrpc_setno_2_args_u.rev1.setno = setno; 4044 args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL; 4045 4046 /* do it */ 4047 if (md_in_daemon && strcmp(mynode(), hostname) == 0) { 4048 int bool; 4049 /* 4050 * Call v2 procedure directly if rpc.metad on this node is 4051 * sending message to itself. 4052 */ 4053 bool = mdrpc_mn_mirror_resync_all_2_svc(&args, &res, NULL); 4054 assert(bool == TRUE); 4055 (void) mdstealerror(ep, &res.status); 4056 } else { 4057 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 4058 return (-1); 4059 4060 /* 4061 * Check the client handle for the version 4062 */ 4063 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 4064 4065 /* 4066 * If the client is version 1, return error 4067 * otherwise, make the remote procedure call. 4068 */ 4069 if (version == METAD_VERSION) { /* version 1 */ 4070 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 4071 setno, hostname, NULL, NULL); 4072 metarpcclose(clntp); 4073 return (-1); 4074 } else { 4075 if (mdrpc_mn_mirror_resync_all_2(&args, &res, clntp) 4076 != RPC_SUCCESS) 4077 (void) mdrpcerror(ep, clntp, hostname, 4078 dgettext(TEXT_DOMAIN, 4079 "metad mn_mirror_resync_all")); 4080 else 4081 (void) mdstealerror(ep, &res.status); 4082 } 4083 4084 metarpcclose(clntp); 4085 } 4086 4087 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 4088 4089 if (! mdisok(ep)) { 4090 if (! mdanyrpcerror(ep)) 4091 return (-1); 4092 if (strcmp(mynode(), hostname) == 0) 4093 return (-1); 4094 mdclrerror(ep); 4095 } 4096 4097 return (0); 4098 } 4099 4100 /* 4101 * Call to update the ABR state for all soft partitions. 4102 * Used when a node has been added to a diskset. 4103 * Should be called after rpc.mdcommd is resumed. 4104 */ 4105 int 4106 clnt_mn_sp_update_abr( 4107 char *hostname, 4108 set_t setno, 4109 md_error_t *ep 4110 ) 4111 { 4112 CLIENT *clntp; 4113 mdrpc_setno_2_args args; 4114 mdrpc_generic_res res; 4115 int version; 4116 4117 /* initialize */ 4118 mdclrerror(ep); 4119 (void) memset(&args, 0, sizeof (args)); 4120 (void) memset(&res, 0, sizeof (res)); 4121 4122 /* build args */ 4123 args.rev = MD_METAD_ARGS_REV_1; 4124 args.mdrpc_setno_2_args_u.rev1.setno = setno; 4125 args.mdrpc_setno_2_args_u.rev1.cl_sk = NULL; 4126 4127 /* 4128 * No need to call function if adding local node as ABR cannot 4129 * be set. 4130 */ 4131 if (strcmp(mynode(), hostname) != 0) { 4132 if ((clntp = metarpcopen(hostname, CL_LONG_TMO, ep)) == NULL) 4133 return (-1); 4134 4135 /* 4136 * Check the client handle for the version 4137 */ 4138 CLNT_CONTROL(clntp, CLGET_VERS, (char *)&version); 4139 4140 /* 4141 * If the client is version 1, return error 4142 * otherwise, make the remote procedure call. 4143 */ 4144 if (version == METAD_VERSION) { /* version 1 */ 4145 (void) mddserror(ep, MDE_DS_RPCVERSMISMATCH, 4146 setno, hostname, NULL, NULL); 4147 metarpcclose(clntp); 4148 return (-1); 4149 } else { 4150 if (mdrpc_mn_sp_update_abr_2(&args, &res, clntp) 4151 != RPC_SUCCESS) 4152 (void) mdrpcerror(ep, clntp, hostname, 4153 dgettext(TEXT_DOMAIN, 4154 "metad mn_sp_update_abr")); 4155 else 4156 (void) mdstealerror(ep, &res.status); 4157 } 4158 4159 metarpcclose(clntp); 4160 } 4161 4162 xdr_free(xdr_mdrpc_generic_res, (char *)&res); 4163 4164 if (! mdisok(ep)) { 4165 if (! mdanyrpcerror(ep)) 4166 return (-1); 4167 mdclrerror(ep); 4168 } 4169 4170 return (0); 4171 } 4172