1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Driver for Virtual Disk. 30 */ 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/buf.h> 34 #include <sys/conf.h> 35 #include <sys/user.h> 36 #include <sys/uio.h> 37 #include <sys/proc.h> 38 #include <sys/t_lock.h> 39 #include <sys/dkio.h> 40 #include <sys/kmem.h> 41 #include <sys/utsname.h> 42 #include <sys/debug.h> 43 #include <sys/sysmacros.h> 44 #include <sys/types.h> 45 #include <sys/mkdev.h> 46 #include <sys/vtoc.h> 47 #include <sys/efi_partition.h> 48 #include <sys/open.h> 49 #include <sys/file.h> 50 #include <sys/ddi.h> 51 #include <sys/sunddi.h> 52 #include <sys/lvm/mdmn_commd.h> 53 54 #include <sys/lvm/mdvar.h> 55 #include <sys/lvm/md_rename.h> 56 #include <sys/lvm/md_names.h> 57 #include <sys/lvm/md_hotspares.h> 58 59 extern md_ops_t **md_ops; 60 extern unit_t md_nunits; 61 extern set_t md_nsets; 62 extern int md_nmedh; 63 extern md_set_t md_set[]; 64 extern md_set_io_t md_set_io[]; 65 extern int md_status; 66 extern int md_ioctl_cnt; 67 extern int md_in_upgrade; 68 extern major_t md_major; 69 70 /* md.c */ 71 extern kmutex_t md_mx; 72 extern kcondvar_t md_cv; 73 74 /* md_hotspares.c */ 75 extern hot_spare_pool_t *find_hot_spare_pool(set_t setno, int hsp_id); 76 77 /* md_med.c */ 78 extern int med_addr_tab_nents; 79 extern int med_get_t_size_ioctl(mddb_med_t_parm_t *tpp, int mode); 80 extern int med_get_t_ioctl(mddb_med_t_parm_t *tpp, int mode); 81 extern int med_set_t_ioctl(mddb_med_t_parm_t *tpp, int mode); 82 extern unit_t md_get_nextunit(set_t setno); 83 84 static int md_mn_commd_present; 85 86 /* md_mddb.c */ 87 extern mddb_set_t *mddb_setenter(set_t setno, int flag, int *errorcodep); 88 extern void mddb_setexit(mddb_set_t *s); 89 extern md_krwlock_t nm_lock; 90 91 /* 92 * md_mn_is_commd_present: 93 * ---------------------- 94 * Determine if commd is running on this node. 95 * 96 * Returns: 97 * 1 if commd has been started 98 * 0 if commd has not been started or has exited 99 */ 100 int 101 md_mn_is_commd_present(void) 102 { 103 return (md_mn_commd_present ? 1 : 0); 104 } 105 106 /* 107 * md_mn_clear_commd_present: 108 * ------------------------- 109 * Clear the commd_present flag. Called only from a CPR request to suspend / 110 * terminate a resync thread. We clear the md_mn_commd_present flag so that 111 * any RPC request that was in transit can complete with a failure and _not_ 112 * result in an unexpected system panic. 113 */ 114 void 115 md_mn_clear_commd_present() 116 { 117 md_mn_commd_present = 0; 118 } 119 120 static int 121 get_lb_inittime_ioctl( 122 mddb_config_t *cp 123 ) 124 { 125 set_t setno = cp->c_setno; 126 int err; 127 mddb_set_t *s; 128 129 if ((s = mddb_setenter(setno, MDDB_MUSTEXIST, &err)) == NULL) 130 return (-1); 131 132 if (s->s_lbp == NULL) { 133 mddb_setexit(s); 134 return (-1); 135 } 136 137 cp->c_timestamp = s->s_lbp->lb_inittime; 138 139 mddb_setexit(s); 140 return (0); 141 } 142 143 static int 144 setnm_ioctl(mdnm_params_t *nm, int mode) 145 { 146 char *name, *minorname = NULL; 147 side_t side; 148 int err = 0; 149 void *devid = NULL; 150 int devid_sz; 151 152 /* 153 * Don't allow addition of new names to namespace during upgrade. 154 */ 155 if (MD_UPGRADE) { 156 return (EAGAIN); 157 } 158 159 mdclrerror(&nm->mde); 160 161 if ((mode & FWRITE) == 0) 162 return (EACCES); 163 164 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 165 return (0); 166 167 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 168 return (ENODEV); 169 170 if (md_get_setstatus(nm->setno) & MD_SET_STALE) 171 return (mdmddberror(&nm->mde, MDE_DB_STALE, NODEV32, 172 nm->setno)); 173 174 name = kmem_alloc(MAXPATHLEN, KM_SLEEP); 175 176 err = ddi_copyin((caddr_t)(uintptr_t)nm->devname, name, 177 (size_t)nm->devname_len, mode); 178 if (err) { 179 err = EFAULT; 180 goto out; 181 } 182 183 if (nm->imp_flag) { 184 if ((nm->devid == NULL) || (nm->minorname == NULL)) { 185 err = EINVAL; 186 goto out; 187 } 188 if (nm->devid) { 189 devid_sz = nm->devid_size; 190 devid = kmem_zalloc(devid_sz, KM_SLEEP); 191 err = ddi_copyin((caddr_t)(uintptr_t)nm->devid, 192 devid, devid_sz, mode); 193 if (err) { 194 err = EFAULT; 195 goto out; 196 } 197 } 198 if (nm->minorname) { 199 if (nm->minorname_len > MAXPATHLEN) { 200 err = EINVAL; 201 goto out; 202 } 203 minorname = kmem_zalloc(nm->minorname_len, KM_SLEEP); 204 err = ddi_copyin((caddr_t)(uintptr_t)nm->minorname, 205 minorname, (size_t)nm->minorname_len, mode); 206 if (err) { 207 err = EFAULT; 208 goto out; 209 } 210 } 211 } 212 213 if (nm->side == -1) 214 side = mddb_getsidenum(nm->setno); 215 else 216 side = nm->side; 217 218 if (strcmp(nm->drvnm, "") == 0) { 219 char *drvnm; 220 drvnm = ddi_major_to_name(nm->major); 221 (void) strncpy(nm->drvnm, drvnm, sizeof (nm->drvnm)); 222 } 223 224 nm->key = md_setdevname(nm->setno, side, nm->key, nm->drvnm, 225 nm->mnum, name, nm->imp_flag, (ddi_devid_t)devid, minorname, 226 0, &nm->mde); 227 /* 228 * If we got an error from md_setdevname & md_setdevname did not 229 * set the error code, we'll default to MDE_DB_NOSPACE. 230 */ 231 if ((((int)nm->key) < 0) && mdisok(&nm->mde)) { 232 err = mdmddberror(&nm->mde, MDE_DB_NOSPACE, NODEV32, nm->setno); 233 goto out; 234 } 235 236 out: 237 kmem_free(name, MAXPATHLEN); 238 if (devid) { 239 kmem_free(devid, devid_sz); 240 } 241 if (minorname) 242 kmem_free(minorname, nm->minorname_len); 243 return (err); 244 } 245 246 static int 247 getnm_ioctl( 248 mdnm_params_t *nm, 249 int mode 250 ) 251 { 252 char *name; 253 side_t side; 254 md_dev64_t dev = NODEV64; 255 mdc_unit_t *un; 256 uint_t id; 257 char *setname; 258 int err = 0; 259 260 mdclrerror(&nm->mde); 261 262 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 263 return (0); 264 265 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 266 return (ENODEV); 267 268 269 name = kmem_alloc(MAXPATHLEN, KM_SLEEP); 270 271 if (nm->side == -1) 272 side = mddb_getsidenum(nm->setno); 273 else 274 side = nm->side; 275 276 if (nm->drvnm[0] == '\0') { 277 char *drvnm; 278 279 if (MD_UPGRADE) 280 drvnm = md_targ_major_to_name(nm->major); 281 else 282 drvnm = ddi_major_to_name(nm->major); 283 if (drvnm != NULL) 284 (void) strncpy(nm->drvnm, drvnm, sizeof (nm->drvnm)); 285 } 286 287 if (nm->drvnm[0] != '\0') { 288 if (MD_UPGRADE) 289 dev = md_makedevice(md_targ_name_to_major(nm->drvnm), 290 nm->mnum); 291 else 292 dev = md_makedevice(ddi_name_to_major(nm->drvnm), 293 nm->mnum); 294 } 295 296 /* 297 * With the introduction of friendly names, all friendly named 298 * metadevices will have an entry in the name space. However, 299 * systems upgraded from pre-friendly name to a friendly name 300 * release won't have name space entries for pre-friendly name 301 * top level metadevices. 302 * 303 * So we search the name space for the our entry with either the 304 * given dev_t or key. If we can't find the entry, we'll try the 305 * un array to get information for our target metadevice. Note 306 * we only use the un array when searching by dev_t since a 307 * key implies an existing device which should have been 308 * found in the name space with the call md_getdevname. 309 */ 310 if (md_getdevname(nm->setno, side, nm->key, dev, name, 311 MAXPATHLEN) == 0) { 312 err = md_getnment(nm->setno, side, nm->key, dev, nm->drvnm, 313 sizeof (nm->drvnm), &nm->major, &nm->mnum, &nm->retkey); 314 if (err) { 315 if (err < 0) 316 err = EINVAL; 317 goto out; 318 } 319 } else { 320 if ((nm->key != MD_KEYWILD) || 321 (MD_UNIT(nm->mnum) == NULL)) { 322 err = ENOENT; 323 goto out; 324 } 325 326 /* 327 * We're here because the mnum is of a pre-friendly 328 * name device. Make sure the major value is for 329 * metadevices. 330 */ 331 if (nm->major != md_major) { 332 err = ENOENT; 333 goto out; 334 } 335 336 /* 337 * get the unit number and setname to construct the 338 * fully qualified name for the metadevice. 339 */ 340 un = MD_UNIT(nm->mnum); 341 id = MD_MIN2UNIT(un->un_self_id); 342 if (nm->setno != MD_LOCAL_SET) { 343 setname = mddb_getsetname(nm->setno); 344 (void) snprintf(name, MAXPATHLEN, 345 "/dev/md/%s/dsk/d%u", setname, id); 346 } else { 347 (void) snprintf(name, MAXPATHLEN, 348 "/dev/md/dsk/d%u", id); 349 } 350 } 351 352 err = ddi_copyout(name, (caddr_t)(uintptr_t)nm->devname, 353 strlen(name) + 1, mode); 354 if (err) { 355 err = EFAULT; 356 goto out; 357 } 358 359 out: 360 kmem_free(name, MAXPATHLEN); 361 return (err); 362 } 363 364 static int 365 gethspnm_ioctl( 366 mdhspnm_params_t *nm, 367 int mode 368 ) 369 { 370 char *name; 371 char *tmpname; 372 char *setname = NULL; 373 side_t side; 374 hot_spare_pool_t *hsp = NULL; 375 mdkey_t key = MD_KEYWILD; 376 int err = 0; 377 378 mdclrerror(&nm->mde); 379 380 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 381 return (0); 382 383 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 384 return (ENODEV); 385 386 name = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 387 388 if (nm->side == -1) 389 side = mddb_getsidenum(nm->setno); 390 else 391 side = nm->side; 392 393 /* 394 * Get the key from input hspid, use different macros 395 * since the hspid could be either a FN or pre-FN hspid. 396 */ 397 if (nm->hspid != MD_HSPID_WILD) { 398 if (HSP_ID_IS_FN(nm->hspid)) 399 key = HSP_ID_TO_KEY(nm->hspid); 400 else 401 key = HSP_ID(nm->hspid); 402 } 403 404 /* 405 * Get the input name if we're searching by hsp name. Check 406 * that the input name length is less than MAXPATHLEN. 407 */ 408 if ((nm->hspid == MD_HSPID_WILD) && 409 (nm->hspname_len <= MAXPATHLEN)) { 410 err = ddi_copyin((caddr_t)(uintptr_t)nm->hspname, 411 name, (sizeof (char)) * nm->hspname_len, mode); 412 413 /* Stop if ddi_copyin failed. */ 414 if (err) { 415 err = EFAULT; 416 goto out; 417 } 418 } 419 420 /* Must have either a valid hspid or a name to continue */ 421 if ((nm->hspid == MD_HSPID_WILD) && (name[0] == '\0')) { 422 err = EINVAL; 423 goto out; 424 } 425 426 /* 427 * Try to find the hsp namespace entry corresponds to either 428 * the given hspid or name. If we can't find it, the hsp maybe 429 * a pre-friendly name hsp so we'll try to find it in the 430 * s_hsp array. 431 */ 432 if ((nm->hspid == MD_HSPID_WILD) || (HSP_ID_IS_FN(nm->hspid))) { 433 434 if (md_gethspinfo(nm->setno, side, key, nm->drvnm, 435 &nm->ret_hspid, name) != 0) { 436 /* 437 * If we were given a key for a FN hsp and 438 * couldn't find its entry, simply errored 439 * out. 440 */ 441 if (HSP_ID_IS_FN(nm->hspid)) { 442 err = ENOENT; 443 goto out; 444 } 445 446 /* 447 * Since md_gethspinfo failed and the hspid is 448 * not a FN hspid, we must have a name for a 449 * pre-FN hotspare pool 450 */ 451 if (name[0] == '\0') { 452 err = EINVAL; 453 goto out; 454 } 455 456 tmpname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 457 if (nm->setno != MD_LOCAL_SET) 458 setname = mddb_getsetname(nm->setno); 459 460 hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp; 461 while (hsp != NULL) { 462 /* Only use the pre-friendly name hsp */ 463 if (!(hsp->hsp_revision & MD_FN_META_DEV)) { 464 465 if (setname != NULL) { 466 (void) snprintf(tmpname, 467 MAXPATHLEN, 468 "%s/hsp%03u", setname, 469 HSP_ID(hsp->hsp_self_id)); 470 } else { 471 (void) snprintf(tmpname, 472 MAXPATHLEN, "hsp%03u", 473 HSP_ID(hsp->hsp_self_id)); 474 } 475 476 if (strcmp(name, tmpname) == 0) 477 break; 478 } 479 480 hsp = hsp->hsp_next; 481 } 482 kmem_free(tmpname, MAXPATHLEN); 483 484 if (hsp == NULL) { 485 err = ENOENT; 486 goto out; 487 } 488 489 /* Return hsp_self_id */ 490 nm->ret_hspid = hsp->hsp_self_id; 491 } 492 493 } else { 494 /* 495 * We have a hspid for a pre-FN hotspare pool. Let's 496 * try to find the matching hsp using the given 497 * hspid. 498 */ 499 if (nm->hspid == MD_HSPID_WILD) { 500 err = ENOENT; 501 goto out; 502 } 503 504 hsp = (hot_spare_pool_t *)md_set[nm->setno].s_hsp; 505 while (hsp != NULL) { 506 if (hsp->hsp_self_id == nm->hspid) 507 break; 508 hsp = hsp->hsp_next; 509 } 510 511 if (hsp == NULL) { 512 err = ENOENT; 513 goto out; 514 } 515 516 /* Prepare a name to return */ 517 if (nm->setno != MD_LOCAL_SET) 518 setname = mddb_getsetname(nm->setno); 519 520 if (setname != NULL) { 521 (void) snprintf(name, MAXPATHLEN, "%s/hsp%03u", 522 setname, HSP_ID(hsp->hsp_self_id)); 523 } else { 524 (void) snprintf(name, MAXPATHLEN, "hsp%03u", 525 HSP_ID(hsp->hsp_self_id)); 526 } 527 528 nm->ret_hspid = hsp->hsp_self_id; 529 } 530 531 if (nm->hspid != MD_HSPID_WILD) { 532 if ((strlen(name) + 1) > nm->hspname_len) { 533 err = EINVAL; 534 goto out; 535 } 536 err = ddi_copyout(name, (caddr_t) 537 (uintptr_t)nm->hspname, strlen(name)+1, mode); 538 } 539 540 if (err) { 541 if (err < 0) 542 err = EINVAL; 543 } 544 545 out: 546 kmem_free(name, MAXPATHLEN); 547 return (err); 548 } 549 550 551 /*ARGSUSED*/ 552 static int 553 update_loc_namespace_ioctl( 554 mdnm_params_t *nm, 555 char *dname, 556 char *pname, 557 int mode 558 ) 559 { 560 561 side_t side; 562 563 mdclrerror(&nm->mde); 564 565 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 566 return (0); 567 568 if (MD_MNSET_SETNO(nm->setno)) 569 return (0); 570 571 if ((md_get_setstatus(nm->setno) & MD_SET_STALE)) 572 return (0); 573 574 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 575 return (ENODEV); 576 577 if (nm->side == -1) 578 side = mddb_getsidenum(nm->setno); 579 else 580 side = nm->side; 581 582 return (md_update_locator_namespace(nm->setno, side, dname, 583 pname, nm->devt)); 584 } 585 586 /*ARGSUSED*/ 587 static int 588 update_namespace_did_ioctl( 589 mdnm_params_t *nm, 590 int mode 591 ) 592 { 593 side_t side; 594 595 mdclrerror(&nm->mde); 596 597 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 598 return (0); 599 600 if (MD_MNSET_SETNO(nm->setno)) 601 return (0); 602 603 if ((md_get_setstatus(nm->setno) & MD_SET_STALE)) 604 return (0); 605 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 606 return (ENODEV); 607 if (nm->side == -1) 608 side = mddb_getsidenum(nm->setno); 609 else 610 side = nm->side; 611 612 return (md_update_namespace_did(nm->setno, side, nm->key, &nm->mde)); 613 } 614 /*ARGSUSED*/ 615 static int 616 update_namespace_ioctl( 617 mdnm_params_t *nm, 618 char *dname, 619 char *pname, 620 int mode 621 ) 622 { 623 side_t side; 624 625 mdclrerror(&nm->mde); 626 627 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 628 return (0); 629 630 if (MD_MNSET_SETNO(nm->setno)) 631 return (0); 632 633 if ((md_get_setstatus(nm->setno) & MD_SET_STALE)) 634 return (0); 635 636 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 637 return (ENODEV); 638 639 if (nm->side == -1) 640 side = mddb_getsidenum(nm->setno); 641 else 642 side = nm->side; 643 644 return (md_update_namespace(nm->setno, side, nm->key, 645 dname, pname, nm->mnum)); 646 647 } 648 649 /*ARGSUSED*/ 650 static int 651 getnextkey_ioctl( 652 mdnm_params_t *nm, 653 int mode 654 ) 655 { 656 side_t side; 657 658 mdclrerror(&nm->mde); 659 660 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 661 return (0); 662 663 if (nm->setno >= md_nsets) 664 return (EINVAL); 665 666 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 667 return (ENODEV); 668 669 if (nm->side == -1) 670 side = mddb_getsidenum(nm->setno); 671 else 672 side = nm->side; 673 674 nm->key = md_getnextkey(nm->setno, side, nm->key, &nm->ref_count); 675 return (0); 676 } 677 678 /*ARGSUSED*/ 679 static int 680 remnm_ioctl(mdnm_params_t *nm, int mode) 681 { 682 side_t side; 683 684 mdclrerror(&nm->mde); 685 686 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 687 return (0); 688 689 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 690 return (ENODEV); 691 692 if (nm->side == -1) 693 side = mddb_getsidenum(nm->setno); 694 else 695 side = nm->side; 696 697 return (md_remdevname(nm->setno, side, nm->key)); 698 } 699 700 701 /*ARGSUSED*/ 702 static int 703 getdrvnm_ioctl(md_dev64_t dev, md_i_driverinfo_t *di, int mode) 704 { 705 mdi_unit_t *ui; 706 minor_t mnum = di->mnum; 707 set_t setno = MD_MIN2SET(mnum); 708 709 mdclrerror(&di->mde); 710 711 if (md_snarf_db_set(MD_LOCAL_SET, &di->mde) != 0) 712 return (0); 713 714 if ((setno >= md_nsets) || (MD_MIN2UNIT(mnum) >= md_nunits)) { 715 return (mdmderror(&di->mde, MDE_INVAL_UNIT, mnum)); 716 } 717 718 if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0) 719 return (ENODEV); 720 721 ui = MDI_UNIT(mnum); 722 if (ui == NULL) { 723 return (mdmderror(&di->mde, MDE_UNIT_NOT_SETUP, mnum)); 724 } 725 726 MD_SETDRIVERNAME(di, md_ops[ui->ui_opsindex]->md_driver.md_drivername, 727 setno); 728 729 return (0); 730 } 731 732 /*ARGSUSED*/ 733 static int 734 getnext_ioctl(md_i_getnext_t *gn, int mode) 735 { 736 int modindex; 737 md_link_t *next; 738 uint_t id; 739 int found = 0; 740 set_t setno = gn->md_driver.md_setno; 741 742 mdclrerror(&gn->mde); 743 744 if (md_snarf_db_set(MD_LOCAL_SET, &gn->mde) != 0) 745 return (0); 746 747 if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0) { 748 if (md_get_setstatus(setno) & MD_SET_TAGDATA) 749 return (mdmddberror(&gn->mde, MDE_DB_TAGDATA, 750 NODEV32, setno)); 751 else 752 return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND)); 753 } 754 755 modindex = md_getmodindex((md_driver_t *)gn, 1, 0); 756 if (modindex == -1) { 757 return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND)); 758 } 759 760 rw_enter(&md_ops[modindex]->md_link_rw.lock, RW_READER); 761 id = gn->id; 762 next = md_ops[modindex]->md_head; 763 while (next) { 764 if ((next->ln_setno == setno) && (next->ln_id == id)) { 765 gn->id = id; 766 found = 1; 767 break; 768 } 769 770 if ((next->ln_setno == setno) &&(next->ln_id > id) && 771 (! found || (next->ln_id < gn->id))) { 772 gn->id = next->ln_id; 773 found = 1; 774 /* continue looking for smallest */ 775 } 776 next = next->ln_next; 777 } 778 rw_exit(&md_ops[modindex]->md_link_rw.lock); 779 780 if (! found) 781 return (mderror(&gn->mde, MDE_UNIT_NOT_FOUND)); 782 783 return (0); 784 } 785 786 /*ARGSUSED*/ 787 static int 788 getnum_ioctl(void *d, int mode) 789 { 790 int modindex; 791 md_link_t *next; 792 int sz; 793 minor_t *minors; 794 minor_t *m_ptr; 795 set_t setno; 796 int err = 0; 797 md_error_t *mdep; 798 int minor_array_length; 799 md_driver_t *driver; 800 int count = 0; 801 struct md_i_getnum *gn = d; 802 803 804 /* number of specified devices in specified set - if 0 return count */ 805 minor_array_length = gn->size; 806 if (minor_array_length > md_nunits) 807 return (EINVAL); 808 809 mdep = &gn->mde; 810 driver = &gn->md_driver; 811 setno = driver->md_setno; 812 813 mdclrerror(mdep); 814 815 if (md_snarf_db_set(MD_LOCAL_SET, mdep) != 0) 816 return (0); 817 818 if ((md_get_setstatus(setno) & MD_SET_SNARFED) == 0) { 819 if (md_get_setstatus(setno) & MD_SET_TAGDATA) { 820 return (mdmddberror(mdep, MDE_DB_TAGDATA, 821 NODEV32, setno)); 822 } else { 823 return (mderror(mdep, MDE_UNIT_NOT_FOUND)); 824 } 825 } 826 827 modindex = md_getmodindex(driver, 0, 0); 828 if (modindex == -1) { 829 830 return (mderror(mdep, MDE_UNIT_NOT_FOUND)); 831 } 832 833 rw_enter(&md_ops[modindex]->md_link_rw.lock, RW_READER); 834 /* if array length is not 0 then allocate the output buffers */ 835 if (minor_array_length != 0) { 836 sz = minor_array_length * ((int)sizeof (minor_t)); 837 minors = kmem_zalloc(sz, KM_SLEEP); 838 m_ptr = minors; 839 } 840 841 next = md_ops[modindex]->md_head; 842 count = 0; 843 while (next) { 844 if (next->ln_setno == setno) { 845 if ((minor_array_length > 0) && 846 (count < minor_array_length)) { 847 *m_ptr = next->ln_id; 848 m_ptr++; 849 } 850 count++; 851 } 852 next = next->ln_next; 853 } 854 rw_exit(&md_ops[modindex]->md_link_rw.lock); 855 856 gn->size = count; 857 /* now copy the array back */ 858 if (minor_array_length > 0) { 859 err = ddi_copyout(minors, 860 (caddr_t)(uintptr_t)gn->minors, sz, mode); 861 kmem_free(minors, sz); 862 } 863 864 return (err); 865 } 866 867 /*ARGSUSED*/ 868 static int 869 didstat_ioctl( 870 md_i_didstat_t *ds 871 ) 872 { 873 int cnt = 0; 874 int err = 0; 875 876 mdclrerror(&ds->mde); 877 878 if (md_snarf_db_set(MD_LOCAL_SET, &ds->mde) != 0) 879 return (0); 880 881 if (ds->setno >= md_nsets) { 882 return (EINVAL); 883 } 884 885 if ((md_get_setstatus(ds->setno) & MD_SET_SNARFED) == 0) 886 return (ENODEV); 887 888 if (ds->mode == MD_FIND_INVDID) { 889 cnt = md_validate_devid(ds->setno, ds->side, &ds->maxsz); 890 if (cnt == -1) 891 err = -1; 892 ds->cnt = cnt; 893 } else if (ds->mode == MD_GET_INVDID) { 894 if (md_get_invdid(ds->setno, ds->side, ds->cnt, ds->maxsz, 895 (caddr_t)(uintptr_t)ds->ctdp) == -1) { 896 err = -1; 897 } 898 } else { 899 /* invalid mode */ 900 err = EINVAL; 901 } 902 903 return (err); 904 } 905 906 /*ARGSUSED*/ 907 static int 908 getdid_ioctl( 909 mdnm_params_t *nm, 910 int mode 911 ) 912 { 913 int err = 0; 914 ddi_devid_t did = NULL; 915 916 mdclrerror(&nm->mde); 917 918 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 919 return (0); 920 921 if (nm->setno >= md_nsets) { 922 return (EINVAL); 923 } 924 925 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 926 return (ENODEV); 927 928 /* 929 * Tell user that replica is not in devid mode 930 */ 931 if (!(((mddb_set_t *)md_set[nm->setno].s_db)->s_lbp->lb_flags 932 & MDDB_DEVID_STYLE) && md_keep_repl_state) { 933 return (mdsyserror(&nm->mde, MDDB_F_NODEVID)); 934 } 935 936 /* 937 * If user is prepared to receive the devid allocate a kernel buffer. 938 */ 939 if (nm->devid_size != 0) { 940 /* check for bogus value of devid_size */ 941 if (nm->devid_size > MAXPATHLEN) { 942 return (EINVAL); 943 } 944 did = kmem_alloc(nm->devid_size, KM_SLEEP); 945 } 946 947 err = md_getdevid(nm->setno, nm->side, nm->key, did, &nm->devid_size); 948 949 if (err) { 950 if (err < 0) 951 err = EINVAL; 952 goto out; 953 } 954 955 /* 956 * If devid size was already known to user then give them the devid. 957 */ 958 if (did != NULL) 959 err = ddi_copyout(did, 960 (caddr_t)(uintptr_t)nm->devid, nm->devid_size, mode); 961 962 out: 963 if (did != NULL) 964 kmem_free(did, nm->devid_size); 965 return (err); 966 } 967 968 int 969 mddb_setmaster_ioctl(mddb_setmaster_config_t *info) 970 { 971 /* Verify that setno is in valid range */ 972 if (info->c_setno >= md_nsets) 973 return (EINVAL); 974 975 /* 976 * When adding the first disk to a MN diskset, the master 977 * needs to be set (in order to write out the mddb) 978 * before the set is snarfed or even before the set 979 * is marked as a MNset in the md_set structure. 980 * So, don't check for MNset or SNARFED and don't call 981 * mddb_setenter. In order to discourage bad ioctl calls, 982 * verify that magic field in structure is set correctly. 983 */ 984 if (info->c_magic != MDDB_SETMASTER_MAGIC) 985 return (EINVAL); 986 987 if (info->c_current_host_master) 988 md_set[info->c_setno].s_am_i_master = 1; 989 else 990 md_set[info->c_setno].s_am_i_master = 0; 991 992 return (0); 993 } 994 995 /* 996 * Set the devid for the namespace record identified by the tuple 997 * [setno, sideno, key]. The key is the namespace key. The md_getdevnum() 998 * function is used to actually regenerate the devid. 999 */ 1000 /*ARGSUSED*/ 1001 static int 1002 setdid_ioctl( 1003 mdnm_params_t *nm, 1004 int mode 1005 ) 1006 { 1007 dev_t devt; 1008 1009 /* 1010 * If upgrading do not allow modification of the namespace. 1011 */ 1012 if (MD_UPGRADE) 1013 return (EAGAIN); 1014 1015 mdclrerror(&nm->mde); 1016 1017 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 1018 return (0); 1019 1020 if (MD_MNSET_SETNO(nm->setno)) 1021 return (0); 1022 1023 if (nm->setno >= md_nsets) 1024 return (EINVAL); 1025 1026 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 1027 return (ENODEV); 1028 1029 devt = md_dev64_to_dev( 1030 md_getdevnum(nm->setno, nm->side, nm->key, MD_TRUST_DEVT)); 1031 1032 if (devt == NODEV) 1033 return (ENODEV); 1034 1035 return (0); 1036 } 1037 1038 /*ARGSUSED*/ 1039 static int 1040 getdidmin_ioctl( 1041 mdnm_params_t *nm, 1042 int mode 1043 ) 1044 { 1045 int err = 0; 1046 char *minorname = NULL; 1047 1048 mdclrerror(&nm->mde); 1049 1050 if (md_snarf_db_set(MD_LOCAL_SET, &nm->mde) != 0) 1051 return (0); 1052 1053 if (MD_MNSET_SETNO(nm->setno)) 1054 return (0); 1055 1056 if ((md_get_setstatus(nm->setno) & MD_SET_SNARFED) == 0) 1057 return (ENODEV); 1058 1059 minorname = kmem_alloc(MAXPATHLEN, KM_SLEEP); 1060 1061 if (nm->side == -1) { 1062 err = EINVAL; 1063 goto out; 1064 } 1065 1066 err = md_getdevidminor(nm->setno, nm->side, nm->key, minorname, 1067 MAXPATHLEN); 1068 1069 if (err) { 1070 if (err < 0) 1071 err = EINVAL; 1072 goto out; 1073 } 1074 1075 err = ddi_copyout(minorname, (caddr_t)(uintptr_t)nm->minorname, 1076 strlen(minorname) + 1, mode); 1077 1078 out: 1079 1080 kmem_free(minorname, MAXPATHLEN); 1081 return (err); 1082 } 1083 1084 static int 1085 mddb_userreq_ioctl(mddb_userreq_t *ur, int mode) 1086 { 1087 void *data; 1088 int status; 1089 mddb_recid_t *recids; 1090 int flags; 1091 1092 if (ur->ur_setno >= md_nsets) 1093 return (EINVAL); 1094 1095 mdclrerror(&ur->ur_mde); 1096 1097 if (md_snarf_db_set(MD_LOCAL_SET, &ur->ur_mde) != 0) 1098 return (0); 1099 1100 if ((md_get_setstatus(ur->ur_setno) & MD_SET_SNARFED) == 0) 1101 return (ENODEV); 1102 1103 switch (ur->ur_cmd) { 1104 case MD_DB_GETNEXTREC: 1105 if (ur->ur_recid == 0) 1106 ur->ur_recid = mddb_makerecid(ur->ur_setno, 0); 1107 /* 1108 * Is ur_recid a valid one ? 1109 */ 1110 if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets) 1111 return (EINVAL); 1112 1113 ur->ur_recid = mddb_getnextrec(ur->ur_recid, ur->ur_type, 1114 ur->ur_type2); 1115 if (ur->ur_recid > 0) { 1116 ur->ur_type = mddb_getrectype1(ur->ur_recid); 1117 ur->ur_type2 = mddb_getrectype2(ur->ur_recid); 1118 ur->ur_recstat = mddb_getrecstatus(ur->ur_recid); 1119 } 1120 break; 1121 1122 case MD_DB_COMMIT_ONE: 1123 /* 1124 * Is ur_recid a valid one? 1125 */ 1126 if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets) 1127 return (EINVAL); 1128 1129 ur->ur_recstat = mddb_getrecstatus(ur->ur_recid); 1130 if (ur->ur_recstat == MDDB_NORECORD) 1131 return (ENXIO); 1132 status = mddb_commitrec(ur->ur_recid); 1133 /* 1134 * For MN sets we panic if there are too few database replicas 1135 * and we're attempting to add entries to the log. 1136 */ 1137 if (status != 0) { 1138 if ((MD_MNSET_SETNO(ur->ur_setno) && 1139 (ur->ur_type2 == MDDB_UR_LR)) && 1140 (md_get_setstatus(ur->ur_setno) & MD_SET_TOOFEW)) { 1141 cmn_err(CE_PANIC, 1142 "md: Panic due to lack of DiskSuite state\n" 1143 " database replicas. Fewer than 50%% of " 1144 "the total were available,\n so panic to " 1145 "ensure data integrity."); 1146 } 1147 return (mddbstatus2error(&ur->ur_mde, status, NODEV32, 1148 ur->ur_setno)); 1149 } 1150 break; 1151 1152 case MD_DB_COMMIT_MANY: 1153 if (ur->ur_size <= 0) 1154 return (EINVAL); 1155 1156 data = kmem_alloc(ur->ur_size, KM_SLEEP); 1157 1158 if (ddi_copyin((caddr_t)(uintptr_t)ur->ur_data, data, 1159 (size_t)ur->ur_size, mode)) { 1160 kmem_free(data, ur->ur_size); 1161 return (EFAULT); 1162 } 1163 1164 recids = (mddb_recid_t *)data; 1165 while (*recids != 0) { 1166 /* 1167 * Is recid a valid ? 1168 */ 1169 if (DBSET(*recids) < 0 || DBSET(*recids) >= md_nsets) { 1170 kmem_free(data, ur->ur_size); 1171 return (EINVAL); 1172 } 1173 ur->ur_recstat = mddb_getrecstatus(*recids++); 1174 if (ur->ur_recstat == MDDB_NORECORD) { 1175 kmem_free(data, ur->ur_size); 1176 return (ENXIO); 1177 } 1178 } 1179 status = mddb_commitrecs(data); 1180 kmem_free(data, ur->ur_size); 1181 /* 1182 * For MN sets we panic if there are too few database replicas 1183 * and we're attempting to add entries to the log. 1184 */ 1185 if (status != 0) { 1186 if ((MD_MNSET_SETNO(ur->ur_setno) && 1187 (ur->ur_type2 == MDDB_UR_LR)) && 1188 (md_get_setstatus(ur->ur_setno) & MD_SET_TOOFEW)) { 1189 cmn_err(CE_PANIC, 1190 "md: Panic due to lack of DiskSuite state\n" 1191 " database replicas. Fewer than 50%% of " 1192 "the total were available,\n so panic to " 1193 "ensure data integrity."); 1194 } 1195 return (mddbstatus2error(&ur->ur_mde, status, NODEV32, 1196 ur->ur_setno)); 1197 } 1198 break; 1199 1200 case MD_DB_GETDATA: 1201 /* 1202 * Check ur_recid 1203 */ 1204 if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets) 1205 return (EINVAL); 1206 1207 ur->ur_recstat = mddb_getrecstatus(ur->ur_recid); 1208 if (ur->ur_recstat == MDDB_NORECORD || 1209 ur->ur_recstat == MDDB_NODATA) 1210 return (ENXIO); 1211 1212 if (ur->ur_size > mddb_getrecsize(ur->ur_recid)) 1213 return (EINVAL); 1214 1215 data = mddb_getrecaddr(ur->ur_recid); 1216 if (ddi_copyout(data, (caddr_t)(uintptr_t)ur->ur_data, 1217 (size_t)ur->ur_size, mode)) { 1218 return (EFAULT); 1219 } 1220 break; 1221 1222 case MD_DB_SETDATA: 1223 if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets) 1224 return (EINVAL); 1225 1226 ur->ur_recstat = mddb_getrecstatus(ur->ur_recid); 1227 if (ur->ur_recstat == MDDB_NORECORD) 1228 return (ENXIO); 1229 1230 if (ur->ur_size > mddb_getrecsize(ur->ur_recid)) 1231 return (EINVAL); 1232 1233 data = mddb_getrecaddr(ur->ur_recid); 1234 if (ddi_copyin((caddr_t)(uintptr_t)ur->ur_data, data, 1235 (size_t)ur->ur_size, mode)) { 1236 return (EFAULT); 1237 } 1238 break; 1239 1240 case MD_DB_DELETE: 1241 if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets) 1242 return (EINVAL); 1243 1244 ur->ur_recstat = mddb_getrecstatus(ur->ur_recid); 1245 if (ur->ur_recstat == MDDB_NORECORD) 1246 return (ENXIO); 1247 status = mddb_deleterec(ur->ur_recid); 1248 if (status < 0) 1249 return (mddbstatus2error(&ur->ur_mde, status, NODEV32, 1250 ur->ur_setno)); 1251 break; 1252 1253 case MD_DB_CREATE: 1254 { 1255 int mn_set = 0; 1256 1257 if (md_get_setstatus(ur->ur_setno) & MD_SET_MNSET) 1258 mn_set = 1; 1259 1260 if (ur->ur_setno >= md_nsets) 1261 return (EINVAL); 1262 if ((mn_set) && (ur->ur_type2 == MDDB_UR_LR)) 1263 flags = MD_CRO_32BIT | MD_CRO_CHANGELOG; 1264 else 1265 flags = MD_CRO_32BIT; 1266 ur->ur_recid = mddb_createrec(ur->ur_size, ur->ur_type, 1267 ur->ur_type2, flags, ur->ur_setno); 1268 if (ur->ur_recid < 0) 1269 return (mddbstatus2error(&ur->ur_mde, ur->ur_recid, 1270 NODEV32, ur->ur_setno)); 1271 break; 1272 } 1273 1274 case MD_DB_GETSTATUS: 1275 if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets) 1276 return (EINVAL); 1277 ur->ur_recstat = mddb_getrecstatus(ur->ur_recid); 1278 break; 1279 1280 case MD_DB_GETSIZE: 1281 if (DBSET(ur->ur_recid) < 0 || DBSET(ur->ur_recid) >= md_nsets) 1282 return (EINVAL); 1283 ur->ur_size = mddb_getrecsize(ur->ur_recid); 1284 break; 1285 1286 case MD_DB_MAKEID: 1287 if (ur->ur_setno >= md_nsets) 1288 return (EINVAL); 1289 ur->ur_recid = mddb_makerecid(ur->ur_setno, ur->ur_recid); 1290 break; 1291 1292 default: 1293 return (EINVAL); 1294 } 1295 return (0); 1296 } 1297 1298 static int 1299 setuserflags( 1300 md_set_userflags_t *msu, 1301 IOLOCK *lock 1302 ) 1303 { 1304 minor_t mnum = msu->mnum; 1305 set_t setno = MD_MIN2SET(mnum); 1306 md_unit_t *un; 1307 mdi_unit_t *ui; 1308 1309 mdclrerror(&msu->mde); 1310 1311 if ((setno >= md_nsets) || (MD_MIN2UNIT(mnum) >= md_nunits)) 1312 return (ENXIO); 1313 1314 if (md_get_setstatus(setno) & MD_SET_STALE) 1315 return (mdmddberror(&msu->mde, MDE_DB_STALE, mnum, setno)); 1316 1317 if ((ui = MDI_UNIT(mnum)) == NULL) { 1318 return (mdmderror(&msu->mde, MDE_UNIT_NOT_SETUP, mnum)); 1319 } 1320 1321 un = (md_unit_t *)md_ioctl_writerlock(lock, ui); 1322 1323 un->c.un_user_flags = msu->userflags; 1324 mddb_commitrec_wrapper(un->c.un_record_id); 1325 1326 return (0); 1327 } 1328 1329 /* 1330 * mddb_didstat_from_user -- called for DIDSTAT ioctl. 2 different calling 1331 * scenarios. 1332 * 1) data->mode == MD_FIND_INVDID 1333 * when user is inquiring about the existence of invalid device id's. 1334 * Upon return to the user d->cnt may have a value in it. 1335 * 2) data->mode == MD_GET_INVDID 1336 * when the user wants a list of the invalid device id's. 1337 * In this case d->ctdp is non Null and cnt has a value in it. 1338 * 1339 * Basically this routine along with mddb_didstat_to_user can be eliminated 1340 * by pushing ddi_copyout down to lower level interfaces. To minimize impact 1341 * just keep the current implementation intact. 1342 */ 1343 static int 1344 mddb_didstat_from_user( 1345 void **d, 1346 caddr_t data, 1347 int mode, 1348 caddr_t *ds_ctd_addr 1349 ) 1350 { 1351 size_t sz1 = 0, sz2 = 0; 1352 md_i_didstat_t *d1; 1353 void *d2; 1354 *ds_ctd_addr = 0; 1355 1356 sz1 = sizeof (md_i_didstat_t); 1357 d1 = (md_i_didstat_t *)kmem_zalloc(sz1, KM_SLEEP); 1358 1359 if (ddi_copyin(data, (void *)d1, sz1, mode) != 0) { 1360 kmem_free((void *)d1, sz1); 1361 return (EFAULT); 1362 } 1363 1364 /* 1365 * ds_ctd_addr has actual user ctdp 1366 */ 1367 *ds_ctd_addr = (caddr_t)(uintptr_t)d1->ctdp; 1368 if (d1->mode == MD_GET_INVDID) { 1369 sz2 = (d1->cnt * d1->maxsz) + 1; 1370 if (sz2 <= 0) { 1371 kmem_free(d1, sz1); 1372 return (EINVAL); 1373 } 1374 d2 = kmem_zalloc(sz2, KM_SLEEP); 1375 d1->ctdp = (uint64_t)(uintptr_t)d2; 1376 } else if (d1->mode != MD_FIND_INVDID) { 1377 kmem_free(d1, sz1); 1378 return (EINVAL); 1379 } 1380 *d = (void *)d1; 1381 return (0); 1382 } 1383 1384 /* 1385 * mddb_didstat_to_user -- see comment for mddb_didstat_from_user. In this 1386 * case d->cnt could have a value in it for either usage of 1387 * the ioctl. 1388 */ 1389 /*ARGSUSED*/ 1390 static int 1391 mddb_didstat_to_user( 1392 void *d, 1393 caddr_t data, 1394 int mode, 1395 caddr_t ds_ctd_addr 1396 ) 1397 { 1398 size_t sz1 = 0, sz2 = 0; 1399 md_i_didstat_t *d1; 1400 void *d2; 1401 1402 1403 d1 = (md_i_didstat_t *)d; 1404 sz1 = sizeof (md_i_didstat_t); 1405 1406 sz2 = (d1->cnt * d1->maxsz) + 1; 1407 d2 = (caddr_t)(uintptr_t)d1->ctdp; 1408 if (d2 && sz2) { 1409 /* 1410 * Copy out from kernel ctdp to user ctdp area 1411 */ 1412 if (ddi_copyout(d2, (caddr_t)ds_ctd_addr, sz2, mode) != 0) { 1413 kmem_free(d1, sz1); 1414 kmem_free(d2, sz2); 1415 return (EFAULT); 1416 } 1417 d1->ctdp = (uint64_t)(uintptr_t)ds_ctd_addr; 1418 } 1419 if (ddi_copyout(d1, data, sz1, mode) != 0) { 1420 kmem_free(d1, sz1); 1421 if (sz2 && d2) 1422 kmem_free(d2, sz2); 1423 return (EFAULT); 1424 } 1425 kmem_free(d1, sz1); 1426 if (sz2 && d2) 1427 kmem_free(d2, sz2); 1428 return (0); 1429 } 1430 1431 1432 static int 1433 mddb_config_from_user( 1434 void **d, 1435 caddr_t data, 1436 int mode, 1437 caddr_t *c_devid_addr, 1438 caddr_t *c_old_devid_addr 1439 ) 1440 { 1441 size_t sz1 = 0, sz2 = 0, sz3 = 0; 1442 mddb_config_t *d1; 1443 void *d2; 1444 void *d3; 1445 1446 *c_devid_addr = 0; 1447 1448 sz1 = sizeof (mddb_config_t); 1449 d1 = (mddb_config_t *)kmem_zalloc(sz1, KM_SLEEP); 1450 1451 if (ddi_copyin(data, (void *)d1, sz1, mode) != 0) { 1452 kmem_free((void *)d1, sz1); 1453 return (EFAULT); 1454 } 1455 *c_devid_addr = (caddr_t)(uintptr_t)d1->c_locator.l_devid; 1456 1457 if (d1->c_locator.l_devid_flags & MDDB_DEVID_SPACE) { 1458 sz2 = d1->c_locator.l_devid_sz; 1459 if (d1->c_locator.l_devid_sz <= 0 || 1460 d1->c_locator.l_devid_sz > MAXPATHLEN) { 1461 kmem_free((void *)d1, sz1); 1462 return (EINVAL); 1463 } 1464 d2 = kmem_zalloc(sz2, KM_SLEEP); 1465 if (ddi_copyin((caddr_t)(uintptr_t)d1->c_locator.l_devid, 1466 d2, sz2, mode) != 0) { 1467 kmem_free(d1, sz1); 1468 kmem_free(d2, sz2); 1469 return (EFAULT); 1470 } 1471 d1->c_locator.l_devid = (uint64_t)(uintptr_t)d2; 1472 1473 if ((caddr_t)(uintptr_t)d1->c_locator.l_old_devid) { 1474 *c_old_devid_addr = (caddr_t)(uintptr_t) 1475 d1->c_locator.l_old_devid; 1476 1477 sz3 = d1->c_locator.l_old_devid_sz; 1478 if (d1->c_locator.l_old_devid_sz <= 0 || 1479 d1->c_locator.l_old_devid_sz > MAXPATHLEN) { 1480 kmem_free((void *)d1, sz1); 1481 kmem_free(d2, sz2); 1482 return (EINVAL); 1483 } 1484 d3 = kmem_zalloc(sz3, KM_SLEEP); 1485 if (ddi_copyin( 1486 (caddr_t)(uintptr_t)d1->c_locator.l_old_devid, 1487 d3, sz3, mode) != 0) { 1488 kmem_free((void *)d1, sz1); 1489 kmem_free(d2, sz2); 1490 kmem_free(d3, sz3); 1491 return (EFAULT); 1492 } 1493 d1->c_locator.l_old_devid = (uintptr_t)d3; 1494 } 1495 } else { 1496 d1->c_locator.l_devid = (uint64_t)0; 1497 d1->c_locator.l_old_devid = (uint64_t)0; 1498 } 1499 1500 *d = (void *)d1; 1501 return (0); 1502 } 1503 1504 /*ARGSUSED*/ 1505 static int 1506 mddb_config_to_user( 1507 void *d, 1508 caddr_t data, 1509 int mode, 1510 caddr_t c_devid_addr, 1511 caddr_t c_old_devid_addr 1512 ) 1513 { 1514 size_t sz1 = 0, sz2 = 0, sz3 = 0; 1515 mddb_config_t *d1; 1516 void *d2; 1517 void *d3; 1518 1519 d1 = (mddb_config_t *)d; 1520 sz1 = sizeof (mddb_config_t); 1521 1522 if (d1->c_locator.l_devid_flags & MDDB_DEVID_SPACE) { 1523 sz2 = d1->c_locator.l_devid_sz; 1524 d2 = (caddr_t)(uintptr_t)d1->c_locator.l_devid; 1525 /* Only copyout devid if valid */ 1526 if (d1->c_locator.l_devid_flags & MDDB_DEVID_VALID) { 1527 if (ddi_copyout(d2, (caddr_t)c_devid_addr, 1528 sz2, mode) != 0) { 1529 kmem_free(d1, sz1); 1530 kmem_free(d2, sz2); 1531 return (EFAULT); 1532 } 1533 } 1534 } 1535 1536 d1->c_locator.l_devid = (uint64_t)(uintptr_t)c_devid_addr; 1537 1538 if (d1->c_locator.l_old_devid) { 1539 sz3 = d1->c_locator.l_old_devid_sz; 1540 d3 = (caddr_t)(uintptr_t)d1->c_locator.l_old_devid; 1541 if (ddi_copyout(d3, (caddr_t)c_old_devid_addr, 1542 sz3, mode) != 0) { 1543 kmem_free(d1, sz1); 1544 kmem_free(d2, sz2); 1545 kmem_free(d3, sz3); 1546 } 1547 } 1548 d1->c_locator.l_old_devid = (uintptr_t)c_old_devid_addr; 1549 1550 if (ddi_copyout(d1, data, sz1, mode) != 0) { 1551 kmem_free(d1, sz1); 1552 if (sz2) 1553 kmem_free(d2, sz2); 1554 if (sz3) 1555 kmem_free(d3, sz3); 1556 return (EFAULT); 1557 } 1558 1559 if (d1) 1560 kmem_free(d1, sz1); 1561 if (sz2) 1562 kmem_free(d2, sz2); 1563 if (sz3) 1564 kmem_free(d3, sz3); 1565 1566 return (0); 1567 } 1568 1569 /* 1570 * NAME: get_tstate 1571 * PURPOSE: Return unit's transient error state to user. 1572 * INPUT: device node (set + metadevice number) 1573 * OUTPUT: gu->tstate 1574 * RETURNS: 0 on success 1575 * EINVAL on failure 1576 */ 1577 static int 1578 get_tstate(md_i_get_tstate_t *gu, IOLOCK *lock) 1579 { 1580 set_t setno = MD_MIN2SET(gu->id); 1581 unit_t unit = MD_MIN2UNIT(gu->id); 1582 mdi_unit_t *ui; 1583 1584 if (setno >= md_nsets || unit >= md_nunits) { 1585 (void) mdmderror(&gu->mde, MDE_INVAL_UNIT, unit); 1586 return (EINVAL); 1587 } 1588 1589 ui = MDI_UNIT(gu->id); 1590 if (ui == (mdi_unit_t *)NULL) 1591 return (EINVAL); 1592 1593 (void) md_ioctl_readerlock(lock, ui); 1594 gu->tstate = ui->ui_tstate; 1595 md_ioctl_readerexit(lock); 1596 1597 return (0); 1598 } 1599 1600 /* 1601 * NAME: md_clu_ioctl 1602 * PURPOSE: depending on clu_cmd: 1603 * - Check open state, 1604 * - lock opens and check open state 1605 * - unlock opens again 1606 * INPUT: metadevice and clu_cmd 1607 * OUTPUT: open state (for MD_MN_LCU_UNLOCK always 0) 1608 * RETURNS: 0 on success 1609 * EINVAL on failure 1610 */ 1611 int 1612 md_clu_ioctl(md_clu_open_t *clu) 1613 { 1614 mdi_unit_t *ui; 1615 minor_t mnum; 1616 1617 if ((clu->clu_dev <= 0) || 1618 (md_getmajor(clu->clu_dev)) != md_major) { 1619 return (EINVAL); 1620 } 1621 1622 mnum = md_getminor(clu->clu_dev); 1623 if ((ui = MDI_UNIT(mnum)) == NULL) { 1624 return (mdmderror(&clu->clu_mde, MDE_UNIT_NOT_SETUP, mnum)); 1625 } 1626 switch (clu->clu_cmd) { 1627 case MD_MN_LCU_CHECK: 1628 /* No lock here, just checking */ 1629 clu->clu_isopen = md_unit_isopen(ui); 1630 break; 1631 case MD_MN_LCU_LOCK: 1632 /* This inhibits later opens to succeed */ 1633 ui->ui_tstate |= MD_OPENLOCKED; 1634 clu->clu_isopen = md_unit_isopen(ui); 1635 /* In case the md is opened, reset the lock immediately */ 1636 if (clu->clu_isopen != 0) { 1637 ui->ui_tstate &= ~MD_OPENLOCKED; 1638 } 1639 break; 1640 case MD_MN_LCU_UNLOCK: 1641 ui->ui_tstate &= ~MD_OPENLOCKED; 1642 clu->clu_isopen = 0; /* always sucess */ 1643 break; 1644 } 1645 return (0); 1646 } 1647 1648 /* 1649 * NAME: mkdev_ioctl 1650 * PURPOSE: Create device node for specified set / metadevice tuple 1651 * INPUT: device tuple (set number + metadevice number) 1652 * OUTPUT: None 1653 * RETURNS: 0 on success 1654 * EINVAL on failure 1655 */ 1656 static int 1657 mkdev_ioctl(md_mkdev_params_t *p) 1658 { 1659 set_t setno = p->md_driver.md_setno; 1660 unit_t un; 1661 1662 mdclrerror(&p->mde); 1663 1664 /* 1665 * Get the next available unit number in this set 1666 */ 1667 un = md_get_nextunit(setno); 1668 if (un == MD_UNITBAD) { 1669 (void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un); 1670 return (ENODEV); 1671 } 1672 1673 /* Validate arguments passed in to ioctl */ 1674 if (setno >= MD_MAXSETS) { 1675 (void) mderror(&p->mde, MDE_NO_SET); 1676 return (EINVAL); 1677 } 1678 1679 /* Create the device node */ 1680 if (md_create_minor_node(setno, un)) { 1681 (void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, un); 1682 return (ENODEV); 1683 } 1684 1685 /* Return the minor number */ 1686 p->un = un; 1687 1688 return (0); 1689 } 1690 1691 /* 1692 * admin device ioctls 1693 */ 1694 static int 1695 md_base_ioctl(md_dev64_t dev, int cmd, caddr_t data, int mode, IOLOCK *lockp) 1696 { 1697 size_t sz = 0; 1698 void *d = NULL; 1699 mddb_config_t *cp; 1700 set_t setno; 1701 int err = 0; 1702 int err_to_user = 0; 1703 int mddb_config_case = 0; 1704 int mddb_didstat_case = 0; 1705 caddr_t c_devid_addr = 0; 1706 caddr_t c_old_devid_addr = 0; 1707 caddr_t ds_ctd_addr = 0; 1708 mddb_set_node_params_t *snp; 1709 1710 /* For now we can only handle 32-bit clients for internal commands */ 1711 if ((cmd != DKIOCINFO) && 1712 ((mode & DATAMODEL_MASK) != DATAMODEL_ILP32)) { 1713 return (EINVAL); 1714 } 1715 1716 switch (cmd) { 1717 1718 case DKIOCINFO: 1719 { 1720 if (! (mode & FREAD)) 1721 return (EACCES); 1722 1723 sz = sizeof (struct dk_cinfo); 1724 d = kmem_alloc(sz, KM_SLEEP); 1725 1726 get_info((struct dk_cinfo *)d, md_getminor(dev)); 1727 break; 1728 } 1729 1730 case MD_DB_USEDEV: 1731 { 1732 if (! (mode & FWRITE)) 1733 return (EACCES); 1734 1735 mddb_config_case = 1; 1736 1737 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1738 &c_old_devid_addr); 1739 1740 if (err) 1741 return (err); 1742 1743 err = mddb_configure(MDDB_USEDEV, (mddb_config_t *)d); 1744 break; 1745 } 1746 1747 case MD_DB_GETDEV: 1748 { 1749 if (! (mode & FREAD)) 1750 return (EACCES); 1751 1752 mddb_config_case = 1; 1753 1754 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1755 &c_old_devid_addr); 1756 1757 if (err) 1758 return (err); 1759 1760 err = mddb_configure(MDDB_GETDEV, (mddb_config_t *)d); 1761 break; 1762 } 1763 1764 case MD_DB_GETDRVNM: 1765 { 1766 if (! (mode & FREAD)) 1767 return (EACCES); 1768 1769 mddb_config_case = 1; 1770 1771 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1772 &c_old_devid_addr); 1773 1774 if (err) 1775 return (err); 1776 1777 err = mddb_configure(MDDB_GETDRVRNAME, (mddb_config_t *)d); 1778 break; 1779 } 1780 1781 case MD_DB_ENDDEV: 1782 { 1783 if (! (mode & FREAD)) 1784 return (EACCES); 1785 1786 mddb_config_case = 1; 1787 1788 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1789 &c_old_devid_addr); 1790 1791 if (err) 1792 return (err); 1793 1794 err = mddb_configure(MDDB_ENDDEV, (mddb_config_t *)d); 1795 break; 1796 } 1797 1798 case MD_DB_DELDEV: 1799 { 1800 if (! (mode & FWRITE)) 1801 return (EACCES); 1802 1803 mddb_config_case = 1; 1804 1805 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1806 &c_old_devid_addr); 1807 1808 if (err) 1809 return (err); 1810 1811 cp = (mddb_config_t *)d; 1812 setno = cp->c_setno; 1813 err = mddb_configure(MDDB_DELDEV, cp); 1814 if (! mdisok(&cp->c_mde)) 1815 break; 1816 1817 if (setno == MD_LOCAL_SET) 1818 break; 1819 1820 if (cp->c_dbcnt != 0) 1821 break; 1822 1823 /* 1824 * if the last db replica of a diskset is deleted 1825 * unload everything. 1826 */ 1827 1828 /* Requesting a release, clean up everything */ 1829 md_clr_setstatus(setno, MD_SET_KEEPTAG); 1830 1831 err = release_set(cp, mode); 1832 1833 break; 1834 } 1835 1836 case MD_DB_NEWDEV: 1837 { 1838 if (! (mode & FWRITE)) 1839 return (EACCES); 1840 1841 mddb_config_case = 1; 1842 1843 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1844 &c_old_devid_addr); 1845 1846 if (err) 1847 return (err); 1848 1849 cp = (mddb_config_t *)d; 1850 setno = cp->c_setno; 1851 err = mddb_configure(MDDB_NEWDEV, cp); 1852 if (! err && mdisok(&cp->c_mde)) 1853 (void) md_snarf_db_set(setno, &cp->c_mde); 1854 break; 1855 } 1856 1857 case MD_DB_NEWSIDE: 1858 { 1859 if (! (mode & FWRITE)) 1860 return (EACCES); 1861 1862 mddb_config_case = 1; 1863 1864 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1865 &c_old_devid_addr); 1866 1867 if (err) 1868 return (err); 1869 1870 err = mddb_configure(MDDB_NEWSIDE, (mddb_config_t *)d); 1871 break; 1872 } 1873 1874 case MD_DB_DELSIDE: 1875 { 1876 if (! (mode & FWRITE)) 1877 return (EACCES); 1878 1879 mddb_config_case = 1; 1880 1881 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1882 &c_old_devid_addr); 1883 1884 if (err) 1885 return (err); 1886 1887 err = mddb_configure(MDDB_DELSIDE, (mddb_config_t *)d); 1888 break; 1889 } 1890 1891 case MD_DB_SETDID: 1892 { 1893 if (!(mode & FWRITE)) { 1894 return (EACCES); 1895 } 1896 1897 mddb_config_case = 1; 1898 1899 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1900 &c_old_devid_addr); 1901 1902 if (err) { 1903 return (err); 1904 } 1905 1906 err = mddb_configure(MDDB_SETDID, (mddb_config_t *)d); 1907 1908 break; 1909 } 1910 1911 case MD_GRAB_SET: 1912 { 1913 if (! (mode & FWRITE)) 1914 return (EACCES); 1915 1916 mddb_config_case = 1; 1917 1918 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1919 &c_old_devid_addr); 1920 1921 if (err) 1922 return (err); 1923 1924 cp = (mddb_config_t *)d; 1925 setno = cp->c_setno; 1926 1927 err = take_set(cp, mode); 1928 1929 if (err || ! mdisok(&cp->c_mde)) 1930 break; 1931 1932 if (md_get_setstatus(setno) & MD_SET_ACCOK) 1933 err = mdmddberror(&cp->c_mde, MDE_DB_ACCOK, NODEV32, 1934 setno); 1935 1936 md_unblock_setio(setno); 1937 break; 1938 } 1939 1940 case MD_RELEASE_SET: 1941 { 1942 if (! (mode & FWRITE)) 1943 return (EACCES); 1944 1945 mddb_config_case = 1; 1946 1947 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 1948 &c_old_devid_addr); 1949 1950 if (err) 1951 return (err); 1952 1953 /* shorthand */ 1954 cp = (mddb_config_t *)d; 1955 setno = cp->c_setno; 1956 1957 /* If the user requests a release, clean up everything */ 1958 md_clr_setstatus(setno, MD_SET_KEEPTAG); 1959 1960 if (MD_MNSET_SETNO(setno)) { 1961 /* 1962 * md_tas_block_setio will block the set if 1963 * there are no outstanding I/O requests, 1964 * otherwise it returns -1. 1965 */ 1966 if (md_tas_block_setio(setno) != 1) { 1967 err = EBUSY; 1968 break; 1969 } 1970 } else { 1971 /* 1972 * Should not return something other than 1 1973 */ 1974 if (md_block_setio(setno) != 1) { 1975 md_clearblock_setio(setno); 1976 err = EACCES; 1977 break; 1978 } 1979 } 1980 1981 err = release_set(cp, mode); 1982 1983 break; 1984 } 1985 1986 case MD_DB_GETOPTLOC: 1987 { 1988 if (! (mode & FREAD)) 1989 return (EACCES); 1990 1991 sz = sizeof (mddb_optloc_t); 1992 d = kmem_alloc(sz, KM_SLEEP); 1993 1994 if (ddi_copyin(data, d, sz, mode) != 0) { 1995 err = EFAULT; 1996 break; 1997 } 1998 1999 err = mddb_getoptloc((mddb_optloc_t *)d); 2000 break; 2001 } 2002 2003 case MD_HALT: 2004 { 2005 if (! (mode & FWRITE)) 2006 return (EACCES); 2007 2008 /* already have the ioctl lock */ 2009 return (md_halt(MD_GBL_IOCTL_LOCK)); 2010 } 2011 2012 case MD_IOCSET_NM: 2013 { 2014 if (! (mode & FREAD)) 2015 return (EACCES); 2016 2017 sz = sizeof (mdnm_params_t); 2018 d = kmem_alloc(sz, KM_SLEEP); 2019 2020 if (ddi_copyin(data, d, sz, mode) != 0) { 2021 err = EFAULT; 2022 break; 2023 } 2024 2025 /* check data integrity */ 2026 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2027 err = EINVAL; 2028 break; 2029 } 2030 2031 if ((((mdnm_params_t *)d)->devname_len == 0) || 2032 (((mdnm_params_t *)d)->devname_len > MAXPATHLEN)) { 2033 err = EINVAL; 2034 break; 2035 } 2036 2037 if (((mdnm_params_t *)d)->devname == NULL) { 2038 err = EINVAL; 2039 break; 2040 } 2041 2042 err = setnm_ioctl((mdnm_params_t *)d, mode); 2043 break; 2044 } 2045 2046 case MD_IOCGET_NM: 2047 { 2048 if (! (mode & FREAD)) 2049 return (EACCES); 2050 2051 sz = sizeof (mdnm_params_t); 2052 d = kmem_alloc(sz, KM_SLEEP); 2053 2054 if (ddi_copyin(data, d, sz, mode) != 0) { 2055 err = EFAULT; 2056 break; 2057 } 2058 2059 /* check data integrity */ 2060 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2061 err = EINVAL; 2062 break; 2063 } 2064 if (((mdnm_params_t *)d)->devname == NULL) { 2065 err = EINVAL; 2066 break; 2067 } 2068 2069 err = getnm_ioctl((mdnm_params_t *)d, mode); 2070 break; 2071 } 2072 2073 case MD_IOCGET_HSP_NM: 2074 { 2075 if (! (mode & FREAD)) 2076 return (EACCES); 2077 2078 sz = sizeof (mdhspnm_params_t); 2079 d = kmem_alloc(sz, KM_SLEEP); 2080 2081 if (ddi_copyin(data, d, sz, mode) != 0) { 2082 err = EFAULT; 2083 break; 2084 } 2085 2086 /* check data integrity */ 2087 if (((mdhspnm_params_t *)d)->setno >= md_nsets) { 2088 err = EINVAL; 2089 break; 2090 } 2091 if (((mdhspnm_params_t *)d)->hspname == NULL) { 2092 err = EINVAL; 2093 break; 2094 } 2095 2096 err = gethspnm_ioctl((mdhspnm_params_t *)d, mode); 2097 break; 2098 } 2099 2100 case MD_IOCNXTKEY_NM: 2101 { 2102 if (! (mode & FREAD)) 2103 return (EACCES); 2104 2105 sz = sizeof (mdnm_params_t); 2106 d = kmem_alloc(sz, KM_SLEEP); 2107 2108 if (ddi_copyin(data, d, sz, mode) != 0) { 2109 err = EFAULT; 2110 break; 2111 } 2112 2113 err = getnextkey_ioctl((mdnm_params_t *)d, mode); 2114 break; 2115 } 2116 2117 case MD_IOCREM_NM: 2118 { 2119 if (! (mode & FREAD)) 2120 return (EACCES); 2121 2122 sz = sizeof (mdnm_params_t); 2123 d = kmem_alloc(sz, KM_SLEEP); 2124 2125 if (ddi_copyin(data, d, sz, mode) != 0) { 2126 err = EFAULT; 2127 break; 2128 } 2129 2130 /* check data integrity */ 2131 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2132 err = EINVAL; 2133 break; 2134 } 2135 2136 err = remnm_ioctl((mdnm_params_t *)d, mode); 2137 break; 2138 } 2139 2140 case MD_IOCGET_TSTATE: 2141 { 2142 if (! (mode & FREAD)) 2143 return (EACCES); 2144 2145 sz = sizeof (md_i_get_tstate_t); 2146 d = kmem_alloc(sz, KM_SLEEP); 2147 2148 if (ddi_copyin(data, d, sz, mode) != 0) { 2149 err = EFAULT; 2150 break; 2151 } 2152 2153 err = get_tstate((md_i_get_tstate_t *)d, lockp); 2154 break; 2155 } 2156 2157 case MD_IOCGET_DRVNM: 2158 { 2159 if (! (mode & FREAD)) 2160 return (EACCES); 2161 2162 sz = sizeof (md_i_driverinfo_t); 2163 d = kmem_alloc(sz, KM_SLEEP); 2164 2165 if (ddi_copyin(data, d, sz, mode) != 0) { 2166 err = EFAULT; 2167 break; 2168 } 2169 2170 /* check data integrity */ 2171 if (((md_i_driverinfo_t *)d)->md_driver.md_drivername == NULL) { 2172 err = EINVAL; 2173 break; 2174 } 2175 2176 if (MD_MIN2SET(((md_i_driverinfo_t *)d)->mnum) >= md_nsets) { 2177 err = EINVAL; 2178 break; 2179 } 2180 2181 err = getdrvnm_ioctl(dev, (md_i_driverinfo_t *)d, mode); 2182 break; 2183 } 2184 2185 case MD_IOCGET_NEXT: 2186 { 2187 if (! (mode & FREAD)) 2188 return (EACCES); 2189 2190 sz = sizeof (md_i_getnext_t); 2191 d = kmem_alloc(sz, KM_SLEEP); 2192 2193 if (ddi_copyin(data, d, sz, mode) != 0) { 2194 err = EFAULT; 2195 break; 2196 } 2197 2198 /* check data integrity */ 2199 if (((md_i_getnext_t *)d)->md_driver.md_setno >= md_nsets) { 2200 err = EINVAL; 2201 break; 2202 } 2203 2204 err = getnext_ioctl((md_i_getnext_t *)d, mode); 2205 break; 2206 } 2207 2208 case MD_DB_USERREQ: 2209 case MD_MN_DB_USERREQ: 2210 { 2211 if (! (mode & FREAD)) 2212 return (EACCES); 2213 2214 sz = sizeof (mddb_userreq_t); 2215 d = kmem_alloc(sz, KM_SLEEP); 2216 2217 if (ddi_copyin(data, d, sz, mode) != 0) { 2218 err = EFAULT; 2219 break; 2220 } 2221 err = mddb_userreq_ioctl((mddb_userreq_t *)d, mode); 2222 break; 2223 } 2224 2225 case MD_IOCGET_NUM: 2226 { 2227 if (! (mode & FREAD)) 2228 return (EACCES); 2229 2230 sz = sizeof (md_i_getnum_t); 2231 d = kmem_alloc(sz, KM_SLEEP); 2232 2233 if (ddi_copyin(data, d, sz, mode) != 0) { 2234 err = EFAULT; 2235 break; 2236 } 2237 2238 err = getnum_ioctl(d, mode); 2239 break; 2240 } 2241 2242 case MD_DB_OWNSET: 2243 { 2244 if (! (mode & FREAD)) 2245 return (EACCES); 2246 2247 sz = sizeof (mddb_ownset_t); 2248 d = kmem_alloc(sz, KM_SLEEP); 2249 2250 if (ddi_copyin(data, d, sz, mode) != 0) { 2251 err = EFAULT; 2252 break; 2253 } 2254 2255 if (((mddb_ownset_t *)d)->setno >= md_nsets) { 2256 err = EINVAL; 2257 break; 2258 } 2259 2260 ((mddb_ownset_t *)d)->owns_set = 2261 mddb_ownset(((mddb_ownset_t *)d)->setno); 2262 2263 break; 2264 } 2265 2266 case MD_IOCGETNSET: 2267 { 2268 if (! (mode & FREAD)) 2269 return (EACCES); 2270 2271 if (ddi_copyout((caddr_t)&md_nsets, data, 2272 sizeof (set_t), mode) != 0) { 2273 err = EFAULT; 2274 break; 2275 } 2276 break; 2277 } 2278 2279 case MD_IOCGETNUNITS: 2280 { 2281 if (! (mode & FREAD)) 2282 return (EACCES); 2283 2284 if (ddi_copyout((caddr_t)&md_nunits, data, 2285 sizeof (set_t), mode) != 0) { 2286 err = EFAULT; 2287 break; 2288 } 2289 break; 2290 } 2291 2292 case MD_IOCGVERSION: 2293 { 2294 uint_t dversion = MD_DVERSION; 2295 2296 if (! (mode & FREAD)) 2297 return (EACCES); 2298 2299 if (ddi_copyout((caddr_t)&dversion, data, 2300 sizeof (dversion), mode) != 0) { 2301 err = EFAULT; 2302 break; 2303 } 2304 break; 2305 } 2306 2307 case MD_IOCSET_FLAGS: 2308 { 2309 if (! (mode & FWRITE)) 2310 return (EACCES); 2311 2312 sz = sizeof (md_set_userflags_t); 2313 d = kmem_alloc(sz, KM_SLEEP); 2314 2315 if (ddi_copyin(data, d, sz, mode)) { 2316 err = EFAULT; 2317 break; 2318 } 2319 2320 /* check data integrity */ 2321 if (MD_MIN2SET(((md_set_userflags_t *)d)->mnum) >= md_nsets) { 2322 err = EINVAL; 2323 break; 2324 } 2325 2326 err = setuserflags((md_set_userflags_t *)d, lockp); 2327 break; 2328 } 2329 2330 case MD_IOCRENAME: 2331 { 2332 if (! (mode & FWRITE)) { 2333 return (EACCES); 2334 } 2335 2336 sz = sizeof (md_rename_t); 2337 d = kmem_alloc(sz, KM_SLEEP); 2338 2339 if (ddi_copyin(data, d, sz, mode)) { 2340 err = EFAULT; 2341 break; 2342 } 2343 2344 err = md_rename((md_rename_t *)d, lockp); 2345 break; 2346 } 2347 2348 case MD_IOCISOPEN: 2349 { 2350 md_isopen_t *p; 2351 mdi_unit_t *ui; 2352 minor_t mnum; 2353 2354 if (! (mode & FREAD)) 2355 return (EACCES); 2356 2357 sz = sizeof (md_isopen_t); 2358 d = kmem_alloc(sz, KM_SLEEP); 2359 2360 if (ddi_copyin(data, d, sz, mode)) { 2361 err = EFAULT; 2362 break; 2363 } 2364 2365 p = (md_isopen_t *)d; 2366 if ((p->dev <= 0) || (md_getmajor(p->dev)) != md_major) { 2367 err = EINVAL; 2368 break; 2369 } 2370 2371 mnum = md_getminor(p->dev); 2372 if ((ui = MDI_UNIT(mnum)) == NULL) { 2373 err = mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, mnum); 2374 break; 2375 } 2376 2377 p->isopen = md_unit_isopen(ui); 2378 break; 2379 } 2380 2381 case MD_MED_GET_LST: 2382 { 2383 mddb_med_parm_t *medpp; 2384 2385 if (! (mode & FREAD)) 2386 return (EACCES); 2387 2388 sz = sizeof (mddb_med_parm_t); 2389 d = kmem_alloc(sz, KM_SLEEP); 2390 2391 if (ddi_copyin(data, d, sz, mode) != 0) { 2392 err = EFAULT; 2393 break; 2394 } 2395 2396 medpp = (mddb_med_parm_t *)d; 2397 2398 err = getmed_ioctl(medpp, mode); 2399 break; 2400 } 2401 2402 case MD_MED_SET_LST: 2403 { 2404 mddb_med_parm_t *medpp; 2405 2406 if (! (mode & FWRITE)) 2407 return (EACCES); 2408 2409 sz = sizeof (mddb_med_parm_t); 2410 d = kmem_alloc(sz, KM_SLEEP); 2411 2412 if (ddi_copyin(data, d, sz, mode) != 0) { 2413 err = EFAULT; 2414 break; 2415 } 2416 2417 medpp = (mddb_med_parm_t *)d; 2418 2419 err = setmed_ioctl(medpp, mode); 2420 2421 break; 2422 } 2423 2424 case MD_MED_UPD_MED: 2425 { 2426 if (! (mode & FWRITE)) 2427 return (EACCES); 2428 2429 sz = sizeof (mddb_med_upd_parm_t); 2430 d = kmem_alloc(sz, KM_SLEEP); 2431 2432 if (ddi_copyin(data, d, sz, mode) != 0) { 2433 err = EFAULT; 2434 break; 2435 } 2436 2437 err = updmed_ioctl((mddb_med_upd_parm_t *)d, mode); 2438 2439 break; 2440 } 2441 2442 case MD_MED_GET_NMED: 2443 { 2444 if (! (mode & FREAD)) 2445 return (EACCES); 2446 2447 if (ddi_copyout((caddr_t)&md_nmedh, data, 2448 sizeof (int), mode) != 0) { 2449 err = EFAULT; 2450 break; 2451 } 2452 break; 2453 } 2454 2455 case MD_MED_GET_TAG: 2456 { 2457 if (! (mode & FREAD)) 2458 return (EACCES); 2459 2460 sz = sizeof (mddb_dtag_get_parm_t); 2461 d = kmem_alloc(sz, KM_SLEEP); 2462 2463 if (ddi_copyin(data, d, sz, mode) != 0) { 2464 err = EFAULT; 2465 break; 2466 } 2467 2468 err = gettag_ioctl((mddb_dtag_get_parm_t *)d, mode); 2469 2470 break; 2471 } 2472 2473 case MD_MED_USE_TAG: 2474 { 2475 if (! (mode & FWRITE)) 2476 return (EACCES); 2477 2478 sz = sizeof (mddb_dtag_use_parm_t); 2479 d = kmem_alloc(sz, KM_SLEEP); 2480 2481 if (ddi_copyin(data, d, sz, mode) != 0) { 2482 err = EFAULT; 2483 break; 2484 } 2485 2486 err = usetag_ioctl((mddb_dtag_use_parm_t *)d, mode); 2487 2488 break; 2489 } 2490 2491 case MD_MED_ACCEPT: 2492 { 2493 if (! (mode & FWRITE)) 2494 return (EACCES); 2495 2496 sz = sizeof (mddb_accept_parm_t); 2497 d = kmem_alloc(sz, KM_SLEEP); 2498 2499 if (ddi_copyin(data, d, sz, mode) != 0) { 2500 err = EFAULT; 2501 break; 2502 } 2503 2504 err = accept_ioctl((mddb_accept_parm_t *)d, mode); 2505 2506 break; 2507 } 2508 2509 case MD_MED_GET_TLEN: 2510 { 2511 if (! (mode & FREAD)) 2512 return (EACCES); 2513 2514 sz = sizeof (mddb_med_t_parm_t); 2515 d = kmem_alloc(sz, KM_SLEEP); 2516 2517 if (ddi_copyin(data, d, sz, mode) != 0) { 2518 err = EFAULT; 2519 break; 2520 } 2521 2522 err = med_get_t_size_ioctl((mddb_med_t_parm_t *)d, mode); 2523 2524 break; 2525 } 2526 2527 case MD_MED_GET_T: 2528 { 2529 if (! (mode & FREAD)) 2530 return (EACCES); 2531 2532 sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) + 2533 (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents); 2534 d = kmem_alloc(sz, KM_SLEEP); 2535 2536 if (ddi_copyin(data, d, sz, mode) != 0) { 2537 err = EFAULT; 2538 break; 2539 } 2540 2541 err = med_get_t_ioctl((mddb_med_t_parm_t *)d, mode); 2542 2543 break; 2544 } 2545 2546 case MD_MED_SET_T: 2547 { 2548 if (! (mode & FWRITE)) 2549 return (EACCES); 2550 2551 sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) + 2552 (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents); 2553 d = kmem_alloc(sz, KM_SLEEP); 2554 2555 if (ddi_copyin(data, d, sz, mode) != 0) { 2556 err = EFAULT; 2557 break; 2558 } 2559 2560 err = med_set_t_ioctl((mddb_med_t_parm_t *)d, mode); 2561 2562 break; 2563 } 2564 2565 case MD_GET_SETSTAT: 2566 { 2567 md_gs_stat_parm_t *gsp; 2568 2569 if (! (mode & FREAD)) 2570 return (EACCES); 2571 2572 sz = sizeof (md_gs_stat_parm_t); 2573 d = kmem_alloc(sz, KM_SLEEP); 2574 2575 if (ddi_copyin(data, d, sz, mode) != 0) { 2576 err = EFAULT; 2577 break; 2578 } 2579 2580 gsp = (md_gs_stat_parm_t *)d; 2581 2582 if (gsp->gs_setno > (md_nsets - 1)) { 2583 err = EINVAL; 2584 break; 2585 } 2586 2587 gsp->gs_status = md_set[gsp->gs_setno].s_status; 2588 2589 break; 2590 } 2591 2592 case MD_SETNMDID: 2593 { 2594 if (!(mode & FREAD)) 2595 return (EACCES); 2596 2597 sz = sizeof (mdnm_params_t); 2598 d = kmem_alloc(sz, KM_SLEEP); 2599 2600 if (ddi_copyin(data, d, sz, mode) != 0) { 2601 err = EFAULT; 2602 break; 2603 } 2604 2605 err = update_namespace_did_ioctl((mdnm_params_t *)d, mode); 2606 break; 2607 2608 } 2609 case MD_IOCUPD_NM: 2610 { 2611 char *dname; 2612 char *pname; 2613 uint_t devnamelen, pathnamelen; 2614 2615 if (!(mode & FREAD)) 2616 return (EACCES); 2617 2618 sz = sizeof (mdnm_params_t); 2619 d = kmem_alloc(sz, KM_SLEEP); 2620 2621 if (ddi_copyin(data, d, sz, mode) != 0) { 2622 err = EFAULT; 2623 break; 2624 } 2625 2626 devnamelen = ((mdnm_params_t *)d)->devname_len; 2627 pathnamelen = ((mdnm_params_t *)d)->pathname_len; 2628 2629 if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) || 2630 (devnamelen == 0) || (pathnamelen == 0)) { 2631 kmem_free(d, sz); 2632 return (EINVAL); 2633 } 2634 2635 /* alloc memory for devname */ 2636 dname = kmem_alloc(devnamelen + 1, KM_SLEEP); 2637 2638 if (ddi_copyin( 2639 (void *)(uintptr_t)((mdnm_params_t *)d)->devname, 2640 (void *)dname, devnamelen + 1, mode) != 0) { 2641 err = EFAULT; 2642 kmem_free(dname, devnamelen + 1); 2643 break; 2644 } 2645 2646 pname = kmem_alloc(pathnamelen + 1, KM_SLEEP); 2647 2648 if (ddi_copyin( 2649 (void *)(uintptr_t)((mdnm_params_t *)d)->pathname, 2650 (void *)pname, pathnamelen + 1, mode) != 0) { 2651 err = EFAULT; 2652 kmem_free(dname, devnamelen + 1); 2653 kmem_free(pname, pathnamelen + 1); 2654 break; 2655 } 2656 2657 err = update_namespace_ioctl((mdnm_params_t *)d, dname, pname, 2658 mode); 2659 2660 kmem_free(dname, devnamelen + 1); 2661 kmem_free(pname, pathnamelen + 1); 2662 break; 2663 } 2664 2665 case MD_IOCUPD_LOCNM: 2666 { 2667 char *dname; 2668 char *pname; 2669 uint_t devnamelen, pathnamelen; 2670 2671 if (!(mode & FREAD)) 2672 return (EACCES); 2673 2674 sz = sizeof (mdnm_params_t); 2675 d = kmem_alloc(sz, KM_SLEEP); 2676 2677 if (ddi_copyin(data, d, sz, mode) != 0) { 2678 err = EFAULT; 2679 break; 2680 } 2681 2682 devnamelen = ((mdnm_params_t *)d)->devname_len; 2683 pathnamelen = ((mdnm_params_t *)d)->pathname_len; 2684 2685 if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) || 2686 (devnamelen == 0) || (pathnamelen == 0)) { 2687 kmem_free(d, sz); 2688 return (EINVAL); 2689 } 2690 2691 /* alloc memory for devname */ 2692 dname = kmem_alloc(devnamelen + 1, KM_SLEEP); 2693 2694 if (ddi_copyin( 2695 (void *)(uintptr_t)((mdnm_params_t *)d)->devname, 2696 (void *)dname, devnamelen + 1, mode) != 0) { 2697 err = EFAULT; 2698 kmem_free(dname, devnamelen + 1); 2699 break; 2700 } 2701 2702 pname = kmem_alloc(pathnamelen + 1, KM_SLEEP); 2703 2704 if (ddi_copyin( 2705 (void *)(uintptr_t)((mdnm_params_t *)d)->pathname, 2706 (void *)pname, pathnamelen + 1, mode) != 0) { 2707 err = EFAULT; 2708 kmem_free(dname, devnamelen + 1); 2709 kmem_free(pname, pathnamelen + 1); 2710 break; 2711 } 2712 2713 err = update_loc_namespace_ioctl((mdnm_params_t *)d, dname, 2714 pname, mode); 2715 2716 kmem_free(dname, devnamelen + 1); 2717 kmem_free(pname, pathnamelen + 1); 2718 break; 2719 } 2720 2721 case MD_SET_SETSTAT: 2722 { 2723 #ifdef DEBUG 2724 /* Can be used to set the s_status flags from user code */ 2725 md_gs_stat_parm_t *gsp; 2726 2727 if (! (mode & FWRITE)) 2728 return (EACCES); 2729 2730 sz = sizeof (md_gs_stat_parm_t); 2731 d = kmem_alloc(sz, KM_SLEEP); 2732 2733 if (ddi_copyin(data, d, sz, mode) != 0) { 2734 err = EFAULT; 2735 break; 2736 } 2737 2738 gsp = (md_gs_stat_parm_t *)d; 2739 2740 if (gsp->gs_setno > (md_nsets - 1)) { 2741 err = EINVAL; 2742 break; 2743 } 2744 2745 md_set[gsp->gs_setno].s_status = gsp->gs_status; 2746 2747 #endif /* DEBUG */ 2748 break; 2749 } 2750 2751 case MD_IOCGET_DID: 2752 { 2753 if (! (mode & FREAD)) 2754 return (EACCES); 2755 2756 sz = sizeof (mdnm_params_t); 2757 d = kmem_alloc(sz, KM_SLEEP); 2758 2759 if (ddi_copyin(data, d, sz, mode) != 0) { 2760 err = EFAULT; 2761 break; 2762 } 2763 2764 err = getdid_ioctl((mdnm_params_t *)d, mode); 2765 break; 2766 } 2767 2768 case MD_IOCSET_DID: 2769 { 2770 if (! (mode & FWRITE)) 2771 return (EACCES); 2772 2773 sz = sizeof (mdnm_params_t); 2774 d = kmem_alloc(sz, KM_SLEEP); 2775 2776 if (ddi_copyin(data, d, sz, mode) != 0) { 2777 err = EFAULT; 2778 break; 2779 } 2780 2781 err = setdid_ioctl((mdnm_params_t *)d, mode); 2782 break; 2783 } 2784 2785 case MD_IOCGET_DIDMIN: 2786 { 2787 if (! (mode & FREAD)) 2788 return (EACCES); 2789 2790 sz = sizeof (mdnm_params_t); 2791 d = kmem_alloc(sz, KM_SLEEP); 2792 2793 if (ddi_copyin(data, d, sz, mode) != 0) { 2794 err = EFAULT; 2795 break; 2796 } 2797 2798 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2799 err = EINVAL; 2800 break; 2801 } 2802 2803 err = getdidmin_ioctl((mdnm_params_t *)d, mode); 2804 break; 2805 } 2806 2807 case MD_IOCDID_STAT: 2808 { 2809 if (!(mode & FREAD)) 2810 return (EACCES); 2811 2812 mddb_didstat_case = 1; 2813 2814 err = mddb_didstat_from_user(&d, data, mode, &ds_ctd_addr); 2815 2816 if (err) { 2817 return (err); 2818 } 2819 2820 err = didstat_ioctl((md_i_didstat_t *)d); 2821 break; 2822 } 2823 2824 case MD_UPGRADE_STAT: 2825 { 2826 if (! (mode & FREAD)) 2827 return (EACCES); 2828 2829 if (ddi_copyout((caddr_t)&md_in_upgrade, data, 2830 sizeof (int), mode) != 0) { 2831 err = EFAULT; 2832 break; 2833 } 2834 break; 2835 } 2836 2837 case MD_SETMASTER: 2838 { 2839 if (! (mode & FREAD)) 2840 return (EACCES); 2841 2842 sz = sizeof (mddb_setmaster_config_t); 2843 d = kmem_alloc(sz, KM_SLEEP); 2844 2845 if (ddi_copyin(data, d, sz, mode) != 0) { 2846 err = EFAULT; 2847 break; 2848 } 2849 2850 err = mddb_setmaster_ioctl((mddb_setmaster_config_t *)d); 2851 break; 2852 } 2853 2854 case MD_MN_SET_DOORH: 2855 { 2856 /* This ioctl sets the global kernel variable mdmn_door_handle */ 2857 if (ddi_copyin(data, &mdmn_door_did, sizeof (int), mode) != 0) { 2858 err = EFAULT; 2859 } else { 2860 err = 0; 2861 } 2862 mdmn_door_handle = door_ki_lookup(mdmn_door_did); 2863 2864 break; 2865 } 2866 2867 #ifdef DEBUG 2868 case MD_MN_CHECK_DOOR1: 2869 { 2870 /* This ioctl sends a message through a previously opened door */ 2871 int ret; 2872 int msg_test = 11111111; 2873 int nloops = 0; 2874 set_t setno; 2875 md_mn_kresult_t *result; 2876 uint_t flags = MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST; 2877 2878 result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP); 2879 if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) { 2880 err = EFAULT; 2881 } else { 2882 err = 0; 2883 } 2884 2885 /* 2886 * This is a way to tell ksend_message() to use different sets. 2887 * Odd numbers go to set 1 even numbers go to set 2 2888 */ 2889 if (nloops & 0x1) { 2890 setno = 1; 2891 } else { 2892 setno = 2; 2893 } 2894 while (nloops--) { 2895 ret = mdmn_ksend_message( 2896 setno, 2897 MD_MN_MSG_TEST1, 2898 flags, 2899 (char *)&msg_test, 2900 sizeof (msg_test), 2901 result); 2902 2903 if (ret != 0) { 2904 printf("mdmn_ksend_message failed (%d)\n", ret); 2905 } 2906 } 2907 kmem_free(result, sizeof (md_mn_kresult_t)); 2908 2909 break; 2910 } 2911 2912 case MD_MN_CHECK_DOOR2: 2913 { 2914 /* This ioctl sends a message through a previously opened door */ 2915 int ret; 2916 int msg_test = 22222222; 2917 int nloops = 0; 2918 md_mn_kresult_t *result; 2919 set_t setno; 2920 uint_t flags = MD_MSGF_NO_LOG; 2921 2922 result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP); 2923 if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) { 2924 err = EFAULT; 2925 } else { 2926 err = 0; 2927 } 2928 /* 2929 * This is a way to tell ksend_message() to use different sets. 2930 * Odd numbers go to set 1 even numbers go to set 2 2931 */ 2932 if (nloops & 0x1) { 2933 setno = 1; 2934 } else { 2935 setno = 2; 2936 } 2937 while (nloops--) { 2938 ret = mdmn_ksend_message( 2939 setno, 2940 MD_MN_MSG_TEST2, 2941 flags, 2942 (char *)&msg_test, 2943 sizeof (msg_test), 2944 result); 2945 2946 if (ret != 0) { 2947 printf("mdmn_ksend_message failed (%d)\n", ret); 2948 } 2949 } 2950 kmem_free(result, sizeof (md_mn_kresult_t)); 2951 2952 break; 2953 } 2954 #endif 2955 2956 case MD_MN_OPEN_TEST: 2957 { 2958 sz = sizeof (md_clu_open_t); 2959 d = kmem_alloc(sz, KM_SLEEP); 2960 2961 if (ddi_copyin(data, d, sizeof (md_clu_open_t), mode) != 0) { 2962 err = EFAULT; 2963 break; 2964 } 2965 err = md_clu_ioctl((md_clu_open_t *)d); 2966 break; 2967 } 2968 2969 case MD_MN_SET_NODEID: 2970 { 2971 if (! (mode & FWRITE)) 2972 return (EACCES); 2973 2974 sz = sizeof (mddb_set_node_params_t); 2975 d = kmem_alloc(sz, KM_SLEEP); 2976 2977 if (ddi_copyin(data, d, sz, mode) != 0) { 2978 err = EFAULT; 2979 break; 2980 } 2981 snp = (mddb_set_node_params_t *)d; 2982 2983 if (snp->sn_setno >= md_nsets) { 2984 err = EINVAL; 2985 break; 2986 } 2987 2988 md_set[snp->sn_setno].s_nodeid = snp->sn_nodeid; 2989 2990 if (md_mn_mynode_id == MD_MN_INVALID_NID) 2991 md_mn_mynode_id = snp->sn_nodeid; 2992 #ifdef DEBUG 2993 else if (md_mn_mynode_id != snp->sn_nodeid) 2994 cmn_err(CE_WARN, "Previously set nodeid 0x%x for this" 2995 "node doesn't match nodeid being set 0x%x\n", 2996 md_mn_mynode_id, snp->sn_nodeid); 2997 #endif /* DEBUG */ 2998 err = 0; 2999 break; 3000 } 3001 case MD_IOCGUNIQMSGID: 3002 { 3003 md_mn_msgid_t msgid; 3004 struct timeval32 tv; 3005 3006 if (! (mode & FREAD)) 3007 return (EACCES); 3008 3009 uniqtime32(&tv); 3010 3011 /* high 32 bits are the seconds */ 3012 msgid.mid_time = (u_longlong_t)tv.tv_sec << 32; 3013 /* low 32 bits are the micro secs */ 3014 msgid.mid_time |= tv.tv_usec; 3015 3016 msgid.mid_nid = md_mn_mynode_id; 3017 /* 3018 * This is never called for submessages, so we better 3019 * null out the submessage ID 3020 */ 3021 msgid.mid_smid = 0; 3022 3023 if (ddi_copyout((caddr_t)&msgid, data, sizeof (msgid), mode) 3024 != 0) { 3025 err = EFAULT; 3026 break; 3027 } 3028 break; 3029 } 3030 3031 /* 3032 * suspend the IO's for a given set number. 3033 * 3034 * If setno = 0 is specified, try operation on all snarfed MN disksets. 3035 * If there are no snarfed MN disksets, then return success. 3036 * 3037 * If a specific set number is given, then return EINVAL if unable 3038 * to perform operation. 3039 */ 3040 case MD_MN_SUSPEND_SET: 3041 { 3042 set_t setno; 3043 int rval = 0; 3044 int i; 3045 3046 if (! (mode & FWRITE)) 3047 return (EACCES); 3048 3049 if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) { 3050 return (EFAULT); 3051 } 3052 if (setno >= MD_MAXSETS) { 3053 return (EINVAL); 3054 } 3055 3056 mutex_enter(&md_mx); 3057 if (setno == 0) { 3058 /* if set number is 0, we walk all sets */ 3059 for (i = 1; i <= (MD_MAXSETS - 1); i++) { 3060 if ((md_set[i].s_status & 3061 (MD_SET_SNARFED|MD_SET_MNSET)) == 3062 (MD_SET_SNARFED|MD_SET_MNSET)) { 3063 md_set[i].s_status |= MD_SET_HALTED; 3064 } 3065 } 3066 } else { 3067 /* If unable to halt specified set, set EINVAL */ 3068 if ((md_set[setno].s_status & 3069 (MD_SET_SNARFED|MD_SET_MNSET)) == 3070 (MD_SET_SNARFED|MD_SET_MNSET)) { 3071 md_set[setno].s_status |= MD_SET_HALTED; 3072 } else { 3073 rval = EINVAL; 3074 } 3075 } 3076 mutex_exit(&md_mx); 3077 return (rval); 3078 } 3079 3080 /* 3081 * resume the IO's for a given set number. 3082 * 3083 * If setno = 0 is specified, try operation on all snarfed MN disksets. 3084 * If there are no snarfed MN disksets, then return success. 3085 * 3086 * If a specific set number is given, then return EINVAL if unable 3087 * to perform operation. 3088 */ 3089 case MD_MN_RESUME_SET: 3090 { 3091 set_t setno; 3092 int resumed_set = 0; 3093 int rval = 0; 3094 int i; 3095 3096 if (! (mode & FWRITE)) 3097 return (EACCES); 3098 3099 if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) { 3100 return (EFAULT); 3101 } 3102 if (setno >= MD_MAXSETS) { 3103 return (EINVAL); 3104 } 3105 3106 /* if 0 is specified as the set number, we walk all sets */ 3107 mutex_enter(&md_mx); 3108 if (setno == 0) { 3109 /* if set number is 0, we walk all sets */ 3110 for (i = 1; i <= (MD_MAXSETS - 1); i++) { 3111 if ((md_set[i].s_status & 3112 (MD_SET_SNARFED|MD_SET_MNSET)) == 3113 (MD_SET_SNARFED|MD_SET_MNSET)) { 3114 md_set[i].s_status &= ~MD_SET_HALTED; 3115 resumed_set = 1; 3116 } 3117 } 3118 } else { 3119 /* If unable to resume specified set, set EINVAL */ 3120 if ((md_set[setno].s_status & 3121 (MD_SET_SNARFED|MD_SET_MNSET)) == 3122 (MD_SET_SNARFED|MD_SET_MNSET)) { 3123 md_set[setno].s_status &= ~MD_SET_HALTED; 3124 resumed_set = 1; 3125 } else { 3126 rval = EINVAL; 3127 } 3128 } 3129 3130 /* 3131 * In case we actually resumed at least one set, 3132 * Inform all threads waiting for this change 3133 */ 3134 if (resumed_set == 1) { 3135 cv_broadcast(&md_cv); 3136 } 3137 3138 mutex_exit(&md_mx); 3139 return (rval); 3140 } 3141 3142 case MD_MN_MDDB_PARSE: 3143 { 3144 if (! (mode & FWRITE)) 3145 return (EACCES); 3146 3147 sz = sizeof (mddb_parse_parm_t); 3148 d = kmem_alloc(sz, KM_SLEEP); 3149 3150 if (ddi_copyin(data, d, sz, mode) != 0) { 3151 err = EFAULT; 3152 break; 3153 } 3154 err = mddb_parse((mddb_parse_parm_t *)d); 3155 break; 3156 3157 } 3158 3159 case MD_MN_MDDB_BLOCK: 3160 { 3161 if (! (mode & FWRITE)) 3162 return (EACCES); 3163 3164 sz = sizeof (mddb_block_parm_t); 3165 d = kmem_alloc(sz, KM_SLEEP); 3166 3167 if (ddi_copyin(data, d, sz, mode) != 0) { 3168 err = EFAULT; 3169 break; 3170 } 3171 err = mddb_block((mddb_block_parm_t *)d); 3172 break; 3173 3174 } 3175 3176 case MD_MN_MDDB_OPTRECFIX: 3177 { 3178 if (! (mode & FWRITE)) 3179 return (EACCES); 3180 3181 sz = sizeof (mddb_optrec_parm_t); 3182 d = kmem_alloc(sz, KM_SLEEP); 3183 3184 if (ddi_copyin(data, d, sz, mode) != 0) { 3185 err = EFAULT; 3186 break; 3187 } 3188 err = mddb_optrecfix((mddb_optrec_parm_t *)d); 3189 break; 3190 3191 } 3192 3193 case MD_MN_CHK_WRT_MDDB: 3194 { 3195 if (! (mode & FWRITE)) 3196 return (EACCES); 3197 3198 sz = sizeof (mddb_config_t); 3199 d = kmem_alloc(sz, KM_SLEEP); 3200 3201 if (ddi_copyin(data, d, sz, mode) != 0) { 3202 err = EFAULT; 3203 break; 3204 } 3205 3206 err = mddb_check_write_ioctl((mddb_config_t *)d); 3207 break; 3208 } 3209 3210 case MD_MN_SET_SETFLAGS: 3211 case MD_MN_GET_SETFLAGS: 3212 { 3213 if (! (mode & FREAD)) 3214 return (EACCES); 3215 3216 sz = sizeof (mddb_setflags_config_t); 3217 d = kmem_alloc(sz, KM_SLEEP); 3218 3219 if (ddi_copyin(data, d, sz, mode) != 0) { 3220 err = EFAULT; 3221 break; 3222 } 3223 3224 err = mddb_setflags_ioctl((mddb_setflags_config_t *)d); 3225 break; 3226 } 3227 3228 case MD_MN_COMMD_ERR: 3229 { 3230 md_mn_commd_err_t *cmp; 3231 char *msg; 3232 3233 sz = sizeof (md_mn_commd_err_t); 3234 d = kmem_zalloc(sz, KM_SLEEP); 3235 3236 if (ddi_copyin(data, d, sz, mode) != 0) { 3237 err = EFAULT; 3238 break; 3239 } 3240 3241 cmp = (md_mn_commd_err_t *)d; 3242 if (cmp->size > MAXPATHLEN) { 3243 err = EINVAL; 3244 break; 3245 } 3246 3247 msg = (char *)kmem_zalloc(cmp->size + 1, KM_SLEEP); 3248 if (ddi_copyin((caddr_t)(uintptr_t)cmp->md_message, msg, 3249 cmp->size, mode) != 0) { 3250 kmem_free(msg, cmp->size + 1); 3251 err = EFAULT; 3252 break; 3253 } 3254 cmn_err(CE_WARN, "%s\n", msg); 3255 kmem_free(msg, cmp->size + 1); 3256 break; 3257 } 3258 3259 case MD_IOCMAKE_DEV: 3260 { 3261 if (! (mode & FWRITE)) 3262 return (EACCES); 3263 3264 sz = sizeof (md_mkdev_params_t); 3265 3266 if ((d = kmem_alloc(sz, KM_NOSLEEP)) == NULL) 3267 return (ENOMEM); 3268 3269 if (ddi_copyin(data, d, sz, mode) != 0) { 3270 err = EFAULT; 3271 break; 3272 } 3273 3274 err = mkdev_ioctl((md_mkdev_params_t *)d); 3275 break; 3276 } 3277 3278 case MD_IOCREM_DEV: 3279 { 3280 set_t setno; 3281 3282 if (! (mode & FWRITE)) 3283 return (EACCES); 3284 3285 sz = sizeof (minor_t); 3286 3287 d = kmem_zalloc(sz, KM_SLEEP); 3288 3289 if (ddi_copyin(data, d, sz, mode) != 0) { 3290 err = EFAULT; 3291 break; 3292 } 3293 3294 /* 3295 * This ioctl is called to cleanup the device name 3296 * space when metainit fails or -n is invoked 3297 * In this case, reclaim the dispatched un slot 3298 */ 3299 setno = MD_MIN2SET(*(minor_t *)d); 3300 if (md_set[setno].s_un_next <= 0) { 3301 err = EFAULT; 3302 break; 3303 } else { 3304 md_set[setno].s_un_next--; 3305 } 3306 3307 /* 3308 * Attempt to remove the assocated device node 3309 */ 3310 md_remove_minor_node(*(minor_t *)d); 3311 break; 3312 } 3313 3314 /* 3315 * Update md_mn_commd_present global to reflect presence or absence of 3316 * /usr/sbin/rpc.mdcommd. This allows us to determine if an RPC failure 3317 * is expected during a mdmn_ksend_message() handshake. If the commd is 3318 * not present then an RPC failure is acceptable. If the commd _is_ 3319 * present then an RPC failure means we have an inconsistent view across 3320 * the cluster. 3321 */ 3322 case MD_MN_SET_COMMD_RUNNING: 3323 { 3324 if (! (mode & FWRITE)) 3325 return (EACCES); 3326 3327 md_mn_commd_present = (int)(intptr_t)data; 3328 err = 0; 3329 break; 3330 } 3331 3332 case MD_IOCIMP_LOAD: 3333 { 3334 if (! (mode & FWRITE)) 3335 return (EACCES); 3336 3337 mddb_config_case = 1; 3338 3339 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 3340 &c_old_devid_addr); 3341 3342 if (err) { 3343 return (err); 3344 } 3345 3346 err = md_imp_snarf_set((mddb_config_t *)d); 3347 break; 3348 3349 } 3350 3351 case MD_DB_LBINITTIME: 3352 { 3353 if (! (mode & FWRITE)) 3354 return (EACCES); 3355 3356 mddb_config_case = 1; 3357 3358 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 3359 &c_old_devid_addr); 3360 3361 if (err) 3362 return (err); 3363 3364 err = get_lb_inittime_ioctl((mddb_config_t *)d); 3365 break; 3366 } 3367 case MD_IOCUPDATE_NM_RR_DID: 3368 { 3369 if (! (mode & FWRITE)) 3370 return (EACCES); 3371 3372 mddb_config_case = 1; 3373 3374 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 3375 &c_old_devid_addr); 3376 3377 if (err) 3378 return (err); 3379 3380 err = md_update_nm_rr_did_ioctl((mddb_config_t *)d); 3381 break; 3382 } 3383 default: 3384 return (ENOTTY); /* used by next level up */ 3385 } 3386 3387 /* 3388 * copyout and free any args 3389 */ 3390 if (mddb_config_case) { 3391 err_to_user = mddb_config_to_user(d, data, mode, c_devid_addr, 3392 c_old_devid_addr); 3393 } else if (mddb_didstat_case) { 3394 err_to_user = mddb_didstat_to_user(d, data, mode, ds_ctd_addr); 3395 } else if (sz != 0) { 3396 if (ddi_copyout(d, data, sz, mode) != 0) { 3397 err = EFAULT; 3398 } 3399 kmem_free(d, sz); 3400 } 3401 3402 if (err) 3403 return (err); 3404 return (err_to_user); 3405 } 3406 3407 int 3408 md_admin_ioctl(md_dev64_t dev, int cmd, caddr_t data, int mode, IOLOCK *lockp) 3409 { 3410 md_driver_t drv; 3411 int modindex; 3412 int err; 3413 3414 /* 3415 * see if we can do this without involving the subdriver 3416 */ 3417 if ((err = md_base_ioctl(dev, cmd, data, mode, lockp)) != ENOTTY) 3418 return (err); 3419 3420 /* 3421 * see what subdriver we need 3422 */ 3423 if (! ISMDIOC(cmd)) 3424 return (ENOTTY); 3425 3426 if ((!NODBNEEDED(cmd)) && md_snarf_db_set(MD_LOCAL_SET, NULL) != 0) 3427 return (ENODEV); 3428 3429 if (ddi_copyin(data, (caddr_t)&drv, sizeof (drv), mode) != 0) 3430 return (EFAULT); 3431 3432 /* 3433 * load subdriver if not already loaded 3434 */ 3435 if (((modindex = md_getmodindex(&drv, 0, NODBNEEDED(cmd))) == -1) || 3436 (md_ops[modindex]->md_ioctl == NULL)) 3437 return (ENOTTY); 3438 3439 /* 3440 * dispatch to subdriver 3441 */ 3442 return ((*md_ops[modindex]->md_ioctl)(md_dev64_to_dev(dev), cmd, data, 3443 mode, lockp)); 3444 } 3445 3446 void 3447 md_get_geom( 3448 md_unit_t *un, 3449 struct dk_geom *gp 3450 ) 3451 { 3452 diskaddr_t tb = un->c.un_total_blocks; 3453 uint_t cylsize = un->c.un_nhead * un->c.un_nsect; 3454 3455 bzero((caddr_t)gp, sizeof (*gp)); 3456 gp->dkg_nhead = un->c.un_nhead; 3457 gp->dkg_nsect = un->c.un_nsect; 3458 gp->dkg_rpm = un->c.un_rpm; 3459 gp->dkg_write_reinstruct = un->c.un_wr_reinstruct; 3460 gp->dkg_read_reinstruct = un->c.un_rd_reinstruct; 3461 gp->dkg_ncyl = (ushort_t)(tb / cylsize); 3462 if (! (un->c.un_flag & MD_LABELED)) /* skip first cyl */ 3463 gp->dkg_ncyl += 1; 3464 gp->dkg_pcyl = gp->dkg_ncyl; 3465 } 3466 3467 void 3468 md_get_vtoc(md_unit_t *un, struct vtoc *vtoc) 3469 { 3470 caddr_t v; 3471 mddb_recstatus_t status; 3472 struct vtoc32 *vt32; 3473 3474 /* 3475 * Return vtoc structure fields in the provided VTOC area, addressed 3476 * by *vtoc. 3477 * 3478 */ 3479 3480 if (un->c.un_vtoc_id) { 3481 status = mddb_getrecstatus(un->c.un_vtoc_id); 3482 if (status == MDDB_OK) { 3483 v = mddb_getrecaddr(un->c.un_vtoc_id); 3484 /* if this seems to be a sane vtoc, just copy it ... */ 3485 if (((struct vtoc *)v)->v_sanity == VTOC_SANE) { 3486 bcopy(v, (caddr_t)vtoc, sizeof (struct vtoc)); 3487 } else { 3488 /* ... else assume a vtoc32 was stored here */ 3489 vt32 = (struct vtoc32 *)v; 3490 vtoc32tovtoc((*vt32), (*vtoc)); 3491 } 3492 if (un->c.un_flag & MD_LABELED) 3493 vtoc->v_part[0].p_start = 0; 3494 else 3495 vtoc->v_part[0].p_start = 3496 un->c.un_nhead * un->c.un_nsect; 3497 vtoc->v_part[0].p_size = un->c.un_total_blocks; 3498 vtoc->v_version = V_VERSION; 3499 vtoc->v_sectorsz = DEV_BSIZE; 3500 return; 3501 } 3502 3503 un->c.un_vtoc_id = 0; 3504 mddb_commitrec_wrapper(un->c.un_record_id); 3505 } 3506 3507 bzero((caddr_t)vtoc, sizeof (struct vtoc)); 3508 vtoc->v_sanity = VTOC_SANE; 3509 vtoc->v_nparts = 1; 3510 vtoc->v_version = V_VERSION; 3511 vtoc->v_sectorsz = DEV_BSIZE; 3512 if (un->c.un_flag & MD_LABELED) 3513 vtoc->v_part[0].p_start = 0; 3514 else 3515 vtoc->v_part[0].p_start = un->c.un_nhead * un->c.un_nsect; 3516 vtoc->v_part[0].p_size = un->c.un_total_blocks; 3517 } 3518 3519 int 3520 md_set_vtoc(md_unit_t *un, struct vtoc *vtoc) 3521 { 3522 3523 struct partition *vpart; 3524 int i; 3525 mddb_recid_t recid; 3526 mddb_recid_t recids[3]; 3527 mddb_recstatus_t status; 3528 caddr_t v; 3529 daddr_t sb; 3530 3531 /* 3532 * Sanity-check the vtoc 3533 */ 3534 if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts != 1) 3535 return (EINVAL); 3536 3537 /* don't allow to create a vtoc for a big metadevice */ 3538 if (un->c.un_revision & MD_64BIT_META_DEV) 3539 return (ENOTSUP); 3540 /* 3541 * Validate the partition table 3542 */ 3543 vpart = vtoc->v_part; 3544 for (i = 0; i < V_NUMPAR; i++, vpart++) { 3545 if (i == 0) { 3546 if (un->c.un_flag & MD_LABELED) 3547 sb = 0; 3548 else 3549 sb = un->c.un_nhead * un->c.un_nsect; 3550 if (vpart->p_start != sb) 3551 return (EINVAL); 3552 if (vpart->p_size != (long)un->c.un_total_blocks) 3553 return (EINVAL); 3554 continue; 3555 } 3556 /* all other partitions must be zero */ 3557 if (vpart->p_start != 0) 3558 return (EINVAL); 3559 if (vpart->p_size != 0) 3560 return (EINVAL); 3561 } 3562 3563 if (un->c.un_vtoc_id) { 3564 recid = un->c.un_vtoc_id; 3565 status = mddb_getrecstatus(recid); 3566 if (status == MDDB_OK) { 3567 /* 3568 * If there's enough space in the record, and the 3569 * existing record is a vtoc record (not EFI), 3570 * we just can use the existing space. 3571 * Otherwise, we create a new MDDB_VTOC record for 3572 * this unit. 3573 */ 3574 if ((mddb_getrecsize(recid) >= sizeof (struct vtoc)) && 3575 ((un->c.un_flag & MD_EFILABEL) == 0)) { 3576 v = mddb_getrecaddr(recid); 3577 bcopy((caddr_t)vtoc, v, sizeof (struct vtoc)); 3578 mddb_commitrec_wrapper(recid); 3579 recids[0] = recid; 3580 recids[1] = un->c.un_record_id; 3581 recids[2] = 0; 3582 un->c.un_flag &= ~MD_EFILABEL; 3583 mddb_commitrecs_wrapper(recids); 3584 return (0); 3585 } 3586 3587 un->c.un_vtoc_id = 0; 3588 mddb_commitrec_wrapper(un->c.un_record_id); 3589 mddb_deleterec_wrapper(recid); 3590 } 3591 } 3592 3593 recid = mddb_createrec(sizeof (struct vtoc), MDDB_VTOC, 0, 3594 MD_CRO_32BIT, MD_UN2SET(un)); 3595 3596 if (recid < 0) { 3597 return (ENOSPC); 3598 } 3599 3600 recids[0] = recid; 3601 recids[1] = un->c.un_record_id; 3602 recids[2] = 0; 3603 v = mddb_getrecaddr(recid); 3604 bcopy((caddr_t)vtoc, v, sizeof (struct vtoc)); 3605 3606 un->c.un_vtoc_id = recid; 3607 un->c.un_flag &= ~MD_EFILABEL; 3608 mddb_commitrecs_wrapper(recids); 3609 return (0); 3610 } 3611 3612 3613 void 3614 md_get_cgapart(md_unit_t *un, struct dk_map *dkmapp) 3615 { 3616 3617 /* skip the first cyl */ 3618 dkmapp->dkl_cylno = 1; 3619 3620 dkmapp->dkl_nblk = (daddr_t)un->c.un_total_blocks; 3621 } 3622 3623 static struct uuid md_efi_reserved = EFI_RESERVED; 3624 3625 /* 3626 * md_get_efi 3627 * INPUT: 3628 * un; the md_unit 3629 * buf; the buffer that is preallocated by the calling routine and 3630 * capable of taking the EFI label for this unit 3631 * OUTPUT: 3632 * A filled buffer, containing one struct efi_gpt followed by one 3633 * struct efi_gpe, because a md efi only has one valid partition 3634 * We fetch that date either from the mddb (like vtoc) 3635 * or we a fake an EFI label. 3636 * 3637 * NOTES: 3638 * We do not provide for any global unique identifiers, 3639 * We also use the field c.un_vtoc_id, as the semantic is very similar 3640 * When we are called, it's already checked, that this unit has an EFI 3641 * label and not a vtoc 3642 */ 3643 3644 void 3645 md_get_efi(md_unit_t *un, char *buf) 3646 { 3647 caddr_t v; 3648 efi_gpt_t *efi_header = (efi_gpt_t *)buf; 3649 efi_gpe_t *efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t)); 3650 mddb_recstatus_t status; 3651 3652 /* first comes the header */ 3653 efi_header->efi_gpt_Signature = LE_64(EFI_SIGNATURE); 3654 efi_header->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t)); 3655 efi_header->efi_gpt_NumberOfPartitionEntries = LE_32(1); 3656 efi_header->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t)); 3657 efi_header->efi_gpt_LastUsableLBA = LE_64(un->c.un_total_blocks - 1); 3658 efi_header->efi_gpt_FirstUsableLBA = 0; 3659 efi_header->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT); 3660 3661 /* 3662 * We don't fill out any of these: 3663 * 3664 * efi_header->efi_gpt_HeaderCRC32; 3665 * efi_header->efi_gpt_DiskGUID; 3666 * efi_header->efi_gpt_PartitionEntryArrayCRC32; 3667 * efi_header->efi_gpt_Reserved1; 3668 * efi_header->efi_gpt_MyLBA; 3669 * efi_header->efi_gpt_AlternateLBA; 3670 * efi_header->efi_gpt_Reserved2[LEN_EFI_PAD]; 3671 * efi_header->efi_gpt_PartitionEntryLBA; 3672 */ 3673 3674 /* 3675 * We copy back one partition, of type reserved, 3676 * which may contain the name of the metadevice 3677 * (this is what was used to be v_volume for a vtoc device) 3678 * if no name is stored in the vtoc record, we hand an empty name 3679 * to the user 3680 */ 3681 3682 UUID_LE_CONVERT(efi_part->efi_gpe_PartitionTypeGUID, md_efi_reserved); 3683 if (un->c.un_flag & MD_LABELED) 3684 efi_part->efi_gpe_StartingLBA = LE_64(1ULL); 3685 else 3686 efi_part->efi_gpe_StartingLBA = 0; 3687 3688 efi_part->efi_gpe_EndingLBA = LE_64(un->c.un_total_blocks - 1); 3689 3690 if (un->c.un_vtoc_id) { 3691 status = mddb_getrecstatus(un->c.un_vtoc_id); 3692 if (status == MDDB_OK) { 3693 v = mddb_getrecaddr(un->c.un_vtoc_id); 3694 bcopy(v, (caddr_t)&(efi_part->efi_gpe_PartitionName), 3695 MD_EFI_PARTNAME_BYTES); 3696 return; 3697 } 3698 un->c.un_vtoc_id = 0; 3699 mddb_commitrec_wrapper(un->c.un_record_id); 3700 } 3701 3702 /* 3703 * We don't fill out any of these 3704 * efi_part->efi_gpe_UniquePartitionGUID 3705 * efi_part->efi_gpe_Attributes 3706 */ 3707 } 3708 3709 3710 /* 3711 * md_set_efi 3712 * INPUT: 3713 * un; a md_unit 3714 * buf; a buffer that is holding an EFI label for this unit 3715 * 3716 * PURPOSE: 3717 * Perform some sanity checks on the EFI label provided, 3718 * Then store efi_gpe_PartitionName in the mddb 3719 * and link the unit's c.un_vtoc_id field to it. 3720 * 3721 * RETURN: 3722 * EINVAL if any of the sanity checks fail 3723 * 0 on succes 3724 * 3725 * NOTES: 3726 * We do not provide for any global unique identifiers, 3727 * We also use the field c.un_vtoc_id, as the semantic is very similar 3728 * When we are called, it's already checked, that this unit has an EFI 3729 * label and not a vtoc 3730 */ 3731 3732 3733 int 3734 md_set_efi(md_unit_t *un, char *buf) 3735 { 3736 3737 mddb_recid_t recid; 3738 mddb_recid_t recids[3]; 3739 mddb_recstatus_t status; 3740 caddr_t v; 3741 efi_gpt_t *efi_header = (efi_gpt_t *)buf; 3742 efi_gpe_t *efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t)); 3743 struct uuid md_efi_reserved_le; 3744 3745 /* 3746 * Sanity-check the EFI label 3747 */ 3748 if ((efi_header->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) || 3749 (efi_header->efi_gpt_NumberOfPartitionEntries != LE_32(1))) 3750 return (EINVAL); 3751 3752 UUID_LE_CONVERT(md_efi_reserved_le, md_efi_reserved); 3753 3754 /* 3755 * Validate the partition 3756 */ 3757 if (efi_part->efi_gpe_StartingLBA != 0 || 3758 efi_part->efi_gpe_EndingLBA != LE_64(un->c.un_total_blocks - 1) || 3759 bcmp(&efi_part->efi_gpe_PartitionTypeGUID, &md_efi_reserved_le, 3760 sizeof (struct uuid))) { 3761 return (EINVAL); 3762 } 3763 /* 3764 * If no name is specified, we have nothing to do and return success. 3765 * because efi_gpe_PartitionName is in unicode form, we have to 3766 * check the first two bytes of efi_gpe_PartitionName. 3767 */ 3768 if (((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[0] == NULL) && 3769 ((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[1] == NULL)) { 3770 return (0); 3771 } 3772 3773 if (un->c.un_vtoc_id) { 3774 recid = un->c.un_vtoc_id; 3775 status = mddb_getrecstatus(recid); 3776 if (status == MDDB_OK) { 3777 /* 3778 * If there's enough space in the record, and the 3779 * existing record is an EFI record (not vtoc), 3780 * we just can use the existing space. 3781 * Otherwise, we create a new MDDB_EFILABEL record for 3782 * this unit. 3783 */ 3784 if ((mddb_getrecsize(recid) >= MD_EFI_PARTNAME_BYTES) && 3785 (un->c.un_flag & MD_EFILABEL)) { 3786 v = mddb_getrecaddr(recid); 3787 bcopy((caddr_t)&efi_part->efi_gpe_PartitionName, 3788 v, MD_EFI_PARTNAME_BYTES); 3789 mddb_commitrec_wrapper(recid); 3790 return (0); 3791 } 3792 3793 un->c.un_vtoc_id = 0; 3794 mddb_commitrec_wrapper(un->c.un_record_id); 3795 mddb_deleterec_wrapper(recid); 3796 } 3797 } 3798 3799 recid = mddb_createrec(MD_EFI_PARTNAME_BYTES, MDDB_EFILABEL, 0, 3800 MD_CRO_32BIT, MD_UN2SET(un)); 3801 3802 if (recid < 0) { 3803 return (ENOSPC); 3804 } 3805 3806 recids[0] = recid; 3807 recids[1] = un->c.un_record_id; 3808 recids[2] = 0; 3809 v = mddb_getrecaddr(recid); 3810 bcopy((caddr_t)&efi_part->efi_gpe_PartitionName, v, 3811 MD_EFI_PARTNAME_BYTES); 3812 3813 un->c.un_vtoc_id = recid; 3814 un->c.un_flag |= MD_EFILABEL; 3815 mddb_commitrecs_wrapper(recids); 3816 return (0); 3817 } 3818 3819 int 3820 md_dkiocgetefi(minor_t mnum, void *data, int mode) 3821 { 3822 dk_efi_t efi; 3823 caddr_t *buf; 3824 int rval = 0; 3825 mdi_unit_t *ui; 3826 md_unit_t *mdun; 3827 3828 if (!(mode & FREAD)) 3829 return (EACCES); 3830 3831 if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode)) 3832 return (EFAULT); 3833 3834 efi.dki_data = (void *)(uintptr_t)efi.dki_data_64; 3835 3836 /* 3837 * If the user specified a zero length or a null pointer, we give them 3838 * the number of bytes to alloc in user land. 3839 */ 3840 if (efi.dki_length == 0 || efi.dki_data == NULL) { 3841 efi.dki_length = MD_EFI_LABEL_SIZE; 3842 if (ddi_copyout(&efi, data, sizeof (dk_efi_t), mode)) 3843 return (EFAULT); 3844 return (0); 3845 } 3846 /* Bad size specified, better not answer to that query */ 3847 if (efi.dki_length < MD_EFI_LABEL_SIZE) 3848 return (EINVAL); 3849 3850 if ((ui = MDI_UNIT(mnum)) == NULL) 3851 return (ENXIO); 3852 3853 /* 3854 * We don't want to allocate as much bytes as we are told, 3855 * because we know the good size is MD_EFI_LABEL_SIZE 3856 */ 3857 efi.dki_length = MD_EFI_LABEL_SIZE; 3858 buf = kmem_zalloc(MD_EFI_LABEL_SIZE, KM_SLEEP); 3859 3860 mdun = (md_unit_t *)md_unit_readerlock(ui); 3861 md_get_efi(mdun, (char *)buf); 3862 md_unit_readerexit(ui); 3863 3864 if (ddi_copyout(buf, efi.dki_data, efi.dki_length, mode)) 3865 rval = EFAULT; 3866 3867 kmem_free(buf, MD_EFI_LABEL_SIZE); 3868 return (rval); 3869 } 3870 3871 int 3872 md_dkiocsetefi(minor_t mnum, void *data, int mode) 3873 { 3874 dk_efi_t efi; 3875 caddr_t *buf; 3876 int rval = 0; 3877 mdi_unit_t *ui; 3878 md_unit_t *mdun; 3879 3880 if (!(mode & FREAD)) 3881 return (EACCES); 3882 3883 if ((ui = MDI_UNIT(mnum)) == NULL) 3884 return (ENXIO); 3885 3886 if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode)) 3887 return (EFAULT); 3888 3889 efi.dki_data = (void *)(uintptr_t)efi.dki_data_64; 3890 3891 /* Sanity check of the skeleton */ 3892 if ((efi.dki_length > sizeof (efi_gpt_t) + EFI_MIN_ARRAY_SIZE) || 3893 (efi.dki_length < sizeof (efi_gpt_t) + sizeof (efi_gpe_t)) || 3894 (efi.dki_data == NULL)) 3895 return (EINVAL); 3896 3897 /* 3898 * It's only a real EFI label if the location is 1 3899 * in all other cases, we do nothing but say we did. 3900 */ 3901 if (efi.dki_lba != 1) 3902 return (0); /* success */ 3903 3904 buf = kmem_alloc(efi.dki_length, KM_SLEEP); 3905 /* And here we copy in the real data */ 3906 if (ddi_copyin(efi.dki_data, buf, efi.dki_length, mode)) { 3907 rval = EFAULT; 3908 } else { 3909 mdun = (md_unit_t *)md_unit_readerlock(ui); 3910 rval = md_set_efi(mdun, (char *)buf); 3911 md_unit_readerexit(ui); 3912 } 3913 3914 kmem_free(buf, efi.dki_length); 3915 return (rval); 3916 } 3917 3918 /* 3919 * md_dkiocpartition() 3920 * Return the appropriate partition64 structure for a given metadevice. 3921 * 3922 * Actually the only real information being returned is the number of blocks 3923 * of the specified metadevice. 3924 * The starting block is always 0, and so is the partition number, because 3925 * metadevices don't have slices. 3926 * 3927 * This function is generic for all types of metadevices. 3928 */ 3929 int 3930 md_dkiocpartition(minor_t mnum, void *data, int mode) 3931 { 3932 struct partition64 p64; 3933 mdi_unit_t *ui; 3934 md_unit_t *un; 3935 int rval = 0; 3936 3937 if (!(mode & FREAD)) 3938 return (EACCES); 3939 3940 3941 if ((ui = MDI_UNIT(mnum)) == NULL) 3942 return (ENXIO); 3943 3944 if (ddi_copyin(data, &p64, sizeof (struct partition64), mode)) 3945 return (EFAULT); 3946 3947 if (p64.p_partno != 0) 3948 return (ESRCH); 3949 3950 un = (md_unit_t *)md_unit_readerlock(ui); 3951 /* All metadevices share the same PartitionTypeGUID (see md_get_efi) */ 3952 UUID_LE_CONVERT(p64.p_type, md_efi_reserved); 3953 3954 p64.p_partno = 0; 3955 p64.p_start = 0; 3956 p64.p_size = un->c.un_total_blocks; 3957 md_unit_readerexit(ui); 3958 3959 if (ddi_copyout(&p64, data, sizeof (struct partition64), mode)) { 3960 rval = EFAULT; 3961 } 3962 3963 return (rval); 3964 } 3965 3966 3967 /* 3968 * Remove device node 3969 */ 3970 void 3971 md_remove_minor_node(minor_t mnum) 3972 { 3973 char name[16]; 3974 extern dev_info_t *md_devinfo; 3975 3976 /* 3977 * Attempt release of its minor node 3978 */ 3979 (void) snprintf(name, sizeof (name), "%d,%d,blk", MD_MIN2SET(mnum), 3980 MD_MIN2UNIT(mnum)); 3981 ddi_remove_minor_node(md_devinfo, name); 3982 3983 (void) snprintf(name, sizeof (name), "%d,%d,raw", MD_MIN2SET(mnum), 3984 MD_MIN2UNIT(mnum)); 3985 ddi_remove_minor_node(md_devinfo, name); 3986 } 3987