Print this page
    
NEX-3177 enums and string arrays required to be in sync.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
SUP-930 Freed and reused idm_conn_t buffer leads to system panic.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Ping <steve.ping@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/sys/idm/idm_conn_sm.h
          +++ new/usr/src/uts/common/sys/idm/idm_conn_sm.h
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  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   23   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  26   26   */
  27   27  #ifndef _IDM_CONN_SM_H_
  28   28  #define _IDM_CONN_SM_H_
  29   29  
  30   30  #ifdef  __cplusplus
  31   31  extern "C" {
  32   32  #endif
  33   33  
  34   34  
  35   35  /*
  36   36   * IDM connection state machine events.  Most events get generated internally
  37   37   * either by the state machine or by the IDM TX/RX code.  For example when IDM
  38   38   * receives a login request for a target connectionit will generate a
  39   39   * CE_LOGIN_RCV event.  Similarly when the target sends a successful login
  40   40   * response IDM generate a "CE_LOGIN_SUCCESS_SND" event.  The following
  41   41   * events are not detected on the TX/RX path and must be generated explicitly
  42   42   * by the client when appropriate:
  43   43   *
  44   44   * CE_LOGOUT_OTHER_CONN_RCV
  45   45   * CE_ASYNC_DROP_CONN_RCV   (Only because the message may be received on
  46   46   * a different connection from the connection being dropped)
  47   47   * CE_ASYNC_DROP_ALL_CONN_RCV
  48   48   * CE_LOGOUT_OTHER_CONN_SND
  49   49   * CE_ASYNC_DROP_ALL_CONN_SND
  50   50   *
  51   51   * The following events might occur in any state since they are driven
  52   52   * by the PDU's that IDM receives:
  53   53   *
  54   54   * CE_LOGIN_RCV
  55   55   * CE_LOGIN_SUCCESS_RCV
  56   56   * CE_LOGIN_FAIL_RCV
  57   57   * CE_LOGOUT_SUCCESS_RCV
  
    | 
      ↓ open down ↓ | 
    57 lines elided | 
    
      ↑ open up ↑ | 
  
  58   58   * CE_LOGOUT_FAIL_RCV
  59   59   * CE_ASYNC_LOGOUT_RCV
  60   60   * CE_MISC_RCV
  61   61   * CE_RX_PROTOCOL_ERROR
  62   62   */
  63   63  
  64   64  #define IDM_LOGIN_SECONDS       20
  65   65  #define IDM_LOGOUT_SECONDS      20
  66   66  #define IDM_CLEANUP_SECONDS     0
  67   67  
       68 +#define IDM_CONN_EVENT_LIST() \
       69 +        item(CE_UNDEFINED) \
       70 +        /* Initiator events */ \
       71 +        item(CE_CONNECT_REQ) \
       72 +        item(CE_CONNECT_FAIL) \
       73 +        item(CE_CONNECT_SUCCESS) \
       74 +        item(CE_LOGIN_SND) \
       75 +        item(CE_LOGIN_SUCCESS_RCV) \
       76 +        item(CE_LOGIN_FAIL_RCV) \
       77 +        item(CE_LOGOUT_THIS_CONN_SND) \
       78 +        item(CE_LOGOUT_OTHER_CONN_SND) \
       79 +        item(CE_LOGOUT_SESSION_SND) \
       80 +        item(CE_LOGOUT_SUCCESS_RCV) \
       81 +        item(CE_LOGOUT_FAIL_RCV) \
       82 +        item(CE_ASYNC_LOGOUT_RCV) \
       83 +        item(CE_ASYNC_DROP_CONN_RCV) \
       84 +        item(CE_ASYNC_DROP_ALL_CONN_RCV) \
       85 +        /* Target events */ \
       86 +        item(CE_CONNECT_ACCEPT) \
       87 +        item(CE_CONNECT_REJECT) \
       88 +        item(CE_LOGIN_RCV) \
       89 +        item(CE_LOGIN_TIMEOUT) \
       90 +        item(CE_LOGIN_SUCCESS_SND) \
       91 +        item(CE_LOGIN_FAIL_SND) \
       92 +        item(CE_LOGIN_FAIL_SND_DONE) \
       93 +        item(CE_LOGOUT_THIS_CONN_RCV) \
       94 +        item(CE_LOGOUT_OTHER_CONN_RCV) \
       95 +        item(CE_LOGOUT_SESSION_RCV) \
       96 +        item(CE_LOGOUT_SUCCESS_SND) \
       97 +        item(CE_LOGOUT_SUCCESS_SND_DONE) \
       98 +        item(CE_LOGOUT_FAIL_SND) \
       99 +        item(CE_LOGOUT_FAIL_SND_DONE) \
      100 +        item(CE_CLEANUP_TIMEOUT) \
      101 +        item(CE_ASYNC_LOGOUT_SND) \
      102 +        item(CE_ASYNC_DROP_CONN_SND) \
      103 +        item(CE_ASYNC_DROP_ALL_CONN_SND) \
      104 +        item(CE_LOGOUT_TIMEOUT) \
      105 +        /* Common events */ \
      106 +        item(CE_TRANSPORT_FAIL) \
      107 +        item(CE_MISC_TX) \
      108 +        item(CE_TX_PROTOCOL_ERROR) \
      109 +        item(CE_MISC_RX) \
      110 +        item(CE_RX_PROTOCOL_ERROR) \
      111 +        item(CE_LOGOUT_SESSION_SUCCESS) \
      112 +        item(CE_CONN_REINSTATE) \
      113 +        item(CE_CONN_REINSTATE_SUCCESS) \
      114 +        item(CE_CONN_REINSTATE_FAIL) \
      115 +        item(CE_ENABLE_DM_SUCCESS) \
      116 +        item(CE_ENABLE_DM_FAIL) \
      117 +        /* Add new events above CE_MAX_EVENT */ \
      118 +        item(CE_MAX_EVENT)
      119 +
  68  120  /* Update idm_ce_name table whenever connection events are modified */
  69  121  typedef enum {
  70      -        CE_UNDEFINED = 0,
  71      -
  72      -        /* Initiator events */
  73      -        CE_CONNECT_REQ,
  74      -        CE_CONNECT_FAIL,
  75      -        CE_CONNECT_SUCCESS,
  76      -        CE_LOGIN_SND,
  77      -        CE_LOGIN_SUCCESS_RCV,
  78      -        CE_LOGIN_FAIL_RCV,
  79      -        CE_LOGOUT_THIS_CONN_SND,
  80      -        CE_LOGOUT_OTHER_CONN_SND,
  81      -        CE_LOGOUT_SESSION_SND,
  82      -        CE_LOGOUT_SUCCESS_RCV,
  83      -        CE_LOGOUT_FAIL_RCV,
  84      -        CE_ASYNC_LOGOUT_RCV,
  85      -        CE_ASYNC_DROP_CONN_RCV,
  86      -        CE_ASYNC_DROP_ALL_CONN_RCV,
  87      -
  88      -        /* Target events */
  89      -        CE_CONNECT_ACCEPT,
  90      -        CE_CONNECT_REJECT,
  91      -        CE_LOGIN_RCV,
  92      -        CE_LOGIN_TIMEOUT,
  93      -        CE_LOGIN_SUCCESS_SND,
  94      -        CE_LOGIN_FAIL_SND,
  95      -        CE_LOGIN_FAIL_SND_DONE,
  96      -        CE_LOGOUT_THIS_CONN_RCV,
  97      -        CE_LOGOUT_OTHER_CONN_RCV,
  98      -        CE_LOGOUT_SESSION_RCV,
  99      -        CE_LOGOUT_SUCCESS_SND,
 100      -        CE_LOGOUT_SUCCESS_SND_DONE,
 101      -        CE_LOGOUT_FAIL_SND,
 102      -        CE_LOGOUT_FAIL_SND_DONE,
 103      -        CE_CLEANUP_TIMEOUT,
 104      -        CE_ASYNC_LOGOUT_SND,
 105      -        CE_ASYNC_DROP_CONN_SND,
 106      -        CE_ASYNC_DROP_ALL_CONN_SND,
 107      -        CE_LOGOUT_TIMEOUT,
 108      -
 109      -        /* Common events */
 110      -        CE_TRANSPORT_FAIL,
 111      -        CE_MISC_TX,
 112      -        CE_TX_PROTOCOL_ERROR,
 113      -        CE_MISC_RX,
 114      -        CE_RX_PROTOCOL_ERROR,
 115      -        CE_LOGOUT_SESSION_SUCCESS,
 116      -        CE_CONN_REINSTATE,
 117      -        CE_CONN_REINSTATE_SUCCESS,
 118      -        CE_CONN_REINSTATE_FAIL,
 119      -        CE_ENABLE_DM_SUCCESS,
 120      -        CE_ENABLE_DM_FAIL,
 121      -
 122      -        /* Add new events above CE_MAX_EVENT */
 123      -        CE_MAX_EVENT
      122 +#define item(a) a,
      123 +        IDM_CONN_EVENT_LIST()
      124 +#undef  item
 124  125  } idm_conn_event_t;
 125  126  
 126  127  #ifdef IDM_CONN_SM_STRINGS
 127  128  /* An array of event text values, for use in logging events */
 128  129  static const char *idm_ce_name[CE_MAX_EVENT+1] = {
 129      -        "CE_UNDEFINED",
 130      -        "CE_CONNECT_REQ",
 131      -        "CE_CONNECT_FAIL",
 132      -        "CE_CONNECT_SUCCESS",
 133      -        "CE_LOGIN_SND",
 134      -        "CE_LOGIN_SUCCESS_RCV",
 135      -        "CE_LOGIN_FAIL_RCV",
 136      -        "CE_LOGOUT_THIS_CONN_SND",
 137      -        "CE_LOGOUT_OTHER_CONN_SND",
 138      -        "CE_LOGOUT_SESSION_SND",
 139      -        "CE_LOGOUT_SUCCESS_RCV",
 140      -        "CE_LOGOUT_FAIL_RCV",
 141      -        "CE_ASYNC_LOGOUT_RCV",
 142      -        "CE_ASYNC_DROP_CONN_RCV",
 143      -        "CE_ASYNC_DROP_ALL_CONN_RCV",
 144      -        "CE_CONNECT_ACCEPT",
 145      -        "CE_CONNECT_REJECT",
 146      -        "CE_LOGIN_RCV",
 147      -        "CE_LOGIN_TIMEOUT",
 148      -        "CE_LOGIN_SUCCESS_SND",
 149      -        "CE_LOGIN_FAIL_SND",
 150      -        "CE_LOGIN_FAIL_SND_DONE",
 151      -        "CE_LOGOUT_THIS_CONN_RCV",
 152      -        "CE_LOGOUT_OTHER_CONN_RCV",
 153      -        "CE_LOGOUT_SESSION_RCV",
 154      -        "CE_LOGOUT_SUCCESS_SND",
 155      -        "CE_LOGOUT_SUCCESS_SND_DONE",
 156      -        "CE_LOGOUT_FAIL_SND",
 157      -        "CE_LOGOUT_FAIL_SND_DONE",
 158      -        "CE_CLEANUP_TIMEOUT",
 159      -        "CE_ASYNC_LOGOUT_SND",
 160      -        "CE_ASYNC_DROP_CONN_SND",
 161      -        "CE_ASYNC_DROP_ALL_CONN_SND",
 162      -        "CE_LOGOUT_TIMEOUT",
 163      -        "CE_TRANSPORT_FAIL",
 164      -        "CE_MISC_TX",
 165      -        "CE_TX_PROTOCOL_ERROR",
 166      -        "CE_MISC_RX",
 167      -        "CE_RX_PROTOCOL_ERROR",
 168      -        "CE_LOGOUT_SESSION_SUCCESS",
 169      -        "CE_CONN_REINSTATE",
 170      -        "CE_CONN_REINSTATE_SUCCESS",
 171      -        "CE_CONN_REINSTATE_FAIL",
 172      -        "CE_ENABLE_DM_SUCCESS",
 173      -        "CE_ENABLE_DM_FAIL",
 174      -        "CE_MAX_EVENT"
      130 +#define item(a) #a,
      131 +        IDM_CONN_EVENT_LIST()
      132 +#undef  item
 175  133  };
 176  134  #endif
 177  135  
      136 +#define CONN_STATE_LIST() \
      137 +        item(CS_S0_UNDEFINED) \
      138 +        item(CS_S1_FREE) \
      139 +        item(CS_S2_XPT_WAIT) \
      140 +        item(CS_S3_XPT_UP) \
      141 +        item(CS_S4_IN_LOGIN) \
      142 +        item(CS_S5_LOGGED_IN) \
      143 +        item(CS_S6_IN_LOGOUT) \
      144 +        item(CS_S7_LOGOUT_REQ) \
      145 +        item(CS_S8_CLEANUP) \
      146 +        item(CS_S9_INIT_ERROR) \
      147 +        item(CS_S10_IN_CLEANUP) \
      148 +        item(CS_S11_COMPLETE) \
      149 +        item(CS_S12_ENABLE_DM) \
      150 +        item(CS_S9A_REJECTED) \
      151 +        item(CS_S9B_WAIT_SND_DONE) \
      152 +        /* Add new connection states above CS_MAX_STATE */ \
      153 +        item(CS_MAX_STATE)
      154 +
 178  155  /* Update idm_cs_name table whenever connection states are modified */
 179  156  typedef enum {
 180      -        CS_S0_UNDEFINED = 0,
 181      -
 182      -        CS_S1_FREE,
 183      -        CS_S2_XPT_WAIT,
 184      -        CS_S3_XPT_UP,
 185      -        CS_S4_IN_LOGIN,
 186      -        CS_S5_LOGGED_IN,
 187      -        CS_S6_IN_LOGOUT,
 188      -        CS_S7_LOGOUT_REQ,
 189      -        CS_S8_CLEANUP,
 190      -        CS_S9_INIT_ERROR,
 191      -        CS_S10_IN_CLEANUP,
 192      -        CS_S11_COMPLETE,
 193      -        CS_S12_ENABLE_DM,
 194      -        CS_S9A_REJECTED,
 195      -        CS_S9B_WAIT_SND_DONE,
 196      -
 197      -        /* Add new connection states above CS_MAX_STATE */
 198      -        CS_MAX_STATE
      157 +#define item(a) a,
      158 +        CONN_STATE_LIST()
      159 +#undef  item
 199  160  } idm_conn_state_t;
 200  161  
 201  162  #ifdef IDM_CONN_SM_STRINGS
 202  163  /* An array of state text values, for use in logging state transitions */
 203  164  static const char *idm_cs_name[CS_MAX_STATE+1] = {
 204      -        "CS_S0_UNDEFINED",
 205      -        "CS_S1_FREE",
 206      -        "CS_S2_XPT_WAIT",
 207      -        "CS_S3_XPT_UP",
 208      -        "CS_S4_IN_LOGIN",
 209      -        "CS_S5_LOGGED_IN",
 210      -        "CS_S6_IN_LOGOUT",
 211      -        "CS_S7_LOGOUT_REQ",
 212      -        "CS_S8_CLEANUP",
 213      -        "CS_S9_INIT_ERROR",
 214      -        "CS_S10_IN_CLEANUP",
 215      -        "CS_S11_COMPLETE",
 216      -        "CS_S12_ENABLE_DM",
 217      -        "CS_S9A_REJECTED",
 218      -        "CS_S9B_WAIT_SND_DONE",
 219      -        "CS_MAX_STATE"
      165 +#define item(a) #a,
      166 +        CONN_STATE_LIST()
      167 +#undef  item
 220  168  };
 221  169  #endif
 222  170  
 223  171  /*
 224  172   * Currently the state machine has a condition where idm_login_timeout() is
 225  173   * left active after the connection has been closed. This causes the system
 226  174   * to panic when idm_login_timeout() modifies the freed memory. In an attempt
 227  175   * to isolate and find this issue special attention is being placed on
 228  176   * the ic_state_timeout value. After each untimeout call the value will now
 229  177   * be cleared. Just before the value is set the code will check for 0 and
 230  178   * display an error. One final change is being done in idm_conn_sm_fini() which
 231  179   * if ic_state_machine is not 0, an error message will be displayed and
 232  180   * untimeout() called. That should prevent customer sites from seeing the
 233  181   * panic. The code also calls ASSERT(0) which should cause a panic during
 234  182   * system test.
 235  183   */
 236  184  #define IDM_SM_TIMER_CHECK(ic) \
 237  185          if (ic->ic_state_timeout) { \
 238  186                  cmn_err(CE_WARN, "%s: existing timeout still set. " \
 239  187                      "state: %s, last: %s\n", __func__, \
 240  188                      idm_cs_name[ic->ic_state], \
 241  189                      idm_cs_name[ic->ic_last_state]); \
 242  190                  ASSERT(0); \
 243  191          }
 244  192  
 245  193  #define IDM_SM_TIMER_CLEAR(ic) \
 246  194          (void) untimeout(ic->ic_state_timeout); \
 247  195          ic->ic_state_timeout = 0;
 248  196  
 249  197  typedef enum {
 250  198          CT_NONE = 0,
 251  199          CT_RX_PDU,
 252  200          CT_TX_PDU
 253  201  } idm_pdu_event_type_t;
 254  202  
 255  203  typedef enum {
 256  204          CA_TX_PROTOCOL_ERROR,   /* Send "protocol error" to state machine */
 257  205          CA_RX_PROTOCOL_ERROR,   /* Send "protocol error" to state machine */
 258  206          CA_FORWARD,             /* State machine event and forward to client */
 259  207          CA_DROP                 /* Drop PDU */
 260  208  } idm_pdu_event_action_t;
 261  209  
 262  210  typedef struct {
 263  211          struct idm_conn_s       *iec_ic;
 264  212          idm_conn_event_t        iec_event;
 265  213          uintptr_t               iec_info;
 266  214          idm_pdu_event_type_t    iec_pdu_event_type;
 267  215          boolean_t               iec_pdu_forwarded;
 268  216  } idm_conn_event_ctx_t;
 269  217  
 270  218  idm_status_t
 271  219  idm_conn_sm_init(struct idm_conn_s *ic);
 272  220  
 273  221  void
 274  222  idm_conn_sm_fini(struct idm_conn_s *ic);
 275  223  
 276  224  idm_status_t
 277  225  idm_notify_client(struct idm_conn_s *ic, idm_client_notify_t cn,
 278  226      uintptr_t data);
 279  227  
 280  228  void
 281  229  idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data);
 282  230  
 283  231  void
 284  232  idm_conn_event(struct idm_conn_s *ic, idm_conn_event_t event, uintptr_t data);
 285  233  
 286  234  void
 287  235  idm_conn_event_locked(struct idm_conn_s *ic, idm_conn_event_t event,
 288  236      uintptr_t event_info, idm_pdu_event_type_t pdu_event_type);
 289  237  
 290  238  idm_status_t
 291  239  idm_conn_reinstate_event(struct idm_conn_s *old_ic, struct idm_conn_s *new_ic);
 292  240  
 293  241  void
 294  242  idm_conn_tx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event,
 295  243      uintptr_t data);
 296  244  
 297  245  void
 298  246  idm_conn_rx_pdu_event(struct idm_conn_s *ic, idm_conn_event_t event,
 299  247      uintptr_t data);
 300  248  
 301  249  char *
 302  250  idm_conn_state_str(struct idm_conn_s *ic);
 303  251  
 304  252  #ifdef  __cplusplus
 305  253  }
 306  254  #endif
 307  255  
 308  256  #endif /* _IDM_CONN_SM_H_ */
  
    | 
      ↓ open down ↓ | 
    79 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX