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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/ksynch.h> 28 #include <sys/kmem.h> 29 #include <sys/cmn_err.h> 30 #include <sys/errno.h> 31 #include <sys/ddi.h> 32 33 #define __NSC_GEN__ 34 #include <sys/ncall/ncall.h> 35 #include "nsc_dev.h" 36 #include "../nsctl.h" 37 #ifdef DS_DDICT 38 #include "../contract.h" 39 #endif 40 41 42 static int _nsc_attach_fd(nsc_fd_t *, int); 43 static int _nsc_detach_owner(nsc_fd_t *, int); 44 static int _nsc_fd_fn(nsc_fd_t *, int (*)(), int, int); 45 static int _nsc_attach_iodev(nsc_iodev_t *, int); 46 static int _nsc_attach_dev(nsc_dev_t *, int); 47 static int _nsc_call_dev(nsc_dev_t *, blindfn_t, blind_t, 48 int *, int *, int, int, nsc_iodev_t *); 49 50 51 /* 52 * void 53 * _nsc_init_resv (void) 54 * Initialise reserve mechanism. 55 * 56 * Calling/Exit State: 57 * Called at initialisation time to allocate necessary 58 * data structures. 59 */ 60 void 61 _nsc_init_resv() 62 { 63 } 64 65 66 /* 67 * void 68 * _nsc_deinit_resv (void) 69 * De-initialise reserve mechanism. 70 * 71 * Calling/Exit State: 72 * Called at unload time to de-allocate resources. 73 */ 74 void 75 _nsc_deinit_resv() 76 { 77 } 78 79 80 /* 81 * int 82 * nsc_attach (nsc_fd_t *fd, int flag) 83 * Force attach of file descriptor. 84 * 85 * Calling/Exit State: 86 * Returns 0 if the attach succeeds, otherwise 87 * returns an error code. 88 * 89 * Description: 90 * Tries to attach the file descriptor by reserving 91 * and then releasing it. This is intended purely as 92 * a performance aid since there is no guarantee that 93 * the file descriptor will remain attached upon 94 * return. 95 */ 96 int 97 nsc_attach(fd, flag) 98 nsc_fd_t *fd; 99 int flag; 100 { 101 int rc; 102 103 rc = nsc_reserve(fd, flag); 104 105 if (rc == 0) 106 nsc_release(fd); 107 108 return (rc); 109 } 110 111 112 /* 113 * int 114 * nsc_reserve (nsc_fd_t *fd, int flag) 115 * Reserve file descriptor. 116 * 117 * Calling/Exit State: 118 * Returns 0 if the reserve succeeds, otherwise 119 * returns an error code. 120 * 121 * Description: 122 * Reserves the file descriptor for either NSC_READ or 123 * NSC_WRITE access. If neither is specified the mode 124 * with which the file was opened will be used. Trying 125 * to reserve a read only file in write mode will cause 126 * EACCES to be returned. 127 * 128 * If NSC_NOBLOCK is specifed and the reserve cannot be 129 * completed immediately, EAGAIN will be returned. 130 * 131 * If NSC_NOWAIT is set and the device is busy, EAGAIN 132 * will be returned. 133 * 134 * If NSC_TRY is set and the device is already reserved 135 * EAGAIN will be returned. 136 * 137 * If NSC_PCATCH is specified and a signal is received, 138 * the reserve will be terminated and EINTR returned. 139 * 140 * If NSC_MULTI is set then multiple reserves of the 141 * same type are permitted for the file descriptor. 142 */ 143 int 144 nsc_reserve(fd, flag) 145 nsc_fd_t *fd; 146 int flag; 147 { 148 nsc_dev_t *dev = fd->sf_dev; 149 int rc, rw; 150 151 if ((flag & NSC_READ) == 0) 152 flag |= (fd->sf_flag & NSC_RDWR); 153 154 rw = (flag & NSC_RDWR); 155 if ((fd->sf_flag & rw) != rw) 156 return (EACCES); 157 158 mutex_enter(&dev->nsc_lock); 159 160 while ((rc = _nsc_attach_fd(fd, flag)) != 0) 161 if (rc != ERESTART) 162 break; 163 164 if (!rc && !fd->sf_reserve++) { 165 fd->sf_aio = fd->sf_iodev->si_io; 166 fd->sf_mode = (flag & NSC_MULTI); 167 } 168 169 mutex_exit(&dev->nsc_lock); 170 return (rc); 171 } 172 173 174 /* 175 * int 176 * nsc_reserve_lk (nsc_fd_t *fd) 177 * Reserve locked file descriptor. 178 * 179 * Calling/Exit State: 180 * The device lock must be held across calls to 181 * this function. 182 * 183 * Must be preceeded by a successful call to nsc_avail. 184 * 185 * Description: 186 * Reserves the file descriptor using the mode specified 187 * when the file was opened. This is only intended for 188 * use in performance critical situations. 189 */ 190 void 191 nsc_reserve_lk(fd) 192 nsc_fd_t *fd; 193 { 194 fd->sf_reserve = 1; 195 fd->sf_aio = fd->sf_iodev->si_io; 196 } 197 198 199 /* 200 * int 201 * nsc_avail (nsc_fd_t *fd) 202 * Test if file descriptor is available. 203 * 204 * Calling/Exit State: 205 * The device lock must be held across calls to 206 * this function. 207 * 208 * Returns true if the file descriptor is available to 209 * be reserved using the mode specified when the file 210 * was opened. 211 * 212 * Description: 213 * This is only intended for use in performance critical 214 * situations in conjunction with nsc_reserve_lk. 215 */ 216 int 217 nsc_avail(fd) 218 nsc_fd_t *fd; 219 { 220 int rw; 221 222 if (!fd || fd->sf_pend || fd->sf_reserve || fd->sf_reopen) 223 return (0); 224 225 if ((fd->sf_avail & _NSC_ATTACH) == 0) 226 return (0); 227 if ((fd->sf_avail & _NSC_PINNED) == 0) 228 return (0); 229 230 rw = (fd->sf_flag & NSC_RDWR); 231 232 return ((fd->sf_avail & rw) == rw); 233 } 234 235 236 /* 237 * int 238 * nsc_held (nsc_fd_t *fd) 239 * Test if file descriptor is reserved. 240 * 241 * Calling/Exit State: 242 * Returns true if the file descriptor is currently 243 * reserved. 244 */ 245 int 246 nsc_held(fd) 247 nsc_fd_t *fd; 248 { 249 return ((fd) ? fd->sf_reserve : 1); 250 } 251 252 253 /* 254 * int 255 * nsc_waiting (nsc_fd_t *fd) 256 * Test if another client is waiting for this device. 257 * 258 * Calling/Exit State: 259 * Must be called with the file descriptor reserved. 260 * Returns true if another thread is waiting to reserve this device. 261 * 262 * Description: 263 * This is only intended for use in performance critical 264 * situations and inherently returns historical information. 265 */ 266 int 267 nsc_waiting(nsc_fd_t *fd) 268 { 269 nsc_dev_t *dev; 270 271 if (!fd || !nsc_held(fd)) 272 return (FALSE); 273 274 dev = fd->sf_dev; 275 276 return (dev->nsc_wait || dev->nsc_refcnt <= 0); 277 } 278 279 280 /* 281 * int 282 * nsc_release_lk (nsc_fd_t *fd) 283 * Release locked file descriptor. 284 * 285 * Calling/Exit State: 286 * The device lock must be held across calls to 287 * this function. 288 * 289 * Returns true if another node is waiting for the 290 * device and a call to nsc_detach should be made. 291 * 292 * Description: 293 * Releases the file descriptor. This is only intended 294 * for use in performance critical situations in 295 * conjunction with nsc_reserve_lk. 296 */ 297 int 298 nsc_release_lk(fd) 299 nsc_fd_t *fd; 300 { 301 nsc_dev_t *dev = fd->sf_dev; 302 303 fd->sf_reserve = 0; 304 fd->sf_aio = _nsc_null_io; 305 306 if (dev->nsc_wait || dev->nsc_refcnt <= 0) 307 cv_broadcast(&dev->nsc_cv); 308 309 return (dev->nsc_drop > 0); 310 } 311 312 313 /* 314 * int 315 * nsc_release (nsc_fd_t *fd) 316 * Release file descriptor. 317 * 318 * Description: 319 * Releases the file descriptor. If another node 320 * is waiting for the device it will be completely 321 * detached before returning. 322 */ 323 void 324 nsc_release(fd) 325 nsc_fd_t *fd; 326 { 327 nsc_dev_t *dev = fd->sf_dev; 328 int rc; 329 330 mutex_enter(&dev->nsc_lock); 331 332 if (!fd->sf_reserve || --fd->sf_reserve) { 333 mutex_exit(&dev->nsc_lock); 334 return; 335 } 336 337 fd->sf_aio = _nsc_null_io; 338 fd->sf_mode = 0; 339 340 if (dev->nsc_wait || dev->nsc_refcnt <= 0) 341 cv_broadcast(&dev->nsc_cv); 342 343 while (dev->nsc_drop > 0) { 344 rc = _nsc_detach_dev(dev, NULL, NSC_RDWR); 345 if (!rc || rc != ERESTART) 346 break; 347 } 348 349 mutex_exit(&dev->nsc_lock); 350 } 351 352 353 /* 354 * int 355 * nsc_detach (nsc_fd_t *fd, int flag) 356 * Detach device from node. 357 * 358 * Calling/Exit State: 359 * Returns 0 if the reserve succeeds, otherwise 360 * returns an error code. 361 * 362 * Description: 363 * Detaches the device from the current node. If flag 364 * specifies read access then flush is called in preference 365 * to detach. 366 * 367 * If NSC_NOBLOCK is specifed and the detach cannot be 368 * completed immediately, EAGAIN will be returned. 369 * 370 * If NSC_TRY is set and the device is reserved, EAGAIN 371 * will be returned. 372 * 373 * If NSC_NOWAIT is set and the device is busy, EAGAIN 374 * will be returned. 375 * 376 * If NSC_PCATCH is specified and a signal is received, 377 * the reserve will be terminated and EINTR returned. 378 * 379 * If NSC_DEFER is set and the device is reserved, then 380 * the detach will be done on release. 381 */ 382 int 383 nsc_detach(fd, flag) 384 nsc_fd_t *fd; 385 int flag; 386 { 387 nsc_dev_t *dev; 388 int rc; 389 390 if (!fd) 391 return (0); 392 393 dev = fd->sf_dev; 394 395 if (flag & NSC_DEFER) 396 flag |= NSC_TRY; 397 if ((flag & NSC_READ) == 0) 398 flag |= NSC_RDWR; 399 400 mutex_enter(&dev->nsc_lock); 401 402 while ((rc = _nsc_detach_dev(dev, NULL, flag)) != 0) 403 if (rc != ERESTART) 404 break; 405 406 if (rc == EAGAIN && (flag & NSC_DEFER)) 407 dev->nsc_drop = 1; 408 409 mutex_exit(&dev->nsc_lock); 410 return (rc); 411 } 412 413 414 /* 415 * static int 416 * _nsc_attach_fd (nsc_fd_t *fd, int flag) 417 * Attach file descriptor. 418 * 419 * Calling/Exit State: 420 * The device lock must be held across calls to 421 * this function. 422 * 423 * Returns 0 if the attach succeeds without releasing 424 * the device lock, otherwise returns an error code. 425 * 426 * Description: 427 * Attach the specified file descriptor. Other file 428 * descriptors for the same I/O device will be flushed 429 * or detached first as necessary. 430 */ 431 static int 432 _nsc_attach_fd(fd, flag) 433 nsc_fd_t *fd; 434 int flag; 435 { 436 nsc_dev_t *dev = fd->sf_dev; 437 int rw = (flag & NSC_RDWR); 438 nsc_iodev_t *iodev; 439 int rc, av; 440 441 if (fd->sf_pend) 442 return (_nsc_wait_dev(dev, flag)); 443 444 if (fd->sf_reopen) 445 if ((rc = _nsc_close_fd(fd, flag)) != 0) 446 return (rc); 447 448 if (!fd->sf_iodev) 449 if ((rc = _nsc_open_fd(fd, flag)) != 0) 450 return (rc); 451 452 iodev = fd->sf_iodev; 453 454 if ((flag & fd->sf_mode & NSC_MULTI) && fd->sf_reserve) 455 if ((fd->sf_avail & rw) == rw && !iodev->si_rpend) 456 if (dev->nsc_drop == 0) 457 return (0); 458 459 if (fd->sf_reserve) { 460 if (flag & NSC_TRY) 461 return (EAGAIN); 462 return (_nsc_wait_dev(dev, flag)); 463 } 464 465 if (fd->sf_avail & _NSC_ATTACH) 466 if (fd->sf_avail & _NSC_PINNED) 467 if ((fd->sf_avail & rw) == rw) 468 return (0); 469 470 if (iodev->si_rpend && !fd->sf_avail) 471 return (_nsc_wait_dev(dev, flag)); 472 473 if ((rc = _nsc_detach_iodev(iodev, fd, flag)) != 0 || 474 (rc = _nsc_attach_iodev(iodev, flag)) != 0) 475 return (rc); 476 477 if (!fd->sf_avail) { 478 fd->sf_avail = rw; 479 return (_nsc_fd_fn(fd, fd->sf_attach, _NSC_ATTACH, flag)); 480 } 481 482 if ((fd->sf_avail & _NSC_PINNED) == 0) { 483 av = (fd->sf_avail | _NSC_PINNED); 484 485 return _nsc_call_dev(dev, iodev->si_io->getpin, 486 fd->sf_cd, &fd->sf_avail, &fd->sf_pend, av, flag, NULL); 487 } 488 489 fd->sf_avail |= rw; 490 return (0); 491 } 492 493 494 /* 495 * int 496 * _nsc_detach_fd (nsc_fd_t *fd, int flag) 497 * Detach file descriptor. 498 * 499 * Calling/Exit State: 500 * The device lock must be held across calls to 501 * this function. 502 * 503 * Returns 0 if the detach succeeds without releasing 504 * the device lock, otherwise returns an error code. 505 * 506 * Description: 507 * Detach the specified file descriptor. If flag 508 * specifies read access then flush is called in 509 * preference to detach. 510 */ 511 int 512 _nsc_detach_fd(fd, flag) 513 nsc_fd_t *fd; 514 int flag; 515 { 516 nsc_dev_t *dev = fd->sf_dev; 517 int rc; 518 519 if (fd->sf_pend == _NSC_CLOSE) 520 return (0); 521 522 if (fd->sf_pend) 523 return (_nsc_wait_dev(dev, flag)); 524 525 if (fd->sf_flush == nsc_null) 526 flag |= NSC_RDWR; 527 528 if ((fd->sf_avail & NSC_RDWR) == 0) 529 if (!fd->sf_avail || !(flag & NSC_WRITE)) 530 return (0); 531 532 if (fd->sf_reserve && fd->sf_owner) 533 if ((rc = _nsc_detach_owner(fd, flag)) != 0) 534 return (rc); 535 536 if (fd->sf_reserve) { 537 if (flag & NSC_TRY) 538 return (EAGAIN); 539 return (_nsc_wait_dev(dev, flag)); 540 } 541 542 if (flag & NSC_WRITE) { 543 if (fd->sf_iodev->si_busy) 544 return (_nsc_wait_dev(dev, flag)); 545 546 return (_nsc_fd_fn(fd, fd->sf_detach, 0, flag)); 547 } 548 549 return (_nsc_fd_fn(fd, fd->sf_flush, (fd->sf_avail & ~NSC_RDWR), flag)); 550 } 551 552 553 /* 554 * static int 555 * _nsc_detach_owner (nsc_fd_t *fd, int flag) 556 * Detach owner of file descriptor. 557 * 558 * Calling/Exit State: 559 * The device lock must be held across calls to 560 * this function. 561 * 562 * Returns 0 if the detach succeeds without releasing 563 * the device lock, otherwise returns an error code. 564 * 565 * Description: 566 * Detach the owner of the specified file descriptor. 567 * Wherever possible this is done without releasing 568 * the current device lock. 569 */ 570 static int 571 _nsc_detach_owner(fd, flag) 572 nsc_fd_t *fd; 573 int flag; 574 { 575 nsc_dev_t *newdev = fd->sf_owner->si_dev; 576 nsc_dev_t *dev = fd->sf_dev; 577 int try; 578 int rc; 579 580 if (newdev == dev) { 581 if ((rc = _nsc_detach_iodev(fd->sf_owner, NULL, flag)) == 0) 582 fd->sf_owner = NULL; 583 return (rc); 584 } 585 586 if ((try = mutex_tryenter(&newdev->nsc_lock)) != 0) 587 if (!_nsc_detach_iodev(fd->sf_owner, NULL, 588 (flag | NSC_NOBLOCK))) { 589 mutex_exit(&newdev->nsc_lock); 590 return (0); 591 } 592 593 if (flag & NSC_NOBLOCK) { 594 if (try != 0) 595 mutex_exit(&newdev->nsc_lock); 596 return (EAGAIN); 597 } 598 599 fd->sf_pend = _NSC_OWNER; 600 mutex_exit(&dev->nsc_lock); 601 602 if (try == 0) 603 mutex_enter(&newdev->nsc_lock); 604 605 rc = _nsc_detach_iodev(fd->sf_owner, NULL, flag); 606 fd->sf_owner = NULL; 607 608 mutex_exit(&newdev->nsc_lock); 609 610 mutex_enter(&dev->nsc_lock); 611 fd->sf_pend = 0; 612 613 if (dev->nsc_wait || dev->nsc_refcnt <= 0) 614 cv_broadcast(&dev->nsc_cv); 615 616 return (rc ? rc : ERESTART); 617 } 618 619 620 /* 621 * static int 622 * _nsc_fd_fn (nsc_fd_t *fd, int (*fn)(), int a, int flag) 623 * Call function to attach/detach file descriptor. 624 * 625 * Calling/Exit State: 626 * The device lock must be held across calls to 627 * this function. 628 * 629 * Returns an error code if the operation failed, 630 * otherwise returns ERESTART to indicate that the 631 * device state has changed. 632 * 633 * Description: 634 * Sets up the active I/O module and calls the 635 * specified function. 636 */ 637 static int 638 _nsc_fd_fn(nsc_fd_t *fd, int (*fn)(), int a, int flag) 639 { 640 int rc; 641 642 fd->sf_aio = fd->sf_iodev->si_io; 643 644 rc = _nsc_call_dev(fd->sf_dev, fn, fd->sf_arg, 645 &fd->sf_avail, &fd->sf_pend, a, flag, NULL); 646 647 fd->sf_aio = _nsc_null_io; 648 return (rc); 649 } 650 651 652 /* 653 * static int 654 * _nsc_attach_iodev (nsc_iodev_t *iodev, int flag) 655 * Attach I/O device. 656 * 657 * Calling/Exit State: 658 * The device lock must be held across calls to 659 * this function. 660 * 661 * Returns 0 if the attach succeeds without releasing 662 * the device lock, otherwise returns an error code. 663 * 664 * Description: 665 * Attach the specified I/O device. Other I/O devices 666 * for the same device will be flushed or detached first 667 * as necessary. 668 * 669 * It is assumed that any valid cache descriptor for 670 * this device can be used to attach the I/O device. 671 */ 672 static int 673 _nsc_attach_iodev(iodev, flag) 674 nsc_iodev_t *iodev; 675 int flag; 676 { 677 nsc_dev_t *dev = iodev->si_dev; 678 nsc_io_t *io = iodev->si_io; 679 int rc, rw; 680 681 rw = (flag & NSC_RDWR); 682 683 if (iodev->si_pend) 684 return (_nsc_wait_dev(dev, flag)); 685 686 if (iodev->si_avail & _NSC_ATTACH) 687 if ((iodev->si_avail & rw) == rw) 688 return (0); 689 690 if ((io->flag & NSC_FILTER) == 0) { 691 if (dev->nsc_rpend && !iodev->si_avail) 692 return (_nsc_wait_dev(dev, flag)); 693 694 if ((rc = _nsc_detach_dev(dev, iodev, flag)) != 0 || 695 (rc = _nsc_attach_dev(dev, flag)) != 0) 696 return (rc); 697 } 698 699 if (!iodev->si_avail) { 700 iodev->si_avail = rw; 701 702 if (!iodev->si_open) { 703 cmn_err(CE_PANIC, 704 "nsctl: _nsc_attach_iodev: %p no fds", 705 (void *)iodev); 706 } 707 708 return (_nsc_call_dev(dev, io->attach, iodev->si_open->sf_cd, 709 &iodev->si_avail, &iodev->si_pend, _NSC_ATTACH, 710 flag, iodev)); 711 } 712 713 iodev->si_avail |= rw; 714 return (0); 715 } 716 717 718 /* 719 * int 720 * _nsc_detach_iodev (nsc_iodev_t *iodev, nsc_fd_t *keep, int flag) 721 * Detach I/O device. 722 * 723 * Calling/Exit State: 724 * The device lock must be held across calls to 725 * this function. 726 * 727 * Returns 0 if the detach succeeds without releasing 728 * the device lock, otherwise returns an error code. 729 * 730 * Description: 731 * Detach the specified I/O device except for file 732 * descriptor keep. If flag specifies read access then 733 * flush is called in preference to detach. 734 * 735 * It is assumed that any valid cache descriptor for 736 * this device can be used to detach the I/O device. 737 */ 738 int 739 _nsc_detach_iodev(nsc_iodev_t *iodev, nsc_fd_t *keep, int flag) 740 { 741 nsc_dev_t *dev = iodev->si_dev; 742 nsc_io_t *io = iodev->si_io; 743 int (*fn)(), av, rc; 744 nsc_fd_t *fd; 745 746 if (iodev->si_pend == _NSC_CLOSE) 747 return (0); 748 749 if (iodev->si_pend) 750 return (_nsc_wait_dev(dev, flag)); 751 752 if (!keep && io->flush == nsc_null) 753 flag |= NSC_RDWR; 754 755 if ((iodev->si_avail & NSC_RDWR) == 0) 756 if (!iodev->si_avail || !(flag & NSC_WRITE)) 757 return (0); 758 759 iodev->si_rpend++; 760 761 for (fd = iodev->si_open; fd; fd = fd->sf_next) { 762 if (fd == keep) 763 continue; 764 765 if ((rc = _nsc_detach_fd(fd, flag)) != 0) { 766 _nsc_wake_dev(dev, &iodev->si_rpend); 767 return (rc); 768 } 769 } 770 771 _nsc_wake_dev(dev, &iodev->si_rpend); 772 773 if (keep) 774 return (0); 775 776 if (!iodev->si_open) { 777 cmn_err(CE_PANIC, 778 "nsctl: _nsc_detach_iodev: %p no fds", (void *)iodev); 779 } 780 781 fn = (flag & NSC_WRITE) ? io->detach : io->flush; 782 av = (flag & NSC_WRITE) ? 0 : (iodev->si_avail & ~NSC_RDWR); 783 784 return (_nsc_call_dev(dev, fn, iodev->si_open->sf_cd, 785 &iodev->si_avail, &iodev->si_pend, av, flag, iodev)); 786 } 787 788 789 /* 790 * static int 791 * _nsc_attach_dev (nsc_dev_t *dev, int flag) 792 * Attach device to node. 793 * 794 * Calling/Exit State: 795 * The device lock must be held across calls to 796 * this function. 797 * 798 * Returns 0 if the attach succeeds without releasing 799 * the device lock, otherwise returns an error code. 800 * 801 * Description: 802 * Attach the device to the current node. 803 */ 804 static int 805 _nsc_attach_dev(dev, flag) 806 nsc_dev_t *dev; 807 int flag; 808 { 809 if (dev->nsc_pend) { 810 if (flag & NSC_TRY) 811 return (EAGAIN); 812 return (_nsc_wait_dev(dev, flag)); 813 } 814 815 return (0); 816 } 817 818 819 /* 820 * int 821 * _nsc_detach_dev (nsc_dev_t *dev, nsc_iodev_t *keep, int flag) 822 * Detach device. 823 * 824 * Calling/Exit State: 825 * The device lock must be held across calls to 826 * this function. 827 * 828 * Returns 0 if the detach succeeds without releasing 829 * the device lock, otherwise returns an error code. 830 * 831 * Description: 832 * Detach the device except for I/O descriptor keep. 833 * If flag specifies read access then flush is called 834 * in preference to detach. If appropriate the device 835 * will be released for use by another node. 836 * 837 * All I/O devices are detached regardless of the 838 * current owner as a sanity check. 839 */ 840 int 841 _nsc_detach_dev(nsc_dev_t *dev, nsc_iodev_t *keep, int flag) 842 { 843 nsc_iodev_t *iodev; 844 int rc = 0; 845 846 if (dev->nsc_pend) { 847 if (flag & NSC_TRY) 848 return (EAGAIN); 849 return (_nsc_wait_dev(dev, flag)); 850 } 851 852 dev->nsc_rpend++; 853 854 for (iodev = dev->nsc_list; iodev; iodev = iodev->si_next) { 855 if (iodev == keep) 856 continue; 857 if (iodev->si_io->flag & NSC_FILTER) 858 continue; 859 860 if ((rc = _nsc_detach_iodev(iodev, NULL, flag)) != 0) 861 break; 862 } 863 864 _nsc_wake_dev(dev, &dev->nsc_rpend); 865 866 if (keep || !(flag & NSC_WRITE)) 867 return (rc); 868 if (rc == EAGAIN || rc == ERESTART) 869 return (rc); 870 871 dev->nsc_drop = 0; 872 873 return (rc); 874 } 875 876 877 /* 878 * static int 879 * _nsc_call_dev (nsc_dev_t *dev, blindfn_t fn, blind_t arg, 880 * *int *ap, int *pp, int a, int flag, nsc_iodev_t *iodev) 881 * Call attach/detach function. 882 * 883 * Calling/Exit State: 884 * The device lock must be held across calls to this 885 * this function. 886 * 887 * Returns an error code if the operation failed, 888 * otherwise returns ERESTART to indicate that the 889 * device state has changed. 890 * 891 * The flags pointed to by ap are updated to reflect 892 * availability based upon argument a. The pending 893 * flag pointed to by pp is set whilst the operation 894 * is in progress. 895 * 896 * Description: 897 * Marks the device busy, temporarily releases the 898 * device lock and calls the specified function with 899 * the given argument. 900 * 901 * If a detach is being performed then clear _NSC_ATTACH 902 * first to prevent pinned data callbacks. If the detach 903 * fails then clear _NSC_PINNED and indicate that a flush 904 * is required by setting NSC_READ. 905 */ 906 static int 907 _nsc_call_dev(nsc_dev_t *dev, blindfn_t fn, blind_t arg, int *ap, int *pp, 908 int a, int flag, nsc_iodev_t *iodev) 909 { 910 int rc = 0, v = *ap; 911 912 if (flag & NSC_NOBLOCK) 913 if (fn != nsc_null) 914 return (EAGAIN); 915 916 if (!a && v) 917 *ap = (v & ~_NSC_ATTACH) | NSC_READ; 918 919 if (fn != nsc_null) { 920 *pp = (a) ? a : _NSC_DETACH; 921 mutex_exit(&dev->nsc_lock); 922 923 rc = (*fn)(arg, iodev); 924 925 mutex_enter(&dev->nsc_lock); 926 *pp = 0; 927 } 928 929 if (dev->nsc_wait || dev->nsc_refcnt <= 0) 930 cv_broadcast(&dev->nsc_cv); 931 932 if (rc) { 933 if (!a && v) 934 a = (v & ~_NSC_PINNED) | NSC_READ; 935 else if (v & _NSC_ATTACH) 936 a = v; 937 else 938 a = 0; 939 } 940 941 *ap = a; 942 return (rc ? rc : ERESTART); 943 } 944 945 946 /* 947 * int 948 * _nsc_wait_dev (nsc_dev_t *dev, int flag) 949 * Wait for device state to change. 950 * 951 * Calling/Exit State: 952 * Must be called with the device lock held. 953 * Returns EAGAIN if NSC_NOBLOCK or NSC_NOWAIT is set, 954 * or EINTR if the wait was interrupted, otherwise 955 * returns ERESTART to indicate that the device state 956 * has changed. 957 * 958 * Description: 959 * Waits for the device state to change before resuming. 960 * 961 * Remarks: 962 * If the reference count on the device has dropped to 963 * zero then cv_broadcast is called to wakeup _nsc_free_dev. 964 */ 965 int 966 _nsc_wait_dev(dev, flag) 967 nsc_dev_t *dev; 968 int flag; 969 { 970 int rc = 1; 971 972 if (flag & (NSC_NOBLOCK | NSC_NOWAIT)) 973 return (EAGAIN); 974 975 dev->nsc_wait++; 976 977 if (flag & NSC_PCATCH) 978 rc = cv_wait_sig(&dev->nsc_cv, &dev->nsc_lock); 979 else 980 cv_wait(&dev->nsc_cv, &dev->nsc_lock); 981 982 dev->nsc_wait--; 983 984 if (dev->nsc_refcnt <= 0) 985 cv_broadcast(&dev->nsc_cv); 986 987 return ((rc == 0) ? EINTR : ERESTART); 988 } 989 990 991 /* 992 * void 993 * _nsc_wake_dev (nsc_dev_t *dev, int *valp) 994 * Decrement value and wakeup device. 995 * 996 * Calling/Exit State: 997 * The device lock must be held across calls to 998 * this function. 999 * 1000 * Description: 1001 * Decrements the indicated value and if appropriate 1002 * wakes up anybody waiting on the device. 1003 */ 1004 void 1005 _nsc_wake_dev(dev, valp) 1006 nsc_dev_t *dev; 1007 int *valp; 1008 { 1009 if (--(*valp)) 1010 return; 1011 1012 if (dev->nsc_wait || dev->nsc_refcnt <= 0) 1013 cv_broadcast(&dev->nsc_cv); 1014 } 1015