Print this page
9702 HBA drivers don't need the redundant devfs_clean step
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
   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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *







  25  * iSCSI logical unit interfaces
  26  */
  27 
  28 #include "iscsi.h"
  29 #include <sys/fs/dv_node.h>       /* devfs_clean */
  30 #include <sys/bootprops.h>
  31 #include <sys/sysevent/eventdefs.h>
  32 #include <sys/sysevent/dev.h>
  33 
  34 /* tpgt bytes in string form */
  35 #define TPGT_EXT_SIZE   5
  36 
  37 /* logical unit number bytes in string form */
  38 #define LUN_EXT_SIZE    10
  39 
  40 /*
  41  * Addition addr size of size of ',' + max str form of tpgt (2 bytes) +
  42  * ',' + max str form of logical unit number (4 bytes).
  43  */
  44 #define ADDR_EXT_SIZE   (1 + TPGT_EXT_SIZE + 1 + LUN_EXT_SIZE)
  45 
  46 /* internal interfaces */
  47 static iscsi_status_t iscsi_lun_virt_create(iscsi_sess_t *isp,
  48     uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
  49 static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,


 624  * be called to both offline and free the logical unit.
 625  * (This operates soley on the solaris node states.
 626  * iscsi_lun_destroy() should be called when attempting
 627  * to free all iscsi lun resources.)
 628  *
 629  * This function can fail with ISCSI_STATUS_BUSY if the
 630  * logical unit is in use.  The user should unmount or
 631  * close the device and perform the nameservice operation
 632  * again if this occurs.
 633  *
 634  * If we fail to offline a LUN that we don't want to destroy,
 635  * we will mark it with invalid state. If this LUN still
 636  * exists on the target, we can have another chance to online
 637  * it again when we do the LUN enumeration.
 638  */
 639 iscsi_status_t
 640 iscsi_lun_offline(iscsi_hba_t *ihp, iscsi_lun_t *ilp, boolean_t lun_free)
 641 {
 642         iscsi_status_t          status          = ISCSI_STATUS_SUCCESS;
 643         int                     circ            = 0;
 644         dev_info_t              *cdip, *pdip;
 645         char                    *devname        = NULL;
 646         char                    *pathname       = NULL;
 647         int                     rval;
 648         boolean_t               offline         = B_FALSE;
 649         nvlist_t                *attr_list      = NULL;
 650 
 651         ASSERT(ilp != NULL);
 652         ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
 653 
 654         /*
 655          * Since we carry the logical units parent
 656          * lock across the offline call it will not
 657          * issue devfs_clean() and may fail with a
 658          * devi_ref count > 0.
 659          */
 660         if (ilp->lun_pip == NULL) {
 661                 cdip = ilp->lun_dip;
 662         } else {
 663                 cdip = mdi_pi_get_client(ilp->lun_pip);
 664         }
 665 
 666         if ((cdip != NULL) &&
 667             (lun_free == B_TRUE) &&
 668             (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
 669                 /*
 670                  * Make sure node is attached otherwise
 671                  * it won't have related cache nodes to
 672                  * clean up.  i_ddi_devi_attached is
 673                  * similiar to i_ddi_node_state(cdip) >=
 674                  * DS_ATTACHED. We should clean up only
 675                  * when lun_free is set.
 676                  */
 677                 if (i_ddi_devi_attached(cdip)) {
 678 
 679                         /* Get parent dip */
 680                         pdip = ddi_get_parent(cdip);
 681 
 682                         /* Get full devname */
 683                         devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
 684                         ndi_devi_enter(pdip, &circ);
 685                         (void) ddi_deviname(cdip, devname);
 686                         /* Release lock before devfs_clean() */
 687                         ndi_devi_exit(pdip, circ);
 688 
 689                         /* Clean cache */
 690                         (void) devfs_clean(pdip, devname + 1, DV_CLEAN_FORCE);
 691                         kmem_free(devname, MAXNAMELEN + 1);
 692                 }
 693         }
 694 
 695         if (cdip != NULL && ilp->lun_type == DTYPE_DIRECT) {
 696                 pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
 697                 (void) ddi_pathname(cdip, pathname);
 698         }
 699 
 700         /* Attempt to offline the logical units */
 701         if (ilp->lun_pip != NULL) {
 702 
 703                 /* virt/mdi */
 704                 ndi_devi_enter(scsi_vhci_dip, &circ);
 705                 if ((lun_free == B_TRUE) &&
 706                     (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
 707                         rval = mdi_pi_offline(ilp->lun_pip,
 708                             NDI_DEVI_REMOVE);
 709                 } else {
 710                         rval = mdi_pi_offline(ilp->lun_pip, 0);
 711                 }
 712 
 713                 if (rval == MDI_SUCCESS) {
 714                         ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
 715                         ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
 716                         if (lun_free == B_TRUE) {
 717                                 (void) mdi_prop_remove(ilp->lun_pip, NULL);
 718                                 (void) mdi_pi_free(ilp->lun_pip, 0);
 719                         }
 720                         offline = B_TRUE;
 721                 } else {
 722                         status = ISCSI_STATUS_BUSY;
 723                         if (lun_free == B_FALSE) {
 724                                 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
 725                                 offline = B_TRUE;
 726                         }
 727                 }
 728                 ndi_devi_exit(scsi_vhci_dip, circ);
 729 
 730         } else  {
 731 
 732                 /* phys/ndi */


 733                 ndi_devi_enter(ihp->hba_dip, &circ);
 734                 if ((lun_free == B_TRUE) &&
 735                     (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
 736                         rval = ndi_devi_offline(
 737                             ilp->lun_dip, NDI_DEVI_REMOVE);
 738                 } else {
 739                         rval = ndi_devi_offline(
 740                             ilp->lun_dip, 0);
 741                 }
 742                 if (rval != NDI_SUCCESS) {
 743                         status = ISCSI_STATUS_BUSY;
 744                         if (lun_free == B_FALSE) {
 745                                 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
 746                                 offline = B_TRUE;
 747                         }
 748                 } else {
 749                         ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
 750                         ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
 751                         offline = B_TRUE;
 752                 }
 753                 ndi_devi_exit(ihp->hba_dip, circ);
 754         }
 755 
 756         if (offline == B_TRUE && pathname != NULL &&
 757             ilp->lun_type == DTYPE_DIRECT) {
 758                 if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
 759                     DDI_SUCCESS) {
 760                         kmem_free(pathname, MAXNAMELEN + 1);
 761                         return (status);
 762                 }
   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 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  */
  27 
  28 /*
  29  * Copyright 2018 Nexenta Systems, Inc.
  30  */
  31 
  32 /*
  33  * iSCSI logical unit interfaces
  34  */
  35 
  36 #include "iscsi.h"

  37 #include <sys/bootprops.h>
  38 #include <sys/sysevent/eventdefs.h>
  39 #include <sys/sysevent/dev.h>
  40 
  41 /* tpgt bytes in string form */
  42 #define TPGT_EXT_SIZE   5
  43 
  44 /* logical unit number bytes in string form */
  45 #define LUN_EXT_SIZE    10
  46 
  47 /*
  48  * Addition addr size of size of ',' + max str form of tpgt (2 bytes) +
  49  * ',' + max str form of logical unit number (4 bytes).
  50  */
  51 #define ADDR_EXT_SIZE   (1 + TPGT_EXT_SIZE + 1 + LUN_EXT_SIZE)
  52 
  53 /* internal interfaces */
  54 static iscsi_status_t iscsi_lun_virt_create(iscsi_sess_t *isp,
  55     uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
  56 static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,


 631  * be called to both offline and free the logical unit.
 632  * (This operates soley on the solaris node states.
 633  * iscsi_lun_destroy() should be called when attempting
 634  * to free all iscsi lun resources.)
 635  *
 636  * This function can fail with ISCSI_STATUS_BUSY if the
 637  * logical unit is in use.  The user should unmount or
 638  * close the device and perform the nameservice operation
 639  * again if this occurs.
 640  *
 641  * If we fail to offline a LUN that we don't want to destroy,
 642  * we will mark it with invalid state. If this LUN still
 643  * exists on the target, we can have another chance to online
 644  * it again when we do the LUN enumeration.
 645  */
 646 iscsi_status_t
 647 iscsi_lun_offline(iscsi_hba_t *ihp, iscsi_lun_t *ilp, boolean_t lun_free)
 648 {
 649         iscsi_status_t          status          = ISCSI_STATUS_SUCCESS;
 650         int                     circ            = 0;
 651         dev_info_t              *cdip;

 652         char                    *pathname       = NULL;

 653         boolean_t               offline         = B_FALSE;
 654         nvlist_t                *attr_list      = NULL;
 655 
 656         ASSERT(ilp != NULL);
 657         ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
 658 
 659         if (ilp->lun_pip == NULL)






 660                 cdip = ilp->lun_dip;
 661         else
 662                 cdip = mdi_pi_get_client(ilp->lun_pip);

 663 





























 664         if (cdip != NULL && ilp->lun_type == DTYPE_DIRECT) {
 665                 pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
 666                 (void) ddi_pathname(cdip, pathname);
 667         }
 668 
 669         /* Attempt to offline the logical units */
 670         if (ilp->lun_pip != NULL) {

 671                 /* virt/mdi */
 672                 ndi_devi_enter(scsi_vhci_dip, &circ);
 673                 if (mdi_pi_offline(ilp->lun_pip, 0) == MDI_SUCCESS) {








 674                         ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
 675                         ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
 676                         if (lun_free == B_TRUE) {
 677                                 (void) mdi_prop_remove(ilp->lun_pip, NULL);
 678                                 (void) mdi_pi_free(ilp->lun_pip, 0);
 679                         }
 680                         offline = B_TRUE;
 681                 } else {
 682                         status = ISCSI_STATUS_BUSY;
 683                         if (lun_free == B_FALSE) {
 684                                 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
 685                                 offline = B_TRUE;
 686                         }
 687                 }
 688                 ndi_devi_exit(scsi_vhci_dip, circ);
 689 
 690         } else  {

 691                 /* phys/ndi */
 692                 int flags = NDI_DEVFS_CLEAN;
 693 
 694                 ndi_devi_enter(ihp->hba_dip, &circ);
 695                 if (lun_free == B_TRUE &&
 696                     (ilp->lun_state & ISCSI_LUN_STATE_ONLINE))
 697                         flags |= NDI_DEVI_REMOVE;
 698                 if (ndi_devi_offline(ilp->lun_dip, flags) != NDI_SUCCESS) {





 699                         status = ISCSI_STATUS_BUSY;
 700                         if (lun_free == B_FALSE) {
 701                                 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
 702                                 offline = B_TRUE;
 703                         }
 704                 } else {
 705                         ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
 706                         ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
 707                         offline = B_TRUE;
 708                 }
 709                 ndi_devi_exit(ihp->hba_dip, circ);
 710         }
 711 
 712         if (offline == B_TRUE && pathname != NULL &&
 713             ilp->lun_type == DTYPE_DIRECT) {
 714                 if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
 715                     DDI_SUCCESS) {
 716                         kmem_free(pathname, MAXNAMELEN + 1);
 717                         return (status);
 718                 }