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