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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 26 #include <limits.h> 27 #include <sys/types.h> 28 #include <sys/mkdev.h> 29 #include <sys/file.h> 30 #include <pthread.h> 31 #include <synch.h> 32 #include <ctype.h> 33 #include <signal.h> 34 #include <pwd.h> 35 #include <auth_attr.h> 36 #include <secdb.h> 37 #include <ucred.h> 38 #include <fcntl.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <unistd.h> 42 #include <dlfcn.h> 43 #include <link.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <strings.h> 47 #include <dirent.h> 48 #include <errno.h> 49 #include <sys/scsi/impl/uscsi.h> 50 #include <sys/scsi/generic/sense.h> 51 #include <sys/scsi/generic/status.h> 52 #include <dmd_impl.h> 53 #include <dm_impl.h> 54 #include <dm_drive.h> 55 #include <mms_sym.h> 56 #include <dm_msg.h> 57 #include <mms_trace.h> 58 #include <mms_dmd.h> 59 #include <dm_proto.h> 60 #include <mms_strapp.h> 61 62 63 64 static char *_SrcFile = __FILE__; 65 66 67 /* 68 * Minor device number of the ST driver. 69 * 70 * Change device to bn device - turn BSD and norewind bits 71 * 72 * The minor device byte structure is (from mtio(7I)): 73 * 74 * 15-7 6 5 4 3 2 1 0 75 * ___________________________________________________________________ 76 * Unit # BSD Reserved Density Density No rewind Unit # 77 * behavior Select Select on Close Bits 0-1 78 * 79 */ 80 81 minor_t 82 dm_get_targ(minor_t minor) 83 { 84 minor &= ~0x18; /* turn off density select */ 85 minor |= 0x44; /* BSD, norewind */ 86 87 return (minor); 88 } 89 90 minor_t 91 dm_hdl_minor(void) 92 { 93 minor_t minor = 0; 94 95 minor = (((wka->dm_counter % 255) + 1) << 8) | wka->dm_drm_minor; 96 return (minor); 97 } 98 99 int 100 dm_get_target_base(void) 101 { 102 if (drv->drv_serial_num[0] == '\0') { 103 /* 104 * Serial number unknown. Have to use specified path 105 */ 106 return (dm_get_target_pathname()); 107 } else { 108 /* 109 * Have serial number, look in /dev/rmt (tape devices) 110 * for device matching serial number. 111 */ 112 return (dm_get_target_by_serial_num()); 113 } 114 } 115 116 int 117 dm_get_target_pathname(void) 118 { 119 char *show_cmd; 120 char *task; 121 mms_par_node_t *root; 122 dm_command_t *cmd; 123 char *val; 124 125 TRACE((MMS_DEVP, "Getting target base")); 126 task = dm_bld_task("show-target-base"); 127 show_cmd = mms_strapp(NULL, 128 "show task['%s'] reportmode[namevalue] " 129 "match[streq(DM.'DMName' '%s')] " 130 "report[ DM.'DMTargetPath']" ";", task, DMNAME); 131 cmd = dm_send_cmd(show_cmd, dm_cmd_response, task); 132 free(show_cmd); 133 free(task); 134 if (cmd == NULL || cmd->cmd_rc != 0) { 135 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 136 "unable to get DM.'DMTargetPath'")); 137 if (cmd) { 138 dm_destroy_cmd(cmd); 139 } 140 return (-1); 141 } 142 root = cmd->cmd_root; 143 /* 144 * Save tape path 145 */ 146 val = dm_get_attr_value(root, "DM", "DMTargetPath"); 147 if (val == NULL) { 148 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 149 "No TargetPath")); 150 dm_destroy_cmd(cmd); 151 return (-1); 152 } 153 if (dm_verify_target_dev(val) != 0) { 154 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 155 "invalid device pathname %s", val)); 156 dm_destroy_cmd(cmd); 157 return (-1); 158 } 159 wka->dm_target_base = strdup(val); 160 TRACE((MMS_OPER, "dm_get_target_base: Target base is %s", 161 wka->dm_target_base)); 162 dm_destroy_cmd(cmd); 163 return (0); 164 } 165 166 int 167 dm_get_target_by_serial_num(void) 168 { 169 char **dirtab; 170 int i; 171 int rc = -1; 172 173 /* 174 * Search in the default dir 175 */ 176 if (dm_probe_dir(drv->drv_dev_dir) == 0) { 177 /* Found it */ 178 return (0); 179 } 180 181 /* 182 * Build a dir table from *.so 183 */ 184 dirtab = dm_bld_dir_tab(); 185 if (dirtab == NULL) { 186 return (-1); 187 } 188 189 /* 190 * Search each entry in dir table 191 */ 192 rc = -1; /* assume not found */ 193 for (i = 0; dirtab[i] != NULL; i++) { 194 if (dm_probe_dir(dirtab[i]) == 0) { 195 /* Found it */ 196 rc = 0; 197 break; 198 } 199 } 200 201 /* 202 * Can't find a device that matches the serial number 203 */ 204 for (i = 0; dirtab[i] != NULL; i++) { 205 free(dirtab[i]); 206 } 207 free(dirtab); 208 209 return (rc); 210 } 211 212 int 213 dm_probe_dir(char *dirname) 214 { 215 DIR *dir; 216 struct dirent *dirent; 217 int len; 218 char sernum[MMS_SER_NUM_LEN + 1]; 219 int fd; 220 int rc = -1; 221 struct ent { 222 ino_t ino; 223 char *name; 224 }; 225 struct ent ptab[64]; 226 int nument = 0; 227 int probe = 1; 228 drm_probe_dev_t dev; 229 int i; 230 int err; 231 int zero = 0; 232 233 234 if ((dir = opendir(dirname)) == NULL) { 235 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 236 "unable to open directory %s: %s", 237 dirname, strerror(errno))); 238 return (-1); 239 } 240 241 while ((dirent = readdir(dir)) != NULL) { 242 /* 243 * Read the serial number of this device 244 */ 245 len = strlen(dirent->d_name); 246 if (strcmp(dirname, DRV_TAPE_DIR) == 0) { 247 if (len < 2) { 248 /* Device name must be >= 2 chars */ 249 continue; 250 } 251 /* If tape device, look at only norewind devices */ 252 if (dirent->d_name[len - 1] != 'n' || 253 !isdigit(dirent->d_name[len - 2])) { 254 continue; 255 } 256 } 257 ptab[nument].name = mms_strapp(NULL, 258 "%s/%s", dirname, dirent->d_name); 259 ptab[nument].ino = dirent->d_ino; 260 nument++; 261 } 262 closedir(dir); 263 264 while (probe) { 265 /* 266 * Continue to probe until all devices are probed. 267 */ 268 probe = 0; 269 for (i = 0; i < nument; i++) { 270 /* 271 * Set the ino in dmd. If EBUSY, then skip for now 272 */ 273 if (ptab[i].name == NULL) { 274 /* Already checked */ 275 continue; 276 } 277 278 /* 279 * Tell DMD probing this device 280 */ 281 dev.drm_dev = 0; 282 ioctl(drv->drv_fd, DRM_PROBE_DEV, &dev); 283 dev.drm_dev = ptab[i].ino; 284 if (ioctl(drv->drv_fd, DRM_PROBE_DEV, &dev) < 0) { 285 err = errno; 286 if (err == EBUSY) { 287 TRACE((MMS_DEBUG, "Busy: %s", 288 ptab[i].name)); 289 continue; 290 } 291 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 292 "unable to probe device: %s", 293 strerror(err))); 294 errno = err; 295 rc = -1; 296 goto done; 297 } 298 299 /* 300 * Check serial number of this device 301 */ 302 probe = 1; 303 do { 304 TRACE((MMS_DEBUG, "Looking at: %s", 305 ptab[i].name)); 306 fd = open(ptab[i].name, O_NDELAY | O_RDWR); 307 if (fd < 0) { 308 /* 309 * If can't open this device, 310 * then skip it 311 */ 312 TRACE((MMS_DEBUG, "probe open error: " 313 "%s: %s", 314 ptab[i].name, strerror(errno))); 315 break; 316 } 317 318 /* Read the serial number */ 319 drv->drv_fd = fd; 320 /* drv_*() uses drv->drv_fd */ 321 if (DRV_CALL(drv_get_serial_num, 322 (sernum)) != 0) { 323 TRACE((MMS_DEBUG, "probe get " 324 "serial num error: %s: %s", 325 ptab[i].name, strerror(errno))); 326 close(fd); 327 drv->drv_fd = wka->dm_drm_fd; 328 /* restoredrv->drv_fd */ 329 break; 330 } 331 close(fd); 332 drv->drv_fd = wka->dm_drm_fd; 333 /* restoredrv->drv_fd */ 334 335 TRACE((MMS_DEBUG, "path %s, serial num %s", 336 ptab[i].name, sernum)); 337 338 /* 339 * Compare serial numbers 340 */ 341 if (strcmp(sernum, drv->drv_serial_num) == 0) { 342 /* Found device matching serial num */ 343 wka->dm_target_base = 344 strdup(ptab[i].name); 345 /* Drop the "n" from pathname */ 346 wka->dm_target_base[ 347 strlen(wka->dm_target_base) - 1] = 348 '\0'; 349 TRACE((MMS_OPER, "dm_probe_dir: " 350 "Target base is %s", 351 wka->dm_target_base)); 352 rc = 0; 353 probe = 0; /* probe done */ 354 } 355 } while (zero); 356 357 free(ptab[i].name); 358 ptab[i].name = NULL; 359 /* 360 * Unlock this dev 361 */ 362 dev.drm_dev = 0; 363 ioctl(drv->drv_fd, DRM_PROBE_DEV, &dev); 364 365 if (probe == 0) { 366 break; 367 } 368 } 369 if (nument == i) { 370 DM_MSG_PREPEND(("dm_probe_dir: " 371 "cannot find a matching drive " 372 "with serial num %s in %s: ", 373 drv->drv_serial_num, dirname)); 374 } 375 } 376 377 done: 378 for (i = 0; i < nument; i++) { 379 if (ptab[i].name != NULL) { 380 free(ptab[i].name); 381 } 382 } 383 384 return (rc); 385 } 386 387 char ** 388 dm_bld_dir_tab(void) 389 { 390 char **dirtab; 391 char **newtab; 392 int taboff = 0; 393 int size = DRV_DIR_TAB_SIZE; 394 char *libpath; 395 char *libname; 396 int len; 397 void *dlhdl; 398 char *devdir; 399 DIR *dir; 400 dirent_t *dirent; 401 int i; 402 403 dirtab = (char **)malloc(size * sizeof (char *)); 404 if (dirtab == NULL) { 405 DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL, 406 "out of memory")); 407 return (NULL); 408 } 409 memset(dirtab, 0, size); 410 411 dir = opendir(DM_DEV_LIB_DIR); 412 if (dir == NULL) { 413 DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL, 414 "unable to open %s", DM_DEV_LIB_DIR)); 415 free(dirtab); 416 return (NULL); 417 } 418 419 while (dirent = readdir(dir)) { 420 libname = dirent->d_name; 421 len = strlen(libname); 422 if (strncmp(libname, "lib", 3) || 423 strncmp(libname + len - 3, ".so", 3)) { 424 /* Not lib*.so */ 425 continue; 426 } 427 428 TRACE((MMS_DEBUG, "looking at lib %s", libname)); 429 libpath = mms_strapp(NULL, 430 "%s/%s", DM_DEV_LIB_DIR, libname); 431 dlhdl = dlopen(libpath, RTLD_LAZY); 432 if (dlhdl == NULL) { 433 DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL, 434 "unable to open %s", libpath)); 435 free(libpath); 436 continue; 437 } 438 free(libpath); 439 440 devdir = dlsym(dlhdl, "drv_dev_dir"); 441 if (devdir != NULL) { 442 if (devdir[0] == '\0') { 443 /* dev dir not specified */ 444 dlclose(dlhdl); 445 continue; 446 } 447 448 if (strcmp(devdir, DRV_TAPE_DIR) == 0) { 449 /* Already probed DRV_TAPE_DIR */ 450 dlclose(dlhdl); 451 continue; 452 } 453 454 /* 455 * Add to dirtab if not in it already 456 */ 457 for (i = 0; i < taboff && dirtab[i] != NULL; i++) { 458 if (strcmp(devdir, dirtab[i]) == 0) { 459 /* dir name already in dirtab */ 460 dlclose(dlhdl); 461 continue; 462 } 463 } 464 /* Not in table yet */ 465 TRACE((MMS_DEBUG, "adding to dirtab: %s", devdir)); 466 dirtab[taboff] = strdup(devdir); 467 taboff++; 468 if (taboff == size) { 469 size += DRV_DIR_TAB_SIZE; 470 newtab = (char **) 471 realloc(dirtab, size * sizeof (char *)); 472 if (newtab == NULL) { 473 DM_MSG_ADD((MMS_EXIST, 474 MMS_DM_E_INTERNAL, 475 "out of memory")); 476 return (NULL); 477 } 478 dirtab = newtab; 479 } 480 481 } 482 } 483 484 /* 485 * Done 486 */ 487 return (dirtab); 488 } 489 490 /* 491 * Verify target device name 492 */ 493 int 494 dm_verify_target_dev(char *devname) 495 { 496 int i; 497 498 if (devname[0] == '\0') { 499 return (-1); 500 } 501 502 if (strncmp(devname, DRV_TAPE_DIR "/", 9) != 0) { 503 /* If not a tape dev, ignore */ 504 return (0); 505 } 506 507 if (!isdigit(devname[9])) { 508 return (-1); 509 } 510 511 /* 512 * strip device attribute from devname 513 */ 514 515 for (i = 9; devname[i] != '\0'; i++) { 516 if (!isdigit(devname[i])) { 517 devname[i] = '\0'; 518 return (0); 519 } 520 } 521 return (0); 522 } 523 524 int 525 dm_stat_targ_base(void) 526 { 527 struct stat buf; 528 int fd; 529 530 if (wka->dm_target_base == NULL || wka->dm_target_base[0] == '\0') { 531 DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL, 532 "target base device not available")); 533 return (-1); 534 } 535 536 if ((fd = open(wka->dm_target_base, O_RDWR | O_NDELAY)) < 0 || 537 fstat(fd, &buf)) { 538 DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL, 539 "stat '%s' error: %s", 540 wka->dm_target_base, strerror(errno))); 541 if (fd >= 0) { 542 close(fd); 543 } 544 return (-1); 545 } 546 547 wka->dm_targ_base_major = major(buf.st_rdev); 548 wka->dm_targ_base_minor = minor(buf.st_rdev); 549 TRACE((MMS_DEVP, "dm_stat_targ_base: %s - (%d:%d)", 550 wka->dm_target_base, wka->dm_targ_base_major, 551 wka->dm_targ_base_minor)); 552 close(fd); 553 return (0); 554 } 555 556 int 557 dm_reserve_target(void) 558 { 559 int rc = 0; 560 561 if (drv->drv_flags & DRV_USE_PRSV) { 562 for (;;) { 563 rc = dm_reserve_target_prsv(); 564 if (rc == 0) { /* drive reserved */ 565 break; 566 } else if (rc > 0) { 567 /* error other than reservation conflict */ 568 DM_MSG_ADD_HEAD((MMS_INTERNAL, 569 MMS_DM_E_INTERNAL, 570 "unable to reserve drive: " 571 "I/O error")); 572 return (-1); 573 } 574 /* 575 * If already have MMS reservation, just preempt it. 576 * Otherwise see if we have to ask. 577 */ 578 rc = DM_REP_YES; /* assume preempt */ 579 if (!dm_have_mms_rsv()) { /* no mms rsv */ 580 if (wka->dm_flags & DM_ASK_PREEMPT_RSV) { 581 rc = dm_ask_preempt(); 582 } 583 if (rc == DM_REP_ERROR) { 584 /* Ask got an error, assume "no" */ 585 rc = DM_REP_NO; 586 } 587 if (rc == DM_REP_NO) { 588 DM_MSG_ADD_HEAD((MMS_INTERNAL, 589 MMS_DM_E_INTERNAL, 590 "drive reservation " 591 "denied by operator")); 592 return (-1); 593 } else if (rc == DM_REP_RETRY) { 594 sleep(1); 595 continue; 596 } 597 } 598 if (rc == DM_REP_YES) { 599 TRACE((MMS_DEBUG, "Preempting reservation")); 600 if (dm_preempt_rsv()) { 601 return (-1); 602 } 603 rc = 0; 604 break; 605 } 606 607 608 } 609 } else { 610 rc = dm_reserve_target_rsv(); 611 } 612 613 TRACE((MMS_DEBUG, "Drive reserved successfully")); 614 615 return (rc); 616 } 617 618 619 int 620 dm_reserve_target_prsv(void) 621 { 622 int status = 0; 623 uint64_t key; 624 625 TRACE((MMS_DEVP, "dm_reserve_target_prsv: Using PRSV")); 626 627 /* 628 * Register key 629 */ 630 631 if (DRV_CALL(drv_prsv_register, ())) { 632 status = serr->se_dsreg; 633 char_to_uint64((uchar_t *)DRV_PRSV_KEY, 8, &key); 634 TRACE((MMS_DEVP, "Can't register PRSV " 635 "reservation key: %16.16llx: %s", 636 key, mms_scsi_status(status))); 637 if (status == STATUS_RESERVATION_CONFLICT) { 638 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 639 "unable to register key, " 640 "reservation conflict")); 641 return (-1); 642 } else { 643 /* other error */ 644 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 645 "registration error: %s", strerror(errno))); 646 return (EIO); 647 } 648 } 649 650 /* 651 * Do an exclusive persistent reservation 652 */ 653 if (DRV_CALL(drv_prsv_reserve, ()) != 0) { 654 status = serr->se_dsreg; 655 TRACE((MMS_ERR, "Unable to reserve drive")); 656 if (status == STATUS_RESERVATION_CONFLICT) { 657 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 658 "unable to reserve drive: " 659 "reservation conflict")); 660 return (-1); 661 } else { 662 /* other error */ 663 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 664 "reservation error: %s", strerror(errno))); 665 return (EIO); 666 } 667 } 668 669 /* 670 * Now, get rid of all the attentions 671 */ 672 TRACE((MMS_DEVP, "dm_reserve_target_prsv: Clear attentions")); 673 while (DRV_CALL(drv_tur, ()) != 0 && 674 serr->se_senkey == KEY_UNIT_ATTENTION) { 675 ; 676 } 677 678 TRACE((MMS_DEVP, "dm_reserve_target_prsv: Drive %s reserved", 679 DRVNAME)); 680 681 return (0); 682 } 683 684 int 685 dm_reserve_target_rsv(void) 686 { 687 int rc = 0; 688 689 /* 690 * Since the target is opened (via ldi_open()) with O_NDELAY, 691 * the st drive will not do reserve/release on open/close. 692 * until an I/O is done. A TUR will be done after binding 693 * the target. This causes the st driver to reserve the drive. 694 */ 695 while (DRV_CALL(drv_tur, ()) != 0 && errno == EACCES) { 696 TRACE((MMS_INFO, "TUR error: %s", strerror(errno))); 697 /* 698 * Drive is reserved, find out if it is assigned to 699 * another DM 700 */ 701 if (dm_drv_assigned() != 0) { 702 /* 703 * No, not assigned. This means that the drive 704 * is being used by a non MMS client. 705 */ 706 if ((wka->dm_flags & DM_PREEMPT_RSV) == 0) { 707 /* Do not preempt */ 708 return (-1); 709 } 710 711 rc = DM_REP_YES; /* assume freserve */ 712 if (wka->dm_flags & DM_ASK_PREEMPT_RSV) { 713 rc = dm_ask_freserve(); 714 } 715 if (rc == DM_REP_ERROR) { 716 /* Ask got an error, assume "no" */ 717 rc = DM_REP_NO; 718 } 719 if (rc == DM_REP_YES) { 720 TRACE((MMS_DEBUG, "Doing forcereserve")); 721 if (ioctl(wka->dm_drm_fd, MTIOCFORCERESERVE)) { 722 return (-1); 723 } 724 } else if (rc == DM_REP_NO) { 725 return (-1); 726 } else if (rc == DM_REP_RETRY) { 727 continue; 728 } 729 } else { 730 /* 731 * If drive is assigned to another DM, then 732 * silently wait for it to be unassigned. 733 */ 734 TRACE((MMS_ERR, "Drive %s is reserved by " 735 "another DM. " 736 "Will keep trying reserve until " 737 "successful", wka->dm_target_base)); 738 } 739 } 740 741 /* 742 * Release the reservation made by the ST driver and tell it 743 * not to do reserve/release at open/close. 744 * Then do my own reservations 745 */ 746 ioctl(drv->drv_fd, MTIOCRESERVE); 747 DRV_CALL(drv_release, ()); 748 if (DRV_CALL(drv_reserve, ()) != 0) { 749 ioctl(drv->drv_fd, MTIOCRELEASE); 750 return (-1); 751 } 752 drv->drv_flags |= DRV_RESERVED; 753 return (0); 754 } 755 756 int 757 dm_release_target(void) 758 { 759 if ((drv->drv_flags & DRV_USE_PRSV) == 0) { 760 /* Using reserve/release */ 761 DRV_CALL(drv_release, ()); 762 return (0); 763 } 764 765 /* 766 * Using persistent reserve out 767 */ 768 DRV_CALL(drv_prsv_register, ()); 769 DRV_CALL(drv_prsv_release, ()); 770 return (0); 771 } 772 773 int 774 dm_force_release(void) 775 { 776 if (ioctl(wka->dm_drm_fd, MTIOCFORCERESERVE)) { 777 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 778 "Can't do FORCERESERVE: %s", strerror(errno))); 779 return (-1); 780 } 781 TRACE((MMS_DEBUG, "FORCERESERVE successful")); 782 783 if (DRV_CALL(drv_release, ()) != 0) { 784 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 785 "release error: %s", strerror(errno))); 786 return (-1); 787 } 788 TRACE((MMS_DEBUG, "RELEASE successful")); 789 790 return (0); 791 } 792 793 int 794 dm_preempt_rsv(void) 795 { 796 char buf[24]; 797 uint32_t num; 798 799 if (DRV_CALL(drv_prsv_register, ()) != 0 || 800 DRV_CALL(drv_prsv_read_rsv, (buf, sizeof (buf))) != 0) { 801 if (serr->se_dsreg == STATUS_RESERVATION_CONFLICT) { 802 /* Try force reserve and release */ 803 if (dm_force_release() != 0) { 804 /* Can't force release */ 805 return (-1); 806 } 807 if (DRV_CALL(drv_prsv_register, ()) != 0 || 808 DRV_CALL(drv_prsv_reserve, ())) { 809 DM_MSG_ADD_HEAD((MMS_INTERNAL, 810 MMS_DM_E_INTERNAL, 811 "persistent reservation " "error")); 812 return (-1); 813 } 814 return (0); 815 } else { 816 /* Other error */ 817 DM_MSG_ADD_HEAD((MMS_INTERNAL, 818 MMS_DM_E_INTERNAL, 819 "reservation error", strerror(errno))); 820 return (-1); 821 } 822 } 823 824 char_to_uint32((uchar_t *)buf + 4, 4, &num); 825 if (num == 0) { /* no reservation */ 826 if (DRV_CALL(drv_prsv_register, ()) != 0 || 827 DRV_CALL(drv_prsv_reserve, ()) != 0) { 828 DM_MSG_ADD_HEAD((MMS_INTERNAL, 829 MMS_DM_E_INTERNAL, 830 "persistent reservation " "error")); 831 return (-1); 832 } 833 } else { 834 /* Preempt the current reservation */ 835 if (DRV_CALL(drv_prsv_preempt, (buf + 8)) != 0) { 836 DM_MSG_ADD_HEAD((MMS_INTERNAL, 837 MMS_DM_E_INTERNAL, 838 "persistent reservation preempt" "error")); 839 return (-1); 840 } 841 } 842 843 return (0); 844 } 845 846 int 847 dm_have_mms_rsv(void) 848 { 849 char buf[24]; 850 uint32_t num; 851 852 if (DRV_CALL(drv_prsv_register, ()) != 0 || 853 DRV_CALL(drv_prsv_read_rsv, (buf, sizeof (buf))) != 0) { 854 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 855 "unable to read reservation")); 856 /* Can't read reservation */ 857 return (0); 858 } 859 860 char_to_uint32((uchar_t *)buf + 4, 4, &num); 861 if (num == 0) { /* no reservation */ 862 return (0); 863 } 864 865 if (memcmp(buf + 8, DRV_PRSV_KEY_PFX, 4) != 0) { 866 return (0); 867 } 868 869 /* 870 * Have MMS reservation 871 */ 872 return (1); 873 } 874 875 int 876 dm_rebind_target(void) 877 { 878 drm_target_t targ; 879 880 wka->dm_targ_base_minor = dm_get_targ(wka->dm_targ_base_minor); 881 memset(&targ, 0, sizeof (targ)); 882 targ.drm_targ_oflags |= FREAD | FWRITE | FNDELAY; 883 targ.drm_targ_major = wka->dm_targ_base_major; 884 targ.drm_targ_minor = wka->dm_targ_base_minor; 885 if (ioctl(wka->dm_drm_fd, DRM_REBIND_DEV, &targ)) { 886 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 887 "Rebind base device error: %s", 888 strerror(errno))); 889 return (-1); 890 } 891 TRACE((MMS_DEBUG, "Target rebound to (%d:%d)", 892 wka->dm_targ_base_major, wka->dm_targ_base_minor)); 893 return (0); 894 } 895 896 int 897 dm_open_dm_device(void) 898 { 899 int fd; 900 901 /* 902 * close the device if it has been opened to unbind it 903 * from the target (most likely, the ST) driver. 904 */ 905 if (wka->dm_drm_fd != -1) { 906 close(wka->dm_drm_fd); 907 wka->dm_drm_fd = -1; 908 } 909 /* 910 * Open the drive manager device 911 */ 912 fd = open(wka->dm_drm_path, O_RDWR | O_NDELAY); 913 if (fd < 0) { 914 DM_MSG_ADD((MMS_EXIST, MMS_DM_E_INTERNAL, 915 "open '%s' error: %s", 916 wka->dm_drm_path, strerror(errno))); 917 wka->dm_drm_fd = -1; 918 return (-1); 919 } 920 wka->dm_drm_fd = fd; 921 drv->drv_fd = fd; 922 923 return (0); 924 } 925 926 int 927 dm_bind_target(void) 928 { 929 struct stat statbuf; 930 931 /* 932 * Get the major and minor of the DRM device 933 */ 934 fstat(wka->dm_drm_fd, &statbuf); 935 wka->dm_drm_major = major(statbuf.st_rdev); 936 wka->dm_drm_minor = minor(statbuf.st_rdev); 937 938 /* 939 * Bind the drive manager to the target device. 940 * Since the target is opened (via ldi_open()) with O_NDELAY, 941 * the st drive will not do reserve/release on open/close. 942 * until an I/O is done. A TUR will be done after binding 943 * the target. This causes the st driver to reserve the drive. 944 */ 945 if (dm_bind_target_base() != 0) { 946 return (-1); 947 } 948 949 return (0); 950 } 951 952 /* 953 * Bind manager drive to target 954 */ 955 int 956 dm_bind_target_base(void) 957 { 958 drm_target_t targ; 959 int err; 960 uint32_t buf; 961 char pid[20]; 962 963 targ.drm_targ_major = wka->dm_targ_base_major; 964 targ.drm_targ_minor = wka->dm_targ_base_minor; 965 966 targ.drm_targ_oflags = FWRITE | FNDELAY; 967 968 pthread_mutex_lock(&wka->dm_tdv_close_mutex); 969 while (ioctl(wka->dm_drm_fd, DRM_BIND_DEV, &targ)) { 970 err = errno; 971 if (err == EMFILE) { 972 /* drive is still opened. wait for close */ 973 ioctl(wka->dm_drm_fd, DRM_TDV_PID, &buf); 974 snprintf(pid, sizeof (pid), "%d", buf); 975 TRACE((MMS_DEBUG, 976 "Waiting for App to close target device, pid %s", 977 pid)); 978 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 979 "waiting for close")); 980 DM_MSG_SEND((DM_ADM_ERR, DM_6521_MSG, 981 "drive", drv->drv_drvname, "pid", pid, 982 DM_MSG_REASON)); 983 pthread_cond_wait(&wka->dm_tdv_close_cv, 984 &wka->dm_tdv_close_mutex); 985 TRACE((MMS_DEBUG, "Waken up by tdv close")); 986 } else { 987 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 988 "unable to bind target device: %s", strerror(err))); 989 pthread_mutex_unlock(&wka->dm_tdv_close_mutex); 990 return (-1); 991 } 992 } 993 pthread_mutex_unlock(&wka->dm_tdv_close_mutex); 994 TRACE((MMS_OPER, "Device %s (%lld, %lld) bound to %s", 995 wka->dm_target_base, targ.drm_targ_major, targ.drm_targ_minor, 996 wka->dm_drm_path)); 997 998 return (0); 999 } 1000 1001 int 1002 dm_bind_raw_dev(int oflag) 1003 { 1004 int err; 1005 char *path; 1006 char *den = ""; 1007 char *bsd = ""; 1008 char *rew = ""; 1009 struct stat statbuf; 1010 drm_target_t targ; 1011 1012 if (mnt->mnt_flags & MNT_LOW) { 1013 den = "l"; 1014 } else if (mnt->mnt_flags & MNT_MEDIUM) { 1015 den = "m"; 1016 } else if (mnt->mnt_flags & MNT_HIGH) { 1017 den = "h"; 1018 } else if (mnt->mnt_flags & (MNT_ULTRA | MNT_COMPRESSION)) { 1019 den = "c"; 1020 } 1021 if (mnt->mnt_flags & (MNT_MMS | MNT_MMS_TM | MNT_BSD)) { 1022 /* MMS mode always use "b" */ 1023 bsd = "b"; 1024 } 1025 if (mnt->mnt_flags & (MNT_MMS | MNT_NOREWIND)) { 1026 /* MMS mode always use "n" */ 1027 rew = "n"; 1028 } 1029 1030 path = mms_strapp(NULL, 1031 "%s%s%s%s", wka->dm_target_base, den, bsd, rew); 1032 TRACE((MMS_DEBUG, "Device path chosen = %s", path)); 1033 1034 if (stat(path, &statbuf) != 0) { 1035 err = errno; 1036 TRACE((MMS_ERR, "Can't stat %s: %s", path, strerror(err))); 1037 return (err); 1038 } 1039 free(path); 1040 targ.drm_targ_oflags = oflag; 1041 targ.drm_targ_major = major(statbuf.st_rdev); 1042 targ.drm_targ_minor = minor(statbuf.st_rdev); 1043 if (ioctl(wka->dm_drm_fd, DRM_REBIND_DEV, &targ)) { 1044 err = errno; 1045 TRACE((MMS_ERR, "Rebind raw device error: %s", 1046 strerror(err))); 1047 return (err); 1048 } 1049 1050 dm_clear_dev(); 1051 1052 return (0); 1053 } 1054 1055 void 1056 dm_init_sense_buf(void) 1057 { 1058 struct scsi_extended_sense *es; 1059 1060 if (DRV_CALL(drv_req_sense, (sizeof (struct scsi_extended_sense)))) { 1061 /* Can't read sense data */ 1062 drv->drv_mtee_stat_len = sizeof (struct scsi_extended_sense); 1063 TRACE((MMS_DEBUG, "drv_req_sense error: Sense buf size set " 1064 "to %d", sizeof (struct scsi_extended_sense))); 1065 return; 1066 } 1067 es = (struct scsi_extended_sense *)drv->drv_iobuf; 1068 drv->drv_num_sen_bytes = 1069 es->es_add_len + ((char *)&es->es_add_len - (char *)es) + 1; 1070 drv->drv_mtee_stat_len = 1071 sizeof (struct scsi_arq_status) - 1072 sizeof (struct scsi_extended_sense) + drv->drv_num_sen_bytes; 1073 if (drv->drv_mtee_stat_len < sizeof (struct scsi_arq_status)) { 1074 drv->drv_mtee_stat_len = sizeof (struct scsi_arq_status); 1075 } 1076 if (drv->drv_mtee_stat_len > DRV_SENSE_LEN) { 1077 drv->drv_mtee_stat_len = DRV_SENSE_LEN; 1078 } 1079 TRACE((MMS_DEBUG, "add sense length = %d, num of sen bytes = %d", 1080 es->es_add_len, drv->drv_num_sen_bytes)); 1081 TRACE((MMS_DEBUG, "Sense buf size set = %d", drv->drv_mtee_stat_len)); 1082 } 1083 1084 char * 1085 dm_get_user(pid_t pid) 1086 { 1087 /* 1088 * Given the pid, return the user login name 1089 */ 1090 struct passwd pwd; 1091 struct passwd *pwent; 1092 ucred_t *ucred; 1093 uid_t uid; 1094 1095 ucred = ucred_get(pid); 1096 uid = ucred_getruid(ucred); 1097 1098 setpwent(); 1099 pwent = getpwuid_r(uid, &pwd, wka->dm_pwbuf, wka->dm_pwbuf_size); 1100 if (pwent == NULL) { 1101 endpwent(); 1102 ucred_free(ucred); 1103 return (NULL); 1104 } 1105 TRACE((MMS_DEBUG, "pid %ld, uid %ld, user %s", 1106 (long)pid, (long)uid, pwent->pw_name)); 1107 endpwent(); 1108 ucred_free(ucred); 1109 return (strdup(pwent->pw_name)); 1110 } 1111 1112 int 1113 dm_chk_dev_auth(char *user) 1114 { 1115 /* 1116 * Check to see if the user is authorized to use MMS 1117 */ 1118 setauthattr(); 1119 if (!chkauthattr(MMS_AUTHNAME, user)) { 1120 endauthattr(); 1121 return (-1); 1122 } 1123 endauthattr(); 1124 return (0); 1125 } 1126