Print this page
    
re #8726 rb4027 Autogenerated iSCSI initiator IQN should use com.nexenta instead of com.sun
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/scsi/adapters/iscsi/iscsid.c
          +++ new/usr/src/uts/common/io/scsi/adapters/iscsi/iscsid.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
  
    | 
      ↓ 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) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  23   25   */
  24   26  
  25   27  /*
  26   28   * ISCSID --
  27   29   *
  28   30   * Discovery of targets and access to the persistent storage starts here.
  29   31   */
  30   32  
  31   33  #include <sys/thread.h>
  32   34  #include <sys/types.h>
  33   35  #include <sys/proc.h>           /* declares:    p0 */
  34   36  #include <sys/cmn_err.h>
  35   37  #include <sys/scsi/adapters/iscsi_if.h>
  36   38  #include <netinet/in.h>
  37   39  #include "iscsi_targetparam.h"
  38   40  #include "isns_client.h"
  39   41  #include "isns_protocol.h"
  40   42  #include "persistent.h"
  41   43  #include "iscsi.h"
  42   44  #include <sys/ethernet.h>
  43   45  #include <sys/bootprops.h>
  44   46  
  45   47  /*
  46   48   * local function prototypes
  47   49   */
  48   50  static boolean_t iscsid_init_config(iscsi_hba_t *ihp);
  49   51  static boolean_t iscsid_init_targets(iscsi_hba_t *ihp);
  50   52  static void iscsid_thread_static(iscsi_thread_t *thread, void *p);
  51   53  static void iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p);
  52   54  static void iscsid_thread_isns(iscsi_thread_t *thread, void *p);
  53   55  static void iscsid_thread_slp(iscsi_thread_t *thread, void *p);
  54   56  static void iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p);
  55   57  static void iscsid_threads_create(iscsi_hba_t *ihp);
  56   58  static void iscsid_threads_destroy(void);
  57   59  static int iscsid_copyto_param_set(uint32_t param_id,
  58   60      iscsi_login_params_t *params, iscsi_param_set_t *ipsp);
  59   61  static void iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp,
  60   62      isns_portal_group_list_t *pg_list);
  61   63  static void iscsid_remove_target_param(char *name);
  62   64  static boolean_t iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
  63   65      struct sockaddr *addr_dsc, char *target_name, int tpgt,
  64   66      struct sockaddr *addr_tgt);
  65   67  static void iscsi_discovery_event(iscsi_hba_t *ihp,
  66   68      iSCSIDiscoveryMethod_t m, boolean_t start);
  67   69  static boolean_t iscsid_boot_init_config(iscsi_hba_t *ihp);
  68   70  static iscsi_sess_t *iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid);
  69   71  static boolean_t iscsid_make_entry(ib_boot_prop_t *boot_prop_entry,
  70   72      entry_t *entry);
  71   73  static boolean_t iscsid_check_active_boot_conn(iscsi_hba_t *ihp);
  72   74  
  73   75  extern int modrootloaded;
  74   76  int iscsi_configroot_retry = 20;
  75   77  static boolean_t iscsi_configroot_printed = FALSE;
  76   78  static int iscsi_net_up = 0;
  77   79  extern ib_boot_prop_t   *iscsiboot_prop;
  78   80  
  79   81  #define ISCSI_CONFIGROOT_DELAY  1
  80   82  
  81   83  /*
  82   84   * iSCSI target discovery thread table
  83   85   */
  84   86  typedef struct iscsid_thr_table {
  85   87          void                    (*func_start)(iscsi_thread_t *, void *);
  86   88          iscsi_thread_t          *thr_id;
  87   89          iSCSIDiscoveryMethod_t  method;
  88   90          char                    *name;
  89   91  } iscsid_thr_table;
  90   92  
  91   93  static iscsid_thr_table iscsid_thr[] = {
  92   94          { iscsid_thread_static, NULL,
  93   95              iSCSIDiscoveryMethodStatic,
  94   96              "Static" },
  95   97          { iscsid_thread_sendtgts, NULL,
  96   98              iSCSIDiscoveryMethodSendTargets,
  97   99              "SendTarget" },
  98  100          { iscsid_thread_slp, NULL,
  99  101              iSCSIDiscoveryMethodSLP,
 100  102              "SLP" },
 101  103          { iscsid_thread_isns, NULL,
 102  104              iSCSIDiscoveryMethodISNS,
 103  105              "iSNS" },
 104  106          { NULL, NULL,
 105  107              iSCSIDiscoveryMethodUnknown,
 106  108              NULL }
 107  109  };
 108  110  
 109  111  /*
 110  112   * discovery method event table
 111  113   */
 112  114  iSCSIDiscoveryMethod_t  for_failure[] = {
 113  115          iSCSIDiscoveryMethodStatic,
 114  116          iSCSIDiscoveryMethodSLP,
 115  117          iSCSIDiscoveryMethodISNS,
 116  118          iSCSIDiscoveryMethodSendTargets,
 117  119          iSCSIDiscoveryMethodUnknown /* terminating value */
 118  120  };
 119  121  
 120  122  /*
 121  123   * The following private tunable, set in /etc/system, e.g.,
 122  124   *      set iscsi:iscsi_boot_max_delay = 360
 123  125   * , provides with customer a max wait time in
 124  126   * seconds to wait for boot lun online during iscsi boot.
 125  127   * Defaults to 180s.
 126  128   */
 127  129  int iscsi_boot_max_delay = ISCSI_BOOT_DEFAULT_MAX_DELAY;
 128  130  
 129  131  /*
 130  132   * discovery configuration semaphore
 131  133   */
 132  134  ksema_t iscsid_config_semaphore;
 133  135  
 134  136  static iscsi_thread_t   *iscsi_boot_wd_handle = NULL;
 135  137  
 136  138  #define CHECK_METHOD(v) ((dm & v) ? B_TRUE : B_FALSE)
 137  139  
 138  140  /*
 139  141   * Check if IP is valid
 140  142   */
 141  143  static boolean_t
 142  144  iscsid_ip_check(char *ip)
 143  145  {
 144  146          int     i       = 0;
 145  147  
 146  148          if (!ip)
 147  149                  return (B_FALSE);
 148  150          for (; (ip[i] == 0) && (i < IB_IP_BUFLEN); i++) {}
 149  151          if (i == IB_IP_BUFLEN) {
 150  152                  /* invalid IP address */
 151  153                  return (B_FALSE);
 152  154          }
 153  155          return (B_TRUE);
 154  156  }
 155  157  
 156  158  /*
 157  159   * Make an entry for the boot target.
 158  160   * return B_TRUE upon success
 159  161   *        B_FALSE if fail
 160  162   */
 161  163  static boolean_t
 162  164  iscsid_make_entry(ib_boot_prop_t *boot_prop_entry, entry_t *entry)
 163  165  {
 164  166          if (entry == NULL || boot_prop_entry == NULL) {
 165  167                  return (B_FALSE);
 166  168          }
 167  169  
 168  170          if (!iscsid_ip_check(
 169  171              (char *)&boot_prop_entry->boot_tgt.tgt_ip_u))
 170  172                  return (B_FALSE);
 171  173  
 172  174          if (boot_prop_entry->boot_tgt.sin_family != AF_INET &&
 173  175              boot_prop_entry->boot_tgt.sin_family != AF_INET6)
 174  176                  return (B_FALSE);
 175  177  
 176  178          entry->e_vers = ISCSI_INTERFACE_VERSION;
 177  179  
 178  180          mutex_enter(&iscsi_oid_mutex);
 179  181          entry->e_oid = iscsi_oid++;
 180  182          mutex_exit(&iscsi_oid_mutex);
 181  183  
 182  184          entry->e_tpgt = ISCSI_DEFAULT_TPGT;
 183  185  
 184  186          if (boot_prop_entry->boot_tgt.sin_family == AF_INET) {
 185  187                  entry->e_u.u_in4.s_addr =
 186  188                      boot_prop_entry->boot_tgt.tgt_ip_u.u_in4.s_addr;
 187  189                  entry->e_insize = sizeof (struct in_addr);
 188  190          } else {
 189  191                  (void) bcopy(
 190  192                      &boot_prop_entry->boot_tgt.tgt_ip_u.u_in6.s6_addr,
 191  193                      entry->e_u.u_in6.s6_addr, 16);
 192  194                  entry->e_insize = sizeof (struct in6_addr);
 193  195          }
 194  196  
 195  197          entry->e_port = boot_prop_entry->boot_tgt.tgt_port;
 196  198          entry->e_boot = B_TRUE;
 197  199          return (B_TRUE);
 198  200  }
 199  201  
 200  202  /*
 201  203   * Create the boot session
 202  204   */
 203  205  static void
 204  206  iscsi_boot_session_create(iscsi_hba_t *ihp,
 205  207      ib_boot_prop_t      *boot_prop_table)
 206  208  {
 207  209          iSCSIDiscoveryMethod_t  dm;
 208  210          entry_t                 e;
 209  211          iscsi_sockaddr_t        addr_dsc;
 210  212  
 211  213          if (ihp == NULL || boot_prop_table == NULL) {
 212  214                  return;
 213  215          }
 214  216  
 215  217          if (!iscsid_ip_check(
 216  218              (char *)&boot_prop_table->boot_tgt.tgt_ip_u)) {
 217  219                  return;
 218  220          }
 219  221  
 220  222          if (boot_prop_table->boot_tgt.tgt_name != NULL) {
 221  223                  dm = iSCSIDiscoveryMethodStatic |
 222  224                      iSCSIDiscoveryMethodBoot;
 223  225                  if (!iscsid_make_entry(boot_prop_table, &e))
 224  226                          return;
 225  227                  iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
 226  228                      e.e_port, &addr_dsc.sin);
 227  229  
 228  230                  (void) iscsid_add(ihp, dm, &addr_dsc.sin,
 229  231                      (char *)boot_prop_table->boot_tgt.tgt_name,
 230  232                      e.e_tpgt, &addr_dsc.sin);
 231  233          } else {
 232  234                  dm = iSCSIDiscoveryMethodSendTargets |
 233  235                      iSCSIDiscoveryMethodBoot;
 234  236                  if (!iscsid_make_entry(boot_prop_table, &e))
 235  237                          return;
 236  238                  iscsid_addr_to_sockaddr(e.e_insize, &e.e_u,
 237  239                      e.e_port, &addr_dsc.sin);
 238  240                  iscsid_do_sendtgts(&e);
 239  241                  (void) iscsid_login_tgt(ihp, NULL, dm,
 240  242                      &addr_dsc.sin);
 241  243          }
 242  244  }
 243  245  
 244  246  /*
 245  247   * iscsid_init -- to initialize stuffs related to iscsi daemon,
 246  248   * and to create boot session if needed
 247  249   */
 248  250  boolean_t
 249  251  iscsid_init(iscsi_hba_t *ihp)
 250  252  {
 251  253          boolean_t               rval = B_TRUE;
 252  254  
 253  255          sema_init(&iscsid_config_semaphore, 1, NULL,
 254  256              SEMA_DRIVER, NULL);
 255  257          persistent_init();
 256  258          iscsid_threads_create(ihp);
 257  259  
 258  260          if (modrootloaded == 1) {
 259  261                  /* normal case, load the persistent store */
 260  262                  if (persistent_load() == B_TRUE) {
 261  263                          ihp->hba_persistent_loaded = B_TRUE;
 262  264                  } else {
 263  265                          return (B_FALSE);
 264  266                  }
 265  267          }
 266  268  
 267  269          if ((modrootloaded == 0) && (iscsiboot_prop != NULL)) {
 268  270                  if (!iscsid_boot_init_config(ihp)) {
 269  271                          rval = B_FALSE;
 270  272                  } else {
 271  273                          iscsi_boot_session_create(ihp, iscsiboot_prop);
 272  274                          iscsi_boot_wd_handle =
 273  275                              iscsi_thread_create(ihp->hba_dip,
 274  276                              "BootWD", iscsid_thread_boot_wd, ihp);
 275  277                          if (iscsi_boot_wd_handle) {
 276  278                                  rval = iscsi_thread_start(
 277  279                                      iscsi_boot_wd_handle);
 278  280                          } else {
 279  281                                  rval = B_FALSE;
 280  282                          }
 281  283                  }
 282  284                  if (rval == B_FALSE) {
 283  285                          cmn_err(CE_NOTE, "Initializaton of iscsi boot session"
 284  286                              " partially failed");
 285  287                  }
 286  288          }
 287  289  
 288  290          return (rval);
 289  291  }
 290  292  
 291  293  /*
 292  294   * iscsid_start -- start the iscsi initiator daemon, actually this code
 293  295   * is just to enable discovery methods which are set enabled in
 294  296   * persistent store, as an economic way to present the 'daemon' funtionality
 295  297   */
 296  298  boolean_t
 297  299  iscsid_start(iscsi_hba_t *ihp) {
 298  300          boolean_t               rval = B_FALSE;
 299  301          iSCSIDiscoveryMethod_t  dm;
 300  302          iSCSIDiscoveryMethod_t  *fdm;
 301  303  
 302  304          rval = iscsid_init_config(ihp);
 303  305          if (rval == B_TRUE) {
 304  306                  rval = iscsid_init_targets(ihp);
 305  307          }
 306  308  
 307  309          if (rval == B_TRUE) {
 308  310                  dm = persistent_disc_meth_get();
 309  311                  rval = iscsid_enable_discovery(ihp, dm, B_TRUE);
 310  312                  if (rval == B_TRUE) {
 311  313                          iscsid_poke_discovery(ihp,
 312  314                              iSCSIDiscoveryMethodUnknown);
 313  315                          (void) iscsid_login_tgt(ihp, NULL,
 314  316                              iSCSIDiscoveryMethodUnknown, NULL);
 315  317                  }
 316  318          }
 317  319  
 318  320          if (rval == B_FALSE) {
 319  321                  /*
 320  322                   * In case of failure the events still need to be sent
 321  323                   * because the door daemon will pause until all these
 322  324                   * events have occurred.
 323  325                   */
 324  326                  for (fdm = &for_failure[0]; *fdm !=
 325  327                      iSCSIDiscoveryMethodUnknown; fdm++) {
 326  328                          /* ---- Send both start and end events ---- */
 327  329                          iscsi_discovery_event(ihp, *fdm, B_TRUE);
 328  330                          iscsi_discovery_event(ihp, *fdm, B_FALSE);
 329  331                  }
 330  332          }
 331  333  
 332  334          return (rval);
 333  335  }
 334  336  
 335  337  /*
 336  338   * iscsid_stop -- stop the iscsi initiator daemon, by disabling
 337  339   * all the discovery methods first, and then try to stop all
 338  340   * related threads. This is a try-best effort, leave any 'busy' device
 339  341   * (and therefore session) there and just return.
 340  342   */
 341  343  boolean_t
 342  344  iscsid_stop(iscsi_hba_t *ihp) {
 343  345          boolean_t               rval = B_FALSE;
 344  346          iscsi_sess_t            *isp = NULL;
 345  347  
 346  348          (void) iscsid_disable_discovery(ihp, ISCSI_ALL_DISCOVERY_METHODS);
 347  349  
 348  350          /* final check */
 349  351          rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
 350  352          if (ihp->hba_sess_list == NULL) {
 351  353                  rval = B_TRUE;
 352  354          } else {
 353  355                  /*
 354  356                   * If only boot session is left, that is OK.
 355  357                   * Otherwise, we should report that some sessions are left.
 356  358                   */
 357  359                  rval = B_TRUE;
 358  360                  for (isp = ihp->hba_sess_list; isp != NULL;
 359  361                      isp = isp->sess_next) {
 360  362                          if (isp->sess_boot == B_FALSE) {
 361  363                                  rval = B_FALSE;
 362  364                                  break;
 363  365                          }
 364  366                  }
 365  367          }
 366  368          rw_exit(&ihp->hba_sess_list_rwlock);
 367  369  
 368  370          return (rval);
 369  371  }
 370  372  
 371  373  /*
 372  374   * iscsid_fini -- do whatever is required to clean up
 373  375   */
 374  376  /* ARGSUSED */
 375  377  void
 376  378  iscsid_fini()
 377  379  {
 378  380          if (iscsi_boot_wd_handle != NULL) {
 379  381                  iscsi_thread_destroy(iscsi_boot_wd_handle);
 380  382                  iscsi_boot_wd_handle = NULL;
 381  383          }
 382  384          iscsid_threads_destroy();
 383  385          persistent_fini();
 384  386          sema_destroy(&iscsid_config_semaphore);
 385  387  }
 386  388  
 387  389  /*
 388  390   * iscsid_props -- returns discovery thread information, used by ioctl code
 389  391   */
 390  392  void
 391  393  iscsid_props(iSCSIDiscoveryProperties_t *props)
 392  394  {
 393  395          iSCSIDiscoveryMethod_t  dm;
 394  396  
 395  397          dm = persistent_disc_meth_get();
 396  398  
 397  399          props->vers = ISCSI_INTERFACE_VERSION;
 398  400  
 399  401          /* ---- change once thread is implemented ---- */
 400  402          props->iSNSDiscoverySettable            = B_FALSE;
 401  403          props->SLPDiscoverySettable             = B_FALSE;
 402  404          props->StaticDiscoverySettable          = B_TRUE;
 403  405          props->SendTargetsDiscoverySettable     = B_TRUE;
 404  406          props->iSNSDiscoveryMethod              = iSNSDiscoveryMethodStatic;
 405  407  
 406  408          props->iSNSDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodISNS);
 407  409          props->StaticDiscoveryEnabled =
 408  410              CHECK_METHOD(iSCSIDiscoveryMethodStatic);
 409  411          props->SendTargetsDiscoveryEnabled =
 410  412              CHECK_METHOD(iSCSIDiscoveryMethodSendTargets);
 411  413          props->SLPDiscoveryEnabled = CHECK_METHOD(iSCSIDiscoveryMethodSLP);
 412  414  }
 413  415  
 414  416  /*
 415  417   * iscsid_enable_discovery - start specified discovery methods
 416  418   */
 417  419  /* ARGSUSED */
 418  420  boolean_t
 419  421  iscsid_enable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm,
 420  422      boolean_t poke)
 421  423  {
 422  424          boolean_t               rval = B_TRUE;
 423  425          iscsid_thr_table        *dt;
 424  426  
 425  427          /*
 426  428           * start the specified discovery method(s)
 427  429           */
 428  430          for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
 429  431              dt++) {
 430  432                  if (idm & dt->method) {
 431  433                          if (dt->thr_id != NULL) {
 432  434                                  rval = iscsi_thread_start(dt->thr_id);
 433  435                                  if (rval == B_FALSE) {
 434  436                                          break;
 435  437                                  }
 436  438                                  if (poke == B_TRUE) {
 437  439                                          (void) iscsi_thread_send_wakeup(
 438  440                                              dt->thr_id);
 439  441                                  }
 440  442                          } else {
 441  443                                  /*
 442  444                                   * unexpected condition.  The threads for each
 443  445                                   * discovery method should have started at
 444  446                                   * initialization
 445  447                                   */
 446  448                                  ASSERT(B_FALSE);
 447  449                          }
 448  450                  }
 449  451          } /* END for() */
 450  452  
 451  453          return (rval);
 452  454  }
 453  455  
 454  456  
 455  457  /*
 456  458   * iscsid_disable_discovery - stop specified discovery methods
 457  459   */
 458  460  boolean_t
 459  461  iscsid_disable_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t idm)
 460  462  {
 461  463          boolean_t               rval = B_TRUE;
 462  464          iscsid_thr_table        *dt;
 463  465  
 464  466          /*
 465  467           * stop the specified discovery method(s)
 466  468           */
 467  469          for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
 468  470              dt++) {
 469  471                  if (idm & dt->method) {
 470  472  
 471  473                          /* signal discovery event change - begin */
 472  474                          iscsi_discovery_event(ihp, dt->method, B_TRUE);
 473  475  
 474  476                          /* Attempt to logout of all associated targets */
 475  477                          rval = iscsid_del(ihp, NULL, dt->method, NULL);
 476  478                          if (rval == B_TRUE) {
 477  479                                  /* Successfully logged out of targets */
 478  480                                  if (dt->thr_id != NULL) {
 479  481                                          rval = iscsi_thread_stop(dt->thr_id);
 480  482                                          if (rval == B_FALSE) {
 481  483                                                  /*
 482  484                                                   * signal discovery
 483  485                                                   * event change - end
 484  486                                                   */
 485  487                                                  iscsi_discovery_event(ihp,
 486  488                                                      dt->method, B_FALSE);
 487  489                                                  break;
 488  490                                          }
 489  491  
 490  492                                  } else {
 491  493                                          /*
 492  494                                           * unexpected condition.  The threads
 493  495                                           * for each discovery method should
 494  496                                           * have started at initialization
 495  497                                           */
 496  498                                          ASSERT(B_FALSE);
 497  499                                  }
 498  500                          }
 499  501  
 500  502                          /* signal discovery event change - end */
 501  503                          iscsi_discovery_event(ihp, dt->method, B_FALSE);
 502  504  
 503  505                  }
 504  506          } /* END for() */
 505  507  
 506  508          return (rval);
 507  509  }
 508  510  
 509  511  /*
 510  512   * iscsid_poke_discovery - wakeup discovery methods to find any new targets
 511  513   * and wait for all discovery processes to complete.
 512  514   */
 513  515  void
 514  516  iscsid_poke_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method)
 515  517  {
 516  518  #define ISCSI_DISCOVERY_DELAY   1
 517  519  
 518  520          iSCSIDiscoveryMethod_t  dm;
 519  521          iscsid_thr_table        *dt;
 520  522          boolean_t               send_wakeup;
 521  523  
 522  524          ASSERT(ihp != NULL);
 523  525  
 524  526          /* reset discovery flags */
 525  527          mutex_enter(&ihp->hba_discovery_events_mutex);
 526  528          ihp->hba_discovery_in_progress = B_TRUE;
 527  529          ihp->hba_discovery_events = iSCSIDiscoveryMethodUnknown;
 528  530          mutex_exit(&ihp->hba_discovery_events_mutex);
 529  531  
 530  532          /* start all enabled discovery methods */
 531  533          dm = persistent_disc_meth_get();
 532  534          for (dt = &iscsid_thr[0]; dt->method != iSCSIDiscoveryMethodUnknown;
 533  535              dt++) {
 534  536                  send_wakeup = B_FALSE;
 535  537  
 536  538                  if ((method == iSCSIDiscoveryMethodUnknown) ||
 537  539                      (method == dt->method)) {
 538  540                          if ((dm & dt->method) && (dt->thr_id != NULL)) {
 539  541                                  if (iscsi_thread_send_wakeup(dt->thr_id) ==
 540  542                                      B_TRUE) {
 541  543                                          send_wakeup = B_TRUE;
 542  544                                  }
 543  545                          }
 544  546                  }
 545  547  
 546  548                  if (send_wakeup == B_FALSE) {
 547  549                          iscsi_discovery_event(ihp, dt->method, B_TRUE);
 548  550                          iscsi_discovery_event(ihp, dt->method, B_FALSE);
 549  551                  }
 550  552          }
 551  553  
 552  554          mutex_enter(&ihp->hba_discovery_events_mutex);
 553  555          while (ihp->hba_discovery_events != ISCSI_ALL_DISCOVERY_METHODS) {
 554  556                  mutex_exit(&ihp->hba_discovery_events_mutex);
 555  557                  delay(SEC_TO_TICK(ISCSI_DISCOVERY_DELAY));
 556  558                  mutex_enter(&ihp->hba_discovery_events_mutex);
 557  559          }
 558  560          ihp->hba_discovery_in_progress = B_FALSE;
 559  561          mutex_exit(&ihp->hba_discovery_events_mutex);
 560  562  
 561  563  }
 562  564  
 563  565  /*
 564  566   * iscsid_do_sendtgts - issue send targets command to the given discovery
 565  567   * address and then add the discovered targets to the discovery queue
 566  568   */
 567  569  void
 568  570  iscsid_do_sendtgts(entry_t *disc_addr)
 569  571  {
 570  572  
 571  573  #define SENDTGTS_DEFAULT_NUM_TARGETS    10
 572  574  
 573  575          int                     stl_sz;
 574  576          int                     stl_num_tgts = SENDTGTS_DEFAULT_NUM_TARGETS;
 575  577          iscsi_sendtgts_list_t   *stl_hdr = NULL;
 576  578          boolean_t               retry = B_TRUE;
 577  579          char                    inp_buf[INET6_ADDRSTRLEN];
 578  580          const char              *ip;
 579  581          int                     ctr;
 580  582          int                     rc;
 581  583          iscsi_hba_t             *ihp;
 582  584          iSCSIDiscoveryMethod_t  dm = iSCSIDiscoveryMethodSendTargets;
 583  585  
 584  586          /* allocate and initialize sendtargets list header */
 585  587          stl_sz = sizeof (*stl_hdr) + ((stl_num_tgts - 1) *
 586  588              sizeof (iscsi_sendtgts_entry_t));
 587  589          stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP);
 588  590  
 589  591  retry_sendtgts:
 590  592          stl_hdr->stl_in_cnt = stl_num_tgts;
 591  593          bcopy(disc_addr, &(stl_hdr->stl_entry),
 592  594              sizeof (stl_hdr->stl_entry));
 593  595          stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION;
 594  596  
 595  597          /* lock interface so only one SendTargets operation occurs */
 596  598          if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) {
 597  599                  cmn_err(CE_NOTE, "!iscsi discovery failure - SendTargets. "
 598  600                      "failure to get soft state");
 599  601                  kmem_free(stl_hdr, stl_sz);
 600  602                  return;
 601  603          }
 602  604          sema_p(&ihp->hba_sendtgts_semaphore);
 603  605          rc = iscsi_ioctl_sendtgts_get(ihp, stl_hdr);
 604  606          sema_v(&ihp->hba_sendtgts_semaphore);
 605  607          if (rc) {
 606  608                  ip = inet_ntop((disc_addr->e_insize ==
 607  609                      sizeof (struct in_addr) ? AF_INET : AF_INET6),
 608  610                      &disc_addr->e_u, inp_buf, sizeof (inp_buf));
 609  611                  cmn_err(CE_NOTE,
 610  612                      "iscsi discovery failure - SendTargets (%s)\n", ip);
 611  613                  kmem_free(stl_hdr, stl_sz);
 612  614                  return;
 613  615          }
 614  616  
 615  617          /* check if all targets received */
 616  618          if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) {
 617  619                  if (retry == B_TRUE) {
 618  620                          stl_num_tgts = stl_hdr->stl_out_cnt;
 619  621                          kmem_free(stl_hdr, stl_sz);
 620  622                          stl_sz = sizeof (*stl_hdr) +
 621  623                              ((stl_num_tgts - 1) *
 622  624                              sizeof (iscsi_sendtgts_entry_t));
 623  625                          stl_hdr = kmem_zalloc(stl_sz, KM_SLEEP);
 624  626                          retry = B_FALSE;
 625  627                          goto retry_sendtgts;
 626  628                  } else {
 627  629                          ip = inet_ntop((disc_addr->e_insize ==
 628  630                              sizeof (struct in_addr) ?
 629  631                              AF_INET : AF_INET6), &disc_addr->e_u,
 630  632                              inp_buf, sizeof (inp_buf));
 631  633                          cmn_err(CE_NOTE, "iscsi discovery failure - "
 632  634                              "SendTargets overflow (%s)\n", ip);
 633  635                          kmem_free(stl_hdr, stl_sz);
 634  636                          return;
 635  637                  }
 636  638          }
 637  639  
 638  640          for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) {
 639  641                  iscsi_sockaddr_t addr_dsc;
 640  642                  iscsi_sockaddr_t addr_tgt;
 641  643  
 642  644                  iscsid_addr_to_sockaddr(disc_addr->e_insize,
 643  645                      &disc_addr->e_u, disc_addr->e_port, &addr_dsc.sin);
 644  646                  iscsid_addr_to_sockaddr(
 645  647                      stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize,
 646  648                      &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr),
 647  649                      stl_hdr->stl_list[ctr].ste_ipaddr.a_port,
 648  650                      &addr_tgt.sin);
 649  651                  if (disc_addr->e_boot == B_TRUE) {
 650  652                          dm = dm | iSCSIDiscoveryMethodBoot;
 651  653                  }
 652  654                  (void) iscsid_add(ihp, dm,
 653  655                      &addr_dsc.sin, (char *)stl_hdr->stl_list[ctr].ste_name,
 654  656                      stl_hdr->stl_list[ctr].ste_tpgt,
 655  657                      &addr_tgt.sin);
 656  658          }
 657  659          kmem_free(stl_hdr, stl_sz);
 658  660  }
 659  661  
 660  662  void
 661  663  iscsid_do_isns_query_one_server(iscsi_hba_t *ihp, entry_t *isns_server)
 662  664  {
 663  665          int pg_sz, query_status;
 664  666          iscsi_addr_t *ap;
 665  667          isns_portal_group_list_t *pg_list;
 666  668  
 667  669          ap = (iscsi_addr_t *)kmem_zalloc(sizeof (iscsi_addr_t), KM_SLEEP);
 668  670          ap->a_port = isns_server->e_port;
 669  671          ap->a_addr.i_insize = isns_server->e_insize;
 670  672  
 671  673          if (isns_server->e_insize == sizeof (struct in_addr)) {
 672  674                  ap->a_addr.i_addr.in4.s_addr = (isns_server->e_u.u_in4.s_addr);
 673  675          } else if (isns_server->e_insize == sizeof (struct in6_addr)) {
 674  676                  bcopy(&(isns_server->e_u.u_in6.s6_addr),
 675  677                      ap->a_addr.i_addr.in6.s6_addr, 16);
 676  678          } else {
 677  679                  kmem_free(ap, sizeof (iscsi_addr_t));
 678  680                  return;
 679  681          }
 680  682  
 681  683          pg_list = NULL;
 682  684          query_status = isns_query_one_server(
 683  685              ap, ihp->hba_isid,
 684  686              ihp->hba_name, ihp->hba_alias,
 685  687              ISNS_INITIATOR_NODE_TYPE, &pg_list);
 686  688          kmem_free(ap, sizeof (iscsi_addr_t));
 687  689          if (query_status != isns_ok || pg_list == NULL) {
 688  690                  DTRACE_PROBE1(iscsid_do_isns_query_one_server_status,
 689  691                      int, query_status);
 690  692                  return;
 691  693          }
 692  694  
 693  695          iscsid_add_pg_list_to_cache(ihp, pg_list);
 694  696          pg_sz = sizeof (isns_portal_group_list_t);
 695  697          if (pg_list->pg_out_cnt > 0) {
 696  698                  pg_sz += (pg_list->pg_out_cnt - 1) *
 697  699                      sizeof (isns_portal_group_t);
 698  700          }
 699  701          kmem_free(pg_list, pg_sz);
 700  702  }
 701  703  
 702  704  void
 703  705  iscsid_do_isns_query(iscsi_hba_t *ihp)
 704  706  {
 705  707          int pg_sz, query_status;
 706  708          isns_portal_group_list_t *pg_list;
 707  709  
 708  710          pg_list = NULL;
 709  711          query_status = isns_query(ihp->hba_isid,
 710  712              ihp->hba_name,
 711  713              ihp->hba_alias,
 712  714              ISNS_INITIATOR_NODE_TYPE,
 713  715              &pg_list);
 714  716  
 715  717          if (pg_list == NULL) {
 716  718                  DTRACE_PROBE1(iscsid_do_isns_query_status,
 717  719                      int, query_status);
 718  720                  return;
 719  721          }
 720  722  
 721  723          if ((query_status != isns_ok &&
 722  724              query_status != isns_op_partially_failed)) {
 723  725                  DTRACE_PROBE1(iscsid_do_isns_query_status,
 724  726                      int, query_status);
 725  727                  pg_sz = sizeof (isns_portal_group_list_t);
 726  728                  if (pg_list->pg_out_cnt > 0) {
 727  729                          pg_sz += (pg_list->pg_out_cnt - 1) *
 728  730                              sizeof (isns_portal_group_t);
 729  731                  }
 730  732                  kmem_free(pg_list, pg_sz);
 731  733                  return;
 732  734          }
 733  735  
 734  736          iscsid_add_pg_list_to_cache(ihp, pg_list);
 735  737  
 736  738          pg_sz = sizeof (isns_portal_group_list_t);
 737  739          if (pg_list->pg_out_cnt > 0) {
 738  740                  pg_sz += (pg_list->pg_out_cnt - 1) *
 739  741                      sizeof (isns_portal_group_t);
 740  742          }
 741  743          kmem_free(pg_list, pg_sz);
 742  744  }
 743  745  
 744  746  /*
 745  747   * iscsid_config_one - for the given target name, attempt
 746  748   * to login to all targets associated with name.  If target
 747  749   * name is not found in discovery queue, reset the discovery
 748  750   * queue, kick the discovery processes, and then retry.
 749  751   *
 750  752   * NOTE: The caller of this function must hold the
 751  753   *      iscsid_config_semaphore across this call.
 752  754   */
 753  755  void
 754  756  iscsid_config_one(iscsi_hba_t *ihp, char *name, boolean_t protect)
 755  757  {
 756  758          boolean_t       rc          =   B_FALSE;
 757  759          int             retry       =   0;
 758  760          int             lun_online  =   0;
 759  761          int             cur_sec     =   0;
 760  762  
 761  763          if (!modrootloaded && (iscsiboot_prop != NULL)) {
 762  764                  if (!iscsi_configroot_printed) {
 763  765                          cmn_err(CE_NOTE, "Configuring"
 764  766                              " iSCSI boot session...");
 765  767                          iscsi_configroot_printed = B_TRUE;
 766  768                  }
 767  769                  if (iscsi_net_up == 0) {
 768  770                          if (iscsi_net_interface(B_FALSE) ==
 769  771                              ISCSI_STATUS_SUCCESS) {
 770  772                                  iscsi_net_up = 1;
 771  773                          } else {
 772  774                                  cmn_err(CE_WARN, "Failed to configure interface"
 773  775                                      " for iSCSI boot session");
 774  776                                  return;
 775  777                          }
 776  778                  }
 777  779                  while (rc == B_FALSE && retry <
 778  780                      iscsi_configroot_retry) {
 779  781                          rc = iscsid_login_tgt(ihp, name,
 780  782                              iSCSIDiscoveryMethodBoot, NULL);
 781  783                          if (rc == B_FALSE) {
 782  784                                  /*
 783  785                                   * create boot session
 784  786                                   */
 785  787                                  iscsi_boot_session_create(ihp,
 786  788                                      iscsiboot_prop);
 787  789                                  retry++;
 788  790                                  continue;
 789  791                          }
 790  792                          rc = iscsid_check_active_boot_conn(ihp);
 791  793                          if (rc == B_FALSE) {
 792  794                                  /*
 793  795                                   * no active connection for the boot
 794  796                                   * session, retry the login until
 795  797                                   * one is found or the retry count
 796  798                                   * is exceeded
 797  799                                   */
 798  800                                  delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY));
 799  801                                  retry++;
 800  802                                  continue;
 801  803                          }
 802  804                          /*
 803  805                           * The boot session has been created with active
 804  806                           * connection. If the target lun has not been online,
 805  807                           * we should wait here for a while
 806  808                           */
 807  809                          do {
 808  810                                  lun_online =
 809  811                                      iscsiboot_prop->boot_tgt.lun_online;
 810  812                                  if (lun_online == 0) {
 811  813                                          delay(SEC_TO_TICK(
 812  814                                              ISCSI_CONFIGROOT_DELAY));
 813  815                                          cur_sec++;
 814  816                                  }
 815  817                          } while ((lun_online == 0) &&
 816  818                              (cur_sec < iscsi_boot_max_delay));
 817  819                          retry++;
 818  820                  }
 819  821                  if (!rc) {
 820  822                          cmn_err(CE_WARN, "Failed to configure iSCSI"
 821  823                              " boot session");
 822  824                  }
 823  825          } else {
 824  826                  rc = iscsid_login_tgt(ihp, name, iSCSIDiscoveryMethodUnknown,
 825  827                      NULL);
 826  828                  /*
 827  829                   * If we didn't login to the device we might have
 828  830                   * to update our discovery information and attempt
 829  831                   * the login again.
 830  832                   */
 831  833                  if (rc == B_FALSE) {
 832  834                          /*
 833  835                           * Stale /dev links can cause us to get floods
 834  836                           * of config requests.  Prevent these repeated
 835  837                           * requests from causing unneeded discovery updates
 836  838                           * if ISCSI_CONFIG_STORM_PROTECT is set.
 837  839                           */
 838  840                          if ((protect == B_FALSE) ||
 839  841                              (ddi_get_lbolt() > ihp->hba_config_lbolt +
 840  842                              SEC_TO_TICK(ihp->hba_config_storm_delay))) {
 841  843                                  ihp->hba_config_lbolt = ddi_get_lbolt();
 842  844                                  iscsid_poke_discovery(ihp,
 843  845                                      iSCSIDiscoveryMethodUnknown);
 844  846                                  (void) iscsid_login_tgt(ihp, name,
 845  847                                      iSCSIDiscoveryMethodUnknown, NULL);
 846  848                          }
 847  849                  }
 848  850          }
 849  851  }
 850  852  
 851  853  /*
 852  854   * iscsid_config_all - reset the discovery queue, kick the
 853  855   * discovery processes, and login to all targets found
 854  856   *
 855  857   * NOTE: The caller of this function must hold the
 856  858   *      iscsid_config_semaphore across this call.
 857  859   */
 858  860  void
 859  861  iscsid_config_all(iscsi_hba_t *ihp, boolean_t protect)
 860  862  {
 861  863          boolean_t       rc              = B_FALSE;
 862  864          int             retry   = 0;
 863  865          int             lun_online  = 0;
 864  866          int             cur_sec = 0;
 865  867  
 866  868          if (!modrootloaded && iscsiboot_prop != NULL) {
 867  869                  if (!iscsi_configroot_printed) {
 868  870                          cmn_err(CE_NOTE, "Configuring"
 869  871                              " iSCSI boot session...");
 870  872                          iscsi_configroot_printed = B_TRUE;
 871  873                  }
 872  874                  if (iscsi_net_up == 0) {
 873  875                          if (iscsi_net_interface(B_FALSE) ==
 874  876                              ISCSI_STATUS_SUCCESS) {
 875  877                                  iscsi_net_up = 1;
 876  878                          }
 877  879                  }
 878  880                  while (rc == B_FALSE && retry <
 879  881                      iscsi_configroot_retry) {
 880  882                          rc = iscsid_login_tgt(ihp, NULL,
 881  883                              iSCSIDiscoveryMethodBoot, NULL);
 882  884                          if (rc == B_FALSE) {
 883  885                                  /*
 884  886                                   * No boot session has been created.
 885  887                                   * We would like to create the boot
 886  888                                   * Session first.
 887  889                                   */
 888  890                                  iscsi_boot_session_create(ihp,
 889  891                                      iscsiboot_prop);
 890  892                                  retry++;
 891  893                                  continue;
 892  894                          }
 893  895                          rc = iscsid_check_active_boot_conn(ihp);
 894  896                          if (rc == B_FALSE) {
 895  897                                  /*
 896  898                                   * no active connection for the boot
 897  899                                   * session, retry the login until
 898  900                                   * one is found or the retry count
 899  901                                   * is exceeded
 900  902                                   */
 901  903                                  delay(SEC_TO_TICK(ISCSI_CONFIGROOT_DELAY));
 902  904                                  retry++;
 903  905                                  continue;
 904  906                          }
 905  907                          /*
 906  908                           * The boot session has been created with active
 907  909                           * connection. If the target lun has not been online,
 908  910                           * we should wait here for a while
 909  911                           */
 910  912                          do {
 911  913                                  lun_online =
 912  914                                      iscsiboot_prop->boot_tgt.lun_online;
 913  915                                  if (lun_online == 0) {
 914  916                                          delay(SEC_TO_TICK(
 915  917                                              ISCSI_CONFIGROOT_DELAY));
 916  918                                          cur_sec++;
 917  919                                  }
 918  920                          } while ((lun_online == 0) &&
 919  921                              (cur_sec < iscsi_boot_max_delay));
 920  922                          retry++;
 921  923                  }
 922  924                  if (!rc) {
 923  925                          cmn_err(CE_WARN, "Failed to configure"
 924  926                              " boot session");
 925  927                  }
 926  928          } else {
 927  929                  /*
 928  930                   * Stale /dev links can cause us to get floods
 929  931                   * of config requests.  Prevent these repeated
 930  932                   * requests from causing unneeded discovery updates
 931  933                   * if ISCSI_CONFIG_STORM_PROTECT is set.
 932  934                   */
 933  935                  if ((protect == B_FALSE) ||
 934  936                      (ddi_get_lbolt() > ihp->hba_config_lbolt +
 935  937                      SEC_TO_TICK(ihp->hba_config_storm_delay))) {
 936  938                          ihp->hba_config_lbolt = ddi_get_lbolt();
 937  939                          iscsid_poke_discovery(ihp,
 938  940                              iSCSIDiscoveryMethodUnknown);
 939  941                  }
 940  942                  (void) iscsid_login_tgt(ihp, NULL,
 941  943                      iSCSIDiscoveryMethodUnknown, NULL);
 942  944          }
 943  945  }
 944  946  
 945  947  /*
 946  948   * isns_scn_callback - iSNS client received an SCN
 947  949   *
 948  950   * This code processes the iSNS client SCN events.  These
 949  951   * could relate to the addition, removal, or update of a
 950  952   * logical unit.
 951  953   */
 952  954  void
 953  955  isns_scn_callback(void *arg)
 954  956  {
 955  957          int                             i, pg_sz;
 956  958          int                             qry_status;
 957  959          isns_portal_group_list_t        *pg_list;
 958  960          uint32_t                        scn_type;
 959  961          iscsi_hba_t                     *ihp;
 960  962  
 961  963          if (arg == NULL) {
 962  964                  /* No argument */
 963  965                  return;
 964  966          }
 965  967  
 966  968          if ((ihp = (iscsi_hba_t *)ddi_get_soft_state(iscsi_state, 0)) == NULL) {
 967  969                  kmem_free(arg, sizeof (isns_scn_callback_arg_t));
 968  970                  return;
 969  971          }
 970  972  
 971  973          /*
 972  974           * All isns callbacks are from a standalone taskq
 973  975           * therefore the blocking here doesn't affect the enable/disable
 974  976           * of isns discovery method
 975  977           */
 976  978          if (iscsi_client_request_service(ihp) == B_FALSE) {
 977  979                  kmem_free(arg, sizeof (isns_scn_callback_arg_t));
 978  980                  return;
 979  981          }
 980  982  
 981  983          scn_type = ((isns_scn_callback_arg_t *)arg)->scn_type;
 982  984          DTRACE_PROBE1(isns_scn_callback_scn_type, int, scn_type);
 983  985          switch (scn_type) {
 984  986          /*
 985  987           * ISNS_OBJ_ADDED - An object has been added.
 986  988           */
 987  989          case ISNS_OBJ_ADDED:
 988  990                  /* Query iSNS server for contact information */
 989  991                  pg_list = NULL;
 990  992                  qry_status = isns_query_one_node(
 991  993                      ((isns_scn_callback_arg_t *)arg)->source_key_attr,
 992  994                      ihp->hba_isid,
 993  995                      ihp->hba_name,
 994  996                      (uint8_t *)"",
 995  997                      ISNS_INITIATOR_NODE_TYPE,
 996  998                      &pg_list);
 997  999  
 998 1000                  /* Verify portal group is found */
 999 1001                  if ((qry_status != isns_ok &&
1000 1002                      qry_status != isns_op_partially_failed) ||
1001 1003                      pg_list == NULL) {
1002 1004                          break;
1003 1005                  }
1004 1006  
1005 1007                  DTRACE_PROBE1(pg_list,
1006 1008                      isns_portal_group_list_t *, pg_list);
1007 1009  
1008 1010                  /* Add all portals for logical unit to discovery cache */
1009 1011                  for (i = 0; i < pg_list->pg_out_cnt; i++) {
1010 1012                          iscsi_sockaddr_t addr_dsc;
1011 1013                          iscsi_sockaddr_t addr_tgt;
1012 1014  
1013 1015                          iscsid_addr_to_sockaddr(
1014 1016                              pg_list->pg_list[i].isns_server_ip.i_insize,
1015 1017                              &pg_list->pg_list[i].isns_server_ip.i_addr,
1016 1018                              pg_list->pg_list[i].isns_server_port,
1017 1019                              &addr_dsc.sin);
1018 1020                          iscsid_addr_to_sockaddr(pg_list->pg_list[i].insize,
1019 1021                              &pg_list->pg_list[i].pg_ip_addr,
1020 1022                              pg_list->pg_list[i].pg_port, &addr_tgt.sin);
1021 1023  
1022 1024                          (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS,
1023 1025                              &addr_dsc.sin, (char *)pg_list->pg_list[i].
1024 1026                              pg_iscsi_name, pg_list->pg_list[i].pg_tag,
1025 1027                              &addr_tgt.sin);
1026 1028  
1027 1029                          /* Force target to login */
1028 1030                          (void) iscsid_login_tgt(ihp, (char *)pg_list->
1029 1031                              pg_list[i].pg_iscsi_name, iSCSIDiscoveryMethodISNS,
1030 1032                              NULL);
1031 1033                  }
1032 1034  
1033 1035                  if (pg_list != NULL) {
1034 1036                          pg_sz = sizeof (isns_portal_group_list_t);
1035 1037                          if (pg_list->pg_out_cnt > 0) {
1036 1038                                  pg_sz += (pg_list->pg_out_cnt - 1) *
1037 1039                                      sizeof (isns_portal_group_t);
1038 1040                          }
1039 1041                          kmem_free(pg_list, pg_sz);
1040 1042                  }
1041 1043                  break;
1042 1044  
1043 1045          /*
1044 1046           * ISNS_OBJ_REMOVED - logical unit has been removed
1045 1047           */
1046 1048          case ISNS_OBJ_REMOVED:
1047 1049                  if (iscsid_del(ihp,
1048 1050                      (char *)((isns_scn_callback_arg_t *)arg)->
1049 1051                      source_key_attr, iSCSIDiscoveryMethodISNS, NULL) !=
1050 1052                      B_TRUE) {
1051 1053                          cmn_err(CE_NOTE, "iscsi initiator - "
1052 1054                              "isns remove scn failed for target %s\n",
1053 1055                              (char *)((isns_scn_callback_arg_t *)arg)->
1054 1056                              source_key_attr);
1055 1057  
1056 1058                  }
1057 1059                  break;
1058 1060  
1059 1061          /*
1060 1062           * ISNS_OBJ_UPDATED - logical unit has changed
1061 1063           */
1062 1064          case ISNS_OBJ_UPDATED:
1063 1065                  cmn_err(CE_NOTE, "iscsi initiator - "
1064 1066                      "received iSNS update SCN for %s\n",
1065 1067                      (char *)((isns_scn_callback_arg_t *)arg)->
1066 1068                      source_key_attr);
1067 1069                  break;
1068 1070  
1069 1071          /*
1070 1072           * ISNS_OBJ_UNKNOWN -
1071 1073           */
1072 1074          default:
1073 1075                  cmn_err(CE_NOTE, "iscsi initiator - "
1074 1076                      "received unknown iSNS SCN type 0x%x\n", scn_type);
1075 1077                  break;
1076 1078          }
1077 1079  
1078 1080          iscsi_client_release_service(ihp);
1079 1081          kmem_free(arg, sizeof (isns_scn_callback_arg_t));
1080 1082  }
1081 1083  
1082 1084  
1083 1085  /*
1084 1086   * iscsid_add - Creates discovered session and connection
1085 1087   */
1086 1088  static boolean_t
1087 1089  iscsid_add(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method,
1088 1090      struct sockaddr *addr_dsc, char *target_name, int tpgt,
1089 1091      struct sockaddr *addr_tgt)
1090 1092  {
1091 1093          boolean_t           rtn = B_TRUE;
1092 1094          iscsi_sess_t        *isp;
1093 1095          iscsi_conn_t        *icp;
1094 1096          uint_t              oid;
1095 1097          int                 idx;
1096 1098          int                 isid;
1097 1099          iscsi_config_sess_t *ics;
1098 1100          int                 size;
1099 1101          char                *tmp;
1100 1102  
1101 1103          ASSERT(ihp != NULL);
1102 1104          ASSERT(addr_dsc != NULL);
1103 1105          ASSERT(target_name != NULL);
1104 1106          ASSERT(addr_tgt != NULL);
1105 1107  
1106 1108          /* setup initial buffer for configured session information */
1107 1109          size = sizeof (*ics);
1108 1110          ics = kmem_zalloc(size, KM_SLEEP);
1109 1111          ics->ics_in = 1;
1110 1112  
1111 1113          /* get configured sessions information */
1112 1114          tmp = target_name;
1113 1115          if (persistent_get_config_session(tmp, ics) == B_FALSE) {
1114 1116                  /*
1115 1117                   * No target information available check for
1116 1118                   * initiator information.
1117 1119                   */
1118 1120                  tmp = (char *)ihp->hba_name;
1119 1121                  if (persistent_get_config_session(tmp, ics) == B_FALSE) {
1120 1122                          /*
1121 1123                           * No hba information is
1122 1124                           * found.  So assume default
1123 1125                           * one session unbound behavior.
1124 1126                           */
1125 1127                          ics->ics_out = 1;
1126 1128                          ics->ics_bound = B_TRUE;
1127 1129                  }
1128 1130          }
1129 1131  
1130 1132          if (iscsiboot_prop && (ics->ics_out > 1) &&
1131 1133              !iscsi_chk_bootlun_mpxio(ihp)) {
1132 1134                  /*
1133 1135                   * iscsi boot with mpxio disabled
1134 1136                   * no need to search configured boot session
1135 1137                   */
1136 1138  
1137 1139                  if (iscsi_cmp_boot_ini_name(tmp) ||
1138 1140                      iscsi_cmp_boot_tgt_name(tmp)) {
1139 1141                          ics->ics_out = 1;
1140 1142                          ics->ics_bound = B_FALSE;
1141 1143                  }
1142 1144          }
1143 1145          /* Check to see if we need to get more information */
1144 1146          if (ics->ics_out > 1) {
1145 1147                  /* record new size and free last buffer */
1146 1148                  idx = ics->ics_out;
1147 1149                  size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out);
1148 1150                  kmem_free(ics, sizeof (*ics));
1149 1151  
1150 1152                  /* allocate new buffer */
1151 1153                  ics = kmem_zalloc(size, KM_SLEEP);
1152 1154                  ics->ics_in = idx;
1153 1155  
1154 1156                  /* get configured sessions information */
1155 1157                  if (persistent_get_config_session(tmp, ics) != B_TRUE) {
1156 1158                          cmn_err(CE_NOTE, "iscsi session(%s) - "
1157 1159                              "unable to get configured session information\n",
1158 1160                              target_name);
1159 1161                          kmem_free(ics, size);
1160 1162                          return (B_FALSE);
1161 1163                  }
1162 1164          }
1163 1165  
1164 1166          /* loop for all configured sessions */
1165 1167          rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1166 1168          for (isid = 0; isid < ics->ics_out; isid++) {
1167 1169                  /* create or find matching session */
1168 1170                  isp = iscsi_sess_create(ihp, method, addr_dsc, target_name,
1169 1171                      tpgt, isid, ISCSI_SESS_TYPE_NORMAL, &oid);
1170 1172                  if (isp == NULL) {
1171 1173                          rtn = B_FALSE;
1172 1174                          break;
1173 1175                  }
1174 1176  
1175 1177                  /* create or find matching connection */
1176 1178                  if (!ISCSI_SUCCESS(iscsi_conn_create(addr_tgt, isp, &icp))) {
1177 1179                          /*
1178 1180                           * Teardown the session we just created.  It can't
1179 1181                           * have any luns or connections associated with it
1180 1182                           * so this should always succeed (luckily since what
1181 1183                           * would we do if it failed?)
1182 1184                           */
1183 1185                          (void) iscsi_sess_destroy(isp);
1184 1186                          rtn = B_FALSE;
1185 1187                          break;
1186 1188                  }
1187 1189          }
1188 1190          rw_exit(&ihp->hba_sess_list_rwlock);
1189 1191          kmem_free(ics, size);
1190 1192          return (rtn);
1191 1193  }
1192 1194  
1193 1195  /*
1194 1196   * iscsid_del - Attempts to delete all associated sessions
1195 1197   */
1196 1198  boolean_t
1197 1199  iscsid_del(iscsi_hba_t *ihp, char *target_name,
1198 1200      iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc)
1199 1201  {
1200 1202          boolean_t       rtn = B_TRUE;
1201 1203          iscsi_status_t  status;
1202 1204          iscsi_sess_t    *isp;
1203 1205          char            name[ISCSI_MAX_NAME_LEN];
1204 1206  
1205 1207          ASSERT(ihp != NULL);
1206 1208          /* target name can be NULL or !NULL */
1207 1209          /* addr_dsc can be NULL or !NULL */
1208 1210  
1209 1211          rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1210 1212          isp = ihp->hba_sess_list;
1211 1213          while (isp != NULL) {
1212 1214                  /*
1213 1215                   * If no target_name is listed (meaning all targets)
1214 1216                   * or this specific target was listed. And the same
1215 1217                   * discovery method discovered this target then
1216 1218                   * continue evaulation.  Otherwise fail.
1217 1219                   */
1218 1220                  if (((target_name == NULL) ||
1219 1221                      (strcmp((char *)isp->sess_name, target_name) == 0)) &&
1220 1222                      (isp->sess_discovered_by == method)) {
1221 1223                          boolean_t try_destroy;
1222 1224  
1223 1225                          /*
1224 1226                           * If iSNS, SendTargets, or Static then special
1225 1227                           * handling for disc_addr.
1226 1228                           */
1227 1229                          if ((method == iSCSIDiscoveryMethodISNS) ||
1228 1230                              (method == iSCSIDiscoveryMethodSendTargets)) {
1229 1231                                  /*
1230 1232                                   * If NULL addr_dsc (meaning all disc_addr)
1231 1233                                   * or matching discovered addr.
1232 1234                                   */
1233 1235                                  if ((addr_dsc == NULL) ||
1234 1236                                      (bcmp(addr_dsc, &isp->sess_discovered_addr,
1235 1237                                      SIZEOF_SOCKADDR(
1236 1238                                      &isp->sess_discovered_addr.sin)) == 0)) {
1237 1239                                          try_destroy = B_TRUE;
1238 1240                                  } else {
1239 1241                                          try_destroy = B_FALSE;
1240 1242                                  }
1241 1243                          } else if (method == iSCSIDiscoveryMethodStatic) {
1242 1244                                  /*
1243 1245                                   * If NULL addr_dsc (meaning all disc_addr)
1244 1246                                   * or matching active connection.
1245 1247                                   */
1246 1248                                  if ((addr_dsc == NULL) ||
1247 1249                                      ((isp->sess_conn_act != NULL) &&
1248 1250                                      (bcmp(addr_dsc,
1249 1251                                      &isp->sess_conn_act->conn_base_addr.sin,
1250 1252                                      SIZEOF_SOCKADDR(
1251 1253                                      &isp->sess_conn_act->conn_base_addr.sin))
1252 1254                                      == 0))) {
1253 1255                                          try_destroy = B_TRUE;
1254 1256                                  } else {
1255 1257                                          try_destroy = B_FALSE;
1256 1258                                  }
1257 1259                          } else {
1258 1260                                  /* Unknown discovery specified */
1259 1261                                  try_destroy = B_TRUE;
1260 1262                          }
1261 1263  
1262 1264                          if (try_destroy == B_TRUE &&
1263 1265                              isp->sess_boot == B_FALSE) {
1264 1266                                  (void) strcpy(name, (char *)isp->sess_name);
1265 1267                                  status = iscsi_sess_destroy(isp);
1266 1268                                  if (ISCSI_SUCCESS(status)) {
1267 1269                                          iscsid_remove_target_param(name);
1268 1270                                          isp = ihp->hba_sess_list;
1269 1271                                  } else if (status == ISCSI_STATUS_BUSY) {
1270 1272                                          /*
1271 1273                                           * The most likely destroy failure
1272 1274                                           * is that ndi/mdi offline failed.
1273 1275                                           * This means that the resource is
1274 1276                                           * in_use/busy.
1275 1277                                           */
1276 1278                                          cmn_err(CE_NOTE, "iscsi session(%d) - "
1277 1279                                              "resource is in use\n",
1278 1280                                              isp->sess_oid);
1279 1281                                          isp = isp->sess_next;
1280 1282                                          rtn = B_FALSE;
1281 1283                                  } else {
1282 1284                                          cmn_err(CE_NOTE, "iscsi session(%d) - "
1283 1285                                              "session logout failed (%d)\n",
1284 1286                                              isp->sess_oid, status);
1285 1287                                          isp = isp->sess_next;
1286 1288                                          rtn = B_FALSE;
1287 1289                                  }
1288 1290                          } else {
1289 1291                                  isp = isp->sess_next;
1290 1292                          }
1291 1293                  } else {
1292 1294                          isp = isp->sess_next;
1293 1295                  }
1294 1296          }
1295 1297          rw_exit(&ihp->hba_sess_list_rwlock);
1296 1298          return (rtn);
1297 1299  }
1298 1300  
1299 1301  
1300 1302  /*
1301 1303   * iscsid_login_tgt - request target(s) to login
1302 1304   */
1303 1305  boolean_t
1304 1306  iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name,
1305 1307      iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc)
1306 1308  {
1307 1309          boolean_t               rtn             = B_FALSE;
1308 1310          iscsi_sess_t            *isp            = NULL;
1309 1311          iscsi_sess_list_t       *isp_list       = NULL;
1310 1312          iscsi_sess_list_t       *last_sess      = NULL;
1311 1313          iscsi_sess_list_t       *cur_sess       = NULL;
1312 1314          int                     total           = 0;
1313 1315          ddi_taskq_t             *login_taskq    = NULL;
1314 1316          char                    taskq_name[ISCSI_TH_MAX_NAME_LEN] = {0};
1315 1317          time_t                  time_stamp;
1316 1318  
1317 1319          ASSERT(ihp != NULL);
1318 1320  
1319 1321          rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
1320 1322          /* Loop thru sessions */
1321 1323          isp = ihp->hba_sess_list;
1322 1324          while (isp != NULL) {
1323 1325                  boolean_t try_online;
1324 1326                  if (!(method & iSCSIDiscoveryMethodBoot)) {
1325 1327                          if (target_name == NULL) {
1326 1328                                  if (method == iSCSIDiscoveryMethodUnknown) {
1327 1329                                          /* unknown method mean login to all */
1328 1330                                          try_online = B_TRUE;
1329 1331                                  } else if (isp->sess_discovered_by & method) {
1330 1332                                          if ((method ==
1331 1333                                              iSCSIDiscoveryMethodISNS) ||
1332 1334                                              (method ==
1333 1335                                              iSCSIDiscoveryMethodSendTargets)) {
1334 1336  #define SESS_DISC_ADDR  isp->sess_discovered_addr.sin
1335 1337                                                  if ((addr_dsc == NULL) ||
1336 1338                                                      (bcmp(
1337 1339                                                      &isp->sess_discovered_addr,
1338 1340                                                      addr_dsc, SIZEOF_SOCKADDR(
1339 1341                                                      &SESS_DISC_ADDR))
1340 1342                                                      == 0)) {
1341 1343                                                          /*
1342 1344                                                           * iSNS or sendtarget
1343 1345                                                           * discovery and
1344 1346                                                           * discovery address
1345 1347                                                           * is NULL or match
1346 1348                                                           */
1347 1349                                                          try_online = B_TRUE;
1348 1350                                                  } else {
1349 1351                                                  /* addr_dsc not a match */
1350 1352                                                          try_online = B_FALSE;
1351 1353                                                  }
1352 1354  #undef SESS_DISC_ADDR
1353 1355                                          } else {
1354 1356                                                  /* static configuration */
1355 1357                                                  try_online = B_TRUE;
1356 1358                                          }
1357 1359                                  } else {
1358 1360                                          /* method not a match */
1359 1361                                          try_online = B_FALSE;
1360 1362                                  }
1361 1363                          } else if (strcmp(target_name,
1362 1364                              (char *)isp->sess_name) == 0) {
1363 1365                                  /* target_name match */
1364 1366                                  try_online = B_TRUE;
1365 1367                          } else {
1366 1368                                  /* target_name not a match */
1367 1369                                  try_online = B_FALSE;
1368 1370                          }
1369 1371                  } else {
1370 1372                          /*
1371 1373                           * online the boot session.
1372 1374                           */
1373 1375                          if (isp->sess_boot == B_TRUE) {
1374 1376                                  try_online = B_TRUE;
1375 1377                          }
1376 1378                  }
1377 1379  
1378 1380                  if (try_online == B_TRUE &&
1379 1381                      isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1380 1382                          total++;
1381 1383                          /* Copy these sessions to the list. */
1382 1384                          if (isp_list == NULL) {
1383 1385                                  isp_list =
1384 1386                                      (iscsi_sess_list_t *)kmem_zalloc(
1385 1387                                      sizeof (iscsi_sess_list_t), KM_SLEEP);
1386 1388                                  last_sess = isp_list;
1387 1389                                  last_sess->session = isp;
1388 1390                                  last_sess->next = NULL;
1389 1391                          } else {
1390 1392                                  last_sess->next =
1391 1393                                      (iscsi_sess_list_t *)kmem_zalloc(
1392 1394                                      sizeof (iscsi_sess_list_t), KM_SLEEP);
1393 1395                                  last_sess->next->session = isp;
1394 1396                                  last_sess->next->next = NULL;
1395 1397                                  last_sess = last_sess->next;
1396 1398                          }
1397 1399                          rtn = B_TRUE;
1398 1400                  }
1399 1401  
1400 1402                  isp = isp->sess_next;
1401 1403          }
1402 1404  
1403 1405          if (total > 0) {
1404 1406                  time_stamp = ddi_get_time();
1405 1407                  (void) snprintf(taskq_name, (ISCSI_TH_MAX_NAME_LEN - 1),
1406 1408                      "login_queue.%lx", time_stamp);
1407 1409  
1408 1410                  login_taskq = ddi_taskq_create(ihp->hba_dip,
1409 1411                      taskq_name, total, TASKQ_DEFAULTPRI, 0);
1410 1412                  if (login_taskq == NULL) {
1411 1413                          while (isp_list != NULL) {
1412 1414                                  cur_sess = isp_list;
1413 1415                                  isp_list = isp_list->next;
1414 1416                                  kmem_free(cur_sess, sizeof (iscsi_sess_list_t));
1415 1417                          }
1416 1418                          rtn = B_FALSE;
1417 1419                          rw_exit(&ihp->hba_sess_list_rwlock);
1418 1420                          return (rtn);
1419 1421                  }
1420 1422  
1421 1423                  for (cur_sess = isp_list; cur_sess != NULL;
1422 1424                      cur_sess = cur_sess->next) {
1423 1425                          if (ddi_taskq_dispatch(login_taskq,
1424 1426                              iscsi_sess_online, (void *)cur_sess->session,
1425 1427                              DDI_SLEEP) != DDI_SUCCESS) {
1426 1428                                  cmn_err(CE_NOTE, "Can't dispatch the task "
1427 1429                                      "for login to the target: %s",
1428 1430                                      cur_sess->session->sess_name);
1429 1431                          }
1430 1432                  }
1431 1433  
1432 1434                  ddi_taskq_wait(login_taskq);
1433 1435                  ddi_taskq_destroy(login_taskq);
1434 1436                  while (isp_list != NULL) {
1435 1437                          cur_sess = isp_list;
1436 1438                          isp_list = isp_list->next;
1437 1439                          kmem_free(cur_sess, sizeof (iscsi_sess_list_t));
1438 1440                  }
1439 1441  
1440 1442          }
1441 1443  
1442 1444          rw_exit(&ihp->hba_sess_list_rwlock);
1443 1445          return (rtn);
1444 1446  }
1445 1447  
1446 1448  /*
1447 1449   * +--------------------------------------------------------------------+
1448 1450   * | Local Helper Functions                                             |
1449 1451   * +--------------------------------------------------------------------+
1450 1452   */
1451 1453  
1452 1454  /*
1453 1455   * iscsid_init_config -- initialize configuration parameters of iSCSI initiator
1454 1456   */
1455 1457  static boolean_t
1456 1458  iscsid_init_config(iscsi_hba_t *ihp)
1457 1459  {
1458 1460          iscsi_param_set_t       ips;
1459 1461          void *v = NULL;
1460 1462          char *name;
1461 1463          char *initiatorName;
1462 1464          persistent_param_t      pp;
1463 1465          persistent_tunable_param_t pparam;
1464 1466          uint32_t                param_id;
1465 1467          int                     rc;
1466 1468  
1467 1469          /* allocate memory to hold initiator names */
1468 1470          initiatorName = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1469 1471  
1470 1472          /*
1471 1473           * initialize iSCSI initiator name
1472 1474           */
1473 1475          bzero(&ips, sizeof (ips));
1474 1476          if (persistent_initiator_name_get(initiatorName,
1475 1477              ISCSI_MAX_NAME_LEN) == B_TRUE) {
1476 1478                  ips.s_vers      = ISCSI_INTERFACE_VERSION;
1477 1479                  ips.s_param     = ISCSI_LOGIN_PARAM_INITIATOR_NAME;
1478 1480  
1479 1481                  if (iscsiboot_prop && !iscsi_cmp_boot_ini_name(initiatorName)) {
1480 1482                          (void) strncpy(initiatorName,
1481 1483                              (const char *)iscsiboot_prop->boot_init.ini_name,
1482 1484                              ISCSI_MAX_NAME_LEN);
1483 1485                          (void) strncpy((char *)ips.s_value.v_name,
1484 1486                              (const char *)iscsiboot_prop->boot_init.ini_name,
1485 1487                              sizeof (ips.s_value.v_name));
1486 1488                          (void) iscsi_set_params(&ips, ihp, B_TRUE);
1487 1489                          /* use default tunable value */
1488 1490                          ihp->hba_tunable_params.recv_login_rsp_timeout =
1489 1491                              ISCSI_DEFAULT_RX_TIMEOUT_VALUE;
1490 1492                          ihp->hba_tunable_params.polling_login_delay =
1491 1493                              ISCSI_DEFAULT_LOGIN_POLLING_DELAY;
1492 1494                          ihp->hba_tunable_params.conn_login_max =
1493 1495                              ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX;
1494 1496                          cmn_err(CE_NOTE, "Set initiator's name"
1495 1497                              " from firmware");
1496 1498                  } else {
1497 1499                          (void) strncpy((char *)ips.s_value.v_name,
1498 1500                              initiatorName, sizeof (ips.s_value.v_name));
1499 1501  
1500 1502                          (void) iscsi_set_params(&ips, ihp, B_FALSE);
1501 1503                          if (persistent_get_tunable_param(initiatorName,
1502 1504                              &pparam) == B_FALSE) {
1503 1505                                  /* use default value */
1504 1506                                  pparam.p_params.recv_login_rsp_timeout =
1505 1507                                      ISCSI_DEFAULT_RX_TIMEOUT_VALUE;
1506 1508                                  pparam.p_params.polling_login_delay =
1507 1509                                      ISCSI_DEFAULT_LOGIN_POLLING_DELAY;
1508 1510                                  pparam.p_params.conn_login_max =
1509 1511                                      ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX;
1510 1512                          }
1511 1513                          bcopy(&pparam.p_params, &ihp->hba_tunable_params,
1512 1514                              sizeof (iscsi_tunable_params_t));
1513 1515                  }
1514 1516          } else {
1515 1517                  /*
1516 1518                   * if no initiator-node name available it is most
1517 1519                   * likely due to a fresh install, or the persistent
1518 1520                   * store is not working correctly. Set
1519 1521                   * a default initiator name so that the initiator can
1520 1522                   * be brought up properly.
1521 1523                   */
1522 1524                  iscsid_set_default_initiator_node_settings(ihp, B_FALSE);
1523 1525                  (void) strncpy(initiatorName, (const char *)ihp->hba_name,
1524 1526                      ISCSI_MAX_NAME_LEN);
1525 1527          }
1526 1528  
1527 1529          /*
1528 1530           * initialize iSCSI initiator alias (if any)
1529 1531           */
1530 1532          bzero(&ips, sizeof (ips));
1531 1533          if (persistent_alias_name_get((char *)ips.s_value.v_name,
1532 1534              sizeof (ips.s_value.v_name)) == B_TRUE) {
1533 1535                  ips.s_param     = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS;
1534 1536                  (void) iscsi_set_params(&ips, ihp, B_FALSE);
1535 1537          } else {
1536 1538                  /* EMPTY */
1537 1539                  /* No alias defined - not a problem. */
1538 1540          }
1539 1541  
1540 1542          /*
1541 1543           * load up the overriden iSCSI initiator parameters
1542 1544           */
1543 1545          name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1544 1546          persistent_param_lock();
1545 1547          v = NULL;
1546 1548          while (persistent_param_next(&v, name, &pp) == B_TRUE) {
1547 1549                  if (strncmp(name, initiatorName, ISCSI_MAX_NAME_LEN) == 0) {
1548 1550                          ips.s_oid = ihp->hba_oid;
1549 1551                          ips.s_vers = ISCSI_INTERFACE_VERSION;
1550 1552                          for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
1551 1553                              param_id++) {
1552 1554                                  if (pp.p_bitmap & (1 << param_id)) {
1553 1555                                          rc = iscsid_copyto_param_set(param_id,
1554 1556                                              &pp.p_params, &ips);
1555 1557                                          if (rc == 0) {
1556 1558                                                  rc = iscsi_set_params(&ips,
1557 1559                                                      ihp, B_FALSE);
1558 1560                                          }
1559 1561                                          if (rc != 0) {
1560 1562                                                  /* note error but continue  */
1561 1563                                                  cmn_err(CE_NOTE,
1562 1564                                                      "Failed to set "
1563 1565                                                      "param %d for OID %d",
1564 1566                                                      ips.s_param, ips.s_oid);
1565 1567                                          }
1566 1568                                  }
1567 1569                          } /* END for() */
1568 1570                          if (iscsiboot_prop &&
1569 1571                              iscsi_chk_bootlun_mpxio(ihp)) {
1570 1572                                  (void) iscsi_reconfig_boot_sess(ihp);
1571 1573                          }
1572 1574                          break;
1573 1575                  }
1574 1576          } /* END while() */
1575 1577          persistent_param_unlock();
1576 1578  
1577 1579          kmem_free(initiatorName, ISCSI_MAX_NAME_LEN);
1578 1580          kmem_free(name, ISCSI_MAX_NAME_LEN);
1579 1581          return (B_TRUE);
1580 1582  }
1581 1583  
1582 1584  
1583 1585  /*
1584 1586   * iscsid_init_targets -- Load up the driver with known static targets and
1585 1587   * targets whose parameters have been modified.
1586 1588   *
1587 1589   * This is done so that the CLI can find a list of targets the driver
1588 1590   * currently knows about.
1589 1591   *
1590 1592   * The driver doesn't need to log into these targets.  Log in is done based
1591 1593   * upon the enabled discovery methods.
1592 1594   */
1593 1595  static boolean_t
1594 1596  iscsid_init_targets(iscsi_hba_t *ihp)
1595 1597  {
1596 1598          void                    *v = NULL;
1597 1599          char                    *name;
1598 1600          iscsi_param_set_t       ips;
1599 1601          persistent_param_t      pp;
1600 1602          char                    *iname;
1601 1603          uint32_t                param_id;
1602 1604          int                     rc;
1603 1605  
1604 1606          ASSERT(ihp != NULL);
1605 1607  
1606 1608          /* allocate memory to hold target names */
1607 1609          name = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1608 1610  
1609 1611          /*
1610 1612           * load up targets whose parameters have been overriden
1611 1613           */
1612 1614  
1613 1615          /* ---- only need to be set once ---- */
1614 1616          bzero(&ips, sizeof (ips));
1615 1617          ips.s_vers = ISCSI_INTERFACE_VERSION;
1616 1618  
1617 1619          /* allocate memory to hold initiator name */
1618 1620          iname = kmem_zalloc(ISCSI_MAX_NAME_LEN, KM_SLEEP);
1619 1621          (void) persistent_initiator_name_get(iname, ISCSI_MAX_NAME_LEN);
1620 1622  
1621 1623          persistent_param_lock();
1622 1624          v = NULL;
1623 1625          while (persistent_param_next(&v, name, &pp) == B_TRUE) {
1624 1626  
1625 1627                  if (strncmp(iname, name, ISCSI_MAX_NAME_LEN) == 0) {
1626 1628                          /*
1627 1629                           * target name matched initiator's name so,
1628 1630                           * continue to next target.  Initiator's
1629 1631                           * parmeters have already been set.
1630 1632                           */
1631 1633                          continue;
1632 1634                  }
1633 1635  
1634 1636                  if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
1635 1637                      !iscsi_chk_bootlun_mpxio(ihp)) {
1636 1638                          /*
1637 1639                           * boot target is not mpxio enabled
1638 1640                           * simply ignore these overriden parameters
1639 1641                           */
1640 1642                          continue;
1641 1643                  }
1642 1644  
1643 1645                  ips.s_oid = iscsi_targetparam_get_oid((unsigned char *)name);
1644 1646  
1645 1647                  for (param_id = 0; param_id < ISCSI_NUM_LOGIN_PARAM;
1646 1648                      param_id++) {
1647 1649                          if (pp.p_bitmap & (1 << param_id)) {
1648 1650                                  rc = iscsid_copyto_param_set(param_id,
1649 1651                                      &pp.p_params, &ips);
1650 1652                                  if (rc == 0) {
1651 1653                                          rc = iscsi_set_params(&ips,
1652 1654                                              ihp, B_FALSE);
1653 1655                                  }
1654 1656                                  if (rc != 0) {
1655 1657                                          /* note error but continue  ---- */
1656 1658                                          cmn_err(CE_NOTE, "Failed to set "
1657 1659                                              "param %d for OID %d",
1658 1660                                              ips.s_param, ips.s_oid);
1659 1661                                  }
1660 1662                          }
1661 1663                  } /* END for() */
1662 1664                  if (iscsiboot_prop && iscsi_cmp_boot_tgt_name(name) &&
1663 1665                      iscsi_chk_bootlun_mpxio(ihp)) {
1664 1666                          (void) iscsi_reconfig_boot_sess(ihp);
1665 1667                  }
1666 1668          } /* END while() */
1667 1669          persistent_param_unlock();
1668 1670  
1669 1671          kmem_free(iname, ISCSI_MAX_NAME_LEN);
1670 1672          kmem_free(name, ISCSI_MAX_NAME_LEN);
1671 1673  
1672 1674          return (B_TRUE);
1673 1675  }
1674 1676  
1675 1677  
1676 1678  /*
1677 1679   * iscsid_thread_static -- If static discovery is enabled, this routine obtains
1678 1680   * all statically configured targets from the peristent store and issues a
1679 1681   * login request to the driver.
1680 1682   */
1681 1683  /* ARGSUSED */
1682 1684  static void
1683 1685  iscsid_thread_static(iscsi_thread_t *thread, void *p)
1684 1686  {
1685 1687          iSCSIDiscoveryMethod_t  dm;
1686 1688          entry_t                 entry;
1687 1689          char                    name[ISCSI_MAX_NAME_LEN];
1688 1690          void                    *v = NULL;
1689 1691          iscsi_hba_t             *ihp = (iscsi_hba_t *)p;
1690 1692  
1691 1693          while (iscsi_thread_wait(thread, -1) != 0) {
1692 1694                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_TRUE);
1693 1695  
1694 1696                  /* ---- ensure static target discovery is enabled ---- */
1695 1697                  dm = persistent_disc_meth_get();
1696 1698                  if ((dm & iSCSIDiscoveryMethodStatic) == 0) {
1697 1699                          cmn_err(CE_NOTE,
1698 1700                              "iscsi discovery failure - "
1699 1701                              "StaticTargets method is not enabled");
1700 1702                          iscsi_discovery_event(ihp,
1701 1703                              iSCSIDiscoveryMethodStatic, B_FALSE);
1702 1704                          continue;
1703 1705                  }
1704 1706  
1705 1707                  /*
1706 1708                   * walk list of the statically configured targets from the
1707 1709                   * persistent store
1708 1710                   */
1709 1711                  v = NULL;
1710 1712                  persistent_static_addr_lock();
1711 1713                  while (persistent_static_addr_next(&v, name, &entry) ==
1712 1714                      B_TRUE) {
1713 1715                          iscsi_sockaddr_t addr;
1714 1716  
1715 1717                          iscsid_addr_to_sockaddr(entry.e_insize,
1716 1718                              &(entry.e_u), entry.e_port, &addr.sin);
1717 1719  
1718 1720                          (void) iscsid_add(ihp, iSCSIDiscoveryMethodStatic,
1719 1721                              &addr.sin, name, entry.e_tpgt, &addr.sin);
1720 1722                  }
1721 1723                  persistent_static_addr_unlock();
1722 1724                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodStatic, B_FALSE);
1723 1725          }
1724 1726  }
1725 1727  
1726 1728  
1727 1729  /*
1728 1730   * iscsid_thread_sendtgts -- If SendTargets discovery is enabled, this routine
1729 1731   * obtains all target discovery addresses configured from the peristent store
1730 1732   * and probe the IP/port addresses for possible targets.  It will then issue
1731 1733   * a login request to the driver for all discoveryed targets.
1732 1734   */
1733 1735  static void
1734 1736  iscsid_thread_sendtgts(iscsi_thread_t *thread, void *p)
1735 1737  {
1736 1738          iscsi_hba_t             *ihp = (iscsi_hba_t *)p;
1737 1739          iSCSIDiscoveryMethod_t  dm;
1738 1740          entry_t                 entry;
1739 1741          void                    *v = NULL;
1740 1742  
1741 1743          while (iscsi_thread_wait(thread, -1) != 0) {
1742 1744                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets,
1743 1745                      B_TRUE);
1744 1746  
1745 1747                  /* ---- ensure SendTargets discovery is enabled ---- */
1746 1748                  dm = persistent_disc_meth_get();
1747 1749                  if ((dm & iSCSIDiscoveryMethodSendTargets) == 0) {
1748 1750                          cmn_err(CE_NOTE,
1749 1751                              "iscsi discovery failure - "
1750 1752                              "SendTargets method is not enabled");
1751 1753                          iscsi_discovery_event(ihp,
1752 1754                              iSCSIDiscoveryMethodSendTargets, B_FALSE);
1753 1755                          continue;
1754 1756                  }
1755 1757                  /*
1756 1758                   * walk list of the SendTarget discovery addresses from the
1757 1759                   * persistent store
1758 1760                   */
1759 1761                  v = NULL;
1760 1762                  persistent_disc_addr_lock();
1761 1763                  while (persistent_disc_addr_next(&v, &entry) == B_TRUE) {
1762 1764                          iscsid_do_sendtgts(&entry);
1763 1765                  }
1764 1766                  persistent_disc_addr_unlock();
1765 1767  
1766 1768                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSendTargets,
1767 1769                      B_FALSE);
1768 1770          }
1769 1771  }
1770 1772  
1771 1773  /*
1772 1774   * iscsid_thread_slp -- If SLP discovery is enabled,  this routine provides
1773 1775   * the SLP discovery service.
1774 1776   */
1775 1777  static void
1776 1778  iscsid_thread_slp(iscsi_thread_t *thread, void *p)
1777 1779  {
1778 1780          iscsi_hba_t  *ihp = (iscsi_hba_t *)p;
1779 1781  
1780 1782          do {
1781 1783                  /*
1782 1784                   * Even though we don't have support for SLP at this point
1783 1785                   * we'll send the events if someone has enabled this thread.
1784 1786                   * If this is not done the daemon waiting for discovery to
1785 1787                   * complete will pause forever holding up the boot process.
1786 1788                   */
1787 1789                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_TRUE);
1788 1790                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodSLP, B_FALSE);
1789 1791          } while (iscsi_thread_wait(thread, -1) != 0);
1790 1792  }
1791 1793  
1792 1794  /*
1793 1795   * iscsid_thread_isns --
1794 1796   */
1795 1797  static void
1796 1798  iscsid_thread_isns(iscsi_thread_t *thread, void *ptr)
1797 1799  {
1798 1800          iscsi_hba_t             *ihp = (iscsi_hba_t *)ptr;
1799 1801          iSCSIDiscoveryMethod_t  dm;
1800 1802  
1801 1803          while (iscsi_thread_wait(thread, -1) != 0) {
1802 1804                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_TRUE);
1803 1805  
1804 1806                  /* ---- ensure iSNS discovery is enabled ---- */
1805 1807                  dm = persistent_disc_meth_get();
1806 1808                  if ((dm & iSCSIDiscoveryMethodISNS) == 0) {
1807 1809                          cmn_err(CE_NOTE,
1808 1810                              "iscsi discovery failure - "
1809 1811                              "iSNS method is not enabled");
1810 1812                          iscsi_discovery_event(ihp,
1811 1813                              iSCSIDiscoveryMethodISNS, B_FALSE);
1812 1814                          continue;
1813 1815                  }
1814 1816  
1815 1817                  (void) isns_reg(ihp->hba_isid,
1816 1818                      ihp->hba_name,
1817 1819                      ISCSI_MAX_NAME_LEN,
1818 1820                      ihp->hba_alias,
1819 1821                      ISCSI_MAX_NAME_LEN,
1820 1822                      ISNS_INITIATOR_NODE_TYPE,
1821 1823                      isns_scn_callback);
1822 1824                  iscsid_do_isns_query(ihp);
1823 1825                  iscsi_discovery_event(ihp, iSCSIDiscoveryMethodISNS, B_FALSE);
1824 1826          }
1825 1827  
1826 1828          /* Thread stopped. Deregister from iSNS servers(s). */
1827 1829          (void) isns_dereg(ihp->hba_isid, ihp->hba_name);
1828 1830  }
1829 1831  
1830 1832  
1831 1833  /*
1832 1834   * iscsid_threads_create -- Creates all the discovery threads.
1833 1835   */
1834 1836  static void
1835 1837  iscsid_threads_create(iscsi_hba_t *ihp)
1836 1838  {
1837 1839          iscsid_thr_table        *t;
1838 1840  
1839 1841          /*
1840 1842           * start a thread for each discovery method
1841 1843           */
1842 1844          for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown;
1843 1845              t++) {
1844 1846                  if (t->thr_id == NULL) {
1845 1847                          t->thr_id = iscsi_thread_create(ihp->hba_dip, t->name,
1846 1848                              t->func_start, ihp);
1847 1849                  }
1848 1850          }
1849 1851  }
1850 1852  
1851 1853  /*
1852 1854   * iscsid_threads_destroy -- Destroys all the discovery threads.
1853 1855   */
1854 1856  static void
1855 1857  iscsid_threads_destroy(void)
1856 1858  {
1857 1859          iscsid_thr_table        *t;
1858 1860  
1859 1861          for (t = &iscsid_thr[0]; t->method != iSCSIDiscoveryMethodUnknown;
1860 1862              t++) {
1861 1863                  if (t->thr_id != NULL) {
1862 1864                          iscsi_thread_destroy(t->thr_id);
1863 1865                          t->thr_id = NULL;
1864 1866                  }
1865 1867          }
1866 1868  }
1867 1869  
1868 1870  /*
1869 1871   * iscsid_copyto_param_set - helper function for iscsid_init_params.
1870 1872   */
1871 1873  static int
1872 1874  iscsid_copyto_param_set(uint32_t param_id, iscsi_login_params_t *params,
1873 1875      iscsi_param_set_t *ipsp)
1874 1876  {
1875 1877          int rtn = 0;
1876 1878  
1877 1879          if (param_id >= ISCSI_NUM_LOGIN_PARAM) {
1878 1880                  return (EINVAL);
1879 1881          }
1880 1882  
1881 1883          switch (param_id) {
1882 1884  
1883 1885          /*
1884 1886           * Boolean parameters
1885 1887           */
1886 1888          case ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER:
1887 1889                  ipsp->s_value.v_bool = params->data_pdu_in_order;
1888 1890                  break;
1889 1891          case ISCSI_LOGIN_PARAM_IMMEDIATE_DATA:
1890 1892                  ipsp->s_value.v_bool = params->immediate_data;
1891 1893                  break;
1892 1894          case ISCSI_LOGIN_PARAM_INITIAL_R2T:
1893 1895                  ipsp->s_value.v_bool = params->initial_r2t;
1894 1896                  break;
1895 1897          case ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER:
1896 1898                  ipsp->s_value.v_bool = params->data_pdu_in_order;
1897 1899                  break;
1898 1900  
1899 1901          /*
1900 1902           * Integer parameters
1901 1903           */
1902 1904          case ISCSI_LOGIN_PARAM_HEADER_DIGEST:
1903 1905                  ipsp->s_value.v_integer = params->header_digest;
1904 1906                  break;
1905 1907          case ISCSI_LOGIN_PARAM_DATA_DIGEST:
1906 1908                  ipsp->s_value.v_integer = params->data_digest;
1907 1909                  break;
1908 1910          case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN:
1909 1911                  ipsp->s_value.v_integer = params->default_time_to_retain;
1910 1912                  break;
1911 1913          case ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT:
1912 1914                  ipsp->s_value.v_integer = params->default_time_to_wait;
1913 1915                  break;
1914 1916          case ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH:
1915 1917                  ipsp->s_value.v_integer = params->max_recv_data_seg_len;
1916 1918                  break;
1917 1919          case ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH:
1918 1920                  ipsp->s_value.v_integer = params->first_burst_length;
1919 1921                  break;
1920 1922          case ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH:
1921 1923                  ipsp->s_value.v_integer =  params->max_burst_length;
1922 1924                  break;
1923 1925  
1924 1926          /*
1925 1927           * Integer parameters which currently are unsettable
1926 1928           */
1927 1929          case ISCSI_LOGIN_PARAM_MAX_CONNECTIONS:
1928 1930          case ISCSI_LOGIN_PARAM_OUTSTANDING_R2T:
1929 1931          case ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL:
1930 1932          /* ---- drop through to default case ---- */
1931 1933          default:
1932 1934                  rtn = EINVAL;
1933 1935                  break;
1934 1936          }
1935 1937  
1936 1938          /* if all is well, set the parameter identifier */
1937 1939          if (rtn == 0) {
1938 1940                  ipsp->s_param = param_id;
1939 1941          }
1940 1942  
1941 1943          return (rtn);
1942 1944  }
1943 1945  
1944 1946  /*
1945 1947   * iscsid_add_pg_list_to_cache - Add portal groups in the list to the
1946 1948   * discovery cache.
1947 1949   */
1948 1950  static void
1949 1951  iscsid_add_pg_list_to_cache(iscsi_hba_t *ihp,
1950 1952      isns_portal_group_list_t *pg_list)
1951 1953  {
1952 1954          int                 i;
1953 1955  
1954 1956          for (i = 0; i < pg_list->pg_out_cnt; i++) {
1955 1957                  iscsi_sockaddr_t addr_dsc;
1956 1958                  iscsi_sockaddr_t addr_tgt;
1957 1959  
1958 1960                  iscsid_addr_to_sockaddr(
1959 1961                      pg_list->pg_list[i].isns_server_ip.i_insize,
1960 1962                      &pg_list->pg_list[i].isns_server_ip.i_addr,
1961 1963                      pg_list->pg_list[i].isns_server_port,
1962 1964                      &addr_dsc.sin);
1963 1965                  iscsid_addr_to_sockaddr(
1964 1966                      pg_list->pg_list[i].insize,
1965 1967                      &pg_list->pg_list[i].pg_ip_addr,
1966 1968                      pg_list->pg_list[i].pg_port,
1967 1969                      &addr_tgt.sin);
1968 1970  
  
    | 
      ↓ open down ↓ | 
    1936 lines elided | 
    
      ↑ open up ↑ | 
  
1969 1971                  (void) iscsid_add(ihp, iSCSIDiscoveryMethodISNS, &addr_dsc.sin,
1970 1972                      (char *)pg_list->pg_list[i].pg_iscsi_name,
1971 1973                      pg_list->pg_list[i].pg_tag, &addr_tgt.sin);
1972 1974          }
1973 1975  }
1974 1976  
1975 1977  /*
1976 1978   * set_initiator_name - set default initiator name and alias.
1977 1979   *
1978 1980   * This sets the default initiator name and alias.  The
1979      - * initiator name is composed of sun's reverse domain name
1980      - * and registration followed and a unique classifier.  This
1981      - * classifier is the mac address of the first NIC in the
     1981 + * initiator name is composed of vendor's reverse domain name
     1982 + * and registration date followed by a unique classifier.
     1983 + * This classifier is the mac address of the first NIC in the
1982 1984   * host and a timestamp to make sure the classifier is
1983 1985   * unique if the NIC is moved between hosts.  The alias
1984 1986   * is just the hostname.
1985 1987   */
1986 1988  void
1987 1989  iscsid_set_default_initiator_node_settings(iscsi_hba_t *ihp, boolean_t minimal)
1988 1990  {
1989 1991          int                 i;
1990 1992          time_t              x;
1991 1993          struct ether_addr   eaddr;
1992 1994          char                val[10];
1993 1995          iscsi_chap_props_t  *chap = NULL;
1994 1996  
1995 1997          /* Set default initiator-node name */
1996 1998          if (iscsiboot_prop && iscsiboot_prop->boot_init.ini_name != NULL) {
1997 1999                  (void) strncpy((char *)ihp->hba_name,
1998 2000                      (const char *)iscsiboot_prop->boot_init.ini_name,
1999 2001                      ISCSI_MAX_NAME_LEN);
2000 2002          } else {
2001      -                (void) snprintf((char *)ihp->hba_name,
2002      -                    ISCSI_MAX_NAME_LEN,
2003      -                    "iqn.1986-03.com.sun:01:");
     2003 +                (void) snprintf((char *)ihp->hba_name, ISCSI_MAX_NAME_LEN,
     2004 +                    "iqn.2005-07.com.nexenta:01:");
2004 2005  
2005 2006                  (void) localetheraddr(NULL, &eaddr);
2006 2007                  for (i = 0; i <  ETHERADDRL; i++) {
2007 2008                          (void) snprintf(val, sizeof (val), "%02x",
2008 2009                              eaddr.ether_addr_octet[i]);
2009 2010                          (void) strncat((char *)ihp->hba_name, val,
2010 2011                              ISCSI_MAX_NAME_LEN);
2011 2012                  }
2012 2013  
2013 2014                  /* Set default initiator-node alias */
2014 2015                  x = ddi_get_time();
2015 2016                  (void) snprintf(val, sizeof (val), ".%lx", x);
2016 2017                  (void) strncat((char *)ihp->hba_name, val, ISCSI_MAX_NAME_LEN);
2017 2018  
2018 2019                  if (ihp->hba_alias[0] == '\0') {
2019 2020                          (void) strncpy((char *)ihp->hba_alias,
2020 2021                              utsname.nodename, ISCSI_MAX_NAME_LEN);
2021 2022                          ihp->hba_alias_length = strlen((char *)ihp->hba_alias);
2022 2023                          if (minimal == B_FALSE) {
2023 2024                                  (void) persistent_alias_name_set(
2024 2025                                      (char *)ihp->hba_alias);
2025 2026                          }
2026 2027                  }
2027 2028          }
2028 2029  
2029 2030          if (minimal == B_TRUE) {
2030 2031                  return;
2031 2032          }
2032 2033  
2033 2034          (void) persistent_initiator_name_set((char *)ihp->hba_name);
2034 2035  
2035 2036          /* Set default initiator-node CHAP settings */
2036 2037          if (persistent_initiator_name_get((char *)ihp->hba_name,
2037 2038              ISCSI_MAX_NAME_LEN) == B_TRUE) {
2038 2039                  chap = (iscsi_chap_props_t *)kmem_zalloc(sizeof (*chap),
2039 2040                      KM_SLEEP);
2040 2041                  if (persistent_chap_get((char *)ihp->hba_name, chap) ==
2041 2042                      B_FALSE) {
2042 2043                          bcopy((char *)ihp->hba_name, chap->c_user,
2043 2044                              strlen((char *)ihp->hba_name));
2044 2045                          chap->c_user_len = strlen((char *)ihp->hba_name);
2045 2046                          (void) persistent_chap_set((char *)ihp->hba_name, chap);
2046 2047                  }
2047 2048                  kmem_free(chap, sizeof (*chap));
2048 2049          }
2049 2050  }
2050 2051  
2051 2052  static void
2052 2053  iscsid_remove_target_param(char *name)
2053 2054  {
2054 2055          persistent_param_t  *pparam;
2055 2056          uint32_t            t_oid;
2056 2057          iscsi_config_sess_t *ics;
2057 2058  
2058 2059          ASSERT(name != NULL);
2059 2060  
2060 2061          /*
2061 2062           * Remove target-param <-> target mapping.
2062 2063           * Only remove if there is not any overridden
2063 2064           * parameters in the persistent store
2064 2065           */
2065 2066          pparam = (persistent_param_t *)kmem_zalloc(sizeof (*pparam), KM_SLEEP);
2066 2067  
2067 2068          /*
2068 2069           * setup initial buffer for configured session
2069 2070           * information
2070 2071           */
2071 2072          ics = (iscsi_config_sess_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP);
2072 2073          ics->ics_in = 1;
2073 2074  
2074 2075          if ((persistent_param_get(name, pparam) == B_FALSE) &&
2075 2076              (persistent_get_config_session(name, ics) == B_FALSE))  {
2076 2077                  t_oid = iscsi_targetparam_get_oid((uchar_t *)name);
2077 2078                  (void) iscsi_targetparam_remove_target(t_oid);
2078 2079          }
2079 2080  
2080 2081          kmem_free(pparam, sizeof (*pparam));
2081 2082          pparam = NULL;
2082 2083          kmem_free(ics, sizeof (*ics));
2083 2084          ics = NULL;
2084 2085  }
2085 2086  
2086 2087  /*
2087 2088   * iscsid_addr_to_sockaddr - convert other types to struct sockaddr
2088 2089   */
2089 2090  void
2090 2091  iscsid_addr_to_sockaddr(int src_insize, void *src_addr, int src_port,
2091 2092      struct sockaddr *dst_addr)
2092 2093  {
2093 2094          ASSERT((src_insize == sizeof (struct in_addr)) ||
2094 2095              (src_insize == sizeof (struct in6_addr)));
2095 2096          ASSERT(src_addr != NULL);
2096 2097          ASSERT(dst_addr != NULL);
2097 2098  
2098 2099          bzero(dst_addr, sizeof (*dst_addr));
2099 2100  
2100 2101          /* translate discovery information */
2101 2102          if (src_insize == sizeof (struct in_addr)) {
2102 2103                  struct sockaddr_in *addr_in =
2103 2104                      (struct sockaddr_in *)dst_addr;
2104 2105                  addr_in->sin_family = AF_INET;
2105 2106                  bcopy(src_addr, &addr_in->sin_addr.s_addr,
2106 2107                      sizeof (struct in_addr));
2107 2108                  addr_in->sin_port = htons(src_port);
2108 2109          } else {
2109 2110                  struct sockaddr_in6 *addr_in6 =
2110 2111                      (struct sockaddr_in6 *)dst_addr;
2111 2112                  addr_in6->sin6_family = AF_INET6;
2112 2113                  bcopy(src_addr, &addr_in6->sin6_addr.s6_addr,
2113 2114                      sizeof (struct in6_addr));
2114 2115                  addr_in6->sin6_port = htons(src_port);
2115 2116          }
2116 2117  }
2117 2118  
2118 2119  /*
2119 2120   * iscsi_discovery_event -- send event associated with discovery operations
2120 2121   *
2121 2122   * Each discovery event has a start and end event. Which is sent is based
2122 2123   * on the boolean argument start with the obvious results.
2123 2124   */
2124 2125  static void
2125 2126  iscsi_discovery_event(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t m,
2126 2127      boolean_t start)
2127 2128  {
2128 2129          char    *subclass = NULL;
2129 2130  
2130 2131          mutex_enter(&ihp->hba_discovery_events_mutex);
2131 2132          switch (m) {
2132 2133          case iSCSIDiscoveryMethodStatic:
2133 2134                  if (start == B_TRUE) {
2134 2135                          subclass = ESC_ISCSI_STATIC_START;
2135 2136                  } else {
2136 2137                          ihp->hba_discovery_events |= iSCSIDiscoveryMethodStatic;
2137 2138                          subclass = ESC_ISCSI_STATIC_END;
2138 2139                  }
2139 2140                  break;
2140 2141  
2141 2142          case iSCSIDiscoveryMethodSendTargets:
2142 2143                  if (start == B_TRUE) {
2143 2144                          subclass = ESC_ISCSI_SEND_TARGETS_START;
2144 2145                  } else {
2145 2146                          ihp->hba_discovery_events |=
2146 2147                              iSCSIDiscoveryMethodSendTargets;
2147 2148                          subclass = ESC_ISCSI_SEND_TARGETS_END;
2148 2149                  }
2149 2150                  break;
2150 2151  
2151 2152          case iSCSIDiscoveryMethodSLP:
2152 2153                  if (start == B_TRUE) {
2153 2154                          subclass = ESC_ISCSI_SLP_START;
2154 2155                  } else {
2155 2156                          ihp->hba_discovery_events |= iSCSIDiscoveryMethodSLP;
2156 2157                          subclass = ESC_ISCSI_SLP_END;
2157 2158                  }
2158 2159                  break;
2159 2160  
2160 2161          case iSCSIDiscoveryMethodISNS:
2161 2162                  if (start == B_TRUE) {
2162 2163                          subclass = ESC_ISCSI_ISNS_START;
2163 2164                  } else {
2164 2165                          ihp->hba_discovery_events |= iSCSIDiscoveryMethodISNS;
2165 2166                          subclass = ESC_ISCSI_ISNS_END;
2166 2167                  }
2167 2168                  break;
2168 2169          }
2169 2170          mutex_exit(&ihp->hba_discovery_events_mutex);
2170 2171          iscsi_send_sysevent(ihp, EC_ISCSI, subclass, NULL);
2171 2172  }
2172 2173  
2173 2174  /*
2174 2175   * iscsi_send_sysevent -- send sysevent using specified class
2175 2176   */
2176 2177  void
2177 2178  iscsi_send_sysevent(
2178 2179      iscsi_hba_t *ihp,
2179 2180      char        *eventclass,
2180 2181      char        *subclass,
2181 2182      nvlist_t    *np)
2182 2183  {
2183 2184          (void) ddi_log_sysevent(ihp->hba_dip, DDI_VENDOR_SUNW, eventclass,
2184 2185              subclass, np, NULL, DDI_SLEEP);
2185 2186  }
2186 2187  
2187 2188  static boolean_t
2188 2189  iscsid_boot_init_config(iscsi_hba_t *ihp)
2189 2190  {
2190 2191          if (strlen((const char *)iscsiboot_prop->boot_init.ini_name) != 0) {
2191 2192                  bcopy(iscsiboot_prop->boot_init.ini_name,
2192 2193                      ihp->hba_name,
2193 2194                      strlen((const char *)iscsiboot_prop->boot_init.ini_name));
2194 2195          }
2195 2196          /* or using default login param for boot session */
2196 2197          return (B_TRUE);
2197 2198  }
2198 2199  
2199 2200  boolean_t
2200 2201  iscsi_reconfig_boot_sess(iscsi_hba_t *ihp)
2201 2202  {
2202 2203          iscsi_config_sess_t     *ics;
2203 2204          int                     idx;
2204 2205          iscsi_sess_t            *isp, *t_isp;
2205 2206          int                     isid, size;
2206 2207          char                    *name;
2207 2208          boolean_t               rtn = B_TRUE;
2208 2209          uint32_t                event_count;
2209 2210  
2210 2211          if (iscsiboot_prop == NULL) {
2211 2212                  return (B_FALSE);
2212 2213          }
2213 2214          size = sizeof (*ics);
2214 2215          ics = kmem_zalloc(size, KM_SLEEP);
2215 2216          ics->ics_in = 1;
2216 2217  
2217 2218          /* get information of number of sessions to be configured */
2218 2219          name = (char *)iscsiboot_prop->boot_tgt.tgt_name;
2219 2220          if (persistent_get_config_session(name, ics) == B_FALSE) {
2220 2221                  /*
2221 2222                   * No target information available to check
2222 2223                   * initiator information. Assume one session
2223 2224                   * by default.
2224 2225                   */
2225 2226                  name = (char *)iscsiboot_prop->boot_init.ini_name;
2226 2227                  if (persistent_get_config_session(name, ics) == B_FALSE) {
2227 2228                          ics->ics_out = 1;
2228 2229                          ics->ics_bound = B_TRUE;
2229 2230                  }
2230 2231          }
2231 2232  
2232 2233          /* get necessary information */
2233 2234          if (ics->ics_out > 1) {
2234 2235                  idx = ics->ics_out;
2235 2236                  size = ISCSI_SESSION_CONFIG_SIZE(ics->ics_out);
2236 2237                  kmem_free(ics, sizeof (*ics));
2237 2238  
2238 2239                  ics = kmem_zalloc(size, KM_SLEEP);
2239 2240                  ics->ics_in = idx;
2240 2241  
2241 2242                  /* get configured sessions information */
2242 2243                  if (persistent_get_config_session((char *)name,
2243 2244                      ics) != B_TRUE) {
2244 2245                          cmn_err(CE_NOTE, "session(%s) - "
2245 2246                              "failed to setup multiple sessions",
2246 2247                              name);
2247 2248                          kmem_free(ics, size);
2248 2249                          return (B_FALSE);
2249 2250                  }
2250 2251          }
2251 2252  
2252 2253          /* create a temporary session to keep boot session connective */
2253 2254          t_isp = iscsi_add_boot_sess(ihp, ISCSI_MAX_CONFIG_SESSIONS);
2254 2255          if (t_isp == NULL) {
2255 2256                  cmn_err(CE_NOTE, "session(%s) - "
2256 2257                      "failed to setup multiple sessions", name);
2257 2258                  rw_exit(&ihp->hba_sess_list_rwlock);
2258 2259                  kmem_free(ics, size);
2259 2260                  return (B_FALSE);
2260 2261          }
2261 2262  
2262 2263          /* destroy all old boot sessions */
2263 2264          rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
2264 2265          isp = ihp->hba_sess_list;
2265 2266          while (isp != NULL) {
2266 2267                  if (iscsi_chk_bootlun_mpxio(ihp) && isp->sess_boot) {
2267 2268                          if (isp->sess_isid[5] != ISCSI_MAX_CONFIG_SESSIONS) {
2268 2269                                  /*
2269 2270                                   * destroy all stale sessions
2270 2271                                   * except temporary boot session
2271 2272                                   */
2272 2273                                  if (ISCSI_SUCCESS(iscsi_sess_destroy(
2273 2274                                      isp))) {
2274 2275                                          isp = ihp->hba_sess_list;
2275 2276                                  } else {
2276 2277                                          /*
2277 2278                                           * couldn't destroy stale sessions
2278 2279                                           * at least poke it to disconnect
2279 2280                                           */
2280 2281                                          event_count = atomic_inc_32_nv(
2281 2282                                              &isp->sess_state_event_count);
2282 2283                                          iscsi_sess_enter_state_zone(isp);
2283 2284                                          iscsi_sess_state_machine(isp,
2284 2285                                              ISCSI_SESS_EVENT_N7, event_count);
2285 2286                                          iscsi_sess_exit_state_zone(isp);
2286 2287  
2287 2288                                          isp = isp->sess_next;
2288 2289                                          cmn_err(CE_NOTE, "session(%s) - "
2289 2290                                              "failed to setup multiple"
2290 2291                                              " sessions", name);
2291 2292                                  }
2292 2293                          } else {
2293 2294                                  isp = isp->sess_next;
2294 2295                          }
2295 2296                  } else {
2296 2297                          isp = isp->sess_next;
2297 2298                  }
2298 2299          }
2299 2300          rw_exit(&ihp->hba_sess_list_rwlock);
2300 2301  
2301 2302          for (isid = 0; isid < ics->ics_out; isid++) {
2302 2303                  isp = iscsi_add_boot_sess(ihp, isid);
2303 2304                  if (isp == NULL) {
2304 2305                          cmn_err(CE_NOTE, "session(%s) - failed to setup"
2305 2306                              " multiple sessions", name);
2306 2307                          rtn = B_FALSE;
2307 2308                          break;
2308 2309                  }
2309 2310          }
2310 2311          if (!rtn && (isid == 0)) {
2311 2312                  /*
2312 2313                   * fail to create any new boot session
2313 2314                   * so only the temporary session is alive
2314 2315                   * quit without destroying it
2315 2316                   */
2316 2317                  kmem_free(ics, size);
2317 2318                  return (rtn);
2318 2319          }
2319 2320  
2320 2321          rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
2321 2322          if (!ISCSI_SUCCESS(iscsi_sess_destroy(t_isp))) {
2322 2323                  /* couldn't destroy temp boot session */
2323 2324                  cmn_err(CE_NOTE, "session(%s) - "
2324 2325                      "failed to setup multiple sessions", name);
2325 2326                  rw_exit(&ihp->hba_sess_list_rwlock);
2326 2327                  rtn = B_FALSE;
2327 2328          }
2328 2329          rw_exit(&ihp->hba_sess_list_rwlock);
2329 2330  
2330 2331          kmem_free(ics, size);
2331 2332          return (rtn);
2332 2333  }
2333 2334  
2334 2335  static iscsi_sess_t *
2335 2336  iscsi_add_boot_sess(iscsi_hba_t *ihp, int isid)
2336 2337  {
2337 2338          iscsi_sess_t    *isp;
2338 2339          iscsi_conn_t    *icp;
2339 2340          uint_t          oid;
2340 2341  
2341 2342          iscsi_sockaddr_t        addr_dst;
2342 2343  
2343 2344          addr_dst.sin.sa_family = iscsiboot_prop->boot_tgt.sin_family;
2344 2345          if (addr_dst.sin.sa_family == AF_INET) {
2345 2346                  bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in4.s_addr,
2346 2347                      &addr_dst.sin4.sin_addr.s_addr, sizeof (struct in_addr));
2347 2348                  addr_dst.sin4.sin_port =
2348 2349                      htons(iscsiboot_prop->boot_tgt.tgt_port);
2349 2350          } else {
2350 2351                  bcopy(&iscsiboot_prop->boot_tgt.tgt_ip_u.u_in6.s6_addr,
2351 2352                      &addr_dst.sin6.sin6_addr.s6_addr,
2352 2353                      sizeof (struct in6_addr));
2353 2354                  addr_dst.sin6.sin6_port =
2354 2355                      htons(iscsiboot_prop->boot_tgt.tgt_port);
2355 2356          }
2356 2357  
2357 2358          rw_enter(&ihp->hba_sess_list_rwlock, RW_WRITER);
2358 2359          isp = iscsi_sess_create(ihp,
2359 2360              iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
2360 2361              (struct sockaddr *)&addr_dst,
2361 2362              (char *)iscsiboot_prop->boot_tgt.tgt_name,
2362 2363              ISCSI_DEFAULT_TPGT, isid, ISCSI_SESS_TYPE_NORMAL, &oid);
2363 2364          if (isp == NULL) {
2364 2365                  /* create temp booting session failed */
2365 2366                  rw_exit(&ihp->hba_sess_list_rwlock);
2366 2367                  return (NULL);
2367 2368          }
2368 2369          isp->sess_boot = B_TRUE;
2369 2370  
2370 2371          if (!ISCSI_SUCCESS(iscsi_conn_create((struct sockaddr *)&addr_dst,
2371 2372              isp, &icp))) {
2372 2373                  rw_exit(&ihp->hba_sess_list_rwlock);
2373 2374                  return (NULL);
2374 2375          }
2375 2376  
2376 2377          rw_exit(&ihp->hba_sess_list_rwlock);
2377 2378          /* now online created session */
2378 2379          if (iscsid_login_tgt(ihp, (char *)iscsiboot_prop->boot_tgt.tgt_name,
2379 2380              iSCSIDiscoveryMethodBoot|iSCSIDiscoveryMethodStatic,
2380 2381              (struct sockaddr *)&addr_dst) == B_FALSE) {
2381 2382                  return (NULL);
2382 2383          }
2383 2384  
2384 2385          return (isp);
2385 2386  }
2386 2387  
2387 2388  static void
2388 2389  iscsid_thread_boot_wd(iscsi_thread_t *thread, void *p)
2389 2390  {
2390 2391          int                     rc = 1;
2391 2392          iscsi_hba_t             *ihp = (iscsi_hba_t *)p;
2392 2393          boolean_t               reconfigured = B_FALSE;
2393 2394  
2394 2395          while (rc != 0) {
2395 2396                  if (iscsiboot_prop && (modrootloaded == 1)) {
2396 2397                          if (ihp->hba_persistent_loaded == B_FALSE) {
2397 2398                                  if (persistent_load() == B_TRUE) {
2398 2399                                          ihp->hba_persistent_loaded = B_TRUE;
2399 2400                                  }
2400 2401                          }
2401 2402                          if ((ihp->hba_persistent_loaded == B_TRUE) &&
2402 2403                              (reconfigured == B_FALSE)) {
2403 2404                                  if (iscsi_chk_bootlun_mpxio(ihp) == B_TRUE) {
2404 2405                                          (void) iscsi_reconfig_boot_sess(ihp);
2405 2406                                          iscsid_poke_discovery(ihp,
2406 2407                                              iSCSIDiscoveryMethodUnknown);
2407 2408                                          (void) iscsid_login_tgt(ihp, NULL,
2408 2409                                              iSCSIDiscoveryMethodUnknown, NULL);
2409 2410                                  }
2410 2411                                  reconfigured = B_TRUE;
2411 2412                          }
2412 2413                          break;
2413 2414                  }
2414 2415                  rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
2415 2416          }
2416 2417  }
2417 2418  
2418 2419  boolean_t
2419 2420  iscsi_cmp_boot_tgt_name(char *name)
2420 2421  {
2421 2422          if (iscsiboot_prop && (strncmp((const char *)name,
2422 2423              (const char *)iscsiboot_prop->boot_tgt.tgt_name,
2423 2424              ISCSI_MAX_NAME_LEN) == 0)) {
2424 2425                  return (B_TRUE);
2425 2426          } else {
2426 2427                  return (B_FALSE);
2427 2428          }
2428 2429  }
2429 2430  
2430 2431  boolean_t
2431 2432  iscsi_cmp_boot_ini_name(char *name)
2432 2433  {
2433 2434          if (iscsiboot_prop && (strncmp((const char *)name,
2434 2435              (const char *)iscsiboot_prop->boot_init.ini_name,
2435 2436              ISCSI_MAX_NAME_LEN) == 0)) {
2436 2437                  return (B_TRUE);
2437 2438          } else {
2438 2439                  return (B_FALSE);
2439 2440          }
2440 2441  }
2441 2442  
2442 2443  boolean_t
2443 2444  iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp)
2444 2445  {
2445 2446          iscsi_sess_t    *isp;
2446 2447          iscsi_lun_t     *ilp;
2447 2448          isp = ihp->hba_sess_list;
2448 2449          boolean_t       tgt_mpxio_enabled = B_FALSE;
2449 2450          boolean_t       bootlun_found = B_FALSE;
2450 2451          uint16_t    lun_num;
2451 2452  
2452 2453          if (iscsiboot_prop == NULL) {
2453 2454                  return (B_FALSE);
2454 2455          }
2455 2456  
2456 2457          if (!ihp->hba_mpxio_enabled) {
2457 2458                  return (B_FALSE);
2458 2459          }
2459 2460  
2460 2461          lun_num = *((uint64_t *)(iscsiboot_prop->boot_tgt.tgt_boot_lun));
2461 2462  
2462 2463          while (isp != NULL) {
2463 2464                  if ((strncmp((char *)isp->sess_name,
2464 2465                      (const char *)iscsiboot_prop->boot_tgt.tgt_name,
2465 2466                      ISCSI_MAX_NAME_LEN) == 0) &&
2466 2467                      (isp->sess_boot == B_TRUE)) {
2467 2468                          /*
2468 2469                           * found boot session.
2469 2470                           * check its mdi path info is null or not
2470 2471                           */
2471 2472                          ilp = isp->sess_lun_list;
2472 2473                          while (ilp != NULL) {
2473 2474                                  if (lun_num == ilp->lun_num) {
2474 2475                                          if (ilp->lun_pip) {
2475 2476                                                  tgt_mpxio_enabled = B_TRUE;
2476 2477                                          }
2477 2478                                          bootlun_found = B_TRUE;
2478 2479                                  }
2479 2480                                  ilp = ilp->lun_next;
2480 2481                          }
2481 2482                  }
2482 2483                  isp = isp->sess_next;
2483 2484          }
2484 2485          if (bootlun_found) {
2485 2486                  return (tgt_mpxio_enabled);
2486 2487          } else {
2487 2488                  /*
2488 2489                   * iscsiboot_prop not NULL while no boot lun found
2489 2490                   * in most cases this is none iscsi boot while iscsiboot_prop
2490 2491                   * is not NULL, in this scenario return iscsi HBA's mpxio config
2491 2492                   */
2492 2493                  return (ihp->hba_mpxio_enabled);
2493 2494          }
2494 2495  }
2495 2496  
2496 2497  static boolean_t
2497 2498  iscsid_check_active_boot_conn(iscsi_hba_t *ihp)
2498 2499  {
2499 2500          iscsi_sess_t    *isp = NULL;
2500 2501          iscsi_conn_t    *icp = NULL;
2501 2502  
2502 2503          rw_enter(&ihp->hba_sess_list_rwlock, RW_READER);
2503 2504          isp = ihp->hba_sess_list;
2504 2505          while (isp != NULL) {
2505 2506                  if (isp->sess_boot == B_TRUE) {
2506 2507                          rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2507 2508                          icp = isp->sess_conn_list;
2508 2509                          while (icp != NULL) {
2509 2510                                  if (icp->conn_state ==
2510 2511                                      ISCSI_CONN_STATE_LOGGED_IN) {
2511 2512                                          rw_exit(&isp->sess_conn_list_rwlock);
2512 2513                                          rw_exit(&ihp->hba_sess_list_rwlock);
2513 2514                                          return (B_TRUE);
2514 2515                                  }
2515 2516                                  icp = icp->conn_next;
2516 2517                          }
2517 2518                          rw_exit(&isp->sess_conn_list_rwlock);
2518 2519                  }
2519 2520                  isp = isp->sess_next;
2520 2521          }
2521 2522          rw_exit(&ihp->hba_sess_list_rwlock);
2522 2523  
2523 2524          return (B_FALSE);
2524 2525  }
  
    | 
      ↓ open down ↓ | 
    511 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX