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