Print this page
NEX-17446 cleanup of hot unplugged disks fails intermittently
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17944 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>
NEX-17934 NULL pointer reference in kstat_rele()
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-15288 getting kstat_create('mdi'...) errors on each reboot
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-15925 pseudonex, rootnex, and friends don't need to log useless device announcements
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
OS-253 we should not free mdi_pathinfo_t in mptsas when device(s) are retired
OS-126 Creating a LUN for retired device results in sysevent loop

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/sunmdi.c
          +++ new/usr/src/uts/common/os/sunmdi.c
↓ open down ↓ 10 lines elided ↑ open up ↑
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
       21 +
  21   22  /*
  22   23   * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright (c) 2014 Nexenta Systems Inc. All rights reserved.
       24 + * Copyright 2018 Nexenta Systems, Inc.
  24   25   */
  25   26  
  26   27  /*
  27   28   * Multipath driver interface (MDI) implementation; see mdi_impldefs.h for a
  28   29   * more detailed discussion of the overall mpxio architecture.
  29      - *
  30      - * Default locking order:
  31      - *
  32      - * _NOTE(LOCK_ORDER(mdi_mutex, mdi_vhci:vh_phci_mutex);
  33      - * _NOTE(LOCK_ORDER(mdi_mutex, mdi_vhci:vh_client_mutex);
  34      - * _NOTE(LOCK_ORDER(mdi_vhci:vh_phci_mutex, mdi_phci::ph_mutex);
  35      - * _NOTE(LOCK_ORDER(mdi_vhci:vh_client_mutex, mdi_client::ct_mutex);
  36      - * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_pathinfo::pi_mutex))
  37      - * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_client::ct_mutex))
  38      - * _NOTE(LOCK_ORDER(mdi_client::ct_mutex mdi_pathinfo::pi_mutex))
  39   30   */
  40   31  
  41   32  #include <sys/note.h>
  42   33  #include <sys/types.h>
  43   34  #include <sys/varargs.h>
  44   35  #include <sys/param.h>
  45   36  #include <sys/errno.h>
  46   37  #include <sys/uio.h>
  47   38  #include <sys/buf.h>
  48   39  #include <sys/modctl.h>
↓ open down ↓ 1140 lines elided ↑ open up ↑
1189 1180   * i_mdi_devinfo_remove():
1190 1181   *              Remove a client device node
1191 1182   */
1192 1183  static int
1193 1184  i_mdi_devinfo_remove(dev_info_t *vdip, dev_info_t *cdip, int flags)
1194 1185  {
1195 1186          int     rv = MDI_SUCCESS;
1196 1187  
1197 1188          if (i_mdi_is_child_present(vdip, cdip) == MDI_SUCCESS ||
1198 1189              (flags & MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED)) {
1199      -                rv = ndi_devi_offline(cdip, NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
     1190 +                int nflags = NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE;
     1191 +
     1192 +                if (flags & MDI_CLIENT_FLAGS_NO_EVENT)
     1193 +                        nflags |= NDI_NO_EVENT;
     1194 +
     1195 +                rv = ndi_devi_offline(cdip, nflags);
1200 1196                  if (rv != NDI_SUCCESS) {
1201 1197                          MDI_DEBUG(1, (MDI_NOTE, cdip,
1202 1198                              "!failed: cdip %p", (void *)cdip));
1203 1199                  }
1204 1200                  /*
1205 1201                   * Convert to MDI error code
1206 1202                   */
1207 1203                  switch (rv) {
1208 1204                  case NDI_SUCCESS:
1209 1205                          rv = MDI_SUCCESS;
↓ open down ↓ 2046 lines elided ↑ open up ↑
3256 3252                          MDI_DEBUG(4, (MDI_NOTE, ct->ct_dip,
3257 3253                              "i_mdi_pm_rele_client\n"));
3258 3254                          i_mdi_pm_rele_client(ct, 1);
3259 3255                  }
3260 3256                  i_mdi_pi_free(ph, pip, ct);
3261 3257                  if (ct->ct_path_count == 0) {
3262 3258                          /*
3263 3259                           * Client lost its last path.
3264 3260                           * Clean up the client device
3265 3261                           */
     3262 +                        ct->ct_flags |= flags;
3266 3263                          MDI_CLIENT_UNLOCK(ct);
3267 3264                          (void) i_mdi_client_free(ct->ct_vhci, ct);
3268 3265                          MDI_VHCI_CLIENT_UNLOCK(vh);
3269 3266                          return (rv);
3270 3267                  }
3271 3268          }
3272 3269          MDI_CLIENT_UNLOCK(ct);
3273 3270          MDI_VHCI_CLIENT_UNLOCK(vh);
3274 3271  
3275 3272          if (rv == MDI_FAILURE)
↓ open down ↓ 387 lines elided ↑ open up ↑
3663 3660                                          }
3664 3661                                          rv = NDI_SUCCESS;
3665 3662                                  }
3666 3663                                  break;
3667 3664  
3668 3665                          case MDI_CLIENT_STATE_FAILED:
3669 3666                                  /*
3670 3667                                   * This is the last path case for
3671 3668                                   * non-user initiated events.
3672 3669                                   */
3673      -                                if (((flag & NDI_USER_REQ) == 0) &&
3674      -                                    cdip && (i_ddi_node_state(cdip) >=
3675      -                                    DS_INITIALIZED)) {
3676      -                                        MDI_CLIENT_UNLOCK(ct);
3677      -                                        rv = ndi_devi_offline(cdip,
3678      -                                            NDI_DEVFS_CLEAN);
3679      -                                        MDI_CLIENT_LOCK(ct);
     3670 +                                if ((flag & NDI_USER_REQ) ||
     3671 +                                    cdip == NULL || i_ddi_node_state(cdip) <
     3672 +                                    DS_INITIALIZED)
     3673 +                                        break;
3680 3674  
3681      -                                        if (rv != NDI_SUCCESS) {
3682      -                                                /*
3683      -                                                 * ndi_devi_offline failed.
3684      -                                                 * Reset client flags to
3685      -                                                 * online as the path could not
3686      -                                                 * be offlined.
3687      -                                                 */
3688      -                                                MDI_DEBUG(1, (MDI_WARN, cdip,
3689      -                                                    "!ndi_devi_offline failed: "
3690      -                                                    "error %x", rv));
3691      -                                                MDI_CLIENT_SET_ONLINE(ct);
3692      -                                        }
     3675 +                                MDI_CLIENT_UNLOCK(ct);
     3676 +                                rv = ndi_devi_offline(cdip, NDI_DEVFS_CLEAN |
     3677 +                                    NDI_DEVI_GONE);
     3678 +                                MDI_CLIENT_LOCK(ct);
     3679 +
     3680 +                                if (rv != NDI_SUCCESS) {
     3681 +                                        /*
     3682 +                                         * Reset client flags to online as the
     3683 +                                         * path could not be offlined.
     3684 +                                         */
     3685 +                                        MDI_DEBUG(1, (MDI_WARN, cdip,
     3686 +                                            "!ndi_devi_offline failed: %d",
     3687 +                                            rv));
     3688 +                                        MDI_CLIENT_SET_ONLINE(ct);
3693 3689                                  }
3694 3690                                  break;
3695 3691                          }
3696 3692                          /*
3697 3693                           * Convert to MDI error code
3698 3694                           */
3699 3695                          switch (rv) {
3700 3696                          case NDI_SUCCESS:
3701 3697                                  MDI_CLIENT_SET_REPORT_DEV_NEEDED(ct);
3702 3698                                  i_mdi_report_path_state(ct, pip);
↓ open down ↓ 1145 lines elided ↑ open up ↑
4848 4844                  status = "online";
4849 4845                  report_lb_p = 1;
4850 4846          } else if (MDI_PI_IS_STANDBY(pip)) {
4851 4847                  status = "standby";
4852 4848          } else if (MDI_PI_IS_FAULT(pip)) {
4853 4849                  status = "faulted";
4854 4850          } else {
4855 4851                  status = "unknown";
4856 4852          }
4857 4853  
4858      -        if (cdip) {
     4854 +        if (cdip != NULL) {
4859 4855                  ct_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
4860 4856  
4861      -                /*
4862      -                 * NOTE: Keeping "multipath status: %s" and
4863      -                 * "Load balancing: %s" format unchanged in case someone
4864      -                 * scrubs /var/adm/messages looking for these messages.
4865      -                 */
4866 4857                  if (report_lb_c && report_lb_p) {
4867 4858                          if (ct->ct_lb == LOAD_BALANCE_LBA) {
4868 4859                                  (void) snprintf(lb_buf, sizeof (lb_buf),
4869 4860                                      "%s, region-size: %d", mdi_load_balance_lba,
4870 4861                                      ct->ct_lb_args->region_size);
4871 4862                          } else if (ct->ct_lb == LOAD_BALANCE_NONE) {
4872 4863                                  (void) snprintf(lb_buf, sizeof (lb_buf),
4873 4864                                      "%s", mdi_load_balance_none);
4874 4865                          } else {
4875 4866                                  (void) snprintf(lb_buf, sizeof (lb_buf), "%s",
4876 4867                                      mdi_load_balance_rr);
4877 4868                          }
4878 4869  
4879      -                        cmn_err(mdi_debug_consoleonly ? CE_NOTE : CE_CONT,
4880      -                            "?%s (%s%d) multipath status: %s: "
4881      -                            "path %d %s is %s: Load balancing: %s\n",
4882      -                            ddi_pathname(cdip, ct_path), ddi_driver_name(cdip),
4883      -                            ddi_get_instance(cdip), ct_status,
4884      -                            mdi_pi_get_path_instance(pip),
     4870 +                        dev_err(cdip, CE_CONT, "!multipath status: %s: "
     4871 +                            "path %d %s is %s; load balancing: %s\n",
     4872 +                            ct_status, mdi_pi_get_path_instance(pip),
4885 4873                              mdi_pi_spathname(pip), status, lb_buf);
4886 4874                  } else {
4887      -                        cmn_err(mdi_debug_consoleonly ? CE_NOTE : CE_CONT,
4888      -                            "?%s (%s%d) multipath status: %s: "
4889      -                            "path %d %s is %s\n",
4890      -                            ddi_pathname(cdip, ct_path), ddi_driver_name(cdip),
4891      -                            ddi_get_instance(cdip), ct_status,
4892      -                            mdi_pi_get_path_instance(pip),
     4875 +                        dev_err(cdip, CE_CONT,
     4876 +                            "!multipath status: %s: path %d %s is %s\n",
     4877 +                            ct_status, mdi_pi_get_path_instance(pip),
4893 4878                              mdi_pi_spathname(pip), status);
4894 4879                  }
4895 4880  
4896 4881                  kmem_free(ct_path, MAXPATHLEN);
4897 4882                  MDI_CLIENT_CLEAR_REPORT_DEV_NEEDED(ct);
4898 4883          }
4899 4884  }
4900 4885  
4901 4886  #ifdef  DEBUG
4902 4887  /*
↓ open down ↓ 1165 lines elided ↑ open up ↑
6068 6053   * create and install per-path (client - pHCI) statistics
6069 6054   * I/O stats supported: nread, nwritten, reads, and writes
6070 6055   * Error stats - hard errors, soft errors, & transport errors
6071 6056   */
6072 6057  int
6073 6058  mdi_pi_kstat_create(mdi_pathinfo_t *pip, char *ksname)
6074 6059  {
6075 6060          kstat_t                 *kiosp, *kerrsp;
6076 6061          struct pi_errs          *nsp;
6077 6062          struct mdi_pi_kstats    *mdi_statp;
     6063 +        char                    *errksname;
     6064 +        size_t                  len;
6078 6065  
6079      -        if (MDI_PI(pip)->pi_kstats != NULL)
     6066 +        /*
     6067 +         * If the kstat name was already created nothing to do.
     6068 +         */
     6069 +        if ((kiosp = kstat_hold_byname("mdi", 0, ksname,
     6070 +            ALL_ZONES)) != NULL) {
     6071 +                kstat_rele(kiosp);
6080 6072                  return (MDI_SUCCESS);
     6073 +        }
6081 6074  
6082 6075          if ((kiosp = kstat_create("mdi", 0, ksname, "iopath",
6083 6076              KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT)) == NULL) {
6084 6077                  return (MDI_FAILURE);
6085 6078          }
6086 6079  
6087      -        (void) strcat(ksname, ",err");
6088      -        kerrsp = kstat_create("mdi", 0, ksname, "iopath_errors",
     6080 +        len = strlen(ksname) + strlen(",err") + 1;
     6081 +        errksname = kmem_alloc(len, KM_SLEEP);
     6082 +        (void) snprintf(errksname, len, "%s,err", ksname);
     6083 +
     6084 +        kerrsp = kstat_create("mdi", 0, errksname, "iopath_errors",
6089 6085              KSTAT_TYPE_NAMED,
6090 6086              sizeof (struct pi_errs) / sizeof (kstat_named_t), 0);
6091 6087          if (kerrsp == NULL) {
6092 6088                  kstat_delete(kiosp);
     6089 +                kmem_free(errksname, len);
6093 6090                  return (MDI_FAILURE);
6094 6091          }
6095 6092  
6096 6093          nsp = (struct pi_errs *)kerrsp->ks_data;
6097 6094          kstat_named_init(&nsp->pi_softerrs, "Soft Errors", KSTAT_DATA_UINT32);
6098 6095          kstat_named_init(&nsp->pi_harderrs, "Hard Errors", KSTAT_DATA_UINT32);
6099 6096          kstat_named_init(&nsp->pi_transerrs, "Transport Errors",
6100 6097              KSTAT_DATA_UINT32);
6101 6098          kstat_named_init(&nsp->pi_icnt_busy, "Interconnect Busy",
6102 6099              KSTAT_DATA_UINT32);
↓ open down ↓ 9 lines elided ↑ open up ↑
6112 6109              KSTAT_DATA_UINT32);
6113 6110          kstat_named_init(&nsp->pi_failedto, "Failed To", KSTAT_DATA_UINT32);
6114 6111  
6115 6112          mdi_statp = kmem_alloc(sizeof (*mdi_statp), KM_SLEEP);
6116 6113          mdi_statp->pi_kstat_ref = 1;
6117 6114          mdi_statp->pi_kstat_iostats = kiosp;
6118 6115          mdi_statp->pi_kstat_errstats = kerrsp;
6119 6116          kstat_install(kiosp);
6120 6117          kstat_install(kerrsp);
6121 6118          MDI_PI(pip)->pi_kstats = mdi_statp;
     6119 +        kmem_free(errksname, len);
6122 6120          return (MDI_SUCCESS);
6123 6121  }
6124 6122  
6125 6123  /*
6126 6124   * destroy per-path properties
6127 6125   */
6128 6126  static void
6129 6127  i_mdi_pi_kstat_destroy(mdi_pathinfo_t *pip)
6130 6128  {
6131 6129  
↓ open down ↓ 3613 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX