Print this page
    
OS-122 Assertion in e_devid_minor_to_devlist() in devid_cache.c
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/os/devid_cache.c
          +++ new/usr/src/uts/common/os/devid_cache.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  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   * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  23   24   */
  24   25  
  25   26  #include <sys/note.h>
  26   27  #include <sys/t_lock.h>
  27   28  #include <sys/cmn_err.h>
  28   29  #include <sys/instance.h>
  29   30  #include <sys/conf.h>
  30   31  #include <sys/stat.h>
  31   32  #include <sys/ddi.h>
  32   33  #include <sys/hwconf.h>
  33   34  #include <sys/sunddi.h>
  34   35  #include <sys/sunndi.h>
  35   36  #include <sys/sunmdi.h>
  36   37  #include <sys/ddi_impldefs.h>
  37   38  #include <sys/ndi_impldefs.h>
  38   39  #include <sys/kobj.h>
  39   40  #include <sys/devcache.h>
  40   41  #include <sys/devid_cache.h>
  41   42  #include <sys/sysmacros.h>
  42   43  
  43   44  /*
  44   45   * Discovery refers to the heroic effort made to discover a device which
  45   46   * cannot be accessed at the physical path where it once resided.  Discovery
  46   47   * involves walking the entire device tree attaching all possible disk
  47   48   * instances, to search for the device referenced by a devid.  Obviously,
  48   49   * full device discovery is something to be avoided where possible.
  49   50   * Note that simply invoking devfsadm(1M) is equivalent to running full
  50   51   * discovery at the devid cache level.
  51   52   *
  52   53   * Reasons why a disk may not be accessible:
  53   54   *      disk powered off
  54   55   *      disk removed or cable disconnected
  55   56   *      disk or adapter broken
  56   57   *
  57   58   * Note that discovery is not needed and cannot succeed in any of these
  58   59   * cases.
  59   60   *
  60   61   * When discovery may succeed:
  61   62   *      Discovery will result in success when a device has been moved
  62   63   *      to a different address.  Note that it's recommended that
  63   64   *      devfsadm(1M) be invoked (no arguments required) whenever a system's
  64   65   *      h/w configuration has been updated.  Alternatively, a
  65   66   *      reconfiguration boot can be used to accomplish the same result.
  66   67   *
  67   68   * Note that discovery is not necessary to be able to correct an access
  68   69   * failure for a device which was powered off.  Assuming the cache has an
  69   70   * entry for such a device, simply powering it on should permit the system
  70   71   * to access it.  If problems persist after powering it on, invoke
  71   72   * devfsadm(1M).
  72   73   *
  73   74   * Discovery prior to mounting root is only of interest when booting
  74   75   * from a filesystem which accesses devices by device id, which of
  75   76   * not all do.
  76   77   *
  77   78   * Tunables
  78   79   *
  79   80   * devid_discovery_boot (default 1)
  80   81   *      Number of times discovery will be attempted prior to mounting root.
  81   82   *      Must be done at least once to recover from corrupted or missing
  82   83   *      devid cache backing store.  Probably there's no reason to ever
  83   84   *      set this to greater than one as a missing device will remain
  84   85   *      unavailable no matter how often the system searches for it.
  85   86   *
  86   87   * devid_discovery_postboot (default 1)
  87   88   *      Number of times discovery will be attempted after mounting root.
  88   89   *      This must be performed at least once to discover any devices
  89   90   *      needed after root is mounted which may have been powered
  90   91   *      off and moved before booting.
  91   92   *      Setting this to a larger positive number will introduce
  92   93   *      some inconsistency in system operation.  Searching for a device
  93   94   *      will take an indeterminate amount of time, sometimes slower,
  94   95   *      sometimes faster.  In addition, the system will sometimes
  95   96   *      discover a newly powered on device, sometimes it won't.
  96   97   *      Use of this option is not therefore recommended.
  97   98   *
  98   99   * devid_discovery_postboot_always (default 0)
  99  100   *      Set to 1, the system will always attempt full discovery.
 100  101   *
 101  102   * devid_discovery_secs (default 0)
 102  103   *      Set to a positive value, the system will attempt full discovery
 103  104   *      but with a minimum delay between attempts.  A device search
 104  105   *      within the period of time specified will result in failure.
 105  106   *
 106  107   * devid_cache_read_disable (default 0)
 107  108   *      Set to 1 to disable reading /etc/devices/devid_cache.
 108  109   *      Devid cache will continue to operate normally but
 109  110   *      at least one discovery attempt will be required.
 110  111   *
 111  112   * devid_cache_write_disable (default 0)
 112  113   *      Set to 1 to disable updates to /etc/devices/devid_cache.
 113  114   *      Any updates to the devid cache will not be preserved across a reboot.
 114  115   *
 115  116   * devid_report_error (default 0)
 116  117   *      Set to 1 to enable some error messages related to devid
 117  118   *      cache failures.
 118  119   *
 119  120   * The devid is packed in the cache file as a byte array.  For
 120  121   * portability, this could be done in the encoded string format.
 121  122   */
 122  123  
 123  124  
 124  125  int devid_discovery_boot = 1;
 125  126  int devid_discovery_postboot = 1;
 126  127  int devid_discovery_postboot_always = 0;
 127  128  int devid_discovery_secs = 0;
 128  129  
 129  130  int devid_cache_read_disable = 0;
 130  131  int devid_cache_write_disable = 0;
 131  132  
 132  133  int devid_report_error = 0;
 133  134  
 134  135  
 135  136  /*
 136  137   * State to manage discovery of devices providing a devid
 137  138   */
 138  139  static int              devid_discovery_busy = 0;
 139  140  static kmutex_t         devid_discovery_mutex;
 140  141  static kcondvar_t       devid_discovery_cv;
 141  142  static clock_t          devid_last_discovery = 0;
 142  143  
 143  144  
 144  145  #ifdef  DEBUG
 145  146  int nvp_devid_debug = 0;
 146  147  int devid_debug = 0;
 147  148  int devid_log_registers = 0;
 148  149  int devid_log_finds = 0;
 149  150  int devid_log_lookups = 0;
 150  151  int devid_log_discovery = 0;
 151  152  int devid_log_matches = 0;
 152  153  int devid_log_paths = 0;
 153  154  int devid_log_failures = 0;
 154  155  int devid_log_hold = 0;
 155  156  int devid_log_unregisters = 0;
 156  157  int devid_log_removes = 0;
 157  158  int devid_register_debug = 0;
 158  159  int devid_log_stale = 0;
 159  160  int devid_log_detaches = 0;
 160  161  #endif  /* DEBUG */
 161  162  
 162  163  /*
 163  164   * devid cache file registration for cache reads and updates
 164  165   */
 165  166  static nvf_ops_t devid_cache_ops = {
 166  167          "/etc/devices/devid_cache",             /* path to cache */
 167  168          devid_cache_unpack_nvlist,              /* read: nvlist to nvp */
 168  169          devid_cache_pack_list,                  /* write: nvp to nvlist */
 169  170          devid_list_free,                        /* free data list */
 170  171          NULL                                    /* write complete callback */
 171  172  };
 172  173  
 173  174  /*
 174  175   * handle to registered devid cache handlers
 175  176   */
 176  177  nvf_handle_t    dcfd_handle;
 177  178  
 178  179  
 179  180  /*
 180  181   * Initialize devid cache file management
 181  182   */
 182  183  void
 183  184  devid_cache_init(void)
 184  185  {
 185  186          dcfd_handle = nvf_register_file(&devid_cache_ops);
 186  187          ASSERT(dcfd_handle);
 187  188  
 188  189          list_create(nvf_list(dcfd_handle), sizeof (nvp_devid_t),
 189  190              offsetof(nvp_devid_t, nvp_link));
 190  191  
 191  192          mutex_init(&devid_discovery_mutex, NULL, MUTEX_DEFAULT, NULL);
 192  193          cv_init(&devid_discovery_cv, NULL, CV_DRIVER, NULL);
 193  194  }
 194  195  
 195  196  /*
 196  197   * Read and initialize the devid cache from the persistent store
 197  198   */
 198  199  void
 199  200  devid_cache_read(void)
 200  201  {
 201  202          if (!devid_cache_read_disable) {
 202  203                  rw_enter(nvf_lock(dcfd_handle), RW_WRITER);
 203  204                  ASSERT(list_head(nvf_list(dcfd_handle)) == NULL);
 204  205                  (void) nvf_read_file(dcfd_handle);
 205  206                  rw_exit(nvf_lock(dcfd_handle));
 206  207          }
 207  208  }
 208  209  
 209  210  static void
 210  211  devid_nvp_free(nvp_devid_t *dp)
 211  212  {
 212  213          if (dp->nvp_devpath)
 213  214                  kmem_free(dp->nvp_devpath, strlen(dp->nvp_devpath)+1);
 214  215          if (dp->nvp_devid)
 215  216                  kmem_free(dp->nvp_devid, ddi_devid_sizeof(dp->nvp_devid));
 216  217  
 217  218          kmem_free(dp, sizeof (nvp_devid_t));
 218  219  }
 219  220  
 220  221  static void
 221  222  devid_list_free(nvf_handle_t fd)
 222  223  {
 223  224          list_t          *listp;
 224  225          nvp_devid_t     *np;
 225  226  
 226  227          ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle)));
 227  228  
 228  229          listp = nvf_list(fd);
 229  230          while (np = list_head(listp)) {
 230  231                  list_remove(listp, np);
 231  232                  devid_nvp_free(np);
 232  233          }
 233  234  }
 234  235  
 235  236  /*
 236  237   * Free an nvp element in a list
 237  238   */
 238  239  static void
 239  240  devid_nvp_unlink_and_free(nvf_handle_t fd, nvp_devid_t *np)
 240  241  {
 241  242          list_remove(nvf_list(fd), np);
 242  243          devid_nvp_free(np);
 243  244  }
 244  245  
 245  246  /*
 246  247   * Unpack a device path/nvlist pair to the list of devid cache elements.
 247  248   * Used to parse the nvlist format when reading
 248  249   * /etc/devices/devid_cache
 249  250   */
 250  251  static int
 251  252  devid_cache_unpack_nvlist(nvf_handle_t fd, nvlist_t *nvl, char *name)
 252  253  {
 253  254          nvp_devid_t *np;
 254  255          ddi_devid_t devidp;
 255  256          int rval;
 256  257          uint_t n;
 257  258  
 258  259          NVP_DEVID_DEBUG_PATH((name));
 259  260          ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle)));
 260  261  
 261  262          /*
 262  263           * check path for a devid
 263  264           */
 264  265          rval = nvlist_lookup_byte_array(nvl,
 265  266              DP_DEVID_ID, (uchar_t **)&devidp, &n);
 266  267          if (rval == 0) {
 267  268                  if (ddi_devid_valid(devidp) == DDI_SUCCESS) {
 268  269                          ASSERT(n == ddi_devid_sizeof(devidp));
 269  270                          np = kmem_zalloc(sizeof (nvp_devid_t), KM_SLEEP);
 270  271                          np->nvp_devpath = i_ddi_strdup(name, KM_SLEEP);
 271  272                          np->nvp_devid = kmem_alloc(n, KM_SLEEP);
 272  273                          (void) bcopy(devidp, np->nvp_devid, n);
 273  274                          list_insert_tail(nvf_list(fd), np);
 274  275                          NVP_DEVID_DEBUG_DEVID((np->nvp_devid));
 275  276                  } else {
 276  277                          DEVIDERR((CE_CONT,
 277  278                              "%s: invalid devid\n", name));
 278  279                  }
 279  280          } else {
 280  281                  DEVIDERR((CE_CONT,
 281  282                      "%s: devid not available\n", name));
 282  283          }
 283  284  
 284  285          return (0);
 285  286  }
 286  287  
 287  288  /*
 288  289   * Pack the list of devid cache elements into a single nvlist
 289  290   * Used when writing the nvlist file.
 290  291   */
 291  292  static int
 292  293  devid_cache_pack_list(nvf_handle_t fd, nvlist_t **ret_nvl)
 293  294  {
 294  295          nvlist_t        *nvl, *sub_nvl;
 295  296          nvp_devid_t     *np;
 296  297          int             rval;
 297  298          list_t          *listp;
 298  299  
 299  300          ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle)));
 300  301  
 301  302          rval = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
 302  303          if (rval != 0) {
 303  304                  nvf_error("%s: nvlist alloc error %d\n",
 304  305                      nvf_cache_name(fd), rval);
 305  306                  return (DDI_FAILURE);
 306  307          }
 307  308  
 308  309          listp = nvf_list(fd);
 309  310          for (np = list_head(listp); np; np = list_next(listp, np)) {
 310  311                  if (np->nvp_devid == NULL)
 311  312                          continue;
 312  313                  NVP_DEVID_DEBUG_PATH(np->nvp_devpath);
 313  314                  rval = nvlist_alloc(&sub_nvl, NV_UNIQUE_NAME, KM_SLEEP);
 314  315                  if (rval != 0) {
 315  316                          nvf_error("%s: nvlist alloc error %d\n",
 316  317                              nvf_cache_name(fd), rval);
 317  318                          sub_nvl = NULL;
 318  319                          goto err;
 319  320                  }
 320  321  
 321  322                  rval = nvlist_add_byte_array(sub_nvl, DP_DEVID_ID,
 322  323                      (uchar_t *)np->nvp_devid,
 323  324                      ddi_devid_sizeof(np->nvp_devid));
 324  325                  if (rval == 0) {
 325  326                          NVP_DEVID_DEBUG_DEVID(np->nvp_devid);
 326  327                  } else {
 327  328                          nvf_error(
 328  329                              "%s: nvlist add error %d (devid)\n",
 329  330                              nvf_cache_name(fd), rval);
 330  331                          goto err;
 331  332                  }
 332  333  
 333  334                  rval = nvlist_add_nvlist(nvl, np->nvp_devpath, sub_nvl);
 334  335                  if (rval != 0) {
 335  336                          nvf_error("%s: nvlist add error %d (sublist)\n",
 336  337                              nvf_cache_name(fd), rval);
 337  338                          goto err;
 338  339                  }
 339  340                  nvlist_free(sub_nvl);
 340  341          }
 341  342  
 342  343          *ret_nvl = nvl;
 343  344          return (DDI_SUCCESS);
 344  345  
 345  346  err:
 346  347          nvlist_free(sub_nvl);
 347  348          nvlist_free(nvl);
 348  349          *ret_nvl = NULL;
 349  350          return (DDI_FAILURE);
 350  351  }
 351  352  
 352  353  static int
 353  354  e_devid_do_discovery(void)
 354  355  {
 355  356          ASSERT(mutex_owned(&devid_discovery_mutex));
 356  357  
 357  358          if (i_ddi_io_initialized() == 0) {
 358  359                  if (devid_discovery_boot > 0) {
 359  360                          devid_discovery_boot--;
 360  361                          return (1);
 361  362                  }
 362  363          } else {
 363  364                  if (devid_discovery_postboot_always > 0)
 364  365                          return (1);
 365  366                  if (devid_discovery_postboot > 0) {
 366  367                          devid_discovery_postboot--;
 367  368                          return (1);
 368  369                  }
 369  370                  if (devid_discovery_secs > 0) {
 370  371                          if ((ddi_get_lbolt() - devid_last_discovery) >
 371  372                              drv_usectohz(devid_discovery_secs * MICROSEC)) {
 372  373                                  return (1);
 373  374                          }
 374  375                  }
 375  376          }
 376  377  
 377  378          DEVID_LOG_DISC((CE_CONT, "devid_discovery: no discovery\n"));
 378  379          return (0);
 379  380  }
 380  381  
 381  382  static void
 382  383  e_ddi_devid_hold_by_major(major_t major)
 383  384  {
 384  385          DEVID_LOG_DISC((CE_CONT,
 385  386              "devid_discovery: ddi_hold_installed_driver %d\n", major));
 386  387  
 387  388          if (ddi_hold_installed_driver(major) == NULL)
 388  389                  return;
 389  390  
 390  391          ddi_rele_driver(major);
 391  392  }
 392  393  
 393  394  /* legacy support - see below */
 394  395  static char *e_ddi_devid_hold_driver_list[] = { "sd", "ssd" };
 395  396  
 396  397  #define N_DRIVERS_TO_HOLD       \
 397  398          (sizeof (e_ddi_devid_hold_driver_list) / sizeof (char *))
 398  399  
 399  400  static void
 400  401  e_ddi_devid_hold_installed_driver(ddi_devid_t devid)
 401  402  {
 402  403          impl_devid_t    *id = (impl_devid_t *)devid;
 403  404          major_t         major, hint_major;
 404  405          char            hint[DEVID_HINT_SIZE + 1];
 405  406          struct devnames *dnp;
 406  407          char            **drvp;
 407  408          int             i;
 408  409  
 409  410          /* Count non-null bytes */
 410  411          for (i = 0; i < DEVID_HINT_SIZE; i++)
 411  412                  if (id->did_driver[i] == '\0')
 412  413                          break;
 413  414  
 414  415          /* Make a copy of the driver hint */
 415  416          bcopy(id->did_driver, hint, i);
 416  417          hint[i] = '\0';
 417  418  
 418  419          /* search for the devid using the hint driver */
 419  420          hint_major = ddi_name_to_major(hint);
 420  421          if (hint_major != DDI_MAJOR_T_NONE) {
 421  422                  e_ddi_devid_hold_by_major(hint_major);
 422  423          }
 423  424  
 424  425          /*
 425  426           * search for the devid with each driver declaring
 426  427           * itself as a devid registrant.
 427  428           */
 428  429          for (major = 0; major < devcnt; major++) {
 429  430                  if (major == hint_major)
 430  431                          continue;
 431  432                  dnp = &devnamesp[major];
 432  433                  if (dnp->dn_flags & DN_DEVID_REGISTRANT) {
 433  434                          e_ddi_devid_hold_by_major(major);
 434  435                  }
 435  436          }
 436  437  
 437  438          /*
 438  439           * Legacy support: may be removed once an upgrade mechanism
 439  440           * for driver conf files is available.
 440  441           */
 441  442          drvp = e_ddi_devid_hold_driver_list;
 442  443          for (i = 0; i < N_DRIVERS_TO_HOLD; i++, drvp++) {
 443  444                  major = ddi_name_to_major(*drvp);
 444  445                  if (major != DDI_MAJOR_T_NONE && major != hint_major) {
 445  446                          e_ddi_devid_hold_by_major(major);
 446  447                  }
 447  448          }
 448  449  }
 449  450  
 450  451  /*
 451  452   * Return success if discovery was attempted, to indicate
 452  453   * that the desired device may now be available.
 453  454   */
 454  455  int
 455  456  e_ddi_devid_discovery(ddi_devid_t devid)
 456  457  {
 457  458          int flags;
 458  459          int rval = DDI_SUCCESS;
 459  460  
 460  461          mutex_enter(&devid_discovery_mutex);
 461  462  
 462  463          if (devid_discovery_busy) {
 463  464                  DEVID_LOG_DISC((CE_CONT, "devid_discovery: busy\n"));
 464  465                  while (devid_discovery_busy) {
 465  466                          cv_wait(&devid_discovery_cv, &devid_discovery_mutex);
 466  467                  }
 467  468          } else if (e_devid_do_discovery()) {
 468  469                  devid_discovery_busy = 1;
 469  470                  mutex_exit(&devid_discovery_mutex);
 470  471  
 471  472                  if (i_ddi_io_initialized() == 0) {
 472  473                          e_ddi_devid_hold_installed_driver(devid);
 473  474                  } else {
 474  475                          DEVID_LOG_DISC((CE_CONT,
 475  476                              "devid_discovery: ndi_devi_config\n"));
 476  477                          flags = NDI_DEVI_PERSIST | NDI_CONFIG | NDI_NO_EVENT;
 477  478                          if (i_ddi_io_initialized())
 478  479                                  flags |= NDI_DRV_CONF_REPROBE;
 479  480                          (void) ndi_devi_config(ddi_root_node(), flags);
 480  481                  }
 481  482  
 482  483                  mutex_enter(&devid_discovery_mutex);
 483  484                  devid_discovery_busy = 0;
 484  485                  cv_broadcast(&devid_discovery_cv);
 485  486                  if (devid_discovery_secs > 0)
 486  487                          devid_last_discovery = ddi_get_lbolt();
 487  488                  DEVID_LOG_DISC((CE_CONT, "devid_discovery: done\n"));
 488  489          } else {
 489  490                  rval = DDI_FAILURE;
 490  491                  DEVID_LOG_DISC((CE_CONT, "no devid discovery\n"));
 491  492          }
 492  493  
 493  494          mutex_exit(&devid_discovery_mutex);
 494  495  
 495  496          return (rval);
 496  497  }
 497  498  
 498  499  /*
 499  500   * As part of registering a devid for a device,
 500  501   * update the devid cache with this device/devid pair
 501  502   * or note that this combination has registered.
 502  503   *
 503  504   * If a devpath is provided it will be used as the path to register the
 504  505   * devid against, otherwise we use ddi_pathname(dip).  In both cases
 505  506   * we duplicate the path string so that it can be cached/freed indepdently
 506  507   * of the original owner.
 507  508   */
 508  509  static int
 509  510  e_devid_cache_register_cmn(dev_info_t *dip, ddi_devid_t devid, char *devpath)
 510  511  {
 511  512          nvp_devid_t *np;
 512  513          nvp_devid_t *new_nvp;
 513  514          ddi_devid_t new_devid;
 514  515          int new_devid_size;
 515  516          char *path, *fullpath;
 516  517          ddi_devid_t free_devid = NULL;
 517  518          int pathlen;
 518  519          list_t *listp;
 519  520          int is_dirty = 0;
 520  521  
 521  522  
 522  523          ASSERT(ddi_devid_valid(devid) == DDI_SUCCESS);
 523  524  
 524  525          if (devpath) {
 525  526                  pathlen = strlen(devpath) + 1;
 526  527                  path = kmem_alloc(pathlen, KM_SLEEP);
 527  528                  bcopy(devpath, path, pathlen);
 528  529          } else {
 529  530                  /*
 530  531                   * We are willing to accept DS_BOUND nodes if we can form a full
 531  532                   * ddi_pathname (i.e. the node is part way to becomming
 532  533                   * DS_INITIALIZED and devi_addr/ddi_get_name_addr are non-NULL).
 533  534                   */
 534  535                  if (ddi_get_name_addr(dip) == NULL)
 535  536                          return (DDI_FAILURE);
 536  537  
 537  538                  fullpath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 538  539                  (void) ddi_pathname(dip, fullpath);
 539  540                  pathlen = strlen(fullpath) + 1;
 540  541                  path = kmem_alloc(pathlen, KM_SLEEP);
 541  542                  bcopy(fullpath, path, pathlen);
 542  543                  kmem_free(fullpath, MAXPATHLEN);
 543  544          }
 544  545  
 545  546          DEVID_LOG_REG(("register", devid, path));
 546  547  
 547  548          new_nvp = kmem_zalloc(sizeof (nvp_devid_t), KM_SLEEP);
 548  549          new_devid_size = ddi_devid_sizeof(devid);
 549  550          new_devid = kmem_alloc(new_devid_size, KM_SLEEP);
 550  551          (void) bcopy(devid, new_devid, new_devid_size);
 551  552  
 552  553          rw_enter(nvf_lock(dcfd_handle), RW_WRITER);
 553  554  
 554  555          listp = nvf_list(dcfd_handle);
 555  556          for (np = list_head(listp); np; np = list_next(listp, np)) {
 556  557                  if (strcmp(path, np->nvp_devpath) == 0) {
 557  558                          DEVID_DEBUG2((CE_CONT,
 558  559                              "register: %s path match\n", path));
 559  560                          if (np->nvp_devid == NULL) {
 560  561  replace:                        np->nvp_devid = new_devid;
 561  562                                  np->nvp_flags |=
 562  563                                      NVP_DEVID_DIP | NVP_DEVID_REGISTERED;
 563  564                                  np->nvp_dip = dip;
 564  565                                  if (!devid_cache_write_disable) {
 565  566                                          nvf_mark_dirty(dcfd_handle);
 566  567                                          is_dirty = 1;
 567  568                                  }
 568  569                                  rw_exit(nvf_lock(dcfd_handle));
 569  570                                  kmem_free(new_nvp, sizeof (nvp_devid_t));
 570  571                                  kmem_free(path, pathlen);
 571  572                                  goto exit;
 572  573                          }
 573  574                          if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
 574  575                                  /* replace invalid devid */
 575  576                                  free_devid = np->nvp_devid;
 576  577                                  goto replace;
 577  578                          }
 578  579                          /*
 579  580                           * We're registering an already-cached path
 580  581                           * Does the device's devid match the cache?
 581  582                           */
 582  583                          if (ddi_devid_compare(devid, np->nvp_devid) != 0) {
 583  584                                  DEVID_DEBUG((CE_CONT, "devid register: "
 584  585                                      "devid %s does not match\n", path));
 585  586                                  /*
 586  587                                   * Replace cached devid for this path
 587  588                                   * with newly registered devid.  A devid
 588  589                                   * may map to multiple paths but one path
 589  590                                   * should only map to one devid.
 590  591                                   */
 591  592                                  devid_nvp_unlink_and_free(dcfd_handle, np);
 592  593                                  np = NULL;
 593  594                                  break;
 594  595                          } else {
 595  596                                  DEVID_DEBUG2((CE_CONT,
 596  597                                      "devid register: %s devid match\n", path));
 597  598                                  np->nvp_flags |=
 598  599                                      NVP_DEVID_DIP | NVP_DEVID_REGISTERED;
 599  600                                  np->nvp_dip = dip;
 600  601                                  rw_exit(nvf_lock(dcfd_handle));
 601  602                                  kmem_free(new_nvp, sizeof (nvp_devid_t));
 602  603                                  kmem_free(path, pathlen);
 603  604                                  kmem_free(new_devid, new_devid_size);
 604  605                                  return (DDI_SUCCESS);
 605  606                          }
 606  607                  }
 607  608          }
 608  609  
 609  610          /*
 610  611           * Add newly registered devid to the cache
 611  612           */
 612  613          ASSERT(np == NULL);
 613  614  
 614  615          new_nvp->nvp_devpath = path;
 615  616          new_nvp->nvp_flags = NVP_DEVID_DIP | NVP_DEVID_REGISTERED;
 616  617          new_nvp->nvp_dip = dip;
 617  618          new_nvp->nvp_devid = new_devid;
 618  619  
 619  620          if (!devid_cache_write_disable) {
 620  621                  is_dirty = 1;
 621  622                  nvf_mark_dirty(dcfd_handle);
 622  623          }
 623  624          list_insert_tail(nvf_list(dcfd_handle), new_nvp);
 624  625  
 625  626          rw_exit(nvf_lock(dcfd_handle));
 626  627  
 627  628  exit:
 628  629          if (free_devid)
 629  630                  kmem_free(free_devid, ddi_devid_sizeof(free_devid));
 630  631  
 631  632          if (is_dirty)
 632  633                  nvf_wake_daemon();
 633  634  
 634  635          return (DDI_SUCCESS);
 635  636  }
 636  637  
 637  638  int
 638  639  e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
 639  640  {
 640  641          return (e_devid_cache_register_cmn(dip, devid, NULL));
 641  642  }
 642  643  
 643  644  /*
 644  645   * Unregister a device's devid; the devinfo may hit on multiple entries
 645  646   * arising from both pHCI and vHCI paths.
 646  647   * Called as an instance detachs.
 647  648   * Invalidate the devid's devinfo reference.
 648  649   * Devid-path remains in the cache.
 649  650   */
 650  651  
 651  652  void
 652  653  e_devid_cache_unregister(dev_info_t *dip)
 653  654  {
 654  655          nvp_devid_t *np;
 655  656          list_t *listp;
 656  657  
 657  658          rw_enter(nvf_lock(dcfd_handle), RW_WRITER);
 658  659  
 659  660          listp = nvf_list(dcfd_handle);
 660  661          for (np = list_head(listp); np; np = list_next(listp, np)) {
 661  662                  if (np->nvp_devid == NULL)
 662  663                          continue;
 663  664                  if ((np->nvp_flags & NVP_DEVID_DIP) && np->nvp_dip == dip) {
 664  665                          DEVID_LOG_UNREG((CE_CONT,
 665  666                              "unregister: %s\n", np->nvp_devpath));
 666  667                          np->nvp_flags &= ~NVP_DEVID_DIP;
 667  668                          np->nvp_dip = NULL;
 668  669                  }
 669  670          }
 670  671  
 671  672          rw_exit(nvf_lock(dcfd_handle));
 672  673  }
 673  674  
 674  675  int
 675  676  e_devid_cache_pathinfo(mdi_pathinfo_t *pip, ddi_devid_t devid)
 676  677  {
 677  678          char *path = mdi_pi_pathname(pip);
 678  679  
 679  680          return (e_devid_cache_register_cmn(mdi_pi_get_client(pip), devid,
 680  681              path));
 681  682  }
 682  683  
 683  684  /*
 684  685   * Purge devid cache of stale devids
 685  686   */
 686  687  void
 687  688  devid_cache_cleanup(void)
 688  689  {
 689  690          nvp_devid_t *np, *next;
 690  691          list_t *listp;
 691  692          int is_dirty = 0;
 692  693  
 693  694          rw_enter(nvf_lock(dcfd_handle), RW_WRITER);
 694  695  
 695  696          listp = nvf_list(dcfd_handle);
 696  697          for (np = list_head(listp); np; np = next) {
 697  698                  next = list_next(listp, np);
 698  699                  if (np->nvp_devid == NULL)
 699  700                          continue;
 700  701                  if ((np->nvp_flags & NVP_DEVID_REGISTERED) == 0) {
 701  702                          DEVID_LOG_REMOVE((CE_CONT,
 702  703                              "cleanup: %s\n", np->nvp_devpath));
 703  704                          if (!devid_cache_write_disable) {
 704  705                                  nvf_mark_dirty(dcfd_handle);
 705  706                                  is_dirty = 0;
 706  707                          }
 707  708                          devid_nvp_unlink_and_free(dcfd_handle, np);
 708  709                  }
 709  710          }
 710  711  
 711  712          rw_exit(nvf_lock(dcfd_handle));
 712  713  
 713  714          if (is_dirty)
 714  715                  nvf_wake_daemon();
 715  716  }
 716  717  
 717  718  
 718  719  /*
 719  720   * Build a list of dev_t's for a device/devid
 720  721   *
 721  722   * The effect of this function is cumulative, adding dev_t's
 722  723   * for the device to the list of all dev_t's for a given
 723  724   * devid.
 724  725   */
 725  726  static void
 726  727  e_devid_minor_to_devlist(
 727  728          dev_info_t      *dip,
  
    | 
      ↓ open down ↓ | 
    695 lines elided | 
    
      ↑ open up ↑ | 
  
 728  729          char            *minor_name,
 729  730          int             ndevts_alloced,
 730  731          int             *devtcntp,
 731  732          dev_t           *devtsp)
 732  733  {
 733  734          int                     circ;
 734  735          struct ddi_minor_data   *dmdp;
 735  736          int                     minor_all = 0;
 736  737          int                     ndevts = *devtcntp;
 737  738  
 738      -        ASSERT(i_ddi_devi_attached(dip));
      739 +        if (!i_ddi_devi_attached(dip)) {
      740 +                return;
      741 +        }
 739  742  
 740  743          /* are we looking for a set of minor nodes? */
 741  744          if ((minor_name == DEVID_MINOR_NAME_ALL) ||
 742  745              (minor_name == DEVID_MINOR_NAME_ALL_CHR) ||
 743  746              (minor_name == DEVID_MINOR_NAME_ALL_BLK))
 744  747                  minor_all = 1;
 745  748  
 746  749          /* Find matching minor names */
 747  750          ndi_devi_enter(dip, &circ);
 748  751          for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
 749  752  
 750  753                  /* Skip non-minors, and non matching minor names */
 751  754                  if ((dmdp->type != DDM_MINOR) || ((minor_all == 0) &&
 752  755                      strcmp(dmdp->ddm_name, minor_name)))
 753  756                          continue;
 754  757  
 755  758                  /* filter out minor_all mismatches */
 756  759                  if (minor_all &&
 757  760                      (((minor_name == DEVID_MINOR_NAME_ALL_CHR) &&
 758  761                      (dmdp->ddm_spec_type != S_IFCHR)) ||
 759  762                      ((minor_name == DEVID_MINOR_NAME_ALL_BLK) &&
 760  763                      (dmdp->ddm_spec_type != S_IFBLK))))
 761  764                          continue;
 762  765  
 763  766                  if (ndevts < ndevts_alloced)
 764  767                          devtsp[ndevts] = dmdp->ddm_dev;
 765  768                  ndevts++;
 766  769          }
 767  770          ndi_devi_exit(dip, circ);
 768  771  
 769  772          *devtcntp = ndevts;
 770  773  }
 771  774  
 772  775  /*
 773  776   * Search for cached entries matching a devid
 774  777   * Return two lists:
 775  778   *      a list of dev_info nodes, for those devices in the attached state
 776  779   *      a list of pathnames whose instances registered the given devid
 777  780   * If the lists passed in are not sufficient to return the matching
 778  781   * references, return the size of lists required.
 779  782   * The dev_info nodes are returned with a hold that the caller must release.
 780  783   */
 781  784  static int
 782  785  e_devid_cache_devi_path_lists(ddi_devid_t devid, int retmax,
 783  786          int *retndevis, dev_info_t **retdevis, int *retnpaths, char **retpaths)
 784  787  {
 785  788          nvp_devid_t *np;
 786  789          int ndevis, npaths;
 787  790          dev_info_t *dip, *pdip;
 788  791          int circ;
 789  792          int maxdevis = 0;
 790  793          int maxpaths = 0;
 791  794          list_t *listp;
 792  795  
 793  796          ndevis = 0;
 794  797          npaths = 0;
 795  798          listp = nvf_list(dcfd_handle);
 796  799          for (np = list_head(listp); np; np = list_next(listp, np)) {
 797  800                  if (np->nvp_devid == NULL)
 798  801                          continue;
 799  802                  if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
 800  803                          DEVIDERR((CE_CONT,
 801  804                              "find: invalid devid %s\n",
 802  805                              np->nvp_devpath));
 803  806                          continue;
 804  807                  }
 805  808                  if (ddi_devid_compare(devid, np->nvp_devid) == 0) {
 806  809                          DEVID_DEBUG2((CE_CONT,
 807  810                              "find: devid match: %s 0x%x\n",
 808  811                              np->nvp_devpath, np->nvp_flags));
 809  812                          DEVID_LOG_MATCH(("find", devid, np->nvp_devpath));
 810  813                          DEVID_LOG_PATHS((CE_CONT, "%s\n", np->nvp_devpath));
 811  814  
 812  815                          /*
 813  816                           * Check if we have a cached devinfo reference for this
 814  817                           * devid.  Place a hold on it to prevent detach
 815  818                           * Otherwise, use the path instead.
 816  819                           * Note: returns with a hold on each dev_info
 817  820                           * node in the list.
 818  821                           */
 819  822                          dip = NULL;
 820  823                          if (np->nvp_flags & NVP_DEVID_DIP) {
 821  824                                  pdip = ddi_get_parent(np->nvp_dip);
 822  825                                  if (ndi_devi_tryenter(pdip, &circ)) {
 823  826                                          dip = np->nvp_dip;
 824  827                                          ndi_hold_devi(dip);
 825  828                                          ndi_devi_exit(pdip, circ);
 826  829                                          ASSERT(!DEVI_IS_ATTACHING(dip));
 827  830                                          ASSERT(!DEVI_IS_DETACHING(dip));
 828  831                                  } else {
 829  832                                          DEVID_LOG_DETACH((CE_CONT,
 830  833                                              "may be detaching: %s\n",
 831  834                                              np->nvp_devpath));
 832  835                                  }
 833  836                          }
 834  837  
 835  838                          if (dip) {
 836  839                                  if (ndevis < retmax) {
 837  840                                          retdevis[ndevis++] = dip;
 838  841                                  } else {
 839  842                                          ndi_rele_devi(dip);
 840  843                                  }
 841  844                                  maxdevis++;
 842  845                          } else {
 843  846                                  if (npaths < retmax)
 844  847                                          retpaths[npaths++] = np->nvp_devpath;
 845  848                                  maxpaths++;
 846  849                          }
 847  850                  }
 848  851          }
 849  852  
 850  853          *retndevis = ndevis;
 851  854          *retnpaths = npaths;
 852  855          return (maxdevis > maxpaths ? maxdevis : maxpaths);
 853  856  }
 854  857  
 855  858  
 856  859  /*
 857  860   * Search the devid cache, returning dev_t list for all
 858  861   * device paths mapping to the device identified by the
 859  862   * given devid.
 860  863   *
 861  864   * Primary interface used by ddi_lyr_devid_to_devlist()
 862  865   */
 863  866  int
 864  867  e_devid_cache_to_devt_list(ddi_devid_t devid, char *minor_name,
 865  868          int *retndevts, dev_t **retdevts)
 866  869  {
 867  870          char            *path, **paths;
 868  871          int             i, j, n;
 869  872          dev_t           *devts, *udevts;
 870  873          dev_t           tdevt;
 871  874          int             ndevts, undevts, ndevts_alloced;
 872  875          dev_info_t      *devi, **devis;
 873  876          int             ndevis, npaths, nalloced;
 874  877          ddi_devid_t     match_devid;
 875  878  
 876  879          DEVID_LOG_FIND(("find", devid, NULL));
 877  880  
 878  881          ASSERT(ddi_devid_valid(devid) == DDI_SUCCESS);
 879  882          if (ddi_devid_valid(devid) != DDI_SUCCESS) {
 880  883                  DEVID_LOG_ERR(("invalid devid", devid, NULL));
 881  884                  return (DDI_FAILURE);
 882  885          }
 883  886  
 884  887          nalloced = 128;
 885  888  
 886  889          for (;;) {
 887  890                  paths = kmem_zalloc(nalloced * sizeof (char *), KM_SLEEP);
 888  891                  devis = kmem_zalloc(nalloced * sizeof (dev_info_t *), KM_SLEEP);
 889  892  
 890  893                  rw_enter(nvf_lock(dcfd_handle), RW_READER);
 891  894                  n = e_devid_cache_devi_path_lists(devid, nalloced,
 892  895                      &ndevis, devis, &npaths, paths);
 893  896                  if (n <= nalloced)
 894  897                          break;
 895  898                  rw_exit(nvf_lock(dcfd_handle));
 896  899                  for (i = 0; i < ndevis; i++)
 897  900                          ndi_rele_devi(devis[i]);
 898  901                  kmem_free(paths, nalloced * sizeof (char *));
 899  902                  kmem_free(devis, nalloced * sizeof (dev_info_t *));
 900  903                  nalloced = n + 128;
 901  904          }
 902  905  
 903  906          for (i = 0; i < npaths; i++) {
 904  907                  path = i_ddi_strdup(paths[i], KM_SLEEP);
 905  908                  paths[i] = path;
 906  909          }
 907  910          rw_exit(nvf_lock(dcfd_handle));
 908  911  
 909  912          if (ndevis == 0 && npaths == 0) {
 910  913                  DEVID_LOG_ERR(("no devid found", devid, NULL));
 911  914                  kmem_free(paths, nalloced * sizeof (char *));
 912  915                  kmem_free(devis, nalloced * sizeof (dev_info_t *));
 913  916                  return (DDI_FAILURE);
 914  917          }
 915  918  
 916  919          ndevts_alloced = 128;
 917  920  restart:
 918  921          ndevts = 0;
 919  922          devts = kmem_alloc(ndevts_alloced * sizeof (dev_t), KM_SLEEP);
 920  923          for (i = 0; i < ndevis; i++) {
 921  924                  ASSERT(!DEVI_IS_ATTACHING(devis[i]));
 922  925                  ASSERT(!DEVI_IS_DETACHING(devis[i]));
 923  926                  e_devid_minor_to_devlist(devis[i], minor_name,
 924  927                      ndevts_alloced, &ndevts, devts);
 925  928                  if (ndevts > ndevts_alloced) {
 926  929                          kmem_free(devts, ndevts_alloced * sizeof (dev_t));
 927  930                          ndevts_alloced += 128;
 928  931                          goto restart;
 929  932                  }
 930  933          }
 931  934          for (i = 0; i < npaths; i++) {
 932  935                  DEVID_LOG_LOOKUP((CE_CONT, "lookup %s\n", paths[i]));
 933  936                  devi = e_ddi_hold_devi_by_path(paths[i], 0);
 934  937                  if (devi == NULL) {
 935  938                          DEVID_LOG_STALE(("stale device reference",
 936  939                              devid, paths[i]));
 937  940                          continue;
 938  941                  }
 939  942                  /*
 940  943                   * Verify the newly attached device registered a matching devid
 941  944                   */
 942  945                  if (i_ddi_devi_get_devid(DDI_DEV_T_ANY, devi,
 943  946                      &match_devid) != DDI_SUCCESS) {
 944  947                          DEVIDERR((CE_CONT,
 945  948                              "%s: no devid registered on attach\n",
 946  949                              paths[i]));
 947  950                          ddi_release_devi(devi);
 948  951                          continue;
 949  952                  }
 950  953  
 951  954                  if (ddi_devid_compare(devid, match_devid) != 0) {
 952  955                          DEVID_LOG_STALE(("new devid registered",
 953  956                              devid, paths[i]));
 954  957                          ddi_release_devi(devi);
 955  958                          ddi_devid_free(match_devid);
 956  959                          continue;
 957  960                  }
 958  961                  ddi_devid_free(match_devid);
 959  962  
 960  963                  e_devid_minor_to_devlist(devi, minor_name,
 961  964                      ndevts_alloced, &ndevts, devts);
 962  965                  ddi_release_devi(devi);
 963  966                  if (ndevts > ndevts_alloced) {
 964  967                          kmem_free(devts,
 965  968                              ndevts_alloced * sizeof (dev_t));
 966  969                          ndevts_alloced += 128;
 967  970                          goto restart;
 968  971                  }
 969  972          }
 970  973  
 971  974          /* drop hold from e_devid_cache_devi_path_lists */
 972  975          for (i = 0; i < ndevis; i++) {
 973  976                  ndi_rele_devi(devis[i]);
 974  977          }
 975  978          for (i = 0; i < npaths; i++) {
 976  979                  kmem_free(paths[i], strlen(paths[i]) + 1);
 977  980          }
 978  981          kmem_free(paths, nalloced * sizeof (char *));
 979  982          kmem_free(devis, nalloced * sizeof (dev_info_t *));
 980  983  
 981  984          if (ndevts == 0) {
 982  985                  DEVID_LOG_ERR(("no devid found", devid, NULL));
 983  986                  kmem_free(devts, ndevts_alloced * sizeof (dev_t));
 984  987                  return (DDI_FAILURE);
 985  988          }
 986  989  
 987  990          /*
 988  991           * Build the final list of sorted dev_t's with duplicates collapsed so
 989  992           * returned results are consistent. This prevents implementation
 990  993           * artifacts from causing unnecessary changes in SVM namespace.
 991  994           */
 992  995          /* bubble sort */
 993  996          for (i = 0; i < (ndevts - 1); i++) {
 994  997                  for (j = 0; j < ((ndevts - 1) - i); j++) {
 995  998                          if (devts[j + 1] < devts[j]) {
 996  999                                  tdevt = devts[j];
 997 1000                                  devts[j] = devts[j + 1];
 998 1001                                  devts[j + 1] = tdevt;
 999 1002                          }
1000 1003                  }
1001 1004          }
1002 1005  
1003 1006          /* determine number of unique values */
1004 1007          for (undevts = ndevts, i = 1; i < ndevts; i++) {
1005 1008                  if (devts[i - 1] == devts[i])
1006 1009                          undevts--;
1007 1010          }
1008 1011  
1009 1012          /* allocate unique */
1010 1013          udevts = kmem_alloc(undevts * sizeof (dev_t), KM_SLEEP);
1011 1014  
1012 1015          /* copy unique */
1013 1016          udevts[0] = devts[0];
1014 1017          for (i = 1, j = 1; i < ndevts; i++) {
1015 1018                  if (devts[i - 1] != devts[i])
1016 1019                          udevts[j++] = devts[i];
1017 1020          }
1018 1021          ASSERT(j == undevts);
1019 1022  
1020 1023          kmem_free(devts, ndevts_alloced * sizeof (dev_t));
1021 1024  
1022 1025          *retndevts = undevts;
1023 1026          *retdevts = udevts;
1024 1027  
1025 1028          return (DDI_SUCCESS);
1026 1029  }
1027 1030  
1028 1031  void
1029 1032  e_devid_cache_free_devt_list(int ndevts, dev_t *devt_list)
1030 1033  {
1031 1034          kmem_free(devt_list, ndevts * sizeof (dev_t *));
1032 1035  }
1033 1036  
1034 1037  /*
1035 1038   * If given a full path and NULL ua, search for a cache entry
1036 1039   * whose path matches the full path.  On a cache hit duplicate the
1037 1040   * devid of the matched entry into the given devid (caller
1038 1041   * must free);  nodenamebuf is not touched for this usage.
1039 1042   *
1040 1043   * Given a path and a non-NULL unit address, search the cache for any entry
1041 1044   * matching "<path>/%@<unit-address>" where '%' is a wildcard meaning
1042 1045   * any node name.  The path should not end a '/'.  On a cache hit
1043 1046   * duplicate the devid as before (caller must free) and copy into
1044 1047   * the caller-provided nodenamebuf (if not NULL) the nodename of the
1045 1048   * matched entry.
1046 1049   *
1047 1050   * We must not make use of nvp_dip since that may be NULL for cached
1048 1051   * entries that are not present in the current tree.
1049 1052   */
1050 1053  int
1051 1054  e_devid_cache_path_to_devid(char *path, char *ua,
1052 1055      char *nodenamebuf, ddi_devid_t *devidp)
1053 1056  {
1054 1057          size_t pathlen, ualen;
1055 1058          int rv = DDI_FAILURE;
1056 1059          nvp_devid_t *np;
1057 1060          list_t *listp;
1058 1061          char *cand;
1059 1062  
1060 1063          if (path == NULL || *path == '\0' || (ua && *ua == '\0') ||
1061 1064              devidp == NULL)
1062 1065                  return (DDI_FAILURE);
1063 1066  
1064 1067          *devidp = NULL;
1065 1068  
1066 1069          if (ua) {
1067 1070                  pathlen = strlen(path);
1068 1071                  ualen = strlen(ua);
1069 1072          }
1070 1073  
1071 1074          rw_enter(nvf_lock(dcfd_handle), RW_READER);
1072 1075  
1073 1076          listp = nvf_list(dcfd_handle);
1074 1077          for (np = list_head(listp); np; np = list_next(listp, np)) {
1075 1078                  size_t nodelen, candlen, n;
1076 1079                  ddi_devid_t devid_dup;
1077 1080                  char *uasep, *node;
1078 1081  
1079 1082                  if (np->nvp_devid == NULL)
1080 1083                          continue;
1081 1084  
1082 1085                  if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
1083 1086                          DEVIDERR((CE_CONT,
1084 1087                              "pathsearch: invalid devid %s\n",
1085 1088                              np->nvp_devpath));
1086 1089                          continue;
1087 1090                  }
1088 1091  
1089 1092                  cand = np->nvp_devpath;         /* candidate path */
1090 1093  
1091 1094                  /* If a full pathname was provided the compare is easy */
1092 1095                  if (ua == NULL) {
1093 1096                          if (strcmp(cand, path) == 0)
1094 1097                                  goto match;
1095 1098                          else
1096 1099                                  continue;
1097 1100                  }
1098 1101  
1099 1102                  /*
1100 1103                   * The compare for initial path plus ua and unknown nodename
1101 1104                   * is trickier.
1102 1105                   *
1103 1106                   * Does the initial path component match 'path'?
1104 1107                   */
1105 1108                  if (strncmp(path, cand, pathlen) != 0)
1106 1109                          continue;
1107 1110  
1108 1111                  candlen = strlen(cand);
1109 1112  
1110 1113                  /*
1111 1114                   * The next character must be a '/' and there must be no
1112 1115                   * further '/' thereafter.  Begin by checking that the
1113 1116                   * candidate is long enough to include at mininum a
1114 1117                   * "/<nodename>@<ua>" after the initial portion already
1115 1118                   * matched assuming a nodename length of 1.
1116 1119                   */
1117 1120                  if (candlen < pathlen + 1 + 1 + 1 + ualen ||
1118 1121                      cand[pathlen] != '/' ||
1119 1122                      strchr(cand + pathlen + 1, '/') != NULL)
1120 1123                          continue;
1121 1124  
1122 1125                  node = cand + pathlen + 1;      /* <node>@<ua> string */
1123 1126  
1124 1127                  /*
1125 1128                   * Find the '@' before the unit address.  Check for
1126 1129                   * unit address match.
1127 1130                   */
1128 1131                  if ((uasep = strchr(node, '@')) == NULL)
1129 1132                          continue;
1130 1133  
1131 1134                  /*
1132 1135                   * Check we still have enough length and that ua matches
1133 1136                   */
1134 1137                  nodelen = (uintptr_t)uasep - (uintptr_t)node;
1135 1138                  if (candlen < pathlen + 1 + nodelen + 1 + ualen ||
1136 1139                      strncmp(ua, uasep + 1, ualen) != 0)
1137 1140                          continue;
1138 1141  match:
1139 1142                  n = ddi_devid_sizeof(np->nvp_devid);
1140 1143                  devid_dup = kmem_alloc(n, KM_SLEEP);    /* caller must free */
1141 1144                  (void) bcopy(np->nvp_devid, devid_dup, n);
1142 1145                  *devidp = devid_dup;
1143 1146  
1144 1147                  if (ua && nodenamebuf) {
1145 1148                          (void) strncpy(nodenamebuf, node, nodelen);
1146 1149                          nodenamebuf[nodelen] = '\0';
1147 1150                  }
1148 1151  
1149 1152                  rv = DDI_SUCCESS;
1150 1153                  break;
1151 1154          }
1152 1155  
1153 1156          rw_exit(nvf_lock(dcfd_handle));
1154 1157  
1155 1158          return (rv);
1156 1159  }
1157 1160  
1158 1161  #ifdef  DEBUG
1159 1162  static void
1160 1163  devid_log(char *fmt, ddi_devid_t devid, char *path)
1161 1164  {
1162 1165          char *devidstr = ddi_devid_str_encode(devid, NULL);
1163 1166          if (path) {
1164 1167                  cmn_err(CE_CONT, "%s: %s %s\n", fmt, path, devidstr);
1165 1168          } else {
1166 1169                  cmn_err(CE_CONT, "%s: %s\n", fmt, devidstr);
1167 1170          }
1168 1171          ddi_devid_str_free(devidstr);
1169 1172  }
1170 1173  #endif  /* DEBUG */
  
    | 
      ↓ open down ↓ | 
    422 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX