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 /* Always unblock I/O even if release_set fails */ 2007 md_clearblock_setio(setno); 2008 2009 break; 2010 } 2011 2012 case MD_DB_GETOPTLOC: 2013 { 2014 if (! (mode & FREAD)) 2015 return (EACCES); 2016 2017 sz = sizeof (mddb_optloc_t); 2018 d = kmem_alloc(sz, KM_SLEEP); 2019 2020 if (ddi_copyin(data, d, sz, mode) != 0) { 2021 err = EFAULT; 2022 break; 2023 } 2024 2025 err = mddb_getoptloc((mddb_optloc_t *)d); 2026 break; 2027 } 2028 2029 case MD_HALT: 2030 { 2031 if (! (mode & FWRITE)) 2032 return (EACCES); 2033 2034 /* already have the ioctl lock */ 2035 return (md_halt(MD_GBL_IOCTL_LOCK)); 2036 } 2037 2038 case MD_IOCSET_NM: 2039 { 2040 if (! (mode & FREAD)) 2041 return (EACCES); 2042 2043 sz = sizeof (mdnm_params_t); 2044 d = kmem_alloc(sz, KM_SLEEP); 2045 2046 if (ddi_copyin(data, d, sz, mode) != 0) { 2047 err = EFAULT; 2048 break; 2049 } 2050 2051 /* check data integrity */ 2052 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2053 err = EINVAL; 2054 break; 2055 } 2056 2057 if ((((mdnm_params_t *)d)->devname_len == 0) || 2058 (((mdnm_params_t *)d)->devname_len > MAXPATHLEN)) { 2059 err = EINVAL; 2060 break; 2061 } 2062 2063 if (((mdnm_params_t *)d)->devname == NULL) { 2064 err = EINVAL; 2065 break; 2066 } 2067 2068 err = setnm_ioctl((mdnm_params_t *)d, mode); 2069 break; 2070 } 2071 2072 case MD_IOCGET_NM: 2073 { 2074 if (! (mode & FREAD)) 2075 return (EACCES); 2076 2077 sz = sizeof (mdnm_params_t); 2078 d = kmem_alloc(sz, KM_SLEEP); 2079 2080 if (ddi_copyin(data, d, sz, mode) != 0) { 2081 err = EFAULT; 2082 break; 2083 } 2084 2085 /* check data integrity */ 2086 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2087 err = EINVAL; 2088 break; 2089 } 2090 if (((mdnm_params_t *)d)->devname == NULL) { 2091 err = EINVAL; 2092 break; 2093 } 2094 2095 err = getnm_ioctl((mdnm_params_t *)d, mode); 2096 break; 2097 } 2098 2099 case MD_IOCGET_HSP_NM: 2100 { 2101 if (! (mode & FREAD)) 2102 return (EACCES); 2103 2104 sz = sizeof (mdhspnm_params_t); 2105 d = kmem_alloc(sz, KM_SLEEP); 2106 2107 if (ddi_copyin(data, d, sz, mode) != 0) { 2108 err = EFAULT; 2109 break; 2110 } 2111 2112 /* check data integrity */ 2113 if (((mdhspnm_params_t *)d)->setno >= md_nsets) { 2114 err = EINVAL; 2115 break; 2116 } 2117 if (((mdhspnm_params_t *)d)->hspname == NULL) { 2118 err = EINVAL; 2119 break; 2120 } 2121 2122 err = gethspnm_ioctl((mdhspnm_params_t *)d, mode); 2123 break; 2124 } 2125 2126 case MD_IOCNXTKEY_NM: 2127 { 2128 if (! (mode & FREAD)) 2129 return (EACCES); 2130 2131 sz = sizeof (mdnm_params_t); 2132 d = kmem_alloc(sz, KM_SLEEP); 2133 2134 if (ddi_copyin(data, d, sz, mode) != 0) { 2135 err = EFAULT; 2136 break; 2137 } 2138 2139 err = getnextkey_ioctl((mdnm_params_t *)d, mode); 2140 break; 2141 } 2142 2143 case MD_IOCREM_NM: 2144 { 2145 if (! (mode & FREAD)) 2146 return (EACCES); 2147 2148 sz = sizeof (mdnm_params_t); 2149 d = kmem_alloc(sz, KM_SLEEP); 2150 2151 if (ddi_copyin(data, d, sz, mode) != 0) { 2152 err = EFAULT; 2153 break; 2154 } 2155 2156 /* check data integrity */ 2157 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2158 err = EINVAL; 2159 break; 2160 } 2161 2162 err = remnm_ioctl((mdnm_params_t *)d, mode); 2163 break; 2164 } 2165 2166 case MD_IOCGET_TSTATE: 2167 { 2168 md_i_get_tstate_t *p; 2169 2170 if (! (mode & FREAD)) 2171 return (EACCES); 2172 2173 sz = sizeof (md_i_get_tstate_t); 2174 d = kmem_alloc(sz, KM_SLEEP); 2175 2176 if (ddi_copyin(data, d, sz, mode) != 0) { 2177 err = EFAULT; 2178 break; 2179 } 2180 2181 p = (md_i_get_tstate_t *)d; 2182 2183 if ((err = verify_minor(p->id)) != 0) { 2184 if (err == EINVAL) 2185 (void) mdmderror(&p->mde, MDE_INVAL_UNIT, 2186 p->id); 2187 break; 2188 } 2189 2190 err = get_tstate(p, lockp); 2191 break; 2192 } 2193 2194 case MD_IOCGET_DRVNM: 2195 { 2196 md_i_driverinfo_t *p; 2197 2198 if (! (mode & FREAD)) 2199 return (EACCES); 2200 2201 sz = sizeof (md_i_driverinfo_t); 2202 d = kmem_alloc(sz, KM_SLEEP); 2203 2204 if (ddi_copyin(data, d, sz, mode) != 0) { 2205 err = EFAULT; 2206 break; 2207 } 2208 2209 p = (md_i_driverinfo_t *)d; 2210 2211 /* check data integrity */ 2212 if (p->md_driver.md_drivername == NULL) { 2213 err = EINVAL; 2214 break; 2215 } 2216 2217 if ((err = verify_minor(p->mnum)) != 0) { 2218 if (err == EINVAL) 2219 (void) mdmderror(&p->mde, MDE_INVAL_UNIT, 2220 p->mnum); 2221 break; 2222 } 2223 2224 err = getdrvnm_ioctl(dev, p, mode); 2225 break; 2226 } 2227 2228 case MD_IOCGET_NEXT: 2229 { 2230 if (! (mode & FREAD)) 2231 return (EACCES); 2232 2233 sz = sizeof (md_i_getnext_t); 2234 d = kmem_alloc(sz, KM_SLEEP); 2235 2236 if (ddi_copyin(data, d, sz, mode) != 0) { 2237 err = EFAULT; 2238 break; 2239 } 2240 2241 /* check data integrity */ 2242 if (((md_i_getnext_t *)d)->md_driver.md_setno >= md_nsets) { 2243 err = EINVAL; 2244 break; 2245 } 2246 2247 err = getnext_ioctl((md_i_getnext_t *)d, mode); 2248 break; 2249 } 2250 2251 case MD_DB_USERREQ: 2252 case MD_MN_DB_USERREQ: 2253 { 2254 if (! (mode & FREAD)) 2255 return (EACCES); 2256 2257 sz = sizeof (mddb_userreq_t); 2258 d = kmem_alloc(sz, KM_SLEEP); 2259 2260 if (ddi_copyin(data, d, sz, mode) != 0) { 2261 err = EFAULT; 2262 break; 2263 } 2264 err = mddb_userreq_ioctl((mddb_userreq_t *)d, mode); 2265 break; 2266 } 2267 2268 case MD_IOCGET_NUM: 2269 { 2270 if (! (mode & FREAD)) 2271 return (EACCES); 2272 2273 sz = sizeof (md_i_getnum_t); 2274 d = kmem_alloc(sz, KM_SLEEP); 2275 2276 if (ddi_copyin(data, d, sz, mode) != 0) { 2277 err = EFAULT; 2278 break; 2279 } 2280 2281 err = getnum_ioctl(d, mode); 2282 break; 2283 } 2284 2285 case MD_DB_OWNSET: 2286 { 2287 if (! (mode & FREAD)) 2288 return (EACCES); 2289 2290 sz = sizeof (mddb_ownset_t); 2291 d = kmem_alloc(sz, KM_SLEEP); 2292 2293 if (ddi_copyin(data, d, sz, mode) != 0) { 2294 err = EFAULT; 2295 break; 2296 } 2297 2298 if (((mddb_ownset_t *)d)->setno >= md_nsets) { 2299 err = EINVAL; 2300 break; 2301 } 2302 2303 ((mddb_ownset_t *)d)->owns_set = 2304 mddb_ownset(((mddb_ownset_t *)d)->setno); 2305 2306 break; 2307 } 2308 2309 case MD_IOCGETNSET: 2310 { 2311 if (! (mode & FREAD)) 2312 return (EACCES); 2313 2314 if (ddi_copyout((caddr_t)&md_nsets, data, 2315 sizeof (set_t), mode) != 0) { 2316 err = EFAULT; 2317 break; 2318 } 2319 break; 2320 } 2321 2322 case MD_IOCGETNUNITS: 2323 { 2324 if (! (mode & FREAD)) 2325 return (EACCES); 2326 2327 if (ddi_copyout((caddr_t)&md_nunits, data, 2328 sizeof (set_t), mode) != 0) { 2329 err = EFAULT; 2330 break; 2331 } 2332 break; 2333 } 2334 2335 case MD_IOCGVERSION: 2336 { 2337 uint_t dversion = MD_DVERSION; 2338 2339 if (! (mode & FREAD)) 2340 return (EACCES); 2341 2342 if (ddi_copyout((caddr_t)&dversion, data, 2343 sizeof (dversion), mode) != 0) { 2344 err = EFAULT; 2345 break; 2346 } 2347 break; 2348 } 2349 2350 case MD_IOCSET_FLAGS: 2351 { 2352 md_set_userflags_t *p; 2353 2354 if (! (mode & FWRITE)) 2355 return (EACCES); 2356 2357 sz = sizeof (md_set_userflags_t); 2358 d = kmem_alloc(sz, KM_SLEEP); 2359 2360 if (ddi_copyin(data, d, sz, mode)) { 2361 err = EFAULT; 2362 break; 2363 } 2364 2365 p = (md_set_userflags_t *)d; 2366 2367 if ((err = verify_minor(p->mnum)) != 0) { 2368 if (err == EINVAL) 2369 (void) mdmderror(&p->mde, MDE_INVAL_UNIT, 2370 p->mnum); 2371 break; 2372 } 2373 2374 err = setuserflags(p, lockp); 2375 break; 2376 } 2377 2378 case MD_IOCRENAME: 2379 { 2380 md_rename_t *p; 2381 2382 if (! (mode & FWRITE)) { 2383 return (EACCES); 2384 } 2385 2386 sz = sizeof (md_rename_t); 2387 d = kmem_alloc(sz, KM_SLEEP); 2388 2389 if (ddi_copyin(data, d, sz, mode)) { 2390 err = EFAULT; 2391 break; 2392 } 2393 2394 p = (md_rename_t *)d; 2395 2396 if ((err = verify_minor(p->to.mnum)) != 0) { 2397 if (err == EINVAL) 2398 (void) mdmderror(&p->mde, MDE_INVAL_UNIT, 2399 p->to.mnum); 2400 break; 2401 } 2402 2403 if ((err = verify_minor(p->from.mnum)) != 0) { 2404 if (err == EINVAL) 2405 (void) mdmderror(&p->mde, MDE_INVAL_UNIT, 2406 p->from.mnum); 2407 break; 2408 } 2409 2410 err = md_rename(p, lockp); 2411 break; 2412 } 2413 2414 case MD_IOCISOPEN: 2415 { 2416 md_isopen_t *p; 2417 mdi_unit_t *ui; 2418 minor_t mnum; 2419 2420 if (! (mode & FREAD)) 2421 return (EACCES); 2422 2423 sz = sizeof (md_isopen_t); 2424 d = kmem_alloc(sz, KM_SLEEP); 2425 2426 if (ddi_copyin(data, d, sz, mode)) { 2427 err = EFAULT; 2428 break; 2429 } 2430 2431 p = (md_isopen_t *)d; 2432 if ((p->dev <= 0) || (md_getmajor(p->dev)) != md_major) { 2433 err = EINVAL; 2434 break; 2435 } 2436 2437 mnum = md_getminor(p->dev); 2438 2439 if ((err = verify_minor(mnum)) != 0) { 2440 if (err == EINVAL) 2441 (void) mdmderror(&p->mde, MDE_INVAL_UNIT, mnum); 2442 break; 2443 } 2444 2445 if ((ui = MDI_UNIT(mnum)) == NULL) { 2446 (void) mdmderror(&p->mde, MDE_UNIT_NOT_SETUP, mnum); 2447 err = EINVAL; 2448 break; 2449 } 2450 2451 p->isopen = md_unit_isopen(ui); 2452 break; 2453 } 2454 2455 case MD_MED_GET_LST: 2456 { 2457 mddb_med_parm_t *medpp; 2458 2459 if (! (mode & FREAD)) 2460 return (EACCES); 2461 2462 sz = sizeof (mddb_med_parm_t); 2463 d = kmem_alloc(sz, KM_SLEEP); 2464 2465 if (ddi_copyin(data, d, sz, mode) != 0) { 2466 err = EFAULT; 2467 break; 2468 } 2469 2470 medpp = (mddb_med_parm_t *)d; 2471 2472 err = getmed_ioctl(medpp, mode); 2473 break; 2474 } 2475 2476 case MD_MED_SET_LST: 2477 { 2478 mddb_med_parm_t *medpp; 2479 2480 if (! (mode & FWRITE)) 2481 return (EACCES); 2482 2483 sz = sizeof (mddb_med_parm_t); 2484 d = kmem_alloc(sz, KM_SLEEP); 2485 2486 if (ddi_copyin(data, d, sz, mode) != 0) { 2487 err = EFAULT; 2488 break; 2489 } 2490 2491 medpp = (mddb_med_parm_t *)d; 2492 2493 err = setmed_ioctl(medpp, mode); 2494 2495 break; 2496 } 2497 2498 case MD_MED_UPD_MED: 2499 { 2500 if (! (mode & FWRITE)) 2501 return (EACCES); 2502 2503 sz = sizeof (mddb_med_upd_parm_t); 2504 d = kmem_alloc(sz, KM_SLEEP); 2505 2506 if (ddi_copyin(data, d, sz, mode) != 0) { 2507 err = EFAULT; 2508 break; 2509 } 2510 2511 err = updmed_ioctl((mddb_med_upd_parm_t *)d, mode); 2512 2513 break; 2514 } 2515 2516 case MD_MED_GET_NMED: 2517 { 2518 if (! (mode & FREAD)) 2519 return (EACCES); 2520 2521 if (ddi_copyout((caddr_t)&md_nmedh, data, 2522 sizeof (int), mode) != 0) { 2523 err = EFAULT; 2524 break; 2525 } 2526 break; 2527 } 2528 2529 case MD_MED_GET_TAG: 2530 { 2531 if (! (mode & FREAD)) 2532 return (EACCES); 2533 2534 sz = sizeof (mddb_dtag_get_parm_t); 2535 d = kmem_alloc(sz, KM_SLEEP); 2536 2537 if (ddi_copyin(data, d, sz, mode) != 0) { 2538 err = EFAULT; 2539 break; 2540 } 2541 2542 err = gettag_ioctl((mddb_dtag_get_parm_t *)d, mode); 2543 2544 break; 2545 } 2546 2547 case MD_MED_USE_TAG: 2548 { 2549 if (! (mode & FWRITE)) 2550 return (EACCES); 2551 2552 sz = sizeof (mddb_dtag_use_parm_t); 2553 d = kmem_alloc(sz, KM_SLEEP); 2554 2555 if (ddi_copyin(data, d, sz, mode) != 0) { 2556 err = EFAULT; 2557 break; 2558 } 2559 2560 err = usetag_ioctl((mddb_dtag_use_parm_t *)d, mode); 2561 2562 break; 2563 } 2564 2565 case MD_MED_ACCEPT: 2566 { 2567 if (! (mode & FWRITE)) 2568 return (EACCES); 2569 2570 sz = sizeof (mddb_accept_parm_t); 2571 d = kmem_alloc(sz, KM_SLEEP); 2572 2573 if (ddi_copyin(data, d, sz, mode) != 0) { 2574 err = EFAULT; 2575 break; 2576 } 2577 2578 err = accept_ioctl((mddb_accept_parm_t *)d, mode); 2579 2580 break; 2581 } 2582 2583 case MD_MED_GET_TLEN: 2584 { 2585 if (! (mode & FREAD)) 2586 return (EACCES); 2587 2588 sz = sizeof (mddb_med_t_parm_t); 2589 d = kmem_alloc(sz, KM_SLEEP); 2590 2591 if (ddi_copyin(data, d, sz, mode) != 0) { 2592 err = EFAULT; 2593 break; 2594 } 2595 2596 err = med_get_t_size_ioctl((mddb_med_t_parm_t *)d, mode); 2597 2598 break; 2599 } 2600 2601 case MD_MED_GET_T: 2602 { 2603 if (! (mode & FREAD)) 2604 return (EACCES); 2605 2606 sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) + 2607 (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents); 2608 d = kmem_alloc(sz, KM_SLEEP); 2609 2610 if (ddi_copyin(data, d, sz, mode) != 0) { 2611 err = EFAULT; 2612 break; 2613 } 2614 2615 err = med_get_t_ioctl((mddb_med_t_parm_t *)d, mode); 2616 2617 break; 2618 } 2619 2620 case MD_MED_SET_T: 2621 { 2622 if (! (mode & FWRITE)) 2623 return (EACCES); 2624 2625 sz = (sizeof (mddb_med_t_parm_t) - sizeof (mddb_med_t_ent_t)) + 2626 (sizeof (mddb_med_t_ent_t) * med_addr_tab_nents); 2627 d = kmem_alloc(sz, KM_SLEEP); 2628 2629 if (ddi_copyin(data, d, sz, mode) != 0) { 2630 err = EFAULT; 2631 break; 2632 } 2633 2634 err = med_set_t_ioctl((mddb_med_t_parm_t *)d, mode); 2635 2636 break; 2637 } 2638 2639 case MD_GET_SETSTAT: 2640 { 2641 md_gs_stat_parm_t *gsp; 2642 2643 if (! (mode & FREAD)) 2644 return (EACCES); 2645 2646 sz = sizeof (md_gs_stat_parm_t); 2647 d = kmem_alloc(sz, KM_SLEEP); 2648 2649 if (ddi_copyin(data, d, sz, mode) != 0) { 2650 err = EFAULT; 2651 break; 2652 } 2653 2654 gsp = (md_gs_stat_parm_t *)d; 2655 2656 if (gsp->gs_setno > (md_nsets - 1)) { 2657 err = EINVAL; 2658 break; 2659 } 2660 2661 gsp->gs_status = md_set[gsp->gs_setno].s_status; 2662 2663 break; 2664 } 2665 2666 case MD_SETNMDID: 2667 { 2668 if (!(mode & FREAD)) 2669 return (EACCES); 2670 2671 sz = sizeof (mdnm_params_t); 2672 d = kmem_alloc(sz, KM_SLEEP); 2673 2674 if (ddi_copyin(data, d, sz, mode) != 0) { 2675 err = EFAULT; 2676 break; 2677 } 2678 2679 err = update_namespace_did_ioctl((mdnm_params_t *)d, mode); 2680 break; 2681 2682 } 2683 case MD_IOCUPD_NM: 2684 { 2685 char *dname; 2686 char *pname; 2687 uint_t devnamelen, pathnamelen; 2688 2689 if (!(mode & FREAD)) 2690 return (EACCES); 2691 2692 sz = sizeof (mdnm_params_t); 2693 d = kmem_alloc(sz, KM_SLEEP); 2694 2695 if (ddi_copyin(data, d, sz, mode) != 0) { 2696 err = EFAULT; 2697 break; 2698 } 2699 2700 devnamelen = ((mdnm_params_t *)d)->devname_len; 2701 pathnamelen = ((mdnm_params_t *)d)->pathname_len; 2702 2703 if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) || 2704 (devnamelen == 0) || (pathnamelen == 0)) { 2705 kmem_free(d, sz); 2706 return (EINVAL); 2707 } 2708 2709 /* alloc memory for devname */ 2710 dname = kmem_alloc(devnamelen + 1, KM_SLEEP); 2711 2712 if (ddi_copyin( 2713 (void *)(uintptr_t)((mdnm_params_t *)d)->devname, 2714 (void *)dname, devnamelen + 1, mode) != 0) { 2715 err = EFAULT; 2716 kmem_free(dname, devnamelen + 1); 2717 break; 2718 } 2719 2720 pname = kmem_alloc(pathnamelen + 1, KM_SLEEP); 2721 2722 if (ddi_copyin( 2723 (void *)(uintptr_t)((mdnm_params_t *)d)->pathname, 2724 (void *)pname, pathnamelen + 1, mode) != 0) { 2725 err = EFAULT; 2726 kmem_free(dname, devnamelen + 1); 2727 kmem_free(pname, pathnamelen + 1); 2728 break; 2729 } 2730 2731 err = update_namespace_ioctl((mdnm_params_t *)d, dname, pname, 2732 mode); 2733 2734 kmem_free(dname, devnamelen + 1); 2735 kmem_free(pname, pathnamelen + 1); 2736 break; 2737 } 2738 2739 case MD_IOCUPD_LOCNM: 2740 { 2741 char *dname; 2742 char *pname; 2743 uint_t devnamelen, pathnamelen; 2744 2745 if (!(mode & FREAD)) 2746 return (EACCES); 2747 2748 sz = sizeof (mdnm_params_t); 2749 d = kmem_alloc(sz, KM_SLEEP); 2750 2751 if (ddi_copyin(data, d, sz, mode) != 0) { 2752 err = EFAULT; 2753 break; 2754 } 2755 2756 devnamelen = ((mdnm_params_t *)d)->devname_len; 2757 pathnamelen = ((mdnm_params_t *)d)->pathname_len; 2758 2759 if ((devnamelen > MAXPATHLEN) || (pathnamelen > MAXPATHLEN) || 2760 (devnamelen == 0) || (pathnamelen == 0)) { 2761 kmem_free(d, sz); 2762 return (EINVAL); 2763 } 2764 2765 /* alloc memory for devname */ 2766 dname = kmem_alloc(devnamelen + 1, KM_SLEEP); 2767 2768 if (ddi_copyin( 2769 (void *)(uintptr_t)((mdnm_params_t *)d)->devname, 2770 (void *)dname, devnamelen + 1, mode) != 0) { 2771 err = EFAULT; 2772 kmem_free(dname, devnamelen + 1); 2773 break; 2774 } 2775 2776 pname = kmem_alloc(pathnamelen + 1, KM_SLEEP); 2777 2778 if (ddi_copyin( 2779 (void *)(uintptr_t)((mdnm_params_t *)d)->pathname, 2780 (void *)pname, pathnamelen + 1, mode) != 0) { 2781 err = EFAULT; 2782 kmem_free(dname, devnamelen + 1); 2783 kmem_free(pname, pathnamelen + 1); 2784 break; 2785 } 2786 2787 err = update_loc_namespace_ioctl((mdnm_params_t *)d, dname, 2788 pname, mode); 2789 2790 kmem_free(dname, devnamelen + 1); 2791 kmem_free(pname, pathnamelen + 1); 2792 break; 2793 } 2794 2795 case MD_SET_SETSTAT: 2796 { 2797 #ifdef DEBUG 2798 /* Can be used to set the s_status flags from user code */ 2799 md_gs_stat_parm_t *gsp; 2800 2801 if (! (mode & FWRITE)) 2802 return (EACCES); 2803 2804 sz = sizeof (md_gs_stat_parm_t); 2805 d = kmem_alloc(sz, KM_SLEEP); 2806 2807 if (ddi_copyin(data, d, sz, mode) != 0) { 2808 err = EFAULT; 2809 break; 2810 } 2811 2812 gsp = (md_gs_stat_parm_t *)d; 2813 2814 if (gsp->gs_setno > (md_nsets - 1)) { 2815 err = EINVAL; 2816 break; 2817 } 2818 2819 md_set[gsp->gs_setno].s_status = gsp->gs_status; 2820 2821 #endif /* DEBUG */ 2822 break; 2823 } 2824 2825 case MD_IOCGET_DID: 2826 { 2827 if (! (mode & FREAD)) 2828 return (EACCES); 2829 2830 sz = sizeof (mdnm_params_t); 2831 d = kmem_alloc(sz, KM_SLEEP); 2832 2833 if (ddi_copyin(data, d, sz, mode) != 0) { 2834 err = EFAULT; 2835 break; 2836 } 2837 2838 err = getdid_ioctl((mdnm_params_t *)d, mode); 2839 break; 2840 } 2841 2842 case MD_IOCSET_DID: 2843 { 2844 if (! (mode & FWRITE)) 2845 return (EACCES); 2846 2847 sz = sizeof (mdnm_params_t); 2848 d = kmem_alloc(sz, KM_SLEEP); 2849 2850 if (ddi_copyin(data, d, sz, mode) != 0) { 2851 err = EFAULT; 2852 break; 2853 } 2854 2855 err = setdid_ioctl((mdnm_params_t *)d, mode); 2856 break; 2857 } 2858 2859 case MD_IOCGET_DIDMIN: 2860 { 2861 if (! (mode & FREAD)) 2862 return (EACCES); 2863 2864 sz = sizeof (mdnm_params_t); 2865 d = kmem_alloc(sz, KM_SLEEP); 2866 2867 if (ddi_copyin(data, d, sz, mode) != 0) { 2868 err = EFAULT; 2869 break; 2870 } 2871 2872 if (((mdnm_params_t *)d)->setno >= md_nsets) { 2873 err = EINVAL; 2874 break; 2875 } 2876 2877 err = getdidmin_ioctl((mdnm_params_t *)d, mode); 2878 break; 2879 } 2880 2881 case MD_IOCDID_STAT: 2882 { 2883 if (!(mode & FREAD)) 2884 return (EACCES); 2885 2886 mddb_didstat_case = 1; 2887 2888 err = mddb_didstat_from_user(&d, data, mode, &ds_ctd_addr); 2889 2890 if (err) { 2891 return (err); 2892 } 2893 2894 err = didstat_ioctl((md_i_didstat_t *)d); 2895 break; 2896 } 2897 2898 case MD_UPGRADE_STAT: 2899 { 2900 if (! (mode & FREAD)) 2901 return (EACCES); 2902 2903 if (ddi_copyout((caddr_t)&md_in_upgrade, data, 2904 sizeof (int), mode) != 0) { 2905 err = EFAULT; 2906 break; 2907 } 2908 break; 2909 } 2910 2911 case MD_SETMASTER: 2912 { 2913 if (! (mode & FREAD)) 2914 return (EACCES); 2915 2916 sz = sizeof (mddb_setmaster_config_t); 2917 d = kmem_alloc(sz, KM_SLEEP); 2918 2919 if (ddi_copyin(data, d, sz, mode) != 0) { 2920 err = EFAULT; 2921 break; 2922 } 2923 2924 err = mddb_setmaster_ioctl((mddb_setmaster_config_t *)d); 2925 break; 2926 } 2927 2928 case MD_MN_SET_DOORH: 2929 { 2930 /* This ioctl sets the global kernel variable mdmn_door_handle */ 2931 if (ddi_copyin(data, &mdmn_door_did, sizeof (int), mode) != 0) { 2932 err = EFAULT; 2933 } else { 2934 err = 0; 2935 } 2936 mdmn_door_handle = door_ki_lookup(mdmn_door_did); 2937 2938 break; 2939 } 2940 2941 #ifdef DEBUG 2942 case MD_MN_CHECK_DOOR1: 2943 { 2944 /* This ioctl sends a message through a previously opened door */ 2945 int ret; 2946 int msg_test = 11111111; 2947 int nloops = 0; 2948 set_t setno; 2949 md_mn_kresult_t *result; 2950 uint_t flags = MD_MSGF_NO_LOG | MD_MSGF_NO_BCAST; 2951 2952 result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP); 2953 if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) { 2954 err = EFAULT; 2955 } else { 2956 err = 0; 2957 } 2958 2959 /* 2960 * This is a way to tell ksend_message() to use different sets. 2961 * Odd numbers go to set 1 even numbers go to set 2 2962 */ 2963 if (nloops & 0x1) { 2964 setno = 1; 2965 } else { 2966 setno = 2; 2967 } 2968 while (nloops--) { 2969 ret = mdmn_ksend_message( 2970 setno, 2971 MD_MN_MSG_TEST1, 2972 flags, 2973 (char *)&msg_test, 2974 sizeof (msg_test), 2975 result); 2976 2977 if (ret != 0) { 2978 printf("mdmn_ksend_message failed (%d)\n", ret); 2979 } 2980 } 2981 kmem_free(result, sizeof (md_mn_kresult_t)); 2982 2983 break; 2984 } 2985 2986 case MD_MN_CHECK_DOOR2: 2987 { 2988 /* This ioctl sends a message through a previously opened door */ 2989 int ret; 2990 int msg_test = 22222222; 2991 int nloops = 0; 2992 md_mn_kresult_t *result; 2993 set_t setno; 2994 uint_t flags = MD_MSGF_NO_LOG; 2995 2996 result = kmem_zalloc(sizeof (md_mn_kresult_t), KM_SLEEP); 2997 if (ddi_copyin(data, &nloops, sizeof (int), mode) != 0) { 2998 err = EFAULT; 2999 } else { 3000 err = 0; 3001 } 3002 /* 3003 * This is a way to tell ksend_message() to use different sets. 3004 * Odd numbers go to set 1 even numbers go to set 2 3005 */ 3006 if (nloops & 0x1) { 3007 setno = 1; 3008 } else { 3009 setno = 2; 3010 } 3011 while (nloops--) { 3012 ret = mdmn_ksend_message( 3013 setno, 3014 MD_MN_MSG_TEST2, 3015 flags, 3016 (char *)&msg_test, 3017 sizeof (msg_test), 3018 result); 3019 3020 if (ret != 0) { 3021 printf("mdmn_ksend_message failed (%d)\n", ret); 3022 } 3023 } 3024 kmem_free(result, sizeof (md_mn_kresult_t)); 3025 3026 break; 3027 } 3028 #endif 3029 3030 case MD_MN_OPEN_TEST: 3031 { 3032 md_clu_open_t *p; 3033 minor_t mnum; 3034 3035 sz = sizeof (md_clu_open_t); 3036 d = kmem_alloc(sz, KM_SLEEP); 3037 3038 if (ddi_copyin(data, d, sizeof (md_clu_open_t), mode) != 0) { 3039 err = EFAULT; 3040 break; 3041 } 3042 3043 p = (md_clu_open_t *)d; 3044 mnum = md_getminor(p->clu_dev); 3045 3046 if ((err = verify_minor(mnum)) != 0) { 3047 if (err == EINVAL) 3048 (void) mdmderror(&p->clu_mde, MDE_INVAL_UNIT, 3049 mnum); 3050 break; 3051 } 3052 err = md_clu_ioctl(p); 3053 break; 3054 } 3055 3056 case MD_MN_SET_NODEID: 3057 { 3058 if (! (mode & FWRITE)) 3059 return (EACCES); 3060 3061 sz = sizeof (mddb_set_node_params_t); 3062 d = kmem_alloc(sz, KM_SLEEP); 3063 3064 if (ddi_copyin(data, d, sz, mode) != 0) { 3065 err = EFAULT; 3066 break; 3067 } 3068 snp = (mddb_set_node_params_t *)d; 3069 3070 if (snp->sn_setno >= md_nsets) { 3071 err = EINVAL; 3072 break; 3073 } 3074 3075 md_set[snp->sn_setno].s_nodeid = snp->sn_nodeid; 3076 3077 if (md_mn_mynode_id == MD_MN_INVALID_NID) 3078 md_mn_mynode_id = snp->sn_nodeid; 3079 #ifdef DEBUG 3080 else if (md_mn_mynode_id != snp->sn_nodeid) 3081 cmn_err(CE_WARN, "Previously set nodeid 0x%x for this" 3082 "node doesn't match nodeid being set 0x%x\n", 3083 md_mn_mynode_id, snp->sn_nodeid); 3084 #endif /* DEBUG */ 3085 err = 0; 3086 break; 3087 } 3088 case MD_IOCGUNIQMSGID: 3089 { 3090 md_mn_msgid_t msgid; 3091 struct timeval32 tv; 3092 3093 if (! (mode & FREAD)) 3094 return (EACCES); 3095 3096 uniqtime32(&tv); 3097 3098 /* high 32 bits are the seconds */ 3099 msgid.mid_time = (u_longlong_t)tv.tv_sec << 32; 3100 /* low 32 bits are the micro secs */ 3101 msgid.mid_time |= tv.tv_usec; 3102 3103 msgid.mid_nid = md_mn_mynode_id; 3104 /* 3105 * This is never called for submessages, so we better 3106 * null out the submessage ID 3107 */ 3108 msgid.mid_smid = 0; 3109 3110 if (ddi_copyout((caddr_t)&msgid, data, sizeof (msgid), mode) 3111 != 0) { 3112 err = EFAULT; 3113 break; 3114 } 3115 break; 3116 } 3117 3118 /* 3119 * suspend the IO's for a given set number. 3120 * 3121 * If setno = 0 is specified, try operation on all snarfed MN disksets. 3122 * If there are no snarfed MN disksets, then return success. 3123 * 3124 * If a specific set number is given, then return EINVAL if unable 3125 * to perform operation. 3126 */ 3127 case MD_MN_SUSPEND_SET: 3128 { 3129 set_t setno; 3130 int rval = 0; 3131 int i; 3132 3133 if (! (mode & FWRITE)) 3134 return (EACCES); 3135 3136 if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) { 3137 return (EFAULT); 3138 } 3139 if (setno >= MD_MAXSETS) { 3140 return (EINVAL); 3141 } 3142 3143 mutex_enter(&md_mx); 3144 if (setno == 0) { 3145 /* if set number is 0, we walk all sets */ 3146 for (i = 1; i <= (MD_MAXSETS - 1); i++) { 3147 if ((md_set[i].s_status & 3148 (MD_SET_SNARFED|MD_SET_MNSET)) == 3149 (MD_SET_SNARFED|MD_SET_MNSET)) { 3150 md_set[i].s_status |= MD_SET_HALTED; 3151 } 3152 } 3153 } else { 3154 /* If unable to halt specified set, set EINVAL */ 3155 if ((md_set[setno].s_status & 3156 (MD_SET_SNARFED|MD_SET_MNSET)) == 3157 (MD_SET_SNARFED|MD_SET_MNSET)) { 3158 md_set[setno].s_status |= MD_SET_HALTED; 3159 } else { 3160 rval = EINVAL; 3161 } 3162 } 3163 mutex_exit(&md_mx); 3164 return (rval); 3165 } 3166 3167 /* 3168 * resume the IO's for a given set number. 3169 * 3170 * If setno = 0 is specified, try operation on all snarfed MN disksets. 3171 * If there are no snarfed MN disksets, then return success. 3172 * 3173 * If a specific set number is given, then return EINVAL if unable 3174 * to perform operation. 3175 */ 3176 case MD_MN_RESUME_SET: 3177 { 3178 set_t setno; 3179 int resumed_set = 0; 3180 int rval = 0; 3181 int i; 3182 3183 if (! (mode & FWRITE)) 3184 return (EACCES); 3185 3186 if (ddi_copyin(data, &setno, sizeof (set_t), mode) != 0) { 3187 return (EFAULT); 3188 } 3189 if (setno >= MD_MAXSETS) { 3190 return (EINVAL); 3191 } 3192 3193 /* if 0 is specified as the set number, we walk all sets */ 3194 mutex_enter(&md_mx); 3195 if (setno == 0) { 3196 /* if set number is 0, we walk all sets */ 3197 for (i = 1; i <= (MD_MAXSETS - 1); i++) { 3198 if ((md_set[i].s_status & 3199 (MD_SET_SNARFED|MD_SET_MNSET)) == 3200 (MD_SET_SNARFED|MD_SET_MNSET)) { 3201 md_set[i].s_status &= ~MD_SET_HALTED; 3202 resumed_set = 1; 3203 } 3204 } 3205 } else { 3206 /* If unable to resume specified set, set EINVAL */ 3207 if ((md_set[setno].s_status & 3208 (MD_SET_SNARFED|MD_SET_MNSET)) == 3209 (MD_SET_SNARFED|MD_SET_MNSET)) { 3210 md_set[setno].s_status &= ~MD_SET_HALTED; 3211 resumed_set = 1; 3212 } else { 3213 rval = EINVAL; 3214 } 3215 } 3216 3217 /* 3218 * In case we actually resumed at least one set, 3219 * Inform all threads waiting for this change 3220 */ 3221 if (resumed_set == 1) { 3222 cv_broadcast(&md_cv); 3223 } 3224 3225 mutex_exit(&md_mx); 3226 return (rval); 3227 } 3228 3229 case MD_MN_MDDB_PARSE: 3230 { 3231 if (! (mode & FWRITE)) 3232 return (EACCES); 3233 3234 sz = sizeof (mddb_parse_parm_t); 3235 d = kmem_alloc(sz, KM_SLEEP); 3236 3237 if (ddi_copyin(data, d, sz, mode) != 0) { 3238 err = EFAULT; 3239 break; 3240 } 3241 err = mddb_parse((mddb_parse_parm_t *)d); 3242 break; 3243 3244 } 3245 3246 case MD_MN_MDDB_BLOCK: 3247 { 3248 if (! (mode & FWRITE)) 3249 return (EACCES); 3250 3251 sz = sizeof (mddb_block_parm_t); 3252 d = kmem_alloc(sz, KM_SLEEP); 3253 3254 if (ddi_copyin(data, d, sz, mode) != 0) { 3255 err = EFAULT; 3256 break; 3257 } 3258 err = mddb_block((mddb_block_parm_t *)d); 3259 break; 3260 3261 } 3262 3263 case MD_MN_MDDB_OPTRECFIX: 3264 { 3265 if (! (mode & FWRITE)) 3266 return (EACCES); 3267 3268 sz = sizeof (mddb_optrec_parm_t); 3269 d = kmem_alloc(sz, KM_SLEEP); 3270 3271 if (ddi_copyin(data, d, sz, mode) != 0) { 3272 err = EFAULT; 3273 break; 3274 } 3275 err = mddb_optrecfix((mddb_optrec_parm_t *)d); 3276 break; 3277 3278 } 3279 3280 case MD_MN_CHK_WRT_MDDB: 3281 { 3282 if (! (mode & FWRITE)) 3283 return (EACCES); 3284 3285 sz = sizeof (mddb_config_t); 3286 d = kmem_alloc(sz, KM_SLEEP); 3287 3288 if (ddi_copyin(data, d, sz, mode) != 0) { 3289 err = EFAULT; 3290 break; 3291 } 3292 3293 err = mddb_check_write_ioctl((mddb_config_t *)d); 3294 break; 3295 } 3296 3297 case MD_MN_SET_SETFLAGS: 3298 case MD_MN_GET_SETFLAGS: 3299 { 3300 if (! (mode & FREAD)) 3301 return (EACCES); 3302 3303 sz = sizeof (mddb_setflags_config_t); 3304 d = kmem_alloc(sz, KM_SLEEP); 3305 3306 if (ddi_copyin(data, d, sz, mode) != 0) { 3307 err = EFAULT; 3308 break; 3309 } 3310 3311 err = mddb_setflags_ioctl((mddb_setflags_config_t *)d); 3312 break; 3313 } 3314 3315 case MD_MN_COMMD_ERR: 3316 { 3317 md_mn_commd_err_t *cmp; 3318 char *msg; 3319 3320 sz = sizeof (md_mn_commd_err_t); 3321 d = kmem_zalloc(sz, KM_SLEEP); 3322 3323 if (ddi_copyin(data, d, sz, mode) != 0) { 3324 err = EFAULT; 3325 break; 3326 } 3327 3328 cmp = (md_mn_commd_err_t *)d; 3329 if (cmp->size > MAXPATHLEN) { 3330 err = EINVAL; 3331 break; 3332 } 3333 3334 msg = (char *)kmem_zalloc(cmp->size + 1, KM_SLEEP); 3335 if (ddi_copyin((caddr_t)(uintptr_t)cmp->md_message, msg, 3336 cmp->size, mode) != 0) { 3337 kmem_free(msg, cmp->size + 1); 3338 err = EFAULT; 3339 break; 3340 } 3341 cmn_err(CE_WARN, "%s\n", msg); 3342 kmem_free(msg, cmp->size + 1); 3343 break; 3344 } 3345 3346 case MD_IOCMAKE_DEV: 3347 { 3348 if (! (mode & FWRITE)) 3349 return (EACCES); 3350 3351 sz = sizeof (md_mkdev_params_t); 3352 3353 if ((d = kmem_alloc(sz, KM_NOSLEEP)) == NULL) 3354 return (ENOMEM); 3355 3356 if (ddi_copyin(data, d, sz, mode) != 0) { 3357 err = EFAULT; 3358 break; 3359 } 3360 3361 err = mkdev_ioctl((md_mkdev_params_t *)d); 3362 break; 3363 } 3364 3365 case MD_IOCREM_DEV: 3366 { 3367 set_t setno; 3368 3369 if (! (mode & FWRITE)) 3370 return (EACCES); 3371 3372 sz = sizeof (minor_t); 3373 3374 d = kmem_zalloc(sz, KM_SLEEP); 3375 3376 if (ddi_copyin(data, d, sz, mode) != 0) { 3377 err = EFAULT; 3378 break; 3379 } 3380 3381 /* 3382 * This ioctl is called to cleanup the device name 3383 * space when metainit fails or -n is invoked 3384 * In this case, reclaim the dispatched un slot 3385 */ 3386 setno = MD_MIN2SET(*(minor_t *)d); 3387 if (setno >= md_nsets) { 3388 err = EINVAL; 3389 break; 3390 } else if (md_set[setno].s_un_next <= 0) { 3391 err = EFAULT; 3392 break; 3393 } else { 3394 md_set[setno].s_un_next--; 3395 } 3396 3397 /* 3398 * Attempt to remove the assocated device node 3399 */ 3400 md_remove_minor_node(*(minor_t *)d); 3401 break; 3402 } 3403 3404 /* 3405 * Update md_mn_commd_present global to reflect presence or absence of 3406 * /usr/sbin/rpc.mdcommd. This allows us to determine if an RPC failure 3407 * is expected during a mdmn_ksend_message() handshake. If the commd is 3408 * not present then an RPC failure is acceptable. If the commd _is_ 3409 * present then an RPC failure means we have an inconsistent view across 3410 * the cluster. 3411 */ 3412 case MD_MN_SET_COMMD_RUNNING: 3413 { 3414 if (! (mode & FWRITE)) 3415 return (EACCES); 3416 3417 md_mn_commd_present = (int)(intptr_t)data; 3418 err = 0; 3419 break; 3420 } 3421 3422 case MD_IOCIMP_LOAD: 3423 { 3424 if (! (mode & FWRITE)) 3425 return (EACCES); 3426 3427 mddb_config_case = 1; 3428 3429 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 3430 &c_old_devid_addr); 3431 3432 if (err) { 3433 return (err); 3434 } 3435 3436 err = md_imp_snarf_set((mddb_config_t *)d); 3437 break; 3438 3439 } 3440 3441 case MD_DB_LBINITTIME: 3442 { 3443 if (! (mode & FWRITE)) 3444 return (EACCES); 3445 3446 mddb_config_case = 1; 3447 3448 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 3449 &c_old_devid_addr); 3450 3451 if (err) 3452 return (err); 3453 3454 err = get_lb_inittime_ioctl((mddb_config_t *)d); 3455 break; 3456 } 3457 case MD_IOCUPDATE_NM_RR_DID: 3458 { 3459 if (! (mode & FWRITE)) 3460 return (EACCES); 3461 3462 mddb_config_case = 1; 3463 3464 err = mddb_config_from_user(&d, data, mode, &c_devid_addr, 3465 &c_old_devid_addr); 3466 3467 if (err) 3468 return (err); 3469 3470 err = md_update_nm_rr_did_ioctl((mddb_config_t *)d); 3471 break; 3472 } 3473 default: 3474 return (ENOTTY); /* used by next level up */ 3475 } 3476 3477 /* 3478 * copyout and free any args 3479 */ 3480 if (mddb_config_case) { 3481 err_to_user = mddb_config_to_user(d, data, mode, c_devid_addr, 3482 c_old_devid_addr); 3483 } else if (mddb_didstat_case) { 3484 err_to_user = mddb_didstat_to_user(d, data, mode, ds_ctd_addr); 3485 } else if (sz != 0) { 3486 if (ddi_copyout(d, data, sz, mode) != 0) { 3487 err = EFAULT; 3488 } 3489 kmem_free(d, sz); 3490 } 3491 3492 if (err) 3493 return (err); 3494 return (err_to_user); 3495 } 3496 3497 int 3498 md_admin_ioctl(md_dev64_t dev, int cmd, caddr_t data, int mode, IOLOCK *lockp) 3499 { 3500 md_driver_t drv; 3501 int modindex; 3502 int err; 3503 3504 /* 3505 * see if we can do this without involving the subdriver 3506 */ 3507 if ((err = md_base_ioctl(dev, cmd, data, mode, lockp)) != ENOTTY) 3508 return (err); 3509 3510 /* 3511 * see what subdriver we need 3512 */ 3513 if (! ISMDIOC(cmd)) 3514 return (ENOTTY); 3515 3516 if ((!NODBNEEDED(cmd)) && md_snarf_db_set(MD_LOCAL_SET, NULL) != 0) 3517 return (ENODEV); 3518 3519 if (ddi_copyin(data, (caddr_t)&drv, sizeof (drv), mode) != 0) 3520 return (EFAULT); 3521 3522 /* 3523 * load subdriver if not already loaded 3524 */ 3525 if (((modindex = md_getmodindex(&drv, 0, NODBNEEDED(cmd))) == -1) || 3526 (md_ops[modindex]->md_ioctl == NULL)) 3527 return (ENOTTY); 3528 3529 /* 3530 * dispatch to subdriver 3531 */ 3532 return ((*md_ops[modindex]->md_ioctl)(md_dev64_to_dev(dev), cmd, data, 3533 mode, lockp)); 3534 } 3535 3536 void 3537 md_get_geom( 3538 md_unit_t *un, 3539 struct dk_geom *gp 3540 ) 3541 { 3542 diskaddr_t tb = un->c.un_total_blocks; 3543 uint_t cylsize = un->c.un_nhead * un->c.un_nsect; 3544 3545 bzero((caddr_t)gp, sizeof (*gp)); 3546 gp->dkg_nhead = un->c.un_nhead; 3547 gp->dkg_nsect = un->c.un_nsect; 3548 gp->dkg_rpm = un->c.un_rpm; 3549 gp->dkg_write_reinstruct = un->c.un_wr_reinstruct; 3550 gp->dkg_read_reinstruct = un->c.un_rd_reinstruct; 3551 gp->dkg_ncyl = (ushort_t)(tb / cylsize); 3552 if (! (un->c.un_flag & MD_LABELED)) /* skip first cyl */ 3553 gp->dkg_ncyl += 1; 3554 gp->dkg_pcyl = gp->dkg_ncyl; 3555 } 3556 3557 void 3558 md_get_vtoc(md_unit_t *un, struct vtoc *vtoc) 3559 { 3560 caddr_t v; 3561 mddb_recstatus_t status; 3562 struct vtoc32 *vt32; 3563 3564 /* 3565 * Return vtoc structure fields in the provided VTOC area, addressed 3566 * by *vtoc. 3567 * 3568 */ 3569 3570 if (un->c.un_vtoc_id) { 3571 status = mddb_getrecstatus(un->c.un_vtoc_id); 3572 if (status == MDDB_OK) { 3573 v = mddb_getrecaddr(un->c.un_vtoc_id); 3574 /* if this seems to be a sane vtoc, just copy it ... */ 3575 if (((struct vtoc *)v)->v_sanity == VTOC_SANE) { 3576 bcopy(v, (caddr_t)vtoc, sizeof (struct vtoc)); 3577 } else { 3578 /* ... else assume a vtoc32 was stored here */ 3579 vt32 = (struct vtoc32 *)v; 3580 vtoc32tovtoc((*vt32), (*vtoc)); 3581 } 3582 if (un->c.un_flag & MD_LABELED) 3583 vtoc->v_part[0].p_start = 0; 3584 else 3585 vtoc->v_part[0].p_start = 3586 un->c.un_nhead * un->c.un_nsect; 3587 vtoc->v_part[0].p_size = un->c.un_total_blocks; 3588 vtoc->v_version = V_VERSION; 3589 vtoc->v_sectorsz = DEV_BSIZE; 3590 return; 3591 } 3592 3593 un->c.un_vtoc_id = 0; 3594 mddb_commitrec_wrapper(un->c.un_record_id); 3595 } 3596 3597 bzero((caddr_t)vtoc, sizeof (struct vtoc)); 3598 vtoc->v_sanity = VTOC_SANE; 3599 vtoc->v_nparts = 1; 3600 vtoc->v_version = V_VERSION; 3601 vtoc->v_sectorsz = DEV_BSIZE; 3602 if (un->c.un_flag & MD_LABELED) 3603 vtoc->v_part[0].p_start = 0; 3604 else 3605 vtoc->v_part[0].p_start = un->c.un_nhead * un->c.un_nsect; 3606 vtoc->v_part[0].p_size = un->c.un_total_blocks; 3607 } 3608 3609 int 3610 md_set_vtoc(md_unit_t *un, struct vtoc *vtoc) 3611 { 3612 3613 struct partition *vpart; 3614 int i; 3615 mddb_recid_t recid; 3616 mddb_recid_t recids[3]; 3617 mddb_recstatus_t status; 3618 caddr_t v; 3619 daddr_t sb; 3620 3621 /* 3622 * Sanity-check the vtoc 3623 */ 3624 if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts != 1) 3625 return (EINVAL); 3626 3627 /* don't allow to create a vtoc for a big metadevice */ 3628 if (un->c.un_revision & MD_64BIT_META_DEV) 3629 return (ENOTSUP); 3630 /* 3631 * Validate the partition table 3632 */ 3633 vpart = vtoc->v_part; 3634 for (i = 0; i < V_NUMPAR; i++, vpart++) { 3635 if (i == 0) { 3636 if (un->c.un_flag & MD_LABELED) 3637 sb = 0; 3638 else 3639 sb = un->c.un_nhead * un->c.un_nsect; 3640 if (vpart->p_start != sb) 3641 return (EINVAL); 3642 if (vpart->p_size != (long)un->c.un_total_blocks) 3643 return (EINVAL); 3644 continue; 3645 } 3646 /* all other partitions must be zero */ 3647 if (vpart->p_start != 0) 3648 return (EINVAL); 3649 if (vpart->p_size != 0) 3650 return (EINVAL); 3651 } 3652 3653 if (un->c.un_vtoc_id) { 3654 recid = un->c.un_vtoc_id; 3655 status = mddb_getrecstatus(recid); 3656 if (status == MDDB_OK) { 3657 /* 3658 * If there's enough space in the record, and the 3659 * existing record is a vtoc record (not EFI), 3660 * we just can use the existing space. 3661 * Otherwise, we create a new MDDB_VTOC record for 3662 * this unit. 3663 */ 3664 if ((mddb_getrecsize(recid) >= sizeof (struct vtoc)) && 3665 ((un->c.un_flag & MD_EFILABEL) == 0)) { 3666 v = mddb_getrecaddr(recid); 3667 bcopy((caddr_t)vtoc, v, sizeof (struct vtoc)); 3668 mddb_commitrec_wrapper(recid); 3669 recids[0] = recid; 3670 recids[1] = un->c.un_record_id; 3671 recids[2] = 0; 3672 un->c.un_flag &= ~MD_EFILABEL; 3673 mddb_commitrecs_wrapper(recids); 3674 return (0); 3675 } 3676 3677 un->c.un_vtoc_id = 0; 3678 mddb_commitrec_wrapper(un->c.un_record_id); 3679 mddb_deleterec_wrapper(recid); 3680 } 3681 } 3682 3683 recid = mddb_createrec(sizeof (struct vtoc), MDDB_VTOC, 0, 3684 MD_CRO_32BIT, MD_UN2SET(un)); 3685 3686 if (recid < 0) { 3687 return (ENOSPC); 3688 } 3689 3690 recids[0] = recid; 3691 recids[1] = un->c.un_record_id; 3692 recids[2] = 0; 3693 v = mddb_getrecaddr(recid); 3694 bcopy((caddr_t)vtoc, v, sizeof (struct vtoc)); 3695 3696 un->c.un_vtoc_id = recid; 3697 un->c.un_flag &= ~MD_EFILABEL; 3698 mddb_commitrecs_wrapper(recids); 3699 return (0); 3700 } 3701 3702 3703 void 3704 md_get_cgapart(md_unit_t *un, struct dk_map *dkmapp) 3705 { 3706 3707 /* skip the first cyl */ 3708 dkmapp->dkl_cylno = 1; 3709 3710 dkmapp->dkl_nblk = (daddr_t)un->c.un_total_blocks; 3711 } 3712 3713 static struct uuid md_efi_reserved = EFI_RESERVED; 3714 3715 /* 3716 * md_get_efi 3717 * INPUT: 3718 * un; the md_unit 3719 * buf; the buffer that is preallocated by the calling routine and 3720 * capable of taking the EFI label for this unit 3721 * OUTPUT: 3722 * A filled buffer, containing one struct efi_gpt followed by one 3723 * struct efi_gpe, because a md efi only has one valid partition 3724 * We fetch that date either from the mddb (like vtoc) 3725 * or we a fake an EFI label. 3726 * 3727 * NOTES: 3728 * We do not provide for any global unique identifiers, 3729 * We also use the field c.un_vtoc_id, as the semantic is very similar 3730 * When we are called, it's already checked, that this unit has an EFI 3731 * label and not a vtoc 3732 */ 3733 3734 void 3735 md_get_efi(md_unit_t *un, char *buf) 3736 { 3737 caddr_t v; 3738 efi_gpt_t *efi_header = (efi_gpt_t *)buf; 3739 efi_gpe_t *efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t)); 3740 mddb_recstatus_t status; 3741 3742 /* first comes the header */ 3743 efi_header->efi_gpt_Signature = LE_64(EFI_SIGNATURE); 3744 efi_header->efi_gpt_HeaderSize = LE_32(sizeof (efi_gpt_t)); 3745 efi_header->efi_gpt_NumberOfPartitionEntries = LE_32(1); 3746 efi_header->efi_gpt_SizeOfPartitionEntry = LE_32(sizeof (efi_gpe_t)); 3747 efi_header->efi_gpt_LastUsableLBA = LE_64(un->c.un_total_blocks - 1); 3748 efi_header->efi_gpt_FirstUsableLBA = 0; 3749 efi_header->efi_gpt_Revision = LE_32(EFI_VERSION_CURRENT); 3750 3751 /* 3752 * We don't fill out any of these: 3753 * 3754 * efi_header->efi_gpt_HeaderCRC32; 3755 * efi_header->efi_gpt_DiskGUID; 3756 * efi_header->efi_gpt_PartitionEntryArrayCRC32; 3757 * efi_header->efi_gpt_Reserved1; 3758 * efi_header->efi_gpt_MyLBA; 3759 * efi_header->efi_gpt_AlternateLBA; 3760 * efi_header->efi_gpt_Reserved2[LEN_EFI_PAD]; 3761 * efi_header->efi_gpt_PartitionEntryLBA; 3762 */ 3763 3764 /* 3765 * We copy back one partition, of type reserved, 3766 * which may contain the name of the metadevice 3767 * (this is what was used to be v_volume for a vtoc device) 3768 * if no name is stored in the vtoc record, we hand an empty name 3769 * to the user 3770 */ 3771 3772 UUID_LE_CONVERT(efi_part->efi_gpe_PartitionTypeGUID, md_efi_reserved); 3773 if (un->c.un_flag & MD_LABELED) 3774 efi_part->efi_gpe_StartingLBA = LE_64(1ULL); 3775 else 3776 efi_part->efi_gpe_StartingLBA = 0; 3777 3778 efi_part->efi_gpe_EndingLBA = LE_64(un->c.un_total_blocks - 1); 3779 3780 if (un->c.un_vtoc_id) { 3781 status = mddb_getrecstatus(un->c.un_vtoc_id); 3782 if (status == MDDB_OK) { 3783 v = mddb_getrecaddr(un->c.un_vtoc_id); 3784 bcopy(v, (caddr_t)&(efi_part->efi_gpe_PartitionName), 3785 MD_EFI_PARTNAME_BYTES); 3786 return; 3787 } 3788 un->c.un_vtoc_id = 0; 3789 mddb_commitrec_wrapper(un->c.un_record_id); 3790 } 3791 3792 /* 3793 * We don't fill out any of these 3794 * efi_part->efi_gpe_UniquePartitionGUID 3795 * efi_part->efi_gpe_Attributes 3796 */ 3797 } 3798 3799 3800 /* 3801 * md_set_efi 3802 * INPUT: 3803 * un; a md_unit 3804 * buf; a buffer that is holding an EFI label for this unit 3805 * 3806 * PURPOSE: 3807 * Perform some sanity checks on the EFI label provided, 3808 * Then store efi_gpe_PartitionName in the mddb 3809 * and link the unit's c.un_vtoc_id field to it. 3810 * 3811 * RETURN: 3812 * EINVAL if any of the sanity checks fail 3813 * 0 on succes 3814 * 3815 * NOTES: 3816 * We do not provide for any global unique identifiers, 3817 * We also use the field c.un_vtoc_id, as the semantic is very similar 3818 * When we are called, it's already checked, that this unit has an EFI 3819 * label and not a vtoc 3820 */ 3821 3822 3823 int 3824 md_set_efi(md_unit_t *un, char *buf) 3825 { 3826 3827 mddb_recid_t recid; 3828 mddb_recid_t recids[3]; 3829 mddb_recstatus_t status; 3830 caddr_t v; 3831 efi_gpt_t *efi_header = (efi_gpt_t *)buf; 3832 efi_gpe_t *efi_part = (efi_gpe_t *)(buf + sizeof (efi_gpt_t)); 3833 struct uuid md_efi_reserved_le; 3834 3835 /* 3836 * Sanity-check the EFI label 3837 */ 3838 if ((efi_header->efi_gpt_Signature != LE_64(EFI_SIGNATURE)) || 3839 (efi_header->efi_gpt_NumberOfPartitionEntries != LE_32(1))) 3840 return (EINVAL); 3841 3842 UUID_LE_CONVERT(md_efi_reserved_le, md_efi_reserved); 3843 3844 /* 3845 * Validate the partition 3846 */ 3847 if (efi_part->efi_gpe_StartingLBA != 0 || 3848 efi_part->efi_gpe_EndingLBA != LE_64(un->c.un_total_blocks - 1) || 3849 bcmp(&efi_part->efi_gpe_PartitionTypeGUID, &md_efi_reserved_le, 3850 sizeof (struct uuid))) { 3851 return (EINVAL); 3852 } 3853 /* 3854 * If no name is specified, we have nothing to do and return success. 3855 * because efi_gpe_PartitionName is in unicode form, we have to 3856 * check the first two bytes of efi_gpe_PartitionName. 3857 */ 3858 if (((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[0] == NULL) && 3859 ((char *)(uintptr_t)efi_part->efi_gpe_PartitionName[1] == NULL)) { 3860 return (0); 3861 } 3862 3863 if (un->c.un_vtoc_id) { 3864 recid = un->c.un_vtoc_id; 3865 status = mddb_getrecstatus(recid); 3866 if (status == MDDB_OK) { 3867 /* 3868 * If there's enough space in the record, and the 3869 * existing record is an EFI record (not vtoc), 3870 * we just can use the existing space. 3871 * Otherwise, we create a new MDDB_EFILABEL record for 3872 * this unit. 3873 */ 3874 if ((mddb_getrecsize(recid) >= MD_EFI_PARTNAME_BYTES) && 3875 (un->c.un_flag & MD_EFILABEL)) { 3876 v = mddb_getrecaddr(recid); 3877 bcopy((caddr_t)&efi_part->efi_gpe_PartitionName, 3878 v, MD_EFI_PARTNAME_BYTES); 3879 mddb_commitrec_wrapper(recid); 3880 return (0); 3881 } 3882 3883 un->c.un_vtoc_id = 0; 3884 mddb_commitrec_wrapper(un->c.un_record_id); 3885 mddb_deleterec_wrapper(recid); 3886 } 3887 } 3888 3889 recid = mddb_createrec(MD_EFI_PARTNAME_BYTES, MDDB_EFILABEL, 0, 3890 MD_CRO_32BIT, MD_UN2SET(un)); 3891 3892 if (recid < 0) { 3893 return (ENOSPC); 3894 } 3895 3896 recids[0] = recid; 3897 recids[1] = un->c.un_record_id; 3898 recids[2] = 0; 3899 v = mddb_getrecaddr(recid); 3900 bcopy((caddr_t)&efi_part->efi_gpe_PartitionName, v, 3901 MD_EFI_PARTNAME_BYTES); 3902 3903 un->c.un_vtoc_id = recid; 3904 un->c.un_flag |= MD_EFILABEL; 3905 mddb_commitrecs_wrapper(recids); 3906 return (0); 3907 } 3908 3909 int 3910 md_dkiocgetefi(minor_t mnum, void *data, int mode) 3911 { 3912 dk_efi_t efi; 3913 caddr_t *buf; 3914 int rval = 0; 3915 mdi_unit_t *ui; 3916 md_unit_t *mdun; 3917 3918 if (!(mode & FREAD)) 3919 return (EACCES); 3920 3921 if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode)) 3922 return (EFAULT); 3923 3924 efi.dki_data = (void *)(uintptr_t)efi.dki_data_64; 3925 3926 /* 3927 * If the user specified a zero length or a null pointer, we give them 3928 * the number of bytes to alloc in user land. 3929 */ 3930 if (efi.dki_length == 0 || efi.dki_data == NULL) { 3931 efi.dki_length = MD_EFI_LABEL_SIZE; 3932 if (ddi_copyout(&efi, data, sizeof (dk_efi_t), mode)) 3933 return (EFAULT); 3934 return (0); 3935 } 3936 /* Bad size specified, better not answer to that query */ 3937 if (efi.dki_length < MD_EFI_LABEL_SIZE) 3938 return (EINVAL); 3939 3940 if ((ui = MDI_UNIT(mnum)) == NULL) 3941 return (ENXIO); 3942 3943 /* 3944 * We don't want to allocate as much bytes as we are told, 3945 * because we know the good size is MD_EFI_LABEL_SIZE 3946 */ 3947 efi.dki_length = MD_EFI_LABEL_SIZE; 3948 buf = kmem_zalloc(MD_EFI_LABEL_SIZE, KM_SLEEP); 3949 3950 mdun = (md_unit_t *)md_unit_readerlock(ui); 3951 md_get_efi(mdun, (char *)buf); 3952 md_unit_readerexit(ui); 3953 3954 if (ddi_copyout(buf, efi.dki_data, efi.dki_length, mode)) 3955 rval = EFAULT; 3956 3957 kmem_free(buf, MD_EFI_LABEL_SIZE); 3958 return (rval); 3959 } 3960 3961 int 3962 md_dkiocsetefi(minor_t mnum, void *data, int mode) 3963 { 3964 dk_efi_t efi; 3965 caddr_t *buf; 3966 int rval = 0; 3967 mdi_unit_t *ui; 3968 md_unit_t *mdun; 3969 3970 if (!(mode & FREAD)) 3971 return (EACCES); 3972 3973 if ((ui = MDI_UNIT(mnum)) == NULL) 3974 return (ENXIO); 3975 3976 if (ddi_copyin(data, &efi, sizeof (dk_efi_t), mode)) 3977 return (EFAULT); 3978 3979 efi.dki_data = (void *)(uintptr_t)efi.dki_data_64; 3980 3981 /* Sanity check of the skeleton */ 3982 if ((efi.dki_length > sizeof (efi_gpt_t) + EFI_MIN_ARRAY_SIZE) || 3983 (efi.dki_length < sizeof (efi_gpt_t) + sizeof (efi_gpe_t)) || 3984 (efi.dki_data == NULL)) 3985 return (EINVAL); 3986 3987 /* 3988 * It's only a real EFI label if the location is 1 3989 * in all other cases, we do nothing but say we did. 3990 */ 3991 if (efi.dki_lba != 1) 3992 return (0); /* success */ 3993 3994 buf = kmem_alloc(efi.dki_length, KM_SLEEP); 3995 /* And here we copy in the real data */ 3996 if (ddi_copyin(efi.dki_data, buf, efi.dki_length, mode)) { 3997 rval = EFAULT; 3998 } else { 3999 mdun = (md_unit_t *)md_unit_readerlock(ui); 4000 rval = md_set_efi(mdun, (char *)buf); 4001 md_unit_readerexit(ui); 4002 } 4003 4004 kmem_free(buf, efi.dki_length); 4005 return (rval); 4006 } 4007 4008 /* 4009 * md_dkiocpartition() 4010 * Return the appropriate partition64 structure for a given metadevice. 4011 * 4012 * Actually the only real information being returned is the number of blocks 4013 * of the specified metadevice. 4014 * The starting block is always 0, and so is the partition number, because 4015 * metadevices don't have slices. 4016 * 4017 * This function is generic for all types of metadevices. 4018 */ 4019 int 4020 md_dkiocpartition(minor_t mnum, void *data, int mode) 4021 { 4022 struct partition64 p64; 4023 mdi_unit_t *ui; 4024 md_unit_t *un; 4025 int rval = 0; 4026 4027 if (!(mode & FREAD)) 4028 return (EACCES); 4029 4030 4031 if ((ui = MDI_UNIT(mnum)) == NULL) 4032 return (ENXIO); 4033 4034 if (ddi_copyin(data, &p64, sizeof (struct partition64), mode)) 4035 return (EFAULT); 4036 4037 if (p64.p_partno != 0) 4038 return (ESRCH); 4039 4040 un = (md_unit_t *)md_unit_readerlock(ui); 4041 /* All metadevices share the same PartitionTypeGUID (see md_get_efi) */ 4042 UUID_LE_CONVERT(p64.p_type, md_efi_reserved); 4043 4044 p64.p_partno = 0; 4045 p64.p_start = 0; 4046 p64.p_size = un->c.un_total_blocks; 4047 md_unit_readerexit(ui); 4048 4049 if (ddi_copyout(&p64, data, sizeof (struct partition64), mode)) { 4050 rval = EFAULT; 4051 } 4052 4053 return (rval); 4054 } 4055 4056 4057 /* 4058 * Remove device node 4059 */ 4060 void 4061 md_remove_minor_node(minor_t mnum) 4062 { 4063 char name[16]; 4064 extern dev_info_t *md_devinfo; 4065 4066 /* 4067 * Attempt release of its minor node 4068 */ 4069 (void) snprintf(name, sizeof (name), "%d,%d,blk", MD_MIN2SET(mnum), 4070 MD_MIN2UNIT(mnum)); 4071 ddi_remove_minor_node(md_devinfo, name); 4072 4073 (void) snprintf(name, sizeof (name), "%d,%d,raw", MD_MIN2SET(mnum), 4074 MD_MIN2UNIT(mnum)); 4075 ddi_remove_minor_node(md_devinfo, name); 4076 } 4077