1 1.36 mlelstv /* $NetBSD: iscsi_ioctl.c,v 1.37 2024/11/03 10:53:02 mlelstv Exp $ */ 2 1.1 agc 3 1.1 agc /*- 4 1.1 agc * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. 5 1.1 agc * All rights reserved. 6 1.1 agc * 7 1.1 agc * This code is derived from software contributed to The NetBSD Foundation 8 1.1 agc * by Wasabi Systems, Inc. 9 1.1 agc * 10 1.1 agc * Redistribution and use in source and binary forms, with or without 11 1.1 agc * modification, are permitted provided that the following conditions 12 1.1 agc * are met: 13 1.1 agc * 1. Redistributions of source code must retain the above copyright 14 1.1 agc * notice, this list of conditions and the following disclaimer. 15 1.1 agc * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 agc * notice, this list of conditions and the following disclaimer in the 17 1.1 agc * documentation and/or other materials provided with the distribution. 18 1.1 agc * 19 1.1 agc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 agc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 agc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 agc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 agc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 agc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 agc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 agc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 agc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 agc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 agc * POSSIBILITY OF SUCH DAMAGE. 30 1.1 agc */ 31 1.1 agc 32 1.1 agc #include "iscsi_globals.h" 33 1.1 agc 34 1.1 agc #include <sys/file.h> 35 1.1 agc #include <sys/filedesc.h> 36 1.1 agc #include <sys/proc.h> 37 1.32 chs #include <sys/kmem.h> 38 1.1 agc 39 1.14 mlelstv static kmutex_t iscsi_cleanup_mtx; 40 1.14 mlelstv static kcondvar_t iscsi_cleanup_cv; 41 1.14 mlelstv static kcondvar_t iscsi_event_cv; 42 1.14 mlelstv static struct lwp *iscsi_cleanproc = NULL; 43 1.14 mlelstv 44 1.1 agc static uint16_t current_id = 0; /* Global session ID counter */ 45 1.1 agc 46 1.1 agc /* list of event handlers */ 47 1.1 agc static event_handler_list_t event_handlers = 48 1.1 agc TAILQ_HEAD_INITIALIZER(event_handlers); 49 1.1 agc 50 1.14 mlelstv static connection_list_t iscsi_timeout_conn_list = 51 1.14 mlelstv TAILQ_HEAD_INITIALIZER(iscsi_timeout_conn_list); 52 1.14 mlelstv 53 1.14 mlelstv static ccb_list_t iscsi_timeout_ccb_list = 54 1.14 mlelstv TAILQ_HEAD_INITIALIZER(iscsi_timeout_ccb_list); 55 1.14 mlelstv 56 1.14 mlelstv static session_list_t iscsi_cleanups_list = 57 1.14 mlelstv TAILQ_HEAD_INITIALIZER(iscsi_cleanups_list); 58 1.14 mlelstv 59 1.14 mlelstv static connection_list_t iscsi_cleanupc_list = 60 1.14 mlelstv TAILQ_HEAD_INITIALIZER(iscsi_cleanupc_list); 61 1.14 mlelstv 62 1.1 agc static uint32_t handler_id = 0; /* Handler ID counter */ 63 1.1 agc 64 1.1 agc /* -------------------------------------------------------------------------- */ 65 1.1 agc 66 1.1 agc /* Event management functions */ 67 1.1 agc 68 1.1 agc /* 69 1.1 agc * find_handler: 70 1.1 agc * Search the event handler list for the given ID. 71 1.1 agc * 72 1.1 agc * Parameter: 73 1.1 agc * id The handler ID. 74 1.1 agc * 75 1.1 agc * Returns: 76 1.1 agc * Pointer to handler if found, else NULL. 77 1.1 agc */ 78 1.1 agc 79 1.1 agc 80 1.14 mlelstv static event_handler_t * 81 1.1 agc find_handler(uint32_t id) 82 1.1 agc { 83 1.1 agc event_handler_t *curr; 84 1.1 agc 85 1.14 mlelstv KASSERT(mutex_owned(&iscsi_cleanup_mtx)); 86 1.14 mlelstv 87 1.28 christos TAILQ_FOREACH(curr, &event_handlers, evh_link) 88 1.28 christos if (curr->evh_id == id) 89 1.1 agc break; 90 1.1 agc 91 1.1 agc return curr; 92 1.1 agc } 93 1.1 agc 94 1.1 agc 95 1.1 agc /* 96 1.1 agc * register_event: 97 1.1 agc * Create event handler entry, return ID. 98 1.1 agc * 99 1.1 agc * Parameter: 100 1.1 agc * par The parameter. 101 1.1 agc */ 102 1.1 agc 103 1.14 mlelstv static void 104 1.1 agc register_event(iscsi_register_event_parameters_t *par) 105 1.1 agc { 106 1.1 agc event_handler_t *handler; 107 1.1 agc int was_empty; 108 1.1 agc 109 1.1 agc handler = malloc(sizeof(event_handler_t), M_DEVBUF, M_WAITOK | M_ZERO); 110 1.1 agc if (handler == NULL) { 111 1.1 agc DEBOUT(("No mem for event handler\n")); 112 1.1 agc par->status = ISCSI_STATUS_NO_RESOURCES; 113 1.1 agc return; 114 1.1 agc } 115 1.1 agc 116 1.28 christos TAILQ_INIT(&handler->evh_events); 117 1.1 agc 118 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 119 1.1 agc /* create a unique ID */ 120 1.1 agc do { 121 1.1 agc ++handler_id; 122 1.1 agc } while (!handler_id || find_handler(handler_id) != NULL); 123 1.28 christos par->event_id = handler->evh_id = handler_id; 124 1.1 agc 125 1.1 agc was_empty = TAILQ_FIRST(&event_handlers) == NULL; 126 1.28 christos TAILQ_INSERT_TAIL(&event_handlers, handler, evh_link); 127 1.14 mlelstv if (was_empty) 128 1.14 mlelstv iscsi_notify_cleanup(); 129 1.23 mlelstv mutex_exit(&iscsi_cleanup_mtx); 130 1.1 agc 131 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 132 1.1 agc DEB(5, ("Register Event OK, ID %d\n", par->event_id)); 133 1.1 agc } 134 1.1 agc 135 1.1 agc 136 1.1 agc /* 137 1.1 agc * deregister_event: 138 1.1 agc * Destroy handler entry and any waiting events, wake up waiter. 139 1.1 agc * 140 1.1 agc * Parameter: 141 1.1 agc * par The parameter. 142 1.1 agc */ 143 1.1 agc 144 1.14 mlelstv static void 145 1.1 agc deregister_event(iscsi_register_event_parameters_t *par) 146 1.1 agc { 147 1.1 agc event_handler_t *handler; 148 1.1 agc event_t *evt; 149 1.1 agc 150 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 151 1.1 agc handler = find_handler(par->event_id); 152 1.1 agc if (handler == NULL) { 153 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 154 1.1 agc DEB(1, ("Deregister Event ID %d not found\n", par->event_id)); 155 1.1 agc par->status = ISCSI_STATUS_INVALID_EVENT_ID; 156 1.1 agc return; 157 1.1 agc } 158 1.6 mlelstv 159 1.28 christos TAILQ_REMOVE(&event_handlers, handler, evh_link); 160 1.28 christos if (handler->evh_waiter != NULL) { 161 1.28 christos handler->evh_waiter->status = ISCSI_STATUS_EVENT_DEREGISTERED; 162 1.14 mlelstv cv_broadcast(&iscsi_event_cv); 163 1.1 agc } 164 1.1 agc 165 1.28 christos while ((evt = TAILQ_FIRST(&handler->evh_events)) != NULL) { 166 1.28 christos TAILQ_REMOVE(&handler->evh_events, evt, ev_link); 167 1.1 agc free(evt, M_TEMP); 168 1.1 agc } 169 1.23 mlelstv mutex_exit(&iscsi_cleanup_mtx); 170 1.1 agc 171 1.1 agc free(handler, M_DEVBUF); 172 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 173 1.1 agc DEB(5, ("Deregister Event ID %d complete\n", par->event_id)); 174 1.1 agc } 175 1.1 agc 176 1.1 agc 177 1.1 agc /* 178 1.1 agc * check_event: 179 1.1 agc * Return first queued event. Optionally wait for arrival of event. 180 1.1 agc * 181 1.1 agc * Parameter: 182 1.1 agc * par The parameter. 183 1.1 agc * wait Wait for event if true 184 1.1 agc */ 185 1.1 agc 186 1.14 mlelstv static void 187 1.1 agc check_event(iscsi_wait_event_parameters_t *par, bool wait) 188 1.1 agc { 189 1.1 agc event_handler_t *handler; 190 1.1 agc event_t *evt; 191 1.14 mlelstv int rc; 192 1.1 agc 193 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 194 1.1 agc handler = find_handler(par->event_id); 195 1.1 agc if (handler == NULL) { 196 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 197 1.1 agc DEBOUT(("Wait Event ID %d not found\n", par->event_id)); 198 1.1 agc par->status = ISCSI_STATUS_INVALID_EVENT_ID; 199 1.1 agc return; 200 1.1 agc } 201 1.28 christos if (handler->evh_waiter != NULL) { 202 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 203 1.1 agc DEBOUT(("Wait Event ID %d already waiting\n", par->event_id)); 204 1.1 agc par->status = ISCSI_STATUS_EVENT_WAITING; 205 1.1 agc return; 206 1.1 agc } 207 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 208 1.1 agc DEB(99, ("Wait Event ID %d\n", par->event_id)); 209 1.1 agc 210 1.1 agc do { 211 1.28 christos evt = TAILQ_FIRST(&handler->evh_events); 212 1.1 agc if (evt != NULL) { 213 1.28 christos TAILQ_REMOVE(&handler->evh_events, evt, ev_link); 214 1.1 agc } else { 215 1.1 agc if (!wait) { 216 1.1 agc par->status = ISCSI_STATUS_LIST_EMPTY; 217 1.1 agc return; 218 1.1 agc } 219 1.1 agc if (par->status != ISCSI_STATUS_SUCCESS) { 220 1.1 agc return; 221 1.1 agc } 222 1.28 christos handler->evh_waiter = par; 223 1.14 mlelstv rc = cv_wait_sig(&iscsi_event_cv, &iscsi_cleanup_mtx); 224 1.14 mlelstv if (rc) { 225 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 226 1.14 mlelstv par->status = ISCSI_STATUS_LIST_EMPTY; 227 1.3 mlelstv return; 228 1.14 mlelstv } 229 1.1 agc } 230 1.1 agc } while (evt == NULL); 231 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 232 1.1 agc 233 1.28 christos par->connection_id = evt->ev_connection_id; 234 1.28 christos par->session_id = evt->ev_session_id; 235 1.28 christos par->event_kind = evt->ev_event_kind; 236 1.28 christos par->reason = evt->ev_reason; 237 1.1 agc 238 1.1 agc free(evt, M_TEMP); 239 1.1 agc } 240 1.1 agc 241 1.1 agc /* 242 1.1 agc * add_event 243 1.1 agc * Adds an event entry to each registered handler queue. 244 1.1 agc * Note that events are simply duplicated because we expect the number of 245 1.1 agc * handlers to be very small, usually 1 (the daemon). 246 1.1 agc * 247 1.1 agc * Parameters: 248 1.1 agc * kind The event kind 249 1.1 agc * sid The ID of the affected session 250 1.1 agc * cid The ID of the affected connection 251 1.1 agc * reason The reason code 252 1.1 agc */ 253 1.1 agc 254 1.1 agc void 255 1.1 agc add_event(iscsi_event_t kind, uint32_t sid, uint32_t cid, uint32_t reason) 256 1.1 agc { 257 1.1 agc event_handler_t *curr; 258 1.1 agc event_t *evt; 259 1.1 agc 260 1.1 agc DEB(9, ("Add_event kind %d, sid %d, cid %d, reason %d\n", 261 1.1 agc kind, sid, cid, reason)); 262 1.1 agc 263 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 264 1.28 christos TAILQ_FOREACH(curr, &event_handlers, evh_link) { 265 1.14 mlelstv evt = malloc(sizeof(*evt), M_TEMP, M_NOWAIT); 266 1.1 agc if (evt == NULL) { 267 1.14 mlelstv DEBOUT(("Cannot allocate event\n")); 268 1.14 mlelstv break; 269 1.1 agc } 270 1.28 christos evt->ev_event_kind = kind; 271 1.28 christos evt->ev_session_id = sid; 272 1.28 christos evt->ev_connection_id = cid; 273 1.28 christos evt->ev_reason = reason; 274 1.28 christos 275 1.28 christos TAILQ_INSERT_TAIL(&curr->evh_events, evt, ev_link); 276 1.28 christos if (curr->evh_waiter != NULL) { 277 1.28 christos curr->evh_waiter = NULL; 278 1.14 mlelstv cv_broadcast(&iscsi_event_cv); 279 1.1 agc } 280 1.1 agc } 281 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 282 1.1 agc } 283 1.1 agc 284 1.1 agc 285 1.1 agc /* 286 1.1 agc * check_event_handlers 287 1.1 agc * Checks for dead event handlers. A dead event handler would deplete 288 1.1 agc * memory over time, so we have to make sure someone at the other 289 1.1 agc * end is actively monitoring events. 290 1.1 agc * This function is called every 30 seconds or so (less frequent if there 291 1.1 agc * is other activity for the cleanup thread to deal with) to go through 292 1.1 agc * the list of handlers and check whether the first element in the event 293 1.1 agc * list has changed at all. If not, the event is deregistered. 294 1.1 agc * Note that this will not detect dead handlers if no events are pending, 295 1.1 agc * but we don't care as long as events don't accumulate in the list. 296 1.6 mlelstv * 297 1.1 agc */ 298 1.1 agc 299 1.14 mlelstv static void 300 1.1 agc check_event_handlers(void) 301 1.1 agc { 302 1.1 agc event_handler_t *curr, *next; 303 1.1 agc event_t *evt; 304 1.1 agc 305 1.14 mlelstv KASSERT(mutex_owned(&iscsi_cleanup_mtx)); 306 1.14 mlelstv 307 1.1 agc for (curr = TAILQ_FIRST(&event_handlers); curr != NULL; curr = next) { 308 1.28 christos next = TAILQ_NEXT(curr, evh_link); 309 1.28 christos evt = TAILQ_FIRST(&curr->evh_events); 310 1.1 agc 311 1.28 christos if (evt != NULL && evt == curr->evh_first_in_list) { 312 1.28 christos DEBOUT(("Found Dead Event Handler %d, removing\n", curr->evh_id)); 313 1.1 agc 314 1.28 christos TAILQ_REMOVE(&event_handlers, curr, evh_link); 315 1.28 christos while ((evt = TAILQ_FIRST(&curr->evh_events)) != NULL) { 316 1.28 christos TAILQ_REMOVE(&curr->evh_events, evt, ev_link); 317 1.1 agc free(evt, M_TEMP); 318 1.1 agc } 319 1.1 agc free(curr, M_DEVBUF); 320 1.1 agc } else 321 1.28 christos curr->evh_first_in_list = evt; 322 1.1 agc } 323 1.1 agc } 324 1.1 agc 325 1.1 agc 326 1.1 agc /* -------------------------------------------------------------------------- */ 327 1.1 agc 328 1.1 agc /* 329 1.1 agc * get_socket: 330 1.1 agc * Get the file pointer from the socket handle passed into login. 331 1.1 agc * 332 1.1 agc * Parameter: 333 1.1 agc * fdes IN: The socket handle 334 1.1 agc * fpp OUT: The pointer to the resulting file pointer 335 1.1 agc * 336 1.1 agc * Returns: 0 on success, else an error code. 337 1.1 agc * 338 1.1 agc */ 339 1.1 agc 340 1.14 mlelstv static int 341 1.1 agc get_socket(int fdes, struct file **fpp) 342 1.1 agc { 343 1.1 agc struct file *fp; 344 1.1 agc 345 1.1 agc if ((fp = fd_getfile(fdes)) == NULL) { 346 1.1 agc return EBADF; 347 1.1 agc } 348 1.1 agc if (fp->f_type != DTYPE_SOCKET) { 349 1.1 agc return ENOTSOCK; 350 1.1 agc } 351 1.3 mlelstv 352 1.1 agc /* Add the reference */ 353 1.3 mlelstv mutex_enter(&fp->f_lock); 354 1.1 agc fp->f_count++; 355 1.3 mlelstv mutex_exit(&fp->f_lock); 356 1.1 agc 357 1.1 agc *fpp = fp; 358 1.1 agc return 0; 359 1.1 agc } 360 1.1 agc 361 1.3 mlelstv /* 362 1.3 mlelstv * release_socket: 363 1.3 mlelstv * Release the file pointer from the socket handle passed into login. 364 1.3 mlelstv * 365 1.3 mlelstv * Parameter: 366 1.3 mlelstv * fp IN: The pointer to the resulting file pointer 367 1.3 mlelstv * 368 1.3 mlelstv */ 369 1.3 mlelstv 370 1.14 mlelstv static void 371 1.3 mlelstv release_socket(struct file *fp) 372 1.3 mlelstv { 373 1.3 mlelstv /* Add the reference */ 374 1.3 mlelstv mutex_enter(&fp->f_lock); 375 1.3 mlelstv fp->f_count--; 376 1.3 mlelstv mutex_exit(&fp->f_lock); 377 1.3 mlelstv } 378 1.3 mlelstv 379 1.1 agc 380 1.1 agc /* 381 1.1 agc * find_session: 382 1.1 agc * Find a session by ID. 383 1.1 agc * 384 1.1 agc * Parameter: the session ID 385 1.1 agc * 386 1.1 agc * Returns: The pointer to the session (or NULL if not found) 387 1.1 agc */ 388 1.1 agc 389 1.1 agc session_t * 390 1.1 agc find_session(uint32_t id) 391 1.1 agc { 392 1.28 christos session_t *sess; 393 1.1 agc 394 1.14 mlelstv KASSERT(mutex_owned(&iscsi_cleanup_mtx)); 395 1.14 mlelstv 396 1.28 christos TAILQ_FOREACH(sess, &iscsi_sessions, s_sessions) 397 1.28 christos if (sess->s_id == id) { 398 1.1 agc break; 399 1.1 agc } 400 1.28 christos return sess; 401 1.1 agc } 402 1.1 agc 403 1.1 agc 404 1.1 agc /* 405 1.1 agc * find_connection: 406 1.1 agc * Find a connection by ID. 407 1.1 agc * 408 1.1 agc * Parameter: the session pointer and the connection ID 409 1.1 agc * 410 1.1 agc * Returns: The pointer to the connection (or NULL if not found) 411 1.1 agc */ 412 1.1 agc 413 1.1 agc connection_t * 414 1.28 christos find_connection(session_t *sess, uint32_t id) 415 1.1 agc { 416 1.28 christos connection_t *conn; 417 1.1 agc 418 1.14 mlelstv KASSERT(mutex_owned(&iscsi_cleanup_mtx)); 419 1.14 mlelstv 420 1.28 christos TAILQ_FOREACH(conn, &sess->s_conn_list, c_connections) 421 1.28 christos if (conn->c_id == id) { 422 1.1 agc break; 423 1.1 agc } 424 1.28 christos return conn; 425 1.1 agc } 426 1.1 agc 427 1.22 mlelstv /* 428 1.22 mlelstv * ref_session: 429 1.22 mlelstv * Reference a session 430 1.22 mlelstv * 431 1.22 mlelstv * Session cannot be release until reference count reaches zero 432 1.22 mlelstv * 433 1.22 mlelstv * Returns: 1 if reference counter would overflow 434 1.22 mlelstv */ 435 1.22 mlelstv 436 1.22 mlelstv int 437 1.28 christos ref_session(session_t *sess) 438 1.22 mlelstv { 439 1.22 mlelstv int rc = 1; 440 1.22 mlelstv 441 1.22 mlelstv mutex_enter(&iscsi_cleanup_mtx); 442 1.29 ozaki KASSERT(sess != NULL); 443 1.28 christos if (sess->s_refcount <= CCBS_PER_SESSION) { 444 1.28 christos sess->s_refcount++; 445 1.22 mlelstv rc = 0; 446 1.22 mlelstv } 447 1.22 mlelstv mutex_exit(&iscsi_cleanup_mtx); 448 1.22 mlelstv 449 1.22 mlelstv return rc; 450 1.22 mlelstv } 451 1.22 mlelstv 452 1.22 mlelstv /* 453 1.22 mlelstv * unref_session: 454 1.22 mlelstv * Unreference a session 455 1.22 mlelstv * 456 1.22 mlelstv * Release session reference, trigger cleanup 457 1.22 mlelstv */ 458 1.22 mlelstv 459 1.22 mlelstv void 460 1.22 mlelstv unref_session(session_t *session) 461 1.22 mlelstv { 462 1.22 mlelstv 463 1.27 mlelstv mutex_enter(&iscsi_cleanup_mtx); 464 1.22 mlelstv KASSERT(session != NULL); 465 1.28 christos KASSERT(session->s_refcount > 0); 466 1.28 christos if (--session->s_refcount == 0) 467 1.28 christos cv_broadcast(&session->s_sess_cv); 468 1.27 mlelstv mutex_exit(&iscsi_cleanup_mtx); 469 1.22 mlelstv } 470 1.22 mlelstv 471 1.1 agc 472 1.1 agc /* 473 1.1 agc * kill_connection: 474 1.1 agc * Terminate the connection as gracefully as possible. 475 1.1 agc * 476 1.1 agc * Parameter: 477 1.1 agc * conn The connection to terminate 478 1.1 agc * status The status code for the connection's "terminating" field 479 1.1 agc * logout The logout reason code 480 1.1 agc * recover Attempt to recover connection 481 1.1 agc */ 482 1.1 agc 483 1.1 agc void 484 1.1 agc kill_connection(connection_t *conn, uint32_t status, int logout, bool recover) 485 1.1 agc { 486 1.28 christos session_t *sess = conn->c_session; 487 1.23 mlelstv int terminating; 488 1.1 agc 489 1.1 agc DEBC(conn, 1, ("Kill_connection: terminating=%d, status=%d, logout=%d, " 490 1.1 agc "state=%d\n", 491 1.28 christos conn->c_terminating, status, logout, conn->c_state)); 492 1.1 agc 493 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 494 1.1 agc if (recover && 495 1.28 christos !conn->c_destroy && 496 1.28 christos conn->c_recover > MAX_RECOVERY_ATTEMPTS) { 497 1.33 mlelstv DEBC(conn, 1, ("Kill_connection: Too many recovery attempts, " 498 1.33 mlelstv "destroying\n")); 499 1.28 christos conn->c_destroy = TRUE; 500 1.1 agc } 501 1.1 agc 502 1.28 christos if (!recover || conn->c_destroy) { 503 1.6 mlelstv 504 1.28 christos if (conn->c_in_session) { 505 1.28 christos conn->c_in_session = FALSE; 506 1.28 christos TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections); 507 1.28 christos sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list); 508 1.1 agc } 509 1.6 mlelstv 510 1.28 christos if (!conn->c_destroy) { 511 1.1 agc DEBC(conn, 1, ("Kill_connection setting destroy flag\n")); 512 1.28 christos conn->c_destroy = TRUE; 513 1.1 agc } 514 1.1 agc } 515 1.1 agc 516 1.36 mlelstv mutex_enter(&conn->c_lock); 517 1.28 christos terminating = conn->c_terminating; 518 1.23 mlelstv if (!terminating) 519 1.28 christos conn->c_terminating = status; 520 1.36 mlelstv mutex_exit(&conn->c_lock); 521 1.23 mlelstv 522 1.1 agc /* Don't recurse */ 523 1.23 mlelstv if (terminating) { 524 1.26 mlelstv mutex_exit(&iscsi_cleanup_mtx); 525 1.26 mlelstv 526 1.28 christos KASSERT(conn->c_state != ST_FULL_FEATURE); 527 1.1 agc DEBC(conn, 1, ("Kill_connection exiting (already terminating)\n")); 528 1.23 mlelstv goto done; 529 1.1 agc } 530 1.1 agc 531 1.28 christos if (conn->c_state == ST_FULL_FEATURE) { 532 1.28 christos sess->s_active_connections--; 533 1.28 christos conn->c_state = ST_WINDING_DOWN; 534 1.1 agc 535 1.1 agc /* If this is the last connection and ERL < 2, reset TSIH */ 536 1.28 christos if (!sess->s_active_connections && sess->s_ErrorRecoveryLevel < 2) 537 1.28 christos sess->s_TSIH = 0; 538 1.1 agc 539 1.1 agc /* Don't try to log out if the socket is broken or we're in the middle */ 540 1.1 agc /* of logging in */ 541 1.1 agc if (logout >= 0) { 542 1.28 christos if (sess->s_ErrorRecoveryLevel < 2 && 543 1.1 agc logout == RECOVER_CONNECTION) { 544 1.1 agc logout = LOGOUT_CONNECTION; 545 1.1 agc } 546 1.28 christos if (!sess->s_active_connections && 547 1.1 agc logout == LOGOUT_CONNECTION) { 548 1.1 agc logout = LOGOUT_SESSION; 549 1.1 agc } 550 1.36 mlelstv 551 1.36 mlelstv /* connection is terminating, prevent cleanup */ 552 1.36 mlelstv mutex_enter(&conn->c_lock); 553 1.36 mlelstv conn->c_usecount++; 554 1.36 mlelstv mutex_exit(&conn->c_lock); 555 1.36 mlelstv 556 1.26 mlelstv mutex_exit(&iscsi_cleanup_mtx); 557 1.26 mlelstv 558 1.33 mlelstv DEBC(conn, 1, ("Send_logout for reason %d\n", logout)); 559 1.33 mlelstv 560 1.26 mlelstv connection_timeout_start(conn, CONNECTION_TIMEOUT); 561 1.26 mlelstv 562 1.1 agc if (!send_logout(conn, conn, logout, FALSE)) { 563 1.36 mlelstv mutex_enter(&conn->c_lock); 564 1.36 mlelstv conn->c_usecount--; 565 1.28 christos conn->c_terminating = ISCSI_STATUS_SUCCESS; 566 1.36 mlelstv mutex_exit(&conn->c_lock); 567 1.1 agc return; 568 1.1 agc } 569 1.1 agc /* 570 1.26 mlelstv * if the logout request was successfully sent, 571 1.26 mlelstv * the logout response handler will do the rest 572 1.26 mlelstv * of the termination processing. If the logout 573 1.26 mlelstv * doesn't get a response, we'll get back in here 574 1.26 mlelstv * once the timeout hits. 575 1.1 agc */ 576 1.26 mlelstv 577 1.26 mlelstv mutex_enter(&iscsi_cleanup_mtx); 578 1.36 mlelstv 579 1.36 mlelstv /* release connection */ 580 1.36 mlelstv mutex_enter(&conn->c_lock); 581 1.36 mlelstv conn->c_usecount--; 582 1.36 mlelstv mutex_exit(&conn->c_lock); 583 1.1 agc } 584 1.26 mlelstv 585 1.1 agc } 586 1.1 agc 587 1.28 christos conn->c_state = ST_SETTLING; 588 1.26 mlelstv mutex_exit(&iscsi_cleanup_mtx); 589 1.1 agc 590 1.23 mlelstv done: 591 1.1 agc /* let send thread take over next step of cleanup */ 592 1.28 christos mutex_enter(&conn->c_lock); 593 1.28 christos cv_broadcast(&conn->c_conn_cv); 594 1.28 christos mutex_exit(&conn->c_lock); 595 1.1 agc 596 1.1 agc DEBC(conn, 5, ("kill_connection returns\n")); 597 1.1 agc } 598 1.1 agc 599 1.1 agc 600 1.1 agc /* 601 1.1 agc * kill_session: 602 1.1 agc * Terminate the session as gracefully as possible. 603 1.1 agc * 604 1.1 agc * Parameter: 605 1.1 agc * session Session to terminate 606 1.1 agc * status The status code for the termination 607 1.1 agc * logout The logout reason code 608 1.1 agc 609 1.1 agc */ 610 1.1 agc 611 1.1 agc void 612 1.33 mlelstv kill_session(uint32_t sid, uint32_t status, int logout, bool recover) 613 1.1 agc { 614 1.33 mlelstv session_t *sess; 615 1.22 mlelstv connection_t *conn; 616 1.1 agc 617 1.1 agc DEB(1, ("ISCSI: kill_session %d, status %d, logout %d, recover %d\n", 618 1.33 mlelstv sid, status, logout, recover)); 619 1.1 agc 620 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 621 1.33 mlelstv 622 1.33 mlelstv sess = find_session(sid); 623 1.33 mlelstv if (sess == NULL) { 624 1.33 mlelstv mutex_exit(&iscsi_cleanup_mtx); 625 1.33 mlelstv 626 1.33 mlelstv DEB(5, ("Session %u already gone\n", sid)); 627 1.33 mlelstv return; 628 1.33 mlelstv } 629 1.33 mlelstv 630 1.28 christos if (sess->s_terminating) { 631 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 632 1.22 mlelstv 633 1.28 christos DEB(5, ("Session is being killed with status %d\n",sess->s_terminating)); 634 1.14 mlelstv return; 635 1.14 mlelstv } 636 1.14 mlelstv 637 1.1 agc /* 638 1.1 agc * don't do anything if session isn't established yet, termination will be 639 1.1 agc * handled elsewhere 640 1.1 agc */ 641 1.28 christos if (sess->s_sessions.tqe_next == NULL && sess->s_sessions.tqe_prev == NULL) { 642 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 643 1.22 mlelstv 644 1.22 mlelstv DEB(5, ("Session is being killed which is not yet established\n")); 645 1.1 agc return; 646 1.1 agc } 647 1.1 agc 648 1.1 agc if (recover) { 649 1.1 agc /* 650 1.1 agc * Only recover when there's just one active connection left. 651 1.1 agc * Otherwise we get in all sorts of timing problems, and it doesn't 652 1.1 agc * make much sense anyway to recover when the other side has 653 1.1 agc * requested that we kill a multipathed session. 654 1.1 agc */ 655 1.37 mlelstv conn = NULL; 656 1.37 mlelstv if (sess->s_active_connections == 1) 657 1.28 christos conn = assign_connection(sess, FALSE); 658 1.37 mlelstv 659 1.37 mlelstv mutex_exit(&iscsi_cleanup_mtx); 660 1.37 mlelstv 661 1.37 mlelstv if (conn != NULL) 662 1.37 mlelstv kill_connection(conn, status, logout, TRUE); 663 1.1 agc return; 664 1.1 agc } 665 1.1 agc 666 1.28 christos if (sess->s_refcount > 0) { 667 1.22 mlelstv mutex_exit(&iscsi_cleanup_mtx); 668 1.22 mlelstv 669 1.22 mlelstv DEB(5, ("Session is being killed while in use (refcnt = %d)\n", 670 1.28 christos sess->s_refcount)); 671 1.22 mlelstv return; 672 1.22 mlelstv } 673 1.22 mlelstv 674 1.22 mlelstv /* Remove session from global list */ 675 1.28 christos sess->s_terminating = status; 676 1.28 christos TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions); 677 1.28 christos sess->s_sessions.tqe_next = NULL; 678 1.28 christos sess->s_sessions.tqe_prev = NULL; 679 1.22 mlelstv 680 1.33 mlelstv /* 681 1.33 mlelstv * If all connections are already gone, trigger cleanup 682 1.33 mlelstv * otherwise, the last connection will do this 683 1.33 mlelstv */ 684 1.33 mlelstv if (sess->s_active_connections == 0) 685 1.33 mlelstv iscsi_notify_cleanup(); 686 1.33 mlelstv 687 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 688 1.1 agc 689 1.1 agc /* kill all connections */ 690 1.28 christos while ((conn = TAILQ_FIRST(&sess->s_conn_list)) != NULL) { 691 1.22 mlelstv kill_connection(conn, status, logout, FALSE); 692 1.1 agc logout = NO_LOGOUT; 693 1.1 agc } 694 1.1 agc } 695 1.1 agc 696 1.1 agc 697 1.1 agc /* 698 1.1 agc * create_connection: 699 1.1 agc * Create and init the necessary framework for a connection: 700 1.33 mlelstv * Take over userland socket 701 1.1 agc * Alloc the connection structure itself 702 1.1 agc * Copy connection parameters 703 1.1 agc * Create the send and receive threads 704 1.1 agc * And finally, log in. 705 1.1 agc * 706 1.1 agc * Parameter: 707 1.1 agc * par IN/OUT: The login parameters 708 1.1 agc * session IN: The owning session 709 1.8 joerg * l IN: The lwp pointer of the caller 710 1.1 agc * 711 1.1 agc * Returns: 0 on success 712 1.1 agc * >0 on failure, connection structure deleted 713 1.1 agc * <0 on failure, connection is still terminating 714 1.1 agc */ 715 1.1 agc 716 1.14 mlelstv static int 717 1.28 christos create_connection(iscsi_login_parameters_t *par, session_t *sess, 718 1.8 joerg struct lwp *l) 719 1.1 agc { 720 1.28 christos connection_t *conn; 721 1.14 mlelstv int rc; 722 1.1 agc 723 1.28 christos DEB(1, ("Create Connection for Session %d\n", sess->s_id)); 724 1.1 agc 725 1.28 christos if (sess->s_MaxConnections && 726 1.28 christos sess->s_active_connections >= sess->s_MaxConnections) { 727 1.1 agc DEBOUT(("Too many connections (max = %d, curr = %d)\n", 728 1.28 christos sess->s_MaxConnections, sess->s_active_connections)); 729 1.33 mlelstv /* Always close descriptor */ 730 1.33 mlelstv fd_close(par->socket); 731 1.33 mlelstv 732 1.1 agc par->status = ISCSI_STATUS_MAXED_CONNECTIONS; 733 1.1 agc return EIO; 734 1.1 agc } 735 1.1 agc 736 1.28 christos conn = malloc(sizeof(*conn), M_DEVBUF, M_WAITOK | M_ZERO); 737 1.28 christos if (conn == NULL) { 738 1.1 agc DEBOUT(("No mem for connection\n")); 739 1.33 mlelstv 740 1.33 mlelstv /* Always close descriptor */ 741 1.33 mlelstv fd_close(par->socket); 742 1.33 mlelstv 743 1.1 agc par->status = ISCSI_STATUS_NO_RESOURCES; 744 1.1 agc return EIO; 745 1.1 agc } 746 1.1 agc 747 1.33 mlelstv rc = get_socket(par->socket, &conn->c_sock); 748 1.34 mlelstv if (rc != EBADF) 749 1.34 mlelstv fd_close(par->socket); 750 1.33 mlelstv 751 1.33 mlelstv if (rc) { 752 1.33 mlelstv DEBOUT(("Invalid socket %d\n", par->socket)); 753 1.33 mlelstv free(conn, M_DEVBUF); 754 1.33 mlelstv par->status = ISCSI_STATUS_INVALID_SOCKET; 755 1.33 mlelstv return rc; 756 1.33 mlelstv } 757 1.33 mlelstv 758 1.33 mlelstv DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n", 759 1.33 mlelstv par->socket, conn->c_sock)); 760 1.33 mlelstv 761 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 762 1.1 agc /* create a unique ID */ 763 1.1 agc do { 764 1.28 christos ++sess->s_conn_id; 765 1.28 christos } while (!sess->s_conn_id || 766 1.28 christos find_connection(sess, sess->s_conn_id) != NULL); 767 1.28 christos par->connection_id = conn->c_id = sess->s_conn_id; 768 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 769 1.28 christos DEB(99, ("Connection ID = %d\n", conn->c_id)); 770 1.1 agc 771 1.28 christos conn->c_session = sess; 772 1.1 agc 773 1.28 christos TAILQ_INIT(&conn->c_ccbs_waiting); 774 1.28 christos TAILQ_INIT(&conn->c_pdus_to_send); 775 1.28 christos TAILQ_INIT(&conn->c_pdu_pool); 776 1.1 agc 777 1.28 christos mutex_init(&conn->c_lock, MUTEX_DEFAULT, IPL_BIO); 778 1.28 christos cv_init(&conn->c_conn_cv, "conn"); 779 1.28 christos cv_init(&conn->c_pdu_cv, "pdupool"); 780 1.28 christos cv_init(&conn->c_ccb_cv, "ccbwait"); 781 1.28 christos cv_init(&conn->c_idle_cv, "idle"); 782 1.33 mlelstv rw_init(&conn->c_sock_rw); 783 1.14 mlelstv 784 1.28 christos callout_init(&conn->c_timeout, CALLOUT_MPSAFE); 785 1.28 christos callout_setfunc(&conn->c_timeout, connection_timeout_co, conn); 786 1.28 christos conn->c_idle_timeout_val = CONNECTION_IDLE_TIMEOUT; 787 1.1 agc 788 1.28 christos init_sernum(&conn->c_StatSN_buf); 789 1.28 christos create_pdus(conn); 790 1.1 agc 791 1.28 christos conn->c_threadobj = l; 792 1.28 christos conn->c_login_par = par; 793 1.1 agc 794 1.14 mlelstv DEB(5, ("Creating receive thread\n")); 795 1.22 mlelstv if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_rcv_thread, 796 1.28 christos conn, &conn->c_rcvproc, 797 1.1 agc "ConnRcv")) != 0) { 798 1.1 agc DEBOUT(("Can't create rcv thread (rc %d)\n", rc)); 799 1.1 agc 800 1.28 christos release_socket(conn->c_sock); 801 1.33 mlelstv rw_destroy(&conn->c_sock_rw); 802 1.28 christos callout_destroy(&conn->c_timeout); 803 1.28 christos cv_destroy(&conn->c_idle_cv); 804 1.28 christos cv_destroy(&conn->c_ccb_cv); 805 1.28 christos cv_destroy(&conn->c_pdu_cv); 806 1.28 christos cv_destroy(&conn->c_conn_cv); 807 1.28 christos mutex_destroy(&conn->c_lock); 808 1.28 christos free(conn, M_DEVBUF); 809 1.1 agc par->status = ISCSI_STATUS_NO_RESOURCES; 810 1.1 agc return rc; 811 1.1 agc } 812 1.14 mlelstv DEB(5, ("Creating send thread\n")); 813 1.22 mlelstv if ((rc = kthread_create(PRI_BIO, KTHREAD_MPSAFE, NULL, iscsi_send_thread, 814 1.28 christos conn, &conn->c_sendproc, 815 1.1 agc "ConnSend")) != 0) { 816 1.1 agc DEBOUT(("Can't create send thread (rc %d)\n", rc)); 817 1.1 agc 818 1.28 christos conn->c_terminating = ISCSI_STATUS_NO_RESOURCES; 819 1.1 agc 820 1.1 agc /* 821 1.1 agc * We must close the socket here to force the receive 822 1.1 agc * thread to wake up 823 1.1 agc */ 824 1.28 christos DEBC(conn, 1, ("Closing Socket %p\n", conn->c_sock)); 825 1.28 christos mutex_enter(&conn->c_sock->f_lock); 826 1.28 christos conn->c_sock->f_count += 1; 827 1.28 christos mutex_exit(&conn->c_sock->f_lock); 828 1.28 christos closef(conn->c_sock); 829 1.1 agc 830 1.1 agc /* give receive thread time to exit */ 831 1.14 mlelstv kpause("settle", false, 2 * hz, NULL); 832 1.1 agc 833 1.28 christos release_socket(conn->c_sock); 834 1.28 christos callout_destroy(&conn->c_timeout); 835 1.33 mlelstv rw_destroy(&conn->c_sock_rw); 836 1.28 christos cv_destroy(&conn->c_idle_cv); 837 1.28 christos cv_destroy(&conn->c_ccb_cv); 838 1.28 christos cv_destroy(&conn->c_pdu_cv); 839 1.28 christos cv_destroy(&conn->c_conn_cv); 840 1.28 christos mutex_destroy(&conn->c_lock); 841 1.28 christos free(conn, M_DEVBUF); 842 1.1 agc par->status = ISCSI_STATUS_NO_RESOURCES; 843 1.1 agc return rc; 844 1.1 agc } 845 1.1 agc 846 1.1 agc /* 847 1.1 agc * At this point, each thread will tie 'sock' into its own file descriptor 848 1.1 agc * tables w/o increasing the use count - they will inherit the use 849 1.1 agc * increments performed in get_socket(). 850 1.1 agc */ 851 1.1 agc 852 1.28 christos if ((rc = send_login(conn)) != 0) { 853 1.28 christos DEBC(conn, 0, ("Login failed (rc %d)\n", rc)); 854 1.1 agc /* Don't attempt to recover, there seems to be something amiss */ 855 1.28 christos kill_connection(conn, rc, NO_LOGOUT, FALSE); 856 1.1 agc par->status = rc; 857 1.1 agc return -1; 858 1.1 agc } 859 1.1 agc 860 1.25 mlelstv mutex_enter(&iscsi_cleanup_mtx); 861 1.28 christos if (sess->s_terminating) { 862 1.25 mlelstv mutex_exit(&iscsi_cleanup_mtx); 863 1.28 christos DEBC(conn, 0, ("Session terminating\n")); 864 1.28 christos kill_connection(conn, rc, NO_LOGOUT, FALSE); 865 1.28 christos par->status = sess->s_terminating; 866 1.22 mlelstv return -1; 867 1.22 mlelstv } 868 1.28 christos conn->c_state = ST_FULL_FEATURE; 869 1.28 christos TAILQ_INSERT_TAIL(&sess->s_conn_list, conn, c_connections); 870 1.28 christos conn->c_in_session = TRUE; 871 1.28 christos sess->s_total_connections++; 872 1.28 christos sess->s_active_connections++; 873 1.28 christos sess->s_mru_connection = conn; 874 1.25 mlelstv mutex_exit(&iscsi_cleanup_mtx); 875 1.1 agc 876 1.28 christos DEBC(conn, 5, ("Connection created successfully!\n")); 877 1.1 agc return 0; 878 1.1 agc } 879 1.1 agc 880 1.1 agc 881 1.1 agc /* 882 1.1 agc * recreate_connection: 883 1.1 agc * Revive dead connection 884 1.1 agc * 885 1.1 agc * Parameter: 886 1.1 agc * par IN/OUT: The login parameters 887 1.1 agc * conn IN: The connection 888 1.8 joerg * l IN: The lwp pointer of the caller 889 1.1 agc * 890 1.1 agc * Returns: 0 on success 891 1.1 agc * >0 on failure, connection structure deleted 892 1.1 agc * <0 on failure, connection is still terminating 893 1.1 agc */ 894 1.1 agc 895 1.14 mlelstv static int 896 1.28 christos recreate_connection(iscsi_login_parameters_t *par, session_t *sess, 897 1.28 christos connection_t *conn, struct lwp *l) 898 1.1 agc { 899 1.14 mlelstv int rc; 900 1.1 agc ccb_t *ccb; 901 1.1 agc ccb_list_t old_waiting; 902 1.17 mlelstv pdu_t *pdu; 903 1.17 mlelstv uint32_t sn; 904 1.1 agc 905 1.1 agc DEB(1, ("ReCreate Connection %d for Session %d, ERL=%d\n", 906 1.28 christos conn->c_id, conn->c_session->s_id, 907 1.28 christos conn->c_session->s_ErrorRecoveryLevel)); 908 1.1 agc 909 1.28 christos if (sess->s_MaxConnections && 910 1.28 christos sess->s_active_connections >= sess->s_MaxConnections) { 911 1.1 agc DEBOUT(("Too many connections (max = %d, curr = %d)\n", 912 1.28 christos sess->s_MaxConnections, sess->s_active_connections)); 913 1.33 mlelstv 914 1.34 mlelstv /* Close the desecriptor */ 915 1.34 mlelstv rc = EIO; 916 1.34 mlelstv if (fd_getfile(par->socket) != NULL) 917 1.34 mlelstv rc = fd_close(par->socket); 918 1.33 mlelstv 919 1.1 agc par->status = ISCSI_STATUS_MAXED_CONNECTIONS; 920 1.34 mlelstv return rc; 921 1.1 agc } 922 1.1 agc 923 1.33 mlelstv rw_enter(&conn->c_sock_rw, RW_WRITER); 924 1.28 christos if (conn->c_sock != NULL) { 925 1.28 christos closef(conn->c_sock); 926 1.28 christos conn->c_sock = NULL; 927 1.6 mlelstv } 928 1.33 mlelstv rc = get_socket(par->socket, &conn->c_sock); 929 1.33 mlelstv rw_exit(&conn->c_sock_rw); 930 1.34 mlelstv if (rc != EBADF) 931 1.34 mlelstv fd_close(par->socket); 932 1.6 mlelstv 933 1.33 mlelstv if (rc) { 934 1.1 agc DEBOUT(("Invalid socket %d\n", par->socket)); 935 1.1 agc par->status = ISCSI_STATUS_INVALID_SOCKET; 936 1.1 agc return rc; 937 1.1 agc } 938 1.33 mlelstv 939 1.28 christos DEBC(conn, 1, ("get_socket: par_sock=%d, fdesc=%p\n", 940 1.28 christos par->socket, conn->c_sock)); 941 1.1 agc 942 1.28 christos conn->c_threadobj = l; 943 1.28 christos conn->c_login_par = par; 944 1.28 christos conn->c_terminating = ISCSI_STATUS_SUCCESS; 945 1.28 christos conn->c_recover++; 946 1.28 christos conn->c_num_timeouts = 0; 947 1.28 christos conn->c_state = ST_SEC_NEG; 948 1.28 christos conn->c_HeaderDigest = 0; 949 1.28 christos conn->c_DataDigest = 0; 950 1.1 agc 951 1.28 christos sess->s_active_connections++; 952 1.1 agc 953 1.1 agc TAILQ_INIT(&old_waiting); 954 1.22 mlelstv 955 1.28 christos mutex_enter(&conn->c_lock); 956 1.28 christos while ((ccb = TAILQ_FIRST(&conn->c_ccbs_waiting)) != NULL) { 957 1.22 mlelstv suspend_ccb(ccb, FALSE); 958 1.28 christos TAILQ_INSERT_TAIL(&old_waiting, ccb, ccb_chain); 959 1.22 mlelstv } 960 1.28 christos init_sernum(&conn->c_StatSN_buf); 961 1.28 christos cv_broadcast(&conn->c_idle_cv); 962 1.28 christos mutex_exit(&conn->c_lock); 963 1.1 agc 964 1.28 christos if ((rc = send_login(conn)) != 0) { 965 1.33 mlelstv DEBC(conn, 0, ("Re-Login failed (rc %d)\n", rc)); 966 1.1 agc while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) { 967 1.28 christos TAILQ_REMOVE(&old_waiting, ccb, ccb_chain); 968 1.6 mlelstv wake_ccb(ccb, rc); 969 1.1 agc } 970 1.1 agc /* Don't attempt to recover, there seems to be something amiss */ 971 1.28 christos kill_connection(conn, rc, NO_LOGOUT, FALSE); 972 1.1 agc par->status = rc; 973 1.1 agc return -1; 974 1.1 agc } 975 1.1 agc 976 1.28 christos DEBC(conn, 9, ("Re-Login successful\n")); 977 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 978 1.6 mlelstv 979 1.28 christos conn->c_state = ST_FULL_FEATURE; 980 1.28 christos sess->s_mru_connection = conn; 981 1.1 agc 982 1.1 agc while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) { 983 1.28 christos TAILQ_REMOVE(&old_waiting, ccb, ccb_chain); 984 1.28 christos mutex_enter(&conn->c_lock); 985 1.6 mlelstv suspend_ccb(ccb, TRUE); 986 1.28 christos mutex_exit(&conn->c_lock); 987 1.1 agc 988 1.28 christos rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN); 989 1.1 agc /* if we get an error on reassign, restart the original request */ 990 1.28 christos if (rc && ccb->ccb_pdu_waiting != NULL) { 991 1.28 christos mutex_enter(&sess->s_lock); 992 1.28 christos if (sn_a_lt_b(ccb->ccb_CmdSN, sess->s_ExpCmdSN)) { 993 1.28 christos pdu = ccb->ccb_pdu_waiting; 994 1.28 christos sn = get_sernum(sess, pdu); 995 1.1 agc 996 1.1 agc /* update CmdSN */ 997 1.28 christos DEBC(conn, 0, ("Resend ccb %p (%d) - updating CmdSN old %u, new %u\n", 998 1.28 christos ccb, rc, ccb->ccb_CmdSN, sn)); 999 1.28 christos ccb->ccb_CmdSN = sn; 1000 1.28 christos pdu->pdu_hdr.pduh_p.command.CmdSN = htonl(ccb->ccb_CmdSN); 1001 1.22 mlelstv } else { 1002 1.28 christos DEBC(conn, 0, ("Resend ccb %p (%d) - CmdSN %u\n", 1003 1.28 christos ccb, rc, ccb->ccb_CmdSN)); 1004 1.1 agc } 1005 1.28 christos mutex_exit(&sess->s_lock); 1006 1.1 agc resend_pdu(ccb); 1007 1.1 agc } else { 1008 1.28 christos DEBC(conn, 0, ("Resend ccb %p (%d) CmdSN %u - reassigned\n", 1009 1.28 christos ccb, rc, ccb->ccb_CmdSN)); 1010 1.16 mlelstv ccb_timeout_start(ccb, COMMAND_TIMEOUT); 1011 1.1 agc } 1012 1.1 agc } 1013 1.1 agc 1014 1.28 christos mutex_enter(&sess->s_lock); 1015 1.28 christos cv_broadcast(&sess->s_sess_cv); 1016 1.28 christos mutex_exit(&sess->s_lock); 1017 1.1 agc 1018 1.28 christos DEBC(conn, 0, ("Connection ReCreated successfully - status %d\n", 1019 1.1 agc par->status)); 1020 1.3 mlelstv 1021 1.1 agc return 0; 1022 1.1 agc } 1023 1.1 agc 1024 1.1 agc /* -------------------------------------------------------------------------- */ 1025 1.1 agc 1026 1.1 agc /* 1027 1.1 agc * check_login_pars: 1028 1.1 agc * Check the parameters passed into login/add_connection 1029 1.1 agc * for validity and consistency. 1030 1.1 agc * 1031 1.1 agc * Parameter: 1032 1.1 agc * par The login parameters 1033 1.1 agc * 1034 1.1 agc * Returns: 0 on success, else an error code. 1035 1.1 agc */ 1036 1.1 agc 1037 1.14 mlelstv static int 1038 1.1 agc check_login_pars(iscsi_login_parameters_t *par) 1039 1.1 agc { 1040 1.1 agc int i, n; 1041 1.1 agc 1042 1.1 agc if (par->is_present.auth_info) { 1043 1.1 agc /* check consistency of authentication parameters */ 1044 1.1 agc 1045 1.1 agc if (par->auth_info.auth_number > ISCSI_AUTH_OPTIONS) { 1046 1.1 agc DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number)); 1047 1.1 agc return ISCSI_STATUS_PARAMETER_INVALID; 1048 1.1 agc } 1049 1.1 agc 1050 1.1 agc if (par->auth_info.auth_number > 2) { 1051 1.1 agc DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number)); 1052 1.1 agc return ISCSI_STATUS_NOTIMPL; 1053 1.1 agc } 1054 1.1 agc 1055 1.1 agc for (i = 0, n = 0; i < par->auth_info.auth_number; i++) { 1056 1.1 agc #if 0 1057 1.1 agc if (par->auth_info.auth_type[i] < ISCSI_AUTH_None) { 1058 1.1 agc DEBOUT(("Auth type invalid: %d\n", 1059 1.1 agc par->auth_info.auth_type[i])); 1060 1.1 agc return ISCSI_STATUS_PARAMETER_INVALID; 1061 1.1 agc } 1062 1.1 agc #endif 1063 1.1 agc if (par->auth_info.auth_type[i] > ISCSI_AUTH_CHAP) { 1064 1.1 agc DEBOUT(("Auth type invalid: %d\n", 1065 1.1 agc par->auth_info.auth_type[i])); 1066 1.1 agc return ISCSI_STATUS_NOTIMPL; 1067 1.1 agc } 1068 1.1 agc n = max(n, par->auth_info.auth_type[i]); 1069 1.1 agc } 1070 1.1 agc if (n) { 1071 1.1 agc if (!par->is_present.password || 1072 1.1 agc (par->auth_info.mutual_auth && 1073 1.1 agc !par->is_present.target_password)) { 1074 1.1 agc DEBOUT(("Password missing\n")); 1075 1.1 agc return ISCSI_STATUS_PARAMETER_MISSING; 1076 1.1 agc } 1077 1.1 agc /* Note: Default for user-name is initiator name */ 1078 1.1 agc } 1079 1.1 agc } 1080 1.1 agc if (par->login_type != ISCSI_LOGINTYPE_DISCOVERY && 1081 1.1 agc !par->is_present.TargetName) { 1082 1.1 agc DEBOUT(("Target name missing, login type %d\n", par->login_type)); 1083 1.1 agc return ISCSI_STATUS_PARAMETER_MISSING; 1084 1.1 agc } 1085 1.1 agc if (par->is_present.MaxRecvDataSegmentLength) { 1086 1.1 agc if (par->MaxRecvDataSegmentLength < 512 || 1087 1.1 agc par->MaxRecvDataSegmentLength > 0xffffff) { 1088 1.1 agc DEBOUT(("MaxRecvDataSegmentLength invalid: %d\n", 1089 1.1 agc par->MaxRecvDataSegmentLength)); 1090 1.1 agc return ISCSI_STATUS_PARAMETER_INVALID; 1091 1.1 agc } 1092 1.1 agc } 1093 1.4 mlelstv return 0; 1094 1.1 agc } 1095 1.1 agc 1096 1.1 agc 1097 1.1 agc /* 1098 1.1 agc * login: 1099 1.1 agc * Handle the login ioctl - Create a session: 1100 1.1 agc * Alloc the session structure 1101 1.1 agc * Copy session parameters 1102 1.1 agc * And call create_connection to establish the connection. 1103 1.1 agc * 1104 1.1 agc * Parameter: 1105 1.1 agc * par IN/OUT: The login parameters 1106 1.8 joerg * l IN: The lwp pointer of the caller 1107 1.1 agc */ 1108 1.1 agc 1109 1.14 mlelstv static void 1110 1.14 mlelstv login(iscsi_login_parameters_t *par, struct lwp *l, device_t dev) 1111 1.1 agc { 1112 1.28 christos session_t *sess; 1113 1.14 mlelstv int rc; 1114 1.1 agc 1115 1.1 agc DEB(99, ("ISCSI: login\n")); 1116 1.1 agc 1117 1.5 mlelstv if (!iscsi_InitiatorName[0]) { 1118 1.1 agc DEB(1, ("No Initiator Name\n")); 1119 1.1 agc par->status = ISCSI_STATUS_NO_INITIATOR_NAME; 1120 1.1 agc return; 1121 1.1 agc } 1122 1.1 agc 1123 1.1 agc if ((par->status = check_login_pars(par)) != 0) 1124 1.1 agc return; 1125 1.1 agc 1126 1.1 agc /* alloc the session */ 1127 1.28 christos sess = malloc(sizeof(*sess), M_DEVBUF, M_WAITOK | M_ZERO); 1128 1.28 christos if (sess == NULL) { 1129 1.1 agc DEBOUT(("No mem for session\n")); 1130 1.1 agc par->status = ISCSI_STATUS_NO_RESOURCES; 1131 1.1 agc return; 1132 1.1 agc } 1133 1.28 christos TAILQ_INIT(&sess->s_conn_list); 1134 1.28 christos TAILQ_INIT(&sess->s_ccb_pool); 1135 1.1 agc 1136 1.28 christos mutex_init(&sess->s_lock, MUTEX_DEFAULT, IPL_BIO); 1137 1.28 christos cv_init(&sess->s_sess_cv, "session"); 1138 1.28 christos cv_init(&sess->s_ccb_cv, "ccb"); 1139 1.14 mlelstv 1140 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1141 1.1 agc /* create a unique ID */ 1142 1.1 agc do { 1143 1.1 agc ++current_id; 1144 1.1 agc } while (!current_id || find_session(current_id) != NULL); 1145 1.28 christos par->session_id = sess->s_id = current_id; 1146 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1147 1.1 agc 1148 1.28 christos create_ccbs(sess); 1149 1.28 christos sess->s_login_type = par->login_type; 1150 1.28 christos sess->s_CmdSN = 1; 1151 1.1 agc 1152 1.28 christos if ((rc = create_connection(par, sess, l)) != 0) { 1153 1.1 agc if (rc > 0) { 1154 1.28 christos destroy_ccbs(sess); 1155 1.28 christos cv_destroy(&sess->s_ccb_cv); 1156 1.28 christos cv_destroy(&sess->s_sess_cv); 1157 1.28 christos mutex_destroy(&sess->s_lock); 1158 1.28 christos free(sess, M_DEVBUF); 1159 1.1 agc } 1160 1.1 agc return; 1161 1.1 agc } 1162 1.1 agc 1163 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1164 1.28 christos TAILQ_INSERT_HEAD(&iscsi_sessions, sess, s_sessions); 1165 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1166 1.1 agc 1167 1.1 agc /* Session established, map LUNs? */ 1168 1.1 agc if (par->login_type == ISCSI_LOGINTYPE_MAP) { 1169 1.28 christos copyinstr(par->TargetName, sess->s_tgtname, 1170 1.28 christos sizeof(sess->s_tgtname), NULL); 1171 1.28 christos DEB(1, ("Login: map session %d\n", sess->s_id)); 1172 1.28 christos if (!map_session(sess, dev)) { 1173 1.28 christos DEB(1, ("Login: map session %d failed\n", sess->s_id)); 1174 1.33 mlelstv kill_session(par->session_id, ISCSI_STATUS_MAP_FAILED, 1175 1.1 agc LOGOUT_SESSION, FALSE); 1176 1.1 agc par->status = ISCSI_STATUS_MAP_FAILED; 1177 1.1 agc return; 1178 1.1 agc } 1179 1.1 agc } 1180 1.1 agc } 1181 1.1 agc 1182 1.1 agc 1183 1.1 agc /* 1184 1.1 agc * logout: 1185 1.1 agc * Handle the logout ioctl - Kill a session. 1186 1.1 agc * 1187 1.1 agc * Parameter: 1188 1.1 agc * par IN/OUT: The login parameters 1189 1.1 agc */ 1190 1.1 agc 1191 1.14 mlelstv static void 1192 1.1 agc logout(iscsi_logout_parameters_t *par) 1193 1.1 agc { 1194 1.1 agc session_t *session; 1195 1.1 agc 1196 1.1 agc DEB(5, ("ISCSI: logout session %d\n", par->session_id)); 1197 1.1 agc 1198 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1199 1.1 agc if ((session = find_session(par->session_id)) == NULL) { 1200 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1201 1.1 agc DEBOUT(("Session %d not found\n", par->session_id)); 1202 1.1 agc par->status = ISCSI_STATUS_INVALID_SESSION_ID; 1203 1.1 agc return; 1204 1.1 agc } 1205 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1206 1.1 agc /* If the session exists, this always succeeds */ 1207 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 1208 1.1 agc 1209 1.33 mlelstv kill_session(par->session_id, 1210 1.33 mlelstv ISCSI_STATUS_LOGOUT, LOGOUT_SESSION, 1211 1.33 mlelstv FALSE); 1212 1.1 agc } 1213 1.1 agc 1214 1.1 agc 1215 1.1 agc /* 1216 1.1 agc * add_connection: 1217 1.1 agc * Handle the add_connection ioctl. 1218 1.1 agc * 1219 1.1 agc * Parameter: 1220 1.1 agc * par IN/OUT: The login parameters 1221 1.8 joerg * l IN: The lwp pointer of the caller 1222 1.1 agc */ 1223 1.1 agc 1224 1.33 mlelstv static int 1225 1.8 joerg add_connection(iscsi_login_parameters_t *par, struct lwp *l) 1226 1.1 agc { 1227 1.1 agc session_t *session; 1228 1.1 agc 1229 1.1 agc DEB(5, ("ISCSI: add_connection to session %d\n", par->session_id)); 1230 1.1 agc 1231 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1232 1.1 agc if ((session = find_session(par->session_id)) == NULL) { 1233 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1234 1.1 agc DEBOUT(("Session %d not found\n", par->session_id)); 1235 1.1 agc par->status = ISCSI_STATUS_INVALID_SESSION_ID; 1236 1.33 mlelstv return -1; 1237 1.1 agc } 1238 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1239 1.33 mlelstv 1240 1.33 mlelstv par->status = check_login_pars(par); 1241 1.33 mlelstv if (par->status) 1242 1.33 mlelstv return -1; 1243 1.33 mlelstv 1244 1.33 mlelstv return create_connection(par, session, l); 1245 1.1 agc } 1246 1.1 agc 1247 1.1 agc 1248 1.1 agc /* 1249 1.1 agc * remove_connection: 1250 1.1 agc * Handle the remove_connection ioctl. 1251 1.1 agc * 1252 1.1 agc * Parameter: 1253 1.1 agc * par IN/OUT: The remove parameters 1254 1.1 agc */ 1255 1.1 agc 1256 1.14 mlelstv static void 1257 1.1 agc remove_connection(iscsi_remove_parameters_t *par) 1258 1.1 agc { 1259 1.1 agc connection_t *conn; 1260 1.1 agc session_t *session; 1261 1.1 agc 1262 1.1 agc DEB(5, ("ISCSI: remove_connection %d from session %d\n", 1263 1.1 agc par->connection_id, par->session_id)); 1264 1.1 agc 1265 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1266 1.1 agc if ((session = find_session(par->session_id)) == NULL) { 1267 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1268 1.1 agc DEBOUT(("Session %d not found\n", par->session_id)); 1269 1.1 agc par->status = ISCSI_STATUS_INVALID_SESSION_ID; 1270 1.1 agc return; 1271 1.1 agc } 1272 1.1 agc 1273 1.1 agc if ((conn = find_connection(session, par->connection_id)) == NULL) { 1274 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1275 1.1 agc DEBOUT(("Connection %d not found in session %d\n", 1276 1.1 agc par->connection_id, par->session_id)); 1277 1.1 agc 1278 1.1 agc par->status = ISCSI_STATUS_INVALID_CONNECTION_ID; 1279 1.1 agc } else { 1280 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1281 1.1 agc kill_connection(conn, ISCSI_STATUS_LOGOUT, LOGOUT_CONNECTION, 1282 1.1 agc FALSE); 1283 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 1284 1.1 agc } 1285 1.1 agc } 1286 1.1 agc 1287 1.1 agc 1288 1.1 agc /* 1289 1.1 agc * restore_connection: 1290 1.1 agc * Handle the restore_connection ioctl. 1291 1.1 agc * 1292 1.1 agc * Parameter: 1293 1.1 agc * par IN/OUT: The login parameters 1294 1.8 joerg * l IN: The lwp pointer of the caller 1295 1.1 agc */ 1296 1.1 agc 1297 1.14 mlelstv static void 1298 1.8 joerg restore_connection(iscsi_login_parameters_t *par, struct lwp *l) 1299 1.1 agc { 1300 1.28 christos session_t *sess; 1301 1.28 christos connection_t *conn; 1302 1.1 agc 1303 1.6 mlelstv DEB(1, ("ISCSI: restore_connection %d of session %d\n", 1304 1.1 agc par->connection_id, par->session_id)); 1305 1.1 agc 1306 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1307 1.28 christos if ((sess = find_session(par->session_id)) == NULL) { 1308 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1309 1.1 agc DEBOUT(("Session %d not found\n", par->session_id)); 1310 1.1 agc par->status = ISCSI_STATUS_INVALID_SESSION_ID; 1311 1.1 agc return; 1312 1.1 agc } 1313 1.28 christos if ((conn = find_connection(sess, par->connection_id)) == NULL) { 1314 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1315 1.1 agc DEBOUT(("Connection %d not found in session %d\n", 1316 1.1 agc par->connection_id, par->session_id)); 1317 1.1 agc par->status = ISCSI_STATUS_INVALID_CONNECTION_ID; 1318 1.1 agc return; 1319 1.1 agc } 1320 1.33 mlelstv if (!conn->c_terminating) { 1321 1.33 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1322 1.33 mlelstv DEBC(conn, 0, ("Connection is alive\n")); 1323 1.33 mlelstv par->status = ISCSI_STATUS_SUCCESS; 1324 1.33 mlelstv return; 1325 1.33 mlelstv } 1326 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1327 1.1 agc 1328 1.1 agc if ((par->status = check_login_pars(par)) == 0) { 1329 1.28 christos recreate_connection(par, sess, conn, l); 1330 1.1 agc } 1331 1.1 agc } 1332 1.1 agc 1333 1.1 agc 1334 1.1 agc #ifndef ISCSI_MINIMAL 1335 1.1 agc 1336 1.1 agc /* 1337 1.1 agc * io_command: 1338 1.1 agc * Handle the io_command ioctl. 1339 1.1 agc * 1340 1.1 agc * Parameter: 1341 1.1 agc * par IN/OUT: The iocommand parameters 1342 1.8 joerg * l IN: The lwp pointer of the caller 1343 1.1 agc */ 1344 1.1 agc 1345 1.14 mlelstv static void 1346 1.8 joerg io_command(iscsi_iocommand_parameters_t *par, struct lwp *l) 1347 1.1 agc { 1348 1.1 agc uint32_t datalen = par->req.datalen; 1349 1.1 agc session_t *session; 1350 1.32 chs void *kbuf = NULL; 1351 1.32 chs int error; 1352 1.1 agc 1353 1.1 agc DEB(9, ("ISCSI: io_command, SID=%d, lun=%" PRIu64 "\n", par->session_id, par->lun)); 1354 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1355 1.1 agc if ((session = find_session(par->session_id)) == NULL) { 1356 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1357 1.1 agc DEBOUT(("Session %d not found\n", par->session_id)); 1358 1.1 agc par->status = ISCSI_STATUS_INVALID_SESSION_ID; 1359 1.1 agc return; 1360 1.1 agc } 1361 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1362 1.1 agc 1363 1.1 agc par->req.senselen_used = 0; 1364 1.1 agc par->req.datalen_used = 0; 1365 1.1 agc par->req.error = 0; 1366 1.1 agc par->req.status = 0; 1367 1.1 agc par->req.retsts = SCCMD_UNKNOWN; /* init to failure code */ 1368 1.1 agc 1369 1.1 agc if (par->req.cmdlen > 16 || par->req.senselen > sizeof(par->req.sense)) { 1370 1.1 agc par->status = ISCSI_STATUS_PARAMETER_INVALID; 1371 1.1 agc return; 1372 1.1 agc } 1373 1.1 agc 1374 1.32 chs if (datalen) { 1375 1.32 chs /* Arbitrarily limit datalen to 8k. */ 1376 1.32 chs if (datalen > 8192) { 1377 1.32 chs par->status = ISCSI_STATUS_PARAMETER_INVALID; 1378 1.32 chs return; 1379 1.32 chs } 1380 1.32 chs kbuf = kmem_zalloc(datalen, KM_SLEEP); 1381 1.32 chs if ((par->req.flags & SCCMD_WRITE) != 0) { 1382 1.32 chs error = copyin(par->req.databuf, kbuf, datalen); 1383 1.32 chs if (error) { 1384 1.32 chs kmem_free(kbuf, datalen); 1385 1.32 chs par->status = ISCSI_STATUS_PARAMETER_INVALID; 1386 1.32 chs return; 1387 1.32 chs } 1388 1.32 chs } 1389 1.1 agc } 1390 1.1 agc par->status = send_io_command(session, par->lun, &par->req, 1391 1.1 agc par->options.immediate, par->connection_id); 1392 1.1 agc 1393 1.32 chs if (kbuf) { 1394 1.32 chs if ((par->req.flags & SCCMD_READ) != 0) { 1395 1.32 chs (void) copyout(kbuf, par->req.databuf, datalen); 1396 1.32 chs } 1397 1.32 chs kmem_free(kbuf, datalen); 1398 1.1 agc } 1399 1.1 agc switch (par->status) { 1400 1.1 agc case ISCSI_STATUS_SUCCESS: 1401 1.1 agc par->req.retsts = SCCMD_OK; 1402 1.1 agc break; 1403 1.1 agc 1404 1.1 agc case ISCSI_STATUS_TARGET_BUSY: 1405 1.1 agc par->req.retsts = SCCMD_BUSY; 1406 1.1 agc break; 1407 1.1 agc 1408 1.1 agc case ISCSI_STATUS_TIMEOUT: 1409 1.1 agc case ISCSI_STATUS_SOCKET_ERROR: 1410 1.1 agc par->req.retsts = SCCMD_TIMEOUT; 1411 1.1 agc break; 1412 1.1 agc 1413 1.1 agc default: 1414 1.1 agc par->req.retsts = (par->req.senselen_used) ? SCCMD_SENSE 1415 1.1 agc : SCCMD_UNKNOWN; 1416 1.1 agc break; 1417 1.1 agc } 1418 1.1 agc } 1419 1.1 agc #endif 1420 1.1 agc 1421 1.1 agc /* 1422 1.1 agc * send_targets: 1423 1.1 agc * Handle the send_targets ioctl. 1424 1.1 agc * Note: If the passed buffer is too small to hold the complete response, 1425 1.1 agc * the response is kept in the session structure so it can be 1426 1.1 agc * retrieved with the next call to this function without having to go to 1427 1.1 agc * the target again. Once the complete response has been retrieved, it 1428 1.1 agc * is discarded. 1429 1.1 agc * 1430 1.1 agc * Parameter: 1431 1.1 agc * par IN/OUT: The send_targets parameters 1432 1.1 agc */ 1433 1.1 agc 1434 1.14 mlelstv static void 1435 1.1 agc send_targets(iscsi_send_targets_parameters_t *par) 1436 1.1 agc { 1437 1.1 agc int rc; 1438 1.1 agc uint32_t rlen, cplen; 1439 1.28 christos session_t *sess; 1440 1.1 agc 1441 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1442 1.28 christos if ((sess = find_session(par->session_id)) == NULL) { 1443 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1444 1.1 agc DEBOUT(("Session %d not found\n", par->session_id)); 1445 1.1 agc par->status = ISCSI_STATUS_INVALID_SESSION_ID; 1446 1.1 agc return; 1447 1.1 agc } 1448 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1449 1.1 agc 1450 1.1 agc DEB(9, ("ISCSI: send_targets, rsp_size=%d; Saved list: %p\n", 1451 1.28 christos par->response_size, sess->s_target_list)); 1452 1.1 agc 1453 1.28 christos if (sess->s_target_list == NULL) { 1454 1.28 christos rc = send_send_targets(sess, par->key); 1455 1.1 agc if (rc) { 1456 1.1 agc par->status = rc; 1457 1.1 agc return; 1458 1.1 agc } 1459 1.1 agc } 1460 1.28 christos rlen = sess->s_target_list_len; 1461 1.1 agc par->response_total = rlen; 1462 1.1 agc cplen = min(par->response_size, rlen); 1463 1.1 agc if (cplen) { 1464 1.28 christos copyout(sess->s_target_list, par->response_buffer, cplen); 1465 1.1 agc } 1466 1.1 agc par->response_used = cplen; 1467 1.1 agc 1468 1.1 agc /* If all of the response was copied, don't keep it around */ 1469 1.1 agc if (rlen && par->response_used == rlen) { 1470 1.28 christos free(sess->s_target_list, M_TEMP); 1471 1.28 christos sess->s_target_list = NULL; 1472 1.1 agc } 1473 1.1 agc 1474 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 1475 1.1 agc } 1476 1.1 agc 1477 1.1 agc 1478 1.1 agc /* 1479 1.1 agc * set_node_name: 1480 1.1 agc * Handle the set_node_name ioctl. 1481 1.1 agc * 1482 1.1 agc * Parameter: 1483 1.1 agc * par IN/OUT: The set_node_name parameters 1484 1.1 agc */ 1485 1.1 agc 1486 1.14 mlelstv static void 1487 1.1 agc set_node_name(iscsi_set_node_name_parameters_t *par) 1488 1.1 agc { 1489 1.1 agc 1490 1.1 agc if (strlen(par->InitiatorName) >= ISCSI_STRING_LENGTH || 1491 1.1 agc strlen(par->InitiatorAlias) >= ISCSI_STRING_LENGTH) { 1492 1.1 agc DEBOUT(("*** set_node_name string too long!\n")); 1493 1.1 agc par->status = ISCSI_STATUS_PARAMETER_INVALID; 1494 1.1 agc return; 1495 1.1 agc } 1496 1.5 mlelstv strlcpy(iscsi_InitiatorName, par->InitiatorName, sizeof(iscsi_InitiatorName)); 1497 1.5 mlelstv strlcpy(iscsi_InitiatorAlias, par->InitiatorAlias, sizeof(iscsi_InitiatorAlias)); 1498 1.5 mlelstv memcpy(&iscsi_InitiatorISID, par->ISID, 6); 1499 1.1 agc DEB(5, ("ISCSI: set_node_name, ISID A=%x, B=%x, C=%x, D=%x\n", 1500 1.5 mlelstv iscsi_InitiatorISID.ISID_A, iscsi_InitiatorISID.ISID_B, 1501 1.5 mlelstv iscsi_InitiatorISID.ISID_C, iscsi_InitiatorISID.ISID_D)); 1502 1.1 agc 1503 1.5 mlelstv if (!iscsi_InitiatorISID.ISID_A && !iscsi_InitiatorISID.ISID_B && 1504 1.5 mlelstv !iscsi_InitiatorISID.ISID_C && !iscsi_InitiatorISID.ISID_D) { 1505 1.5 mlelstv iscsi_InitiatorISID.ISID_A = T_FORMAT_EN; 1506 1.5 mlelstv iscsi_InitiatorISID.ISID_B = htons(0x1); 1507 1.5 mlelstv iscsi_InitiatorISID.ISID_C = 0x37; 1508 1.5 mlelstv iscsi_InitiatorISID.ISID_D = 0; 1509 1.1 agc } 1510 1.1 agc 1511 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 1512 1.1 agc } 1513 1.1 agc 1514 1.1 agc 1515 1.1 agc /* 1516 1.1 agc * connection_status: 1517 1.1 agc * Handle the connection_status ioctl. 1518 1.1 agc * 1519 1.1 agc * Parameter: 1520 1.1 agc * par IN/OUT: The status parameters 1521 1.1 agc */ 1522 1.1 agc 1523 1.14 mlelstv static void 1524 1.1 agc connection_status(iscsi_conn_status_parameters_t *par) 1525 1.1 agc { 1526 1.1 agc connection_t *conn; 1527 1.28 christos session_t *sess; 1528 1.1 agc 1529 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1530 1.28 christos if ((sess = find_session(par->session_id)) == NULL) { 1531 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1532 1.1 agc par->status = ISCSI_STATUS_INVALID_SESSION_ID; 1533 1.1 agc return; 1534 1.1 agc } 1535 1.1 agc 1536 1.1 agc if (par->connection_id) { 1537 1.28 christos conn = find_connection(sess, par->connection_id); 1538 1.1 agc } else { 1539 1.28 christos conn = TAILQ_FIRST(&sess->s_conn_list); 1540 1.1 agc } 1541 1.1 agc par->status = (conn == NULL) ? ISCSI_STATUS_INVALID_CONNECTION_ID : 1542 1.1 agc ISCSI_STATUS_SUCCESS; 1543 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1544 1.1 agc DEB(9, ("ISCSI: connection_status, session %d connection %d --> %d\n", 1545 1.1 agc par->session_id, par->connection_id, par->status)); 1546 1.1 agc } 1547 1.1 agc 1548 1.1 agc 1549 1.1 agc /* 1550 1.1 agc * get_version: 1551 1.1 agc * Handle the get_version ioctl. 1552 1.1 agc * 1553 1.1 agc * Parameter: 1554 1.1 agc * par IN/OUT: The version parameters 1555 1.1 agc */ 1556 1.1 agc 1557 1.14 mlelstv static void 1558 1.1 agc get_version(iscsi_get_version_parameters_t *par) 1559 1.1 agc { 1560 1.1 agc par->status = ISCSI_STATUS_SUCCESS; 1561 1.1 agc par->interface_version = INTERFACE_VERSION; 1562 1.1 agc par->major = VERSION_MAJOR; 1563 1.1 agc par->minor = VERSION_MINOR; 1564 1.1 agc strlcpy(par->version_string, VERSION_STRING, 1565 1.1 agc sizeof(par->version_string)); 1566 1.1 agc } 1567 1.1 agc 1568 1.1 agc 1569 1.1 agc /* -------------------------------------------------------------------- */ 1570 1.1 agc 1571 1.1 agc /* 1572 1.1 agc * kill_all_sessions: 1573 1.1 agc * Terminate all sessions (called when the driver unloads). 1574 1.1 agc */ 1575 1.1 agc 1576 1.22 mlelstv int 1577 1.1 agc kill_all_sessions(void) 1578 1.1 agc { 1579 1.1 agc session_t *sess; 1580 1.22 mlelstv int rc = 0; 1581 1.33 mlelstv uint32_t sid; 1582 1.1 agc 1583 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1584 1.5 mlelstv while ((sess = TAILQ_FIRST(&iscsi_sessions)) != NULL) { 1585 1.33 mlelstv sid = sess->s_id; 1586 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1587 1.33 mlelstv kill_session(sid, ISCSI_STATUS_DRIVER_UNLOAD, LOGOUT_SESSION, 1588 1.1 agc FALSE); 1589 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1590 1.1 agc } 1591 1.22 mlelstv if (TAILQ_FIRST(&iscsi_sessions) != NULL) { 1592 1.22 mlelstv DEBOUT(("Failed to kill all sessions\n")); 1593 1.22 mlelstv rc = EBUSY; 1594 1.22 mlelstv } 1595 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1596 1.22 mlelstv 1597 1.22 mlelstv return rc; 1598 1.1 agc } 1599 1.1 agc 1600 1.1 agc /* 1601 1.1 agc * handle_connection_error: 1602 1.1 agc * Deal with a problem during send or receive. 1603 1.1 agc * 1604 1.1 agc * Parameter: 1605 1.1 agc * conn The connection the problem is associated with 1606 1.1 agc * status The status code to insert into any unfinished CCBs 1607 1.1 agc * dologout Whether Logout should be attempted 1608 1.1 agc */ 1609 1.1 agc 1610 1.1 agc void 1611 1.1 agc handle_connection_error(connection_t *conn, uint32_t status, int dologout) 1612 1.1 agc { 1613 1.1 agc DEBC(conn, 0, ("*** Connection Error, status=%d, logout=%d, state=%d\n", 1614 1.28 christos status, dologout, conn->c_state)); 1615 1.1 agc 1616 1.28 christos if (!conn->c_terminating && conn->c_state <= ST_LOGOUT_SENT) { 1617 1.1 agc /* if we get an error while winding down, escalate it */ 1618 1.28 christos if (dologout >= 0 && conn->c_state >= ST_WINDING_DOWN) { 1619 1.1 agc dologout = NO_LOGOUT; 1620 1.1 agc } 1621 1.1 agc kill_connection(conn, status, dologout, TRUE); 1622 1.1 agc } 1623 1.1 agc } 1624 1.1 agc 1625 1.14 mlelstv /* 1626 1.25 mlelstv * remove a connection from session and add to the cleanup list 1627 1.14 mlelstv */ 1628 1.14 mlelstv void 1629 1.14 mlelstv add_connection_cleanup(connection_t *conn) 1630 1.14 mlelstv { 1631 1.33 mlelstv session_t *sess = NULL; 1632 1.25 mlelstv 1633 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1634 1.28 christos if (conn->c_in_session) { 1635 1.28 christos sess = conn->c_session; 1636 1.28 christos conn->c_in_session = FALSE; 1637 1.28 christos conn->c_session = NULL; 1638 1.28 christos TAILQ_REMOVE(&sess->s_conn_list, conn, c_connections); 1639 1.28 christos sess->s_mru_connection = TAILQ_FIRST(&sess->s_conn_list); 1640 1.25 mlelstv } 1641 1.28 christos TAILQ_INSERT_TAIL(&iscsi_cleanupc_list, conn, c_connections); 1642 1.23 mlelstv iscsi_notify_cleanup(); 1643 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1644 1.14 mlelstv } 1645 1.14 mlelstv 1646 1.14 mlelstv /* 1647 1.14 mlelstv * callout wrappers for timeouts, the work is done by the cleanup thread 1648 1.14 mlelstv */ 1649 1.14 mlelstv void 1650 1.14 mlelstv connection_timeout_co(void *par) 1651 1.14 mlelstv { 1652 1.14 mlelstv connection_t *conn = par; 1653 1.14 mlelstv 1654 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1655 1.35 mlelstv if (conn->c_timedout == TOUT_ARMED) { 1656 1.35 mlelstv conn->c_timedout = TOUT_QUEUED; 1657 1.35 mlelstv TAILQ_INSERT_TAIL(&iscsi_timeout_conn_list, conn, c_tchain); 1658 1.35 mlelstv iscsi_notify_cleanup(); 1659 1.35 mlelstv } 1660 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1661 1.14 mlelstv } 1662 1.14 mlelstv 1663 1.16 mlelstv void 1664 1.16 mlelstv connection_timeout_start(connection_t *conn, int ticks) 1665 1.16 mlelstv { 1666 1.18 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1667 1.28 christos if (conn->c_timedout != TOUT_QUEUED) { 1668 1.28 christos conn->c_timedout = TOUT_ARMED; 1669 1.28 christos callout_schedule(&conn->c_timeout, ticks); 1670 1.18 mlelstv } 1671 1.18 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1672 1.16 mlelstv } 1673 1.16 mlelstv 1674 1.16 mlelstv void 1675 1.16 mlelstv connection_timeout_stop(connection_t *conn) 1676 1.16 mlelstv { 1677 1.28 christos callout_stop(&conn->c_timeout); 1678 1.16 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1679 1.35 mlelstv if (conn->c_timedout == TOUT_QUEUED) 1680 1.28 christos TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain); 1681 1.18 mlelstv if (curlwp != iscsi_cleanproc) { 1682 1.28 christos while (conn->c_timedout == TOUT_BUSY) 1683 1.18 mlelstv kpause("connbusy", false, 1, &iscsi_cleanup_mtx); 1684 1.18 mlelstv } 1685 1.35 mlelstv conn->c_timedout = TOUT_NONE; 1686 1.16 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1687 1.33 mlelstv } 1688 1.16 mlelstv 1689 1.14 mlelstv void 1690 1.14 mlelstv ccb_timeout_co(void *par) 1691 1.14 mlelstv { 1692 1.14 mlelstv ccb_t *ccb = par; 1693 1.14 mlelstv 1694 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1695 1.35 mlelstv if (ccb->ccb_timedout == TOUT_ARMED) { 1696 1.35 mlelstv ccb->ccb_timedout = TOUT_QUEUED; 1697 1.35 mlelstv TAILQ_INSERT_TAIL(&iscsi_timeout_ccb_list, ccb, ccb_tchain); 1698 1.35 mlelstv iscsi_notify_cleanup(); 1699 1.35 mlelstv } 1700 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1701 1.14 mlelstv } 1702 1.1 agc 1703 1.16 mlelstv void 1704 1.16 mlelstv ccb_timeout_start(ccb_t *ccb, int ticks) 1705 1.16 mlelstv { 1706 1.18 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1707 1.28 christos if (ccb->ccb_timedout != TOUT_QUEUED) { 1708 1.28 christos ccb->ccb_timedout = TOUT_ARMED; 1709 1.28 christos callout_schedule(&ccb->ccb_timeout, ticks); 1710 1.18 mlelstv } 1711 1.18 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1712 1.16 mlelstv } 1713 1.16 mlelstv 1714 1.16 mlelstv void 1715 1.16 mlelstv ccb_timeout_stop(ccb_t *ccb) 1716 1.16 mlelstv { 1717 1.28 christos callout_stop(&ccb->ccb_timeout); 1718 1.16 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1719 1.35 mlelstv if (ccb->ccb_timedout == TOUT_QUEUED) 1720 1.28 christos TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain); 1721 1.18 mlelstv if (curlwp != iscsi_cleanproc) { 1722 1.28 christos while (ccb->ccb_timedout == TOUT_BUSY) 1723 1.18 mlelstv kpause("ccbbusy", false, 1, &iscsi_cleanup_mtx); 1724 1.18 mlelstv } 1725 1.35 mlelstv ccb->ccb_timedout = TOUT_NONE; 1726 1.16 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1727 1.16 mlelstv } 1728 1.16 mlelstv 1729 1.1 agc /* 1730 1.1 agc * iscsi_cleanup_thread 1731 1.1 agc * Global thread to handle connection and session cleanup after termination. 1732 1.1 agc */ 1733 1.1 agc 1734 1.14 mlelstv static void 1735 1.1 agc iscsi_cleanup_thread(void *par) 1736 1.1 agc { 1737 1.1 agc int s, rc; 1738 1.22 mlelstv session_t *sess, *nxts; 1739 1.22 mlelstv connection_t *conn, *nxtc; 1740 1.14 mlelstv ccb_t *ccb; 1741 1.1 agc 1742 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1743 1.22 mlelstv while (iscsi_num_send_threads || !iscsi_detaching || 1744 1.22 mlelstv !TAILQ_EMPTY(&iscsi_cleanupc_list) || !TAILQ_EMPTY(&iscsi_cleanups_list)) { 1745 1.28 christos TAILQ_FOREACH_SAFE(conn, &iscsi_cleanupc_list, c_connections, nxtc) { 1746 1.22 mlelstv 1747 1.28 christos TAILQ_REMOVE(&iscsi_cleanupc_list, conn, c_connections); 1748 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1749 1.1 agc 1750 1.28 christos sess = conn->c_session; 1751 1.1 agc 1752 1.14 mlelstv /* 1753 1.14 mlelstv * This implies that connection cleanup only runs when 1754 1.14 mlelstv * the send/recv threads have been killed 1755 1.14 mlelstv */ 1756 1.1 agc DEBC(conn, 5, ("Cleanup: Waiting for threads to exit\n")); 1757 1.34 mlelstv 1758 1.34 mlelstv mutex_enter(&conn->c_lock); 1759 1.28 christos while (conn->c_sendproc || conn->c_rcvproc) 1760 1.34 mlelstv kpause("threads", false, hz, &conn->c_lock); 1761 1.1 agc 1762 1.28 christos for (s=1; conn->c_usecount > 0 && s < 3; ++s) 1763 1.34 mlelstv kpause("usecount", false, hz, &conn->c_lock); 1764 1.22 mlelstv 1765 1.28 christos if (conn->c_usecount > 0) { 1766 1.28 christos DEBC(conn, 5, ("Cleanup: %d CCBs busy\n", conn->c_usecount)); 1767 1.34 mlelstv mutex_exit(&conn->c_lock); 1768 1.22 mlelstv /* retry later */ 1769 1.22 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1770 1.28 christos TAILQ_INSERT_HEAD(&iscsi_cleanupc_list, conn, c_connections); 1771 1.22 mlelstv continue; 1772 1.14 mlelstv } 1773 1.34 mlelstv mutex_exit(&conn->c_lock); 1774 1.1 agc 1775 1.28 christos KASSERT(!conn->c_in_session); 1776 1.22 mlelstv 1777 1.30 mlelstv callout_halt(&conn->c_timeout, NULL); 1778 1.28 christos closef(conn->c_sock); 1779 1.28 christos callout_destroy(&conn->c_timeout); 1780 1.33 mlelstv rw_destroy(&conn->c_sock_rw); 1781 1.28 christos cv_destroy(&conn->c_idle_cv); 1782 1.28 christos cv_destroy(&conn->c_ccb_cv); 1783 1.28 christos cv_destroy(&conn->c_pdu_cv); 1784 1.28 christos cv_destroy(&conn->c_conn_cv); 1785 1.28 christos mutex_destroy(&conn->c_lock); 1786 1.1 agc free(conn, M_DEVBUF); 1787 1.1 agc 1788 1.22 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1789 1.22 mlelstv 1790 1.28 christos if (--sess->s_total_connections == 0) { 1791 1.28 christos DEB(1, ("Cleanup: session %d\n", sess->s_id)); 1792 1.28 christos if (!sess->s_terminating) { 1793 1.28 christos sess->s_terminating = ISCSI_CONNECTION_TERMINATED; 1794 1.28 christos KASSERT(sess->s_sessions.tqe_prev != NULL); 1795 1.28 christos TAILQ_REMOVE(&iscsi_sessions, sess, s_sessions); 1796 1.28 christos sess->s_sessions.tqe_next = NULL; 1797 1.28 christos sess->s_sessions.tqe_prev = NULL; 1798 1.23 mlelstv } 1799 1.28 christos KASSERT(sess->s_sessions.tqe_prev == NULL); 1800 1.28 christos TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions); 1801 1.15 mlelstv } 1802 1.22 mlelstv } 1803 1.6 mlelstv 1804 1.28 christos TAILQ_FOREACH_SAFE(sess, &iscsi_cleanups_list, s_sessions, nxts) { 1805 1.28 christos if (sess->s_refcount > 0) 1806 1.22 mlelstv continue; 1807 1.28 christos TAILQ_REMOVE(&iscsi_cleanups_list, sess, s_sessions); 1808 1.28 christos sess->s_sessions.tqe_next = NULL; 1809 1.28 christos sess->s_sessions.tqe_prev = NULL; 1810 1.22 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1811 1.22 mlelstv 1812 1.28 christos DEB(1, ("Cleanup: Unmap session %d\n", sess->s_id)); 1813 1.22 mlelstv if (unmap_session(sess) == 0) { 1814 1.28 christos DEB(1, ("Cleanup: Unmap session %d failed\n", sess->s_id)); 1815 1.22 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1816 1.28 christos TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, s_sessions); 1817 1.22 mlelstv continue; 1818 1.1 agc } 1819 1.22 mlelstv 1820 1.28 christos if (sess->s_target_list != NULL) 1821 1.28 christos free(sess->s_target_list, M_TEMP); 1822 1.22 mlelstv 1823 1.22 mlelstv /* notify event handlers of session shutdown */ 1824 1.28 christos add_event(ISCSI_SESSION_TERMINATED, sess->s_id, 0, sess->s_terminating); 1825 1.28 christos DEB(1, ("Cleanup: session ended %d\n", sess->s_id)); 1826 1.22 mlelstv 1827 1.24 mlelstv destroy_ccbs(sess); 1828 1.28 christos cv_destroy(&sess->s_ccb_cv); 1829 1.28 christos cv_destroy(&sess->s_sess_cv); 1830 1.28 christos mutex_destroy(&sess->s_lock); 1831 1.22 mlelstv free(sess, M_DEVBUF); 1832 1.1 agc 1833 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1834 1.22 mlelstv } 1835 1.1 agc 1836 1.22 mlelstv /* handle ccb timeouts */ 1837 1.22 mlelstv while ((ccb = TAILQ_FIRST(&iscsi_timeout_ccb_list)) != NULL) { 1838 1.28 christos TAILQ_REMOVE(&iscsi_timeout_ccb_list, ccb, ccb_tchain); 1839 1.28 christos KASSERT(ccb->ccb_timedout == TOUT_QUEUED); 1840 1.28 christos ccb->ccb_timedout = TOUT_BUSY; 1841 1.22 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1842 1.22 mlelstv ccb_timeout(ccb); 1843 1.22 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1844 1.28 christos if (ccb->ccb_timedout == TOUT_BUSY) 1845 1.28 christos ccb->ccb_timedout = TOUT_NONE; 1846 1.22 mlelstv } 1847 1.14 mlelstv 1848 1.22 mlelstv /* handle connection timeouts */ 1849 1.22 mlelstv while ((conn = TAILQ_FIRST(&iscsi_timeout_conn_list)) != NULL) { 1850 1.28 christos TAILQ_REMOVE(&iscsi_timeout_conn_list, conn, c_tchain); 1851 1.28 christos KASSERT(conn->c_timedout == TOUT_QUEUED); 1852 1.28 christos conn->c_timedout = TOUT_BUSY; 1853 1.22 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1854 1.22 mlelstv connection_timeout(conn); 1855 1.22 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1856 1.28 christos if (conn->c_timedout == TOUT_BUSY) 1857 1.28 christos conn->c_timedout = TOUT_NONE; 1858 1.1 agc } 1859 1.22 mlelstv 1860 1.34 mlelstv /* Go to sleep, but wake up every 120 seconds to 1861 1.22 mlelstv * check for dead event handlers */ 1862 1.22 mlelstv rc = cv_timedwait(&iscsi_cleanup_cv, &iscsi_cleanup_mtx, 1863 1.22 mlelstv (TAILQ_FIRST(&event_handlers)) ? 120 * hz : 0); 1864 1.22 mlelstv 1865 1.22 mlelstv /* if timed out, not woken up */ 1866 1.22 mlelstv if (rc == EWOULDBLOCK) 1867 1.22 mlelstv check_event_handlers(); 1868 1.1 agc } 1869 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1870 1.1 agc 1871 1.1 agc add_event(ISCSI_DRIVER_TERMINATING, 0, 0, ISCSI_STATUS_DRIVER_UNLOAD); 1872 1.1 agc 1873 1.1 agc /* 1874 1.14 mlelstv * Wait for all event handlers to deregister, but don't wait more 1875 1.14 mlelstv * than 1 minute (assume registering app has died if it takes longer). 1876 1.1 agc */ 1877 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1878 1.1 agc for (s = 0; TAILQ_FIRST(&event_handlers) != NULL && s < 60; s++) 1879 1.14 mlelstv kpause("waiteventclr", true, hz, &iscsi_cleanup_mtx); 1880 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1881 1.1 agc 1882 1.5 mlelstv iscsi_cleanproc = NULL; 1883 1.1 agc DEB(5, ("Cleanup thread exits\n")); 1884 1.1 agc kthread_exit(0); 1885 1.1 agc } 1886 1.1 agc 1887 1.14 mlelstv void 1888 1.19 mlelstv iscsi_init_cleanup(void) 1889 1.14 mlelstv { 1890 1.14 mlelstv 1891 1.14 mlelstv mutex_init(&iscsi_cleanup_mtx, MUTEX_DEFAULT, IPL_BIO); 1892 1.14 mlelstv cv_init(&iscsi_cleanup_cv, "cleanup"); 1893 1.14 mlelstv cv_init(&iscsi_event_cv, "iscsievtwait"); 1894 1.14 mlelstv 1895 1.14 mlelstv if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, iscsi_cleanup_thread, 1896 1.14 mlelstv NULL, &iscsi_cleanproc, "iscsi_cleanup") != 0) { 1897 1.14 mlelstv panic("Can't create cleanup thread!"); 1898 1.14 mlelstv } 1899 1.14 mlelstv } 1900 1.14 mlelstv 1901 1.22 mlelstv int 1902 1.19 mlelstv iscsi_destroy_cleanup(void) 1903 1.14 mlelstv { 1904 1.14 mlelstv 1905 1.14 mlelstv iscsi_detaching = true; 1906 1.14 mlelstv mutex_enter(&iscsi_cleanup_mtx); 1907 1.14 mlelstv while (iscsi_cleanproc != NULL) { 1908 1.14 mlelstv iscsi_notify_cleanup(); 1909 1.14 mlelstv kpause("detach_wait", false, hz, &iscsi_cleanup_mtx); 1910 1.14 mlelstv } 1911 1.14 mlelstv mutex_exit(&iscsi_cleanup_mtx); 1912 1.14 mlelstv 1913 1.14 mlelstv cv_destroy(&iscsi_event_cv); 1914 1.14 mlelstv cv_destroy(&iscsi_cleanup_cv); 1915 1.14 mlelstv mutex_destroy(&iscsi_cleanup_mtx); 1916 1.22 mlelstv 1917 1.22 mlelstv return 0; 1918 1.14 mlelstv } 1919 1.14 mlelstv 1920 1.14 mlelstv void 1921 1.19 mlelstv iscsi_notify_cleanup(void) 1922 1.14 mlelstv { 1923 1.23 mlelstv KASSERT(mutex_owned(&iscsi_cleanup_mtx)); 1924 1.23 mlelstv 1925 1.14 mlelstv cv_signal(&iscsi_cleanup_cv); 1926 1.14 mlelstv } 1927 1.14 mlelstv 1928 1.1 agc 1929 1.1 agc /* -------------------------------------------------------------------- */ 1930 1.1 agc 1931 1.1 agc /* 1932 1.1 agc * iscsi_ioctl: 1933 1.1 agc * Driver ioctl entry. 1934 1.1 agc * 1935 1.1 agc * Parameter: 1936 1.14 mlelstv * file File structure 1937 1.1 agc * cmd The ioctl Command 1938 1.1 agc * addr IN/OUT: The command parameter 1939 1.1 agc * flag Flags (ignored) 1940 1.8 joerg * l IN: The lwp object of the caller 1941 1.1 agc */ 1942 1.1 agc 1943 1.1 agc int 1944 1.12 joerg iscsiioctl(struct file *fp, u_long cmd, void *addr) 1945 1.1 agc { 1946 1.12 joerg struct lwp *l = curlwp; 1947 1.14 mlelstv struct iscsifd *d = fp->f_iscsi; 1948 1.1 agc 1949 1.6 mlelstv DEB(1, ("ISCSI Ioctl cmd = %x\n", (int) cmd)); 1950 1.1 agc 1951 1.1 agc switch (cmd) { 1952 1.1 agc case ISCSI_GET_VERSION: 1953 1.1 agc get_version((iscsi_get_version_parameters_t *) addr); 1954 1.1 agc break; 1955 1.1 agc 1956 1.1 agc case ISCSI_LOGIN: 1957 1.28 christos login((iscsi_login_parameters_t *) addr, l, d->fd_dev); 1958 1.1 agc break; 1959 1.1 agc 1960 1.1 agc case ISCSI_ADD_CONNECTION: 1961 1.8 joerg add_connection((iscsi_login_parameters_t *) addr, l); 1962 1.1 agc break; 1963 1.1 agc 1964 1.1 agc case ISCSI_RESTORE_CONNECTION: 1965 1.8 joerg restore_connection((iscsi_login_parameters_t *) addr, l); 1966 1.1 agc break; 1967 1.1 agc 1968 1.1 agc case ISCSI_LOGOUT: 1969 1.1 agc logout((iscsi_logout_parameters_t *) addr); 1970 1.1 agc break; 1971 1.1 agc 1972 1.1 agc case ISCSI_REMOVE_CONNECTION: 1973 1.1 agc remove_connection((iscsi_remove_parameters_t *) addr); 1974 1.1 agc break; 1975 1.1 agc 1976 1.1 agc #ifndef ISCSI_MINIMAL 1977 1.1 agc case ISCSI_IO_COMMAND: 1978 1.8 joerg io_command((iscsi_iocommand_parameters_t *) addr, l); 1979 1.1 agc break; 1980 1.1 agc #endif 1981 1.1 agc 1982 1.1 agc case ISCSI_SEND_TARGETS: 1983 1.1 agc send_targets((iscsi_send_targets_parameters_t *) addr); 1984 1.1 agc break; 1985 1.1 agc 1986 1.1 agc case ISCSI_SET_NODE_NAME: 1987 1.1 agc set_node_name((iscsi_set_node_name_parameters_t *) addr); 1988 1.1 agc break; 1989 1.1 agc 1990 1.1 agc case ISCSI_CONNECTION_STATUS: 1991 1.1 agc connection_status((iscsi_conn_status_parameters_t *) addr); 1992 1.1 agc break; 1993 1.1 agc 1994 1.1 agc case ISCSI_REGISTER_EVENT: 1995 1.1 agc register_event((iscsi_register_event_parameters_t *) addr); 1996 1.1 agc break; 1997 1.1 agc 1998 1.1 agc case ISCSI_DEREGISTER_EVENT: 1999 1.1 agc deregister_event((iscsi_register_event_parameters_t *) addr); 2000 1.1 agc break; 2001 1.1 agc 2002 1.1 agc case ISCSI_WAIT_EVENT: 2003 1.1 agc check_event((iscsi_wait_event_parameters_t *) addr, TRUE); 2004 1.1 agc break; 2005 1.1 agc 2006 1.1 agc case ISCSI_POLL_EVENT: 2007 1.1 agc check_event((iscsi_wait_event_parameters_t *) addr, FALSE); 2008 1.1 agc break; 2009 1.1 agc 2010 1.1 agc default: 2011 1.1 agc DEBOUT(("Invalid IO-Control Code\n")); 2012 1.1 agc return ENOTTY; 2013 1.1 agc } 2014 1.1 agc 2015 1.1 agc /* 2016 1.1 agc * NOTE: We return 0 even if the function fails as long as the ioctl code 2017 1.1 agc * is good, so the status code is copied back to the caller. 2018 1.1 agc */ 2019 1.1 agc return 0; 2020 1.1 agc } 2021