xref: /freebsd/sys/dev/iscsi/iscsi.c (revision dcf58f92e2c19a32fc171f763698e711c719badc)
1 /*-
2  * Copyright (c) 2012 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Edward Tomasz Napierala under sponsorship
6  * from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include <sys/param.h>
35 #include <sys/condvar.h>
36 #include <sys/conf.h>
37 #include <sys/endian.h>
38 #include <sys/eventhandler.h>
39 #include <sys/file.h>
40 #include <sys/kernel.h>
41 #include <sys/kthread.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/mutex.h>
45 #include <sys/module.h>
46 #include <sys/sysctl.h>
47 #include <sys/systm.h>
48 #include <sys/sx.h>
49 #include <vm/uma.h>
50 
51 #include <cam/cam.h>
52 #include <cam/cam_ccb.h>
53 #include <cam/cam_xpt.h>
54 #include <cam/cam_debug.h>
55 #include <cam/cam_sim.h>
56 #include <cam/cam_xpt_sim.h>
57 #include <cam/cam_xpt_periph.h>
58 #include <cam/cam_periph.h>
59 #include <cam/scsi/scsi_all.h>
60 #include <cam/scsi/scsi_message.h>
61 
62 #include <dev/iscsi/icl.h>
63 #include <dev/iscsi/iscsi_ioctl.h>
64 #include <dev/iscsi/iscsi_proto.h>
65 #include <dev/iscsi/iscsi.h>
66 
67 #ifdef ICL_KERNEL_PROXY
68 #include <sys/socketvar.h>
69 #endif
70 
71 #ifdef ICL_KERNEL_PROXY
72 FEATURE(iscsi_kernel_proxy, "iSCSI initiator built with ICL_KERNEL_PROXY");
73 #endif
74 
75 /*
76  * XXX: This is global so the iscsi_unload() can access it.
77  * 	Think about how to do this properly.
78  */
79 static struct iscsi_softc	*sc;
80 
81 SYSCTL_NODE(_kern, OID_AUTO, iscsi, CTLFLAG_RD, 0, "iSCSI initiator");
82 static int debug = 1;
83 SYSCTL_INT(_kern_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN,
84     &debug, 0, "Enable debug messages");
85 static int ping_timeout = 5;
86 SYSCTL_INT(_kern_iscsi, OID_AUTO, ping_timeout, CTLFLAG_RWTUN, &ping_timeout,
87     0, "Timeout for ping (NOP-Out) requests, in seconds");
88 static int iscsid_timeout = 60;
89 SYSCTL_INT(_kern_iscsi, OID_AUTO, iscsid_timeout, CTLFLAG_RWTUN, &iscsid_timeout,
90     0, "Time to wait for iscsid(8) to handle reconnection, in seconds");
91 static int login_timeout = 60;
92 SYSCTL_INT(_kern_iscsi, OID_AUTO, login_timeout, CTLFLAG_RWTUN, &login_timeout,
93     0, "Time to wait for iscsid(8) to finish Login Phase, in seconds");
94 static int maxtags = 255;
95 SYSCTL_INT(_kern_iscsi, OID_AUTO, maxtags, CTLFLAG_RWTUN, &maxtags,
96     0, "Max number of IO requests queued");
97 static int fail_on_disconnection = 0;
98 SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_disconnection, CTLFLAG_RWTUN,
99     &fail_on_disconnection, 0, "Destroy CAM SIM on connection failure");
100 
101 static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator");
102 static uma_zone_t iscsi_outstanding_zone;
103 
104 #define	CONN_SESSION(X)	((struct iscsi_session *)X->ic_prv0)
105 #define	PDU_SESSION(X)	(CONN_SESSION(X->ip_conn))
106 
107 #define	ISCSI_DEBUG(X, ...)						\
108 	do {								\
109 		if (debug > 1) 						\
110 			printf("%s: " X "\n", __func__, ## __VA_ARGS__);\
111 	} while (0)
112 
113 #define	ISCSI_WARN(X, ...)						\
114 	do {								\
115 		if (debug > 0) {					\
116 			printf("WARNING: %s: " X "\n",			\
117 			    __func__, ## __VA_ARGS__);			\
118 		}							\
119 	} while (0)
120 
121 #define	ISCSI_SESSION_DEBUG(S, X, ...)					\
122 	do {								\
123 		if (debug > 1) {					\
124 			printf("%s: %s (%s): " X "\n",			\
125 			    __func__, S->is_conf.isc_target_addr,	\
126 			    S->is_conf.isc_target, ## __VA_ARGS__);	\
127 		}							\
128 	} while (0)
129 
130 #define	ISCSI_SESSION_WARN(S, X, ...)					\
131 	do {								\
132 		if (debug > 0) {					\
133 			printf("WARNING: %s (%s): " X "\n",		\
134 			    S->is_conf.isc_target_addr,			\
135 			    S->is_conf.isc_target, ## __VA_ARGS__);	\
136 		}							\
137 	} while (0)
138 
139 #define ISCSI_SESSION_LOCK(X)		mtx_lock(&X->is_lock)
140 #define ISCSI_SESSION_UNLOCK(X)		mtx_unlock(&X->is_lock)
141 #define ISCSI_SESSION_LOCK_ASSERT(X)	mtx_assert(&X->is_lock, MA_OWNED)
142 #define ISCSI_SESSION_LOCK_ASSERT_NOT(X) mtx_assert(&X->is_lock, MA_NOTOWNED)
143 
144 static int	iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg,
145 		    int mode, struct thread *td);
146 
147 static struct cdevsw iscsi_cdevsw = {
148      .d_version = D_VERSION,
149      .d_ioctl   = iscsi_ioctl,
150      .d_name    = "iscsi",
151 };
152 
153 static void	iscsi_pdu_queue_locked(struct icl_pdu *request);
154 static void	iscsi_pdu_queue(struct icl_pdu *request);
155 static void	iscsi_pdu_update_statsn(const struct icl_pdu *response);
156 static void	iscsi_pdu_handle_nop_in(struct icl_pdu *response);
157 static void	iscsi_pdu_handle_scsi_response(struct icl_pdu *response);
158 static void	iscsi_pdu_handle_task_response(struct icl_pdu *response);
159 static void	iscsi_pdu_handle_data_in(struct icl_pdu *response);
160 static void	iscsi_pdu_handle_logout_response(struct icl_pdu *response);
161 static void	iscsi_pdu_handle_r2t(struct icl_pdu *response);
162 static void	iscsi_pdu_handle_async_message(struct icl_pdu *response);
163 static void	iscsi_pdu_handle_reject(struct icl_pdu *response);
164 static void	iscsi_session_reconnect(struct iscsi_session *is);
165 static void	iscsi_session_terminate(struct iscsi_session *is);
166 static void	iscsi_action(struct cam_sim *sim, union ccb *ccb);
167 static void	iscsi_poll(struct cam_sim *sim);
168 static struct iscsi_outstanding	*iscsi_outstanding_find(struct iscsi_session *is,
169 		    uint32_t initiator_task_tag);
170 static struct iscsi_outstanding	*iscsi_outstanding_add(struct iscsi_session *is,
171 		    uint32_t initiator_task_tag, union ccb *ccb);
172 static void	iscsi_outstanding_remove(struct iscsi_session *is,
173 		    struct iscsi_outstanding *io);
174 
175 static bool
176 iscsi_pdu_prepare(struct icl_pdu *request)
177 {
178 	struct iscsi_session *is;
179 	struct iscsi_bhs_scsi_command *bhssc;
180 
181 	is = PDU_SESSION(request);
182 
183 	ISCSI_SESSION_LOCK_ASSERT(is);
184 
185 	/*
186 	 * We're only using fields common for all the request
187 	 * (initiator -> target) PDUs.
188 	 */
189 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
190 
191 	/*
192 	 * Data-Out PDU does not contain CmdSN.
193 	 */
194 	if (bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_OUT) {
195 		if (is->is_cmdsn > is->is_maxcmdsn &&
196 		    (bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) {
197 			/*
198 			 * Current MaxCmdSN prevents us from sending any more
199 			 * SCSI Command PDUs to the target; postpone the PDU.
200 			 * It will get resent by either iscsi_pdu_queue(),
201 			 * or by maintenance thread.
202 			 */
203 #if 0
204 			ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %d, ExpCmdSN %d, MaxCmdSN %d, opcode 0x%x",
205 			    is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn, bhssc->bhssc_opcode);
206 #endif
207 			return (true);
208 		}
209 		bhssc->bhssc_cmdsn = htonl(is->is_cmdsn);
210 		if ((bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0)
211 			is->is_cmdsn++;
212 	}
213 	bhssc->bhssc_expstatsn = htonl(is->is_statsn + 1);
214 
215 	return (false);
216 }
217 
218 static void
219 iscsi_session_send_postponed(struct iscsi_session *is)
220 {
221 	struct icl_pdu *request;
222 	bool postpone;
223 
224 	ISCSI_SESSION_LOCK_ASSERT(is);
225 
226 	while (!STAILQ_EMPTY(&is->is_postponed)) {
227 		request = STAILQ_FIRST(&is->is_postponed);
228 		postpone = iscsi_pdu_prepare(request);
229 		if (postpone)
230 			break;
231 		STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
232 		icl_pdu_queue(request);
233 	}
234 }
235 
236 static void
237 iscsi_pdu_queue_locked(struct icl_pdu *request)
238 {
239 	struct iscsi_session *is;
240 	bool postpone;
241 
242 	is = PDU_SESSION(request);
243 	ISCSI_SESSION_LOCK_ASSERT(is);
244 	iscsi_session_send_postponed(is);
245 	postpone = iscsi_pdu_prepare(request);
246 	if (postpone) {
247 		STAILQ_INSERT_TAIL(&is->is_postponed, request, ip_next);
248 		return;
249 	}
250 	icl_pdu_queue(request);
251 }
252 
253 static void
254 iscsi_pdu_queue(struct icl_pdu *request)
255 {
256 	struct iscsi_session *is;
257 
258 	is = PDU_SESSION(request);
259 	ISCSI_SESSION_LOCK(is);
260 	iscsi_pdu_queue_locked(request);
261 	ISCSI_SESSION_UNLOCK(is);
262 }
263 
264 static void
265 iscsi_session_logout(struct iscsi_session *is)
266 {
267 	struct icl_pdu *request;
268 	struct iscsi_bhs_logout_request *bhslr;
269 
270 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
271 	if (request == NULL)
272 		return;
273 
274 	bhslr = (struct iscsi_bhs_logout_request *)request->ip_bhs;
275 	bhslr->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_REQUEST;
276 	bhslr->bhslr_reason = BHSLR_REASON_CLOSE_SESSION;
277 	iscsi_pdu_queue_locked(request);
278 }
279 
280 static void
281 iscsi_session_terminate_task(struct iscsi_session *is,
282     struct iscsi_outstanding *io, bool requeue)
283 {
284 
285 	if (io->io_ccb != NULL) {
286 		io->io_ccb->ccb_h.status &= ~(CAM_SIM_QUEUED | CAM_STATUS_MASK);
287 		if (requeue)
288 			io->io_ccb->ccb_h.status |= CAM_REQUEUE_REQ;
289 		else
290 			io->io_ccb->ccb_h.status |= CAM_REQ_ABORTED;
291 		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
292 			io->io_ccb->ccb_h.status |= CAM_DEV_QFRZN;
293 			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
294 			ISCSI_SESSION_DEBUG(is, "freezing devq");
295 		}
296 		xpt_done(io->io_ccb);
297 	}
298 	iscsi_outstanding_remove(is, io);
299 }
300 
301 static void
302 iscsi_session_terminate_tasks(struct iscsi_session *is, bool requeue)
303 {
304 	struct iscsi_outstanding *io, *tmp;
305 
306 	ISCSI_SESSION_LOCK_ASSERT(is);
307 
308 	TAILQ_FOREACH_SAFE(io, &is->is_outstanding, io_next, tmp) {
309 		iscsi_session_terminate_task(is, io, requeue);
310 	}
311 }
312 
313 static void
314 iscsi_session_cleanup(struct iscsi_session *is, bool destroy_sim)
315 {
316 	struct icl_pdu *pdu;
317 
318 	ISCSI_SESSION_LOCK_ASSERT(is);
319 
320 	/*
321 	 * Don't queue any new PDUs.
322 	 */
323 	if (is->is_sim != NULL && is->is_simq_frozen == false) {
324 		ISCSI_SESSION_DEBUG(is, "freezing");
325 		xpt_freeze_simq(is->is_sim, 1);
326 		is->is_simq_frozen = true;
327 	}
328 
329 	/*
330 	 * Remove postponed PDUs.
331 	 */
332 	while (!STAILQ_EMPTY(&is->is_postponed)) {
333 		pdu = STAILQ_FIRST(&is->is_postponed);
334 		STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next);
335 		icl_pdu_free(pdu);
336 	}
337 
338 	if (destroy_sim == false) {
339 		/*
340 		 * Terminate SCSI tasks, asking CAM to requeue them.
341 		 */
342 		iscsi_session_terminate_tasks(is, true);
343 		return;
344 	}
345 
346 	iscsi_session_terminate_tasks(is, false);
347 
348 	if (is->is_sim == NULL)
349 		return;
350 
351 	ISCSI_SESSION_DEBUG(is, "deregistering SIM");
352 	xpt_async(AC_LOST_DEVICE, is->is_path, NULL);
353 
354 	if (is->is_simq_frozen) {
355 		xpt_release_simq(is->is_sim, 1);
356 		is->is_simq_frozen = false;
357 	}
358 
359 	xpt_free_path(is->is_path);
360 	is->is_path = NULL;
361 	xpt_bus_deregister(cam_sim_path(is->is_sim));
362 	cam_sim_free(is->is_sim, TRUE /*free_devq*/);
363 	is->is_sim = NULL;
364 	is->is_devq = NULL;
365 }
366 
367 static void
368 iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
369 {
370 
371 	icl_conn_close(is->is_conn);
372 
373 	ISCSI_SESSION_LOCK(is);
374 
375 	is->is_connected = false;
376 	is->is_reconnecting = false;
377 	is->is_login_phase = false;
378 
379 #ifdef ICL_KERNEL_PROXY
380 	if (is->is_login_pdu != NULL) {
381 		icl_pdu_free(is->is_login_pdu);
382 		is->is_login_pdu = NULL;
383 	}
384 	cv_signal(&is->is_login_cv);
385 #endif
386 
387 	if (fail_on_disconnection) {
388 		ISCSI_SESSION_DEBUG(is, "connection failed, destroying devices");
389 		iscsi_session_cleanup(is, true);
390 	} else {
391 		iscsi_session_cleanup(is, false);
392 	}
393 
394 	KASSERT(TAILQ_EMPTY(&is->is_outstanding),
395 	    ("destroying session with active tasks"));
396 	KASSERT(STAILQ_EMPTY(&is->is_postponed),
397 	    ("destroying session with postponed PDUs"));
398 
399 	/*
400 	 * Request immediate reconnection from iscsid(8).
401 	 */
402 	//ISCSI_SESSION_DEBUG(is, "waking up iscsid(8)");
403 	is->is_waiting_for_iscsid = true;
404 	strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
405 	is->is_timeout = 0;
406 	ISCSI_SESSION_UNLOCK(is);
407 	cv_signal(&is->is_softc->sc_cv);
408 }
409 
410 static void
411 iscsi_maintenance_thread_terminate(struct iscsi_session *is)
412 {
413 	struct iscsi_softc *sc;
414 
415 	sc = is->is_softc;
416 	sx_xlock(&sc->sc_lock);
417 	TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
418 	sx_xunlock(&sc->sc_lock);
419 
420 	icl_conn_close(is->is_conn);
421 
422 	ISCSI_SESSION_LOCK(is);
423 
424 	KASSERT(is->is_terminating, ("is_terminating == false"));
425 
426 #ifdef ICL_KERNEL_PROXY
427 	if (is->is_login_pdu != NULL) {
428 		icl_pdu_free(is->is_login_pdu);
429 		is->is_login_pdu = NULL;
430 	}
431 	cv_signal(&is->is_login_cv);
432 #endif
433 
434 	callout_drain(&is->is_callout);
435 
436 	iscsi_session_cleanup(is, true);
437 
438 	KASSERT(TAILQ_EMPTY(&is->is_outstanding),
439 	    ("destroying session with active tasks"));
440 	KASSERT(STAILQ_EMPTY(&is->is_postponed),
441 	    ("destroying session with postponed PDUs"));
442 
443 	ISCSI_SESSION_UNLOCK(is);
444 
445 	icl_conn_free(is->is_conn);
446 	mtx_destroy(&is->is_lock);
447 	cv_destroy(&is->is_maintenance_cv);
448 #ifdef ICL_KERNEL_PROXY
449 	cv_destroy(&is->is_login_cv);
450 #endif
451 	ISCSI_SESSION_DEBUG(is, "terminated");
452 	free(is, M_ISCSI);
453 
454 	/*
455 	 * The iscsi_unload() routine might be waiting.
456 	 */
457 	cv_signal(&sc->sc_cv);
458 }
459 
460 static void
461 iscsi_maintenance_thread(void *arg)
462 {
463 	struct iscsi_session *is;
464 
465 	is = arg;
466 
467 	for (;;) {
468 		ISCSI_SESSION_LOCK(is);
469 		if (is->is_reconnecting == false &&
470 		    is->is_terminating == false &&
471 		    STAILQ_EMPTY(&is->is_postponed))
472 			cv_wait(&is->is_maintenance_cv, &is->is_lock);
473 
474 		if (is->is_reconnecting) {
475 			ISCSI_SESSION_UNLOCK(is);
476 			iscsi_maintenance_thread_reconnect(is);
477 			continue;
478 		}
479 
480 		if (is->is_terminating) {
481 			ISCSI_SESSION_UNLOCK(is);
482 			iscsi_maintenance_thread_terminate(is);
483 			kthread_exit();
484 			return;
485 		}
486 
487 		iscsi_session_send_postponed(is);
488 		ISCSI_SESSION_UNLOCK(is);
489 	}
490 }
491 
492 static void
493 iscsi_session_reconnect(struct iscsi_session *is)
494 {
495 
496 	/*
497 	 * XXX: We can't use locking here, because
498 	 * 	it's being called from various contexts.
499 	 * 	Hope it doesn't break anything.
500 	 */
501 	if (is->is_reconnecting)
502 		return;
503 
504 	is->is_reconnecting = true;
505 	cv_signal(&is->is_maintenance_cv);
506 }
507 
508 static void
509 iscsi_session_terminate(struct iscsi_session *is)
510 {
511 	if (is->is_terminating)
512 		return;
513 
514 	is->is_terminating = true;
515 
516 #if 0
517 	iscsi_session_logout(is);
518 #endif
519 	cv_signal(&is->is_maintenance_cv);
520 }
521 
522 static void
523 iscsi_callout(void *context)
524 {
525 	struct icl_pdu *request;
526 	struct iscsi_bhs_nop_out *bhsno;
527 	struct iscsi_session *is;
528 	bool reconnect_needed = false;
529 
530 	is = context;
531 
532 	if (is->is_terminating)
533 		return;
534 
535 	callout_schedule(&is->is_callout, 1 * hz);
536 
537 	ISCSI_SESSION_LOCK(is);
538 	is->is_timeout++;
539 
540 	if (is->is_waiting_for_iscsid) {
541 		if (iscsid_timeout > 0 && is->is_timeout > iscsid_timeout) {
542 			ISCSI_SESSION_WARN(is, "timed out waiting for iscsid(8) "
543 			    "for %d seconds; reconnecting",
544 			    is->is_timeout);
545 			reconnect_needed = true;
546 		}
547 		goto out;
548 	}
549 
550 	if (is->is_login_phase) {
551 		if (login_timeout > 0 && is->is_timeout > login_timeout) {
552 			ISCSI_SESSION_WARN(is, "login timed out after %d seconds; "
553 			    "reconnecting", is->is_timeout);
554 			reconnect_needed = true;
555 		}
556 		goto out;
557 	}
558 
559 	if (ping_timeout <= 0) {
560 		/*
561 		 * Pings are disabled.  Don't send NOP-Out in this case.
562 		 * Reset the timeout, to avoid triggering reconnection,
563 		 * should the user decide to reenable them.
564 		 */
565 		is->is_timeout = 0;
566 		goto out;
567 	}
568 
569 	if (is->is_timeout >= ping_timeout) {
570 		ISCSI_SESSION_WARN(is, "no ping reply (NOP-In) after %d seconds; "
571 		    "reconnecting", ping_timeout);
572 		reconnect_needed = true;
573 		goto out;
574 	}
575 
576 	ISCSI_SESSION_UNLOCK(is);
577 
578 	/*
579 	 * If the ping was reset less than one second ago - which means
580 	 * that we've received some PDU during the last second - assume
581 	 * the traffic flows correctly and don't bother sending a NOP-Out.
582 	 *
583 	 * (It's 2 - one for one second, and one for incrementing is_timeout
584 	 * earlier in this routine.)
585 	 */
586 	if (is->is_timeout < 2)
587 		return;
588 
589 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
590 	if (request == NULL) {
591 		ISCSI_SESSION_WARN(is, "failed to allocate PDU");
592 		return;
593 	}
594 	bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
595 	bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
596 	    ISCSI_BHS_OPCODE_IMMEDIATE;
597 	bhsno->bhsno_flags = 0x80;
598 	bhsno->bhsno_target_transfer_tag = 0xffffffff;
599 	iscsi_pdu_queue(request);
600 	return;
601 
602 out:
603 	ISCSI_SESSION_UNLOCK(is);
604 
605 	if (reconnect_needed)
606 		iscsi_session_reconnect(is);
607 }
608 
609 static void
610 iscsi_pdu_update_statsn(const struct icl_pdu *response)
611 {
612 	const struct iscsi_bhs_data_in *bhsdi;
613 	struct iscsi_session *is;
614 	uint32_t expcmdsn, maxcmdsn;
615 
616 	is = PDU_SESSION(response);
617 
618 	ISCSI_SESSION_LOCK_ASSERT(is);
619 
620 	/*
621 	 * We're only using fields common for all the response
622 	 * (target -> initiator) PDUs.
623 	 */
624 	bhsdi = (const struct iscsi_bhs_data_in *)response->ip_bhs;
625 	/*
626 	 * Ok, I lied.  In case of Data-In, "The fields StatSN, Status,
627 	 * and Residual Count only have meaningful content if the S bit
628 	 * is set to 1", so we also need to check the bit specific for
629 	 * Data-In PDU.
630 	 */
631 	if (bhsdi->bhsdi_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN ||
632 	    (bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0) {
633 		if (ntohl(bhsdi->bhsdi_statsn) < is->is_statsn) {
634 			ISCSI_SESSION_WARN(is,
635 			    "PDU StatSN %d >= session StatSN %d, opcode 0x%x",
636 			    is->is_statsn, ntohl(bhsdi->bhsdi_statsn),
637 			    bhsdi->bhsdi_opcode);
638 		}
639 		is->is_statsn = ntohl(bhsdi->bhsdi_statsn);
640 	}
641 
642 	expcmdsn = ntohl(bhsdi->bhsdi_expcmdsn);
643 	maxcmdsn = ntohl(bhsdi->bhsdi_maxcmdsn);
644 
645 	/*
646 	 * XXX: Compare using Serial Arithmetic Sense.
647 	 */
648 	if (maxcmdsn + 1 < expcmdsn) {
649 		ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d + 1 < PDU ExpCmdSN %d; ignoring",
650 		    maxcmdsn, expcmdsn);
651 	} else {
652 		if (maxcmdsn > is->is_maxcmdsn) {
653 			is->is_maxcmdsn = maxcmdsn;
654 
655 			/*
656 			 * Command window increased; kick the maintanance thread
657 			 * to send out postponed commands.
658 			 */
659 			if (!STAILQ_EMPTY(&is->is_postponed))
660 				cv_signal(&is->is_maintenance_cv);
661 		} else if (maxcmdsn < is->is_maxcmdsn) {
662 			ISCSI_SESSION_DEBUG(is, "PDU MaxCmdSN %d < session MaxCmdSN %d; ignoring",
663 			    maxcmdsn, is->is_maxcmdsn);
664 		}
665 
666 		if (expcmdsn > is->is_expcmdsn) {
667 			is->is_expcmdsn = expcmdsn;
668 		} else if (expcmdsn < is->is_expcmdsn) {
669 			ISCSI_SESSION_DEBUG(is, "PDU ExpCmdSN %d < session ExpCmdSN %d; ignoring",
670 			    expcmdsn, is->is_expcmdsn);
671 		}
672 	}
673 
674 	/*
675 	 * Every incoming PDU - not just NOP-In - resets the ping timer.
676 	 * The purpose of the timeout is to reset the connection when it stalls;
677 	 * we don't want this to happen when NOP-In or NOP-Out ends up delayed
678 	 * in some queue.
679 	 */
680 	is->is_timeout = 0;
681 }
682 
683 static void
684 iscsi_receive_callback(struct icl_pdu *response)
685 {
686 	struct iscsi_session *is;
687 
688 	is = PDU_SESSION(response);
689 
690 	ISCSI_SESSION_LOCK(is);
691 
692 #ifdef ICL_KERNEL_PROXY
693 	if (is->is_login_phase) {
694 		if (is->is_login_pdu == NULL)
695 			is->is_login_pdu = response;
696 		else
697 			icl_pdu_free(response);
698 		ISCSI_SESSION_UNLOCK(is);
699 		cv_signal(&is->is_login_cv);
700 		return;
701 	}
702 #endif
703 
704 	iscsi_pdu_update_statsn(response);
705 
706 	/*
707 	 * The handling routine is responsible for freeing the PDU
708 	 * when it's no longer needed.
709 	 */
710 	switch (response->ip_bhs->bhs_opcode) {
711 	case ISCSI_BHS_OPCODE_NOP_IN:
712 		iscsi_pdu_handle_nop_in(response);
713 		ISCSI_SESSION_UNLOCK(is);
714 		break;
715 	case ISCSI_BHS_OPCODE_SCSI_RESPONSE:
716 		iscsi_pdu_handle_scsi_response(response);
717 		/* Session lock dropped inside. */
718 		ISCSI_SESSION_LOCK_ASSERT_NOT(is);
719 		break;
720 	case ISCSI_BHS_OPCODE_TASK_RESPONSE:
721 		iscsi_pdu_handle_task_response(response);
722 		ISCSI_SESSION_UNLOCK(is);
723 		break;
724 	case ISCSI_BHS_OPCODE_SCSI_DATA_IN:
725 		iscsi_pdu_handle_data_in(response);
726 		/* Session lock dropped inside. */
727 		ISCSI_SESSION_LOCK_ASSERT_NOT(is);
728 		break;
729 	case ISCSI_BHS_OPCODE_LOGOUT_RESPONSE:
730 		iscsi_pdu_handle_logout_response(response);
731 		ISCSI_SESSION_UNLOCK(is);
732 		break;
733 	case ISCSI_BHS_OPCODE_R2T:
734 		iscsi_pdu_handle_r2t(response);
735 		ISCSI_SESSION_UNLOCK(is);
736 		break;
737 	case ISCSI_BHS_OPCODE_ASYNC_MESSAGE:
738 		iscsi_pdu_handle_async_message(response);
739 		ISCSI_SESSION_UNLOCK(is);
740 		break;
741 	case ISCSI_BHS_OPCODE_REJECT:
742 		iscsi_pdu_handle_reject(response);
743 		ISCSI_SESSION_UNLOCK(is);
744 		break;
745 	default:
746 		ISCSI_SESSION_WARN(is, "received PDU with unsupported "
747 		    "opcode 0x%x; reconnecting",
748 		    response->ip_bhs->bhs_opcode);
749 		iscsi_session_reconnect(is);
750 		ISCSI_SESSION_UNLOCK(is);
751 		icl_pdu_free(response);
752 	}
753 }
754 
755 static void
756 iscsi_error_callback(struct icl_conn *ic)
757 {
758 	struct iscsi_session *is;
759 
760 	is = CONN_SESSION(ic);
761 
762 	ISCSI_SESSION_WARN(is, "connection error; reconnecting");
763 	iscsi_session_reconnect(is);
764 }
765 
766 static void
767 iscsi_pdu_handle_nop_in(struct icl_pdu *response)
768 {
769 	struct iscsi_session *is;
770 	struct iscsi_bhs_nop_out *bhsno;
771 	struct iscsi_bhs_nop_in *bhsni;
772 	struct icl_pdu *request;
773 	void *data = NULL;
774 	size_t datasize;
775 	int error;
776 
777 	is = PDU_SESSION(response);
778 	bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
779 
780 	if (bhsni->bhsni_target_transfer_tag == 0xffffffff) {
781 		/*
782 		 * Nothing to do; iscsi_pdu_update_statsn() already
783 		 * zeroed the timeout.
784 		 */
785 		icl_pdu_free(response);
786 		return;
787 	}
788 
789 	datasize = icl_pdu_data_segment_length(response);
790 	if (datasize > 0) {
791 		data = malloc(datasize, M_ISCSI, M_NOWAIT | M_ZERO);
792 		if (data == NULL) {
793 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
794 			    "reconnecting");
795 			icl_pdu_free(response);
796 			iscsi_session_reconnect(is);
797 			return;
798 		}
799 		icl_pdu_get_data(response, 0, data, datasize);
800 	}
801 
802 	request = icl_pdu_new(response->ip_conn, M_NOWAIT);
803 	if (request == NULL) {
804 		ISCSI_SESSION_WARN(is, "failed to allocate memory; "
805 		    "reconnecting");
806 		free(data, M_ISCSI);
807 		icl_pdu_free(response);
808 		iscsi_session_reconnect(is);
809 		return;
810 	}
811 	bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
812 	bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
813 	    ISCSI_BHS_OPCODE_IMMEDIATE;
814 	bhsno->bhsno_flags = 0x80;
815 	bhsno->bhsno_initiator_task_tag = 0xffffffff;
816 	bhsno->bhsno_target_transfer_tag = bhsni->bhsni_target_transfer_tag;
817 	if (datasize > 0) {
818 		error = icl_pdu_append_data(request, data, datasize, M_NOWAIT);
819 		if (error != 0) {
820 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
821 			    "reconnecting");
822 			free(data, M_ISCSI);
823 			icl_pdu_free(request);
824 			icl_pdu_free(response);
825 			iscsi_session_reconnect(is);
826 			return;
827 		}
828 		free(data, M_ISCSI);
829 	}
830 
831 	icl_pdu_free(response);
832 	iscsi_pdu_queue_locked(request);
833 }
834 
835 static void
836 iscsi_pdu_handle_scsi_response(struct icl_pdu *response)
837 {
838 	struct iscsi_bhs_scsi_response *bhssr;
839 	struct iscsi_outstanding *io;
840 	struct iscsi_session *is;
841 	union ccb *ccb;
842 	struct ccb_scsiio *csio;
843 	size_t data_segment_len, received;
844 	uint16_t sense_len;
845 
846 	is = PDU_SESSION(response);
847 
848 	bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs;
849 	io = iscsi_outstanding_find(is, bhssr->bhssr_initiator_task_tag);
850 	if (io == NULL || io->io_ccb == NULL) {
851 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhssr->bhssr_initiator_task_tag);
852 		icl_pdu_free(response);
853 		iscsi_session_reconnect(is);
854 		ISCSI_SESSION_UNLOCK(is);
855 		return;
856 	}
857 
858 	ccb = io->io_ccb;
859 	received = io->io_received;
860 	iscsi_outstanding_remove(is, io);
861 	ISCSI_SESSION_UNLOCK(is);
862 
863 	if (bhssr->bhssr_response != BHSSR_RESPONSE_COMMAND_COMPLETED) {
864 		ISCSI_SESSION_WARN(is, "service response 0x%x", bhssr->bhssr_response);
865  		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
866  			xpt_freeze_devq(ccb->ccb_h.path, 1);
867 			ISCSI_SESSION_DEBUG(is, "freezing devq");
868 		}
869  		ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
870 	} else if (bhssr->bhssr_status == 0) {
871 		ccb->ccb_h.status = CAM_REQ_CMP;
872 	} else {
873  		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
874  			xpt_freeze_devq(ccb->ccb_h.path, 1);
875 			ISCSI_SESSION_DEBUG(is, "freezing devq");
876 		}
877  		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
878 		ccb->csio.scsi_status = bhssr->bhssr_status;
879 	}
880 
881 	csio = &ccb->csio;
882 	data_segment_len = icl_pdu_data_segment_length(response);
883 	if (data_segment_len > 0) {
884 		if (data_segment_len < sizeof(sense_len)) {
885 			ISCSI_SESSION_WARN(is, "truncated data segment (%zd bytes)",
886 			    data_segment_len);
887 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
888 				xpt_freeze_devq(ccb->ccb_h.path, 1);
889 				ISCSI_SESSION_DEBUG(is, "freezing devq");
890 			}
891 			ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
892 			goto out;
893 		}
894 		icl_pdu_get_data(response, 0, &sense_len, sizeof(sense_len));
895 		sense_len = ntohs(sense_len);
896 #if 0
897 		ISCSI_SESSION_DEBUG(is, "sense_len %d, data len %zd",
898 		    sense_len, data_segment_len);
899 #endif
900 		if (sizeof(sense_len) + sense_len > data_segment_len) {
901 			ISCSI_SESSION_WARN(is, "truncated data segment "
902 			    "(%zd bytes, should be %zd)",
903 			    data_segment_len, sizeof(sense_len) + sense_len);
904 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
905 				xpt_freeze_devq(ccb->ccb_h.path, 1);
906 				ISCSI_SESSION_DEBUG(is, "freezing devq");
907 			}
908 			ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
909 			goto out;
910 		} else if (sizeof(sense_len) + sense_len < data_segment_len)
911 			ISCSI_SESSION_WARN(is, "oversize data segment "
912 			    "(%zd bytes, should be %zd)",
913 			    data_segment_len, sizeof(sense_len) + sense_len);
914 		if (sense_len > csio->sense_len) {
915 			ISCSI_SESSION_DEBUG(is, "truncating sense from %d to %d",
916 			    sense_len, csio->sense_len);
917 			sense_len = csio->sense_len;
918 		}
919 		icl_pdu_get_data(response, sizeof(sense_len), &csio->sense_data, sense_len);
920 		csio->sense_resid = csio->sense_len - sense_len;
921 		ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
922 	}
923 
924 out:
925 	if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_UNDERFLOW)
926 		csio->resid = ntohl(bhssr->bhssr_residual_count);
927 
928 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
929 		KASSERT(received <= csio->dxfer_len,
930 		    ("received > csio->dxfer_len"));
931 		if (received < csio->dxfer_len) {
932 			if (csio->resid != csio->dxfer_len - received) {
933 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
934 				    "target indicates %d, we calculated %zd",
935 				    csio->resid, csio->dxfer_len - received);
936 			}
937 			csio->resid = csio->dxfer_len - received;
938 		}
939 	}
940 
941 	xpt_done(ccb);
942 	icl_pdu_free(response);
943 }
944 
945 static void
946 iscsi_pdu_handle_task_response(struct icl_pdu *response)
947 {
948 	struct iscsi_bhs_task_management_response *bhstmr;
949 	struct iscsi_outstanding *io, *aio;
950 	struct iscsi_session *is;
951 
952 	is = PDU_SESSION(response);
953 
954 	bhstmr = (struct iscsi_bhs_task_management_response *)response->ip_bhs;
955 	io = iscsi_outstanding_find(is, bhstmr->bhstmr_initiator_task_tag);
956 	if (io == NULL || io->io_ccb != NULL) {
957 		ISCSI_SESSION_WARN(is, "bad itt 0x%x",
958 		    bhstmr->bhstmr_initiator_task_tag);
959 		icl_pdu_free(response);
960 		iscsi_session_reconnect(is);
961 		return;
962 	}
963 
964 	if (bhstmr->bhstmr_response != BHSTMR_RESPONSE_FUNCTION_COMPLETE) {
965 		ISCSI_SESSION_WARN(is, "task response 0x%x",
966 		    bhstmr->bhstmr_response);
967 	} else {
968 		aio = iscsi_outstanding_find(is, io->io_datasn);
969 		if (aio != NULL && aio->io_ccb != NULL)
970 			iscsi_session_terminate_task(is, aio, false);
971 	}
972 
973 	iscsi_outstanding_remove(is, io);
974 	icl_pdu_free(response);
975 }
976 
977 static void
978 iscsi_pdu_handle_data_in(struct icl_pdu *response)
979 {
980 	struct iscsi_bhs_data_in *bhsdi;
981 	struct iscsi_outstanding *io;
982 	struct iscsi_session *is;
983 	union ccb *ccb;
984 	struct ccb_scsiio *csio;
985 	size_t data_segment_len, received, oreceived;
986 
987 	is = PDU_SESSION(response);
988 	bhsdi = (struct iscsi_bhs_data_in *)response->ip_bhs;
989 	io = iscsi_outstanding_find(is, bhsdi->bhsdi_initiator_task_tag);
990 	if (io == NULL || io->io_ccb == NULL) {
991 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhsdi->bhsdi_initiator_task_tag);
992 		icl_pdu_free(response);
993 		iscsi_session_reconnect(is);
994 		ISCSI_SESSION_UNLOCK(is);
995 		return;
996 	}
997 
998 	data_segment_len = icl_pdu_data_segment_length(response);
999 	if (data_segment_len == 0) {
1000 		/*
1001 		 * "The sending of 0 length data segments should be avoided,
1002 		 * but initiators and targets MUST be able to properly receive
1003 		 * 0 length data segments."
1004 		 */
1005 		ISCSI_SESSION_UNLOCK(is);
1006 		icl_pdu_free(response);
1007 		return;
1008 	}
1009 
1010 	/*
1011 	 * We need to track this for security reasons - without it, malicious target
1012 	 * could respond to SCSI READ without sending Data-In PDUs, which would result
1013 	 * in read operation on the initiator side returning random kernel data.
1014 	 */
1015 	if (ntohl(bhsdi->bhsdi_buffer_offset) != io->io_received) {
1016 		ISCSI_SESSION_WARN(is, "data out of order; expected offset %zd, got %zd",
1017 		    io->io_received, (size_t)ntohl(bhsdi->bhsdi_buffer_offset));
1018 		icl_pdu_free(response);
1019 		iscsi_session_reconnect(is);
1020 		ISCSI_SESSION_UNLOCK(is);
1021 		return;
1022 	}
1023 
1024 	ccb = io->io_ccb;
1025 	csio = &ccb->csio;
1026 
1027 	if (io->io_received + data_segment_len > csio->dxfer_len) {
1028 		ISCSI_SESSION_WARN(is, "oversize data segment (%zd bytes "
1029 		    "at offset %zd, buffer is %d)",
1030 		    data_segment_len, io->io_received, csio->dxfer_len);
1031 		icl_pdu_free(response);
1032 		iscsi_session_reconnect(is);
1033 		ISCSI_SESSION_UNLOCK(is);
1034 		return;
1035 	}
1036 
1037 	oreceived = io->io_received;
1038 	io->io_received += data_segment_len;
1039 	received = io->io_received;
1040 	if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0)
1041 		iscsi_outstanding_remove(is, io);
1042 	ISCSI_SESSION_UNLOCK(is);
1043 
1044 	icl_pdu_get_data(response, 0, csio->data_ptr + oreceived, data_segment_len);
1045 
1046 	/*
1047 	 * XXX: Check DataSN.
1048 	 * XXX: Check F.
1049 	 */
1050 	if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) == 0) {
1051 		/*
1052 		 * Nothing more to do.
1053 		 */
1054 		icl_pdu_free(response);
1055 		return;
1056 	}
1057 
1058 	//ISCSI_SESSION_DEBUG(is, "got S flag; status 0x%x", bhsdi->bhsdi_status);
1059 	if (bhsdi->bhsdi_status == 0) {
1060 		ccb->ccb_h.status = CAM_REQ_CMP;
1061 	} else {
1062 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1063 			xpt_freeze_devq(ccb->ccb_h.path, 1);
1064 			ISCSI_SESSION_DEBUG(is, "freezing devq");
1065 		}
1066 		ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
1067 		csio->scsi_status = bhsdi->bhsdi_status;
1068 	}
1069 
1070 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1071 		KASSERT(received <= csio->dxfer_len,
1072 		    ("received > csio->dxfer_len"));
1073 		if (received < csio->dxfer_len) {
1074 			csio->resid = ntohl(bhsdi->bhsdi_residual_count);
1075 			if (csio->resid != csio->dxfer_len - received) {
1076 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
1077 				    "target indicates %d, we calculated %zd",
1078 				    csio->resid, csio->dxfer_len - received);
1079 			}
1080 			csio->resid = csio->dxfer_len - received;
1081 		}
1082 	}
1083 
1084 	xpt_done(ccb);
1085 	icl_pdu_free(response);
1086 }
1087 
1088 static void
1089 iscsi_pdu_handle_logout_response(struct icl_pdu *response)
1090 {
1091 
1092 	ISCSI_SESSION_DEBUG(PDU_SESSION(response), "logout response");
1093 	icl_pdu_free(response);
1094 }
1095 
1096 static void
1097 iscsi_pdu_handle_r2t(struct icl_pdu *response)
1098 {
1099 	struct icl_pdu *request;
1100 	struct iscsi_session *is;
1101 	struct iscsi_bhs_r2t *bhsr2t;
1102 	struct iscsi_bhs_data_out *bhsdo;
1103 	struct iscsi_outstanding *io;
1104 	struct ccb_scsiio *csio;
1105 	size_t off, len, total_len;
1106 	int error;
1107 
1108 	is = PDU_SESSION(response);
1109 
1110 	bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs;
1111 	io = iscsi_outstanding_find(is, bhsr2t->bhsr2t_initiator_task_tag);
1112 	if (io == NULL || io->io_ccb == NULL) {
1113 		ISCSI_SESSION_WARN(is, "bad itt 0x%x; reconnecting",
1114 		    bhsr2t->bhsr2t_initiator_task_tag);
1115 		icl_pdu_free(response);
1116 		iscsi_session_reconnect(is);
1117 		return;
1118 	}
1119 
1120 	csio = &io->io_ccb->csio;
1121 
1122 	if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_OUT) {
1123 		ISCSI_SESSION_WARN(is, "received R2T for read command; reconnecting");
1124 		icl_pdu_free(response);
1125 		iscsi_session_reconnect(is);
1126 		return;
1127 	}
1128 
1129 	/*
1130 	 * XXX: Verify R2TSN.
1131 	 */
1132 
1133 	io->io_datasn = 0;
1134 
1135 	off = ntohl(bhsr2t->bhsr2t_buffer_offset);
1136 	if (off > csio->dxfer_len) {
1137 		ISCSI_SESSION_WARN(is, "target requested invalid offset "
1138 		    "%zd, buffer is is %d; reconnecting", off, csio->dxfer_len);
1139 		icl_pdu_free(response);
1140 		iscsi_session_reconnect(is);
1141 		return;
1142 	}
1143 
1144 	total_len = ntohl(bhsr2t->bhsr2t_desired_data_transfer_length);
1145 	if (total_len == 0 || total_len > csio->dxfer_len) {
1146 		ISCSI_SESSION_WARN(is, "target requested invalid length "
1147 		    "%zd, buffer is %d; reconnecting", total_len, csio->dxfer_len);
1148 		icl_pdu_free(response);
1149 		iscsi_session_reconnect(is);
1150 		return;
1151 	}
1152 
1153 	//ISCSI_SESSION_DEBUG(is, "r2t; off %zd, len %zd", off, total_len);
1154 
1155 	for (;;) {
1156 		len = total_len;
1157 
1158 		if (len > is->is_max_data_segment_length)
1159 			len = is->is_max_data_segment_length;
1160 
1161 		if (off + len > csio->dxfer_len) {
1162 			ISCSI_SESSION_WARN(is, "target requested invalid "
1163 			    "length/offset %zd, buffer is %d; reconnecting",
1164 			    off + len, csio->dxfer_len);
1165 			icl_pdu_free(response);
1166 			iscsi_session_reconnect(is);
1167 			return;
1168 		}
1169 
1170 		request = icl_pdu_new(response->ip_conn, M_NOWAIT);
1171 		if (request == NULL) {
1172 			icl_pdu_free(response);
1173 			iscsi_session_reconnect(is);
1174 			return;
1175 		}
1176 
1177 		bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs;
1178 		bhsdo->bhsdo_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_OUT;
1179 		bhsdo->bhsdo_lun = bhsr2t->bhsr2t_lun;
1180 		bhsdo->bhsdo_initiator_task_tag =
1181 		    bhsr2t->bhsr2t_initiator_task_tag;
1182 		bhsdo->bhsdo_target_transfer_tag =
1183 		    bhsr2t->bhsr2t_target_transfer_tag;
1184 		bhsdo->bhsdo_datasn = htonl(io->io_datasn++);
1185 		bhsdo->bhsdo_buffer_offset = htonl(off);
1186 		error = icl_pdu_append_data(request, csio->data_ptr + off, len,
1187 		    M_NOWAIT);
1188 		if (error != 0) {
1189 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
1190 			    "reconnecting");
1191 			icl_pdu_free(request);
1192 			icl_pdu_free(response);
1193 			iscsi_session_reconnect(is);
1194 			return;
1195 		}
1196 
1197 		off += len;
1198 		total_len -= len;
1199 
1200 		if (total_len == 0) {
1201 			bhsdo->bhsdo_flags |= BHSDO_FLAGS_F;
1202 			//ISCSI_SESSION_DEBUG(is, "setting F, off %zd", off);
1203 		} else {
1204 			//ISCSI_SESSION_DEBUG(is, "not finished, off %zd", off);
1205 		}
1206 
1207 		iscsi_pdu_queue_locked(request);
1208 
1209 		if (total_len == 0)
1210 			break;
1211 	}
1212 
1213 	icl_pdu_free(response);
1214 }
1215 
1216 static void
1217 iscsi_pdu_handle_async_message(struct icl_pdu *response)
1218 {
1219 	struct iscsi_bhs_asynchronous_message *bhsam;
1220 	struct iscsi_session *is;
1221 
1222 	is = PDU_SESSION(response);
1223 	bhsam = (struct iscsi_bhs_asynchronous_message *)response->ip_bhs;
1224 	switch (bhsam->bhsam_async_event) {
1225 	case BHSAM_EVENT_TARGET_REQUESTS_LOGOUT:
1226 		ISCSI_SESSION_WARN(is, "target requests logout; removing session");
1227 		iscsi_session_logout(is);
1228 		iscsi_session_terminate(is);
1229 		break;
1230 	case BHSAM_EVENT_TARGET_TERMINATES_CONNECTION:
1231 		ISCSI_SESSION_WARN(is, "target indicates it will drop drop the connection");
1232 		break;
1233 	case BHSAM_EVENT_TARGET_TERMINATES_SESSION:
1234 		ISCSI_SESSION_WARN(is, "target indicates it will drop drop the session");
1235 		break;
1236 	default:
1237 		/*
1238 		 * XXX: Technically, we're obligated to also handle
1239 		 * 	parameter renegotiation.
1240 		 */
1241 		ISCSI_SESSION_WARN(is, "ignoring AsyncEvent %d", bhsam->bhsam_async_event);
1242 		break;
1243 	}
1244 
1245 	icl_pdu_free(response);
1246 }
1247 
1248 static void
1249 iscsi_pdu_handle_reject(struct icl_pdu *response)
1250 {
1251 	struct iscsi_bhs_reject *bhsr;
1252 	struct iscsi_session *is;
1253 
1254 	is = PDU_SESSION(response);
1255 	bhsr = (struct iscsi_bhs_reject *)response->ip_bhs;
1256 	ISCSI_SESSION_WARN(is, "received Reject PDU, reason 0x%x; protocol error?",
1257 	    bhsr->bhsr_reason);
1258 
1259 	icl_pdu_free(response);
1260 }
1261 
1262 static int
1263 iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
1264     struct iscsi_daemon_request *request)
1265 {
1266 	struct iscsi_session *is;
1267 	int error;
1268 
1269 	sx_slock(&sc->sc_lock);
1270 	for (;;) {
1271 		TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1272 			ISCSI_SESSION_LOCK(is);
1273 			if (is->is_waiting_for_iscsid)
1274 				break;
1275 			ISCSI_SESSION_UNLOCK(is);
1276 		}
1277 
1278 		if (is == NULL) {
1279 			/*
1280 			 * No session requires attention from iscsid(8); wait.
1281 			 */
1282 			error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
1283 			if (error != 0) {
1284 				sx_sunlock(&sc->sc_lock);
1285 				return (error);
1286 			}
1287 			continue;
1288 		}
1289 
1290 		is->is_waiting_for_iscsid = false;
1291 		is->is_login_phase = true;
1292 		is->is_reason[0] = '\0';
1293 		ISCSI_SESSION_UNLOCK(is);
1294 
1295 		request->idr_session_id = is->is_id;
1296 		memcpy(&request->idr_isid, &is->is_isid,
1297 		    sizeof(request->idr_isid));
1298 		request->idr_tsih = 0;	/* New or reinstated session. */
1299 		memcpy(&request->idr_conf, &is->is_conf,
1300 		    sizeof(request->idr_conf));
1301 
1302 		sx_sunlock(&sc->sc_lock);
1303 		return (0);
1304 	}
1305 }
1306 
1307 static int
1308 iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc,
1309     struct iscsi_daemon_handoff *handoff)
1310 {
1311 	struct iscsi_session *is;
1312 	int error;
1313 
1314 	sx_slock(&sc->sc_lock);
1315 
1316 	/*
1317 	 * Find the session to hand off socket to.
1318 	 */
1319 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1320 		if (is->is_id == handoff->idh_session_id)
1321 			break;
1322 	}
1323 	if (is == NULL) {
1324 		sx_sunlock(&sc->sc_lock);
1325 		return (ESRCH);
1326 	}
1327 	ISCSI_SESSION_LOCK(is);
1328 	if (is->is_conf.isc_discovery || is->is_terminating) {
1329 		ISCSI_SESSION_UNLOCK(is);
1330 		sx_sunlock(&sc->sc_lock);
1331 		return (EINVAL);
1332 	}
1333 	if (is->is_connected) {
1334 		/*
1335 		 * This might have happened because another iscsid(8)
1336 		 * instance handed off the connection in the meantime.
1337 		 * Just return.
1338 		 */
1339 		ISCSI_SESSION_WARN(is, "handoff on already connected "
1340 		    "session");
1341 		ISCSI_SESSION_UNLOCK(is);
1342 		sx_sunlock(&sc->sc_lock);
1343 		return (EBUSY);
1344 	}
1345 
1346 	strlcpy(is->is_target_alias, handoff->idh_target_alias,
1347 	    sizeof(is->is_target_alias));
1348 	is->is_tsih = handoff->idh_tsih;
1349 	is->is_statsn = handoff->idh_statsn;
1350 	is->is_initial_r2t = handoff->idh_initial_r2t;
1351 	is->is_immediate_data = handoff->idh_immediate_data;
1352 	is->is_max_data_segment_length = handoff->idh_max_data_segment_length;
1353 	is->is_max_burst_length = handoff->idh_max_burst_length;
1354 	is->is_first_burst_length = handoff->idh_first_burst_length;
1355 
1356 	if (handoff->idh_header_digest == ISCSI_DIGEST_CRC32C)
1357 		is->is_conn->ic_header_crc32c = true;
1358 	else
1359 		is->is_conn->ic_header_crc32c = false;
1360 	if (handoff->idh_data_digest == ISCSI_DIGEST_CRC32C)
1361 		is->is_conn->ic_data_crc32c = true;
1362 	else
1363 		is->is_conn->ic_data_crc32c = false;
1364 
1365 	is->is_cmdsn = 0;
1366 	is->is_expcmdsn = 0;
1367 	is->is_maxcmdsn = 0;
1368 	is->is_waiting_for_iscsid = false;
1369 	is->is_login_phase = false;
1370 	is->is_timeout = 0;
1371 	is->is_connected = true;
1372 	is->is_reason[0] = '\0';
1373 
1374 	ISCSI_SESSION_UNLOCK(is);
1375 
1376 #ifdef ICL_KERNEL_PROXY
1377 	if (handoff->idh_socket != 0) {
1378 #endif
1379 		/*
1380 		 * Handoff without using ICL proxy.
1381 		 */
1382 		error = icl_conn_handoff(is->is_conn, handoff->idh_socket);
1383 		if (error != 0) {
1384 			sx_sunlock(&sc->sc_lock);
1385 			iscsi_session_terminate(is);
1386 			return (error);
1387 		}
1388 #ifdef ICL_KERNEL_PROXY
1389 	}
1390 #endif
1391 
1392 	sx_sunlock(&sc->sc_lock);
1393 
1394 	if (is->is_sim != NULL) {
1395 		/*
1396 		 * When reconnecting, there already is SIM allocated for the session.
1397 		 */
1398 		KASSERT(is->is_simq_frozen, ("reconnect without frozen simq"));
1399 		ISCSI_SESSION_LOCK(is);
1400 		ISCSI_SESSION_DEBUG(is, "releasing");
1401 		xpt_release_simq(is->is_sim, 1);
1402 		is->is_simq_frozen = false;
1403 		ISCSI_SESSION_UNLOCK(is);
1404 
1405 	} else {
1406 		ISCSI_SESSION_LOCK(is);
1407 		is->is_devq = cam_simq_alloc(maxtags);
1408 		if (is->is_devq == NULL) {
1409 			ISCSI_SESSION_WARN(is, "failed to allocate simq");
1410 			iscsi_session_terminate(is);
1411 			return (ENOMEM);
1412 		}
1413 
1414 		is->is_sim = cam_sim_alloc(iscsi_action, iscsi_poll, "iscsi",
1415 		    is, is->is_id /* unit */, &is->is_lock,
1416 		    1, maxtags, is->is_devq);
1417 		if (is->is_sim == NULL) {
1418 			ISCSI_SESSION_UNLOCK(is);
1419 			ISCSI_SESSION_WARN(is, "failed to allocate SIM");
1420 			cam_simq_free(is->is_devq);
1421 			iscsi_session_terminate(is);
1422 			return (ENOMEM);
1423 		}
1424 
1425 		error = xpt_bus_register(is->is_sim, NULL, 0);
1426 		if (error != 0) {
1427 			ISCSI_SESSION_UNLOCK(is);
1428 			ISCSI_SESSION_WARN(is, "failed to register bus");
1429 			iscsi_session_terminate(is);
1430 			return (ENOMEM);
1431 		}
1432 
1433 		error = xpt_create_path(&is->is_path, /*periph*/NULL,
1434 		    cam_sim_path(is->is_sim), CAM_TARGET_WILDCARD,
1435 		    CAM_LUN_WILDCARD);
1436 		if (error != CAM_REQ_CMP) {
1437 			ISCSI_SESSION_UNLOCK(is);
1438 			ISCSI_SESSION_WARN(is, "failed to create path");
1439 			iscsi_session_terminate(is);
1440 			return (ENOMEM);
1441 		}
1442 		ISCSI_SESSION_UNLOCK(is);
1443 	}
1444 
1445 	return (0);
1446 }
1447 
1448 static int
1449 iscsi_ioctl_daemon_fail(struct iscsi_softc *sc,
1450     struct iscsi_daemon_fail *fail)
1451 {
1452 	struct iscsi_session *is;
1453 
1454 	sx_slock(&sc->sc_lock);
1455 
1456 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1457 		if (is->is_id == fail->idf_session_id)
1458 			break;
1459 	}
1460 	if (is == NULL) {
1461 		sx_sunlock(&sc->sc_lock);
1462 		return (ESRCH);
1463 	}
1464 	ISCSI_SESSION_LOCK(is);
1465 	ISCSI_SESSION_DEBUG(is, "iscsid(8) failed: %s",
1466 	    fail->idf_reason);
1467 	strlcpy(is->is_reason, fail->idf_reason, sizeof(is->is_reason));
1468 	//is->is_waiting_for_iscsid = false;
1469 	//is->is_login_phase = true;
1470 	//iscsi_session_reconnect(is);
1471 	ISCSI_SESSION_UNLOCK(is);
1472 	sx_sunlock(&sc->sc_lock);
1473 
1474 	return (0);
1475 }
1476 
1477 #ifdef ICL_KERNEL_PROXY
1478 static int
1479 iscsi_ioctl_daemon_connect(struct iscsi_softc *sc,
1480     struct iscsi_daemon_connect *idc)
1481 {
1482 	struct iscsi_session *is;
1483 	struct sockaddr *from_sa, *to_sa;
1484 	int error;
1485 
1486 	sx_slock(&sc->sc_lock);
1487 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1488 		if (is->is_id == idc->idc_session_id)
1489 			break;
1490 	}
1491 	if (is == NULL) {
1492 		sx_sunlock(&sc->sc_lock);
1493 		return (ESRCH);
1494 	}
1495 	sx_sunlock(&sc->sc_lock);
1496 
1497 	if (idc->idc_from_addrlen > 0) {
1498 		error = getsockaddr(&from_sa, (void *)idc->idc_from_addr, idc->idc_from_addrlen);
1499 		if (error != 0) {
1500 			ISCSI_SESSION_WARN(is,
1501 			    "getsockaddr failed with error %d", error);
1502 			return (error);
1503 		}
1504 	} else {
1505 		from_sa = NULL;
1506 	}
1507 	error = getsockaddr(&to_sa, (void *)idc->idc_to_addr, idc->idc_to_addrlen);
1508 	if (error != 0) {
1509 		ISCSI_SESSION_WARN(is, "getsockaddr failed with error %d",
1510 		    error);
1511 		free(from_sa, M_SONAME);
1512 		return (error);
1513 	}
1514 
1515 	ISCSI_SESSION_LOCK(is);
1516 	is->is_waiting_for_iscsid = false;
1517 	is->is_login_phase = true;
1518 	is->is_timeout = 0;
1519 	ISCSI_SESSION_UNLOCK(is);
1520 
1521 	error = icl_conn_connect(is->is_conn, idc->idc_iser, idc->idc_domain,
1522 	    idc->idc_socktype, idc->idc_protocol, from_sa, to_sa);
1523 	free(from_sa, M_SONAME);
1524 	free(to_sa, M_SONAME);
1525 
1526 	/*
1527 	 * Digests are always disabled during login phase.
1528 	 */
1529 	is->is_conn->ic_header_crc32c = false;
1530 	is->is_conn->ic_data_crc32c = false;
1531 
1532 	return (error);
1533 }
1534 
1535 static int
1536 iscsi_ioctl_daemon_send(struct iscsi_softc *sc,
1537     struct iscsi_daemon_send *ids)
1538 {
1539 	struct iscsi_session *is;
1540 	struct icl_pdu *ip;
1541 	size_t datalen;
1542 	void *data;
1543 	int error;
1544 
1545 	sx_slock(&sc->sc_lock);
1546 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1547 		if (is->is_id == ids->ids_session_id)
1548 			break;
1549 	}
1550 	if (is == NULL) {
1551 		sx_sunlock(&sc->sc_lock);
1552 		return (ESRCH);
1553 	}
1554 	sx_sunlock(&sc->sc_lock);
1555 
1556 	if (is->is_login_phase == false)
1557 		return (EBUSY);
1558 
1559 	if (is->is_terminating || is->is_reconnecting)
1560 		return (EIO);
1561 
1562 	datalen = ids->ids_data_segment_len;
1563 	if (datalen > ISCSI_MAX_DATA_SEGMENT_LENGTH)
1564 		return (EINVAL);
1565 	if (datalen > 0) {
1566 		data = malloc(datalen, M_ISCSI, M_WAITOK);
1567 		error = copyin(ids->ids_data_segment, data, datalen);
1568 		if (error != 0) {
1569 			free(data, M_ISCSI);
1570 			return (error);
1571 		}
1572 	}
1573 
1574 	ip = icl_pdu_new(is->is_conn, M_WAITOK);
1575 	memcpy(ip->ip_bhs, ids->ids_bhs, sizeof(*ip->ip_bhs));
1576 	if (datalen > 0) {
1577 		error = icl_pdu_append_data(ip, data, datalen, M_WAITOK);
1578 		KASSERT(error == 0, ("icl_pdu_append_data(..., M_WAITOK) failed"));
1579 		free(data, M_ISCSI);
1580 	}
1581 	icl_pdu_queue(ip);
1582 
1583 	return (0);
1584 }
1585 
1586 static int
1587 iscsi_ioctl_daemon_receive(struct iscsi_softc *sc,
1588     struct iscsi_daemon_receive *idr)
1589 {
1590 	struct iscsi_session *is;
1591 	struct icl_pdu *ip;
1592 	void *data;
1593 
1594 	sx_slock(&sc->sc_lock);
1595 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1596 		if (is->is_id == idr->idr_session_id)
1597 			break;
1598 	}
1599 	if (is == NULL) {
1600 		sx_sunlock(&sc->sc_lock);
1601 		return (ESRCH);
1602 	}
1603 	sx_sunlock(&sc->sc_lock);
1604 
1605 	if (is->is_login_phase == false)
1606 		return (EBUSY);
1607 
1608 	ISCSI_SESSION_LOCK(is);
1609 	while (is->is_login_pdu == NULL &&
1610 	    is->is_terminating == false &&
1611 	    is->is_reconnecting == false)
1612 		cv_wait(&is->is_login_cv, &is->is_lock);
1613 	if (is->is_terminating || is->is_reconnecting) {
1614 		ISCSI_SESSION_UNLOCK(is);
1615 		return (EIO);
1616 	}
1617 	ip = is->is_login_pdu;
1618 	is->is_login_pdu = NULL;
1619 	ISCSI_SESSION_UNLOCK(is);
1620 
1621 	if (ip->ip_data_len > idr->idr_data_segment_len) {
1622 		icl_pdu_free(ip);
1623 		return (EMSGSIZE);
1624 	}
1625 
1626 	copyout(ip->ip_bhs, idr->idr_bhs, sizeof(*ip->ip_bhs));
1627 	if (ip->ip_data_len > 0) {
1628 		data = malloc(ip->ip_data_len, M_ISCSI, M_WAITOK);
1629 		icl_pdu_get_data(ip, 0, data, ip->ip_data_len);
1630 		copyout(data, idr->idr_data_segment, ip->ip_data_len);
1631 		free(data, M_ISCSI);
1632 	}
1633 
1634 	icl_pdu_free(ip);
1635 
1636 	return (0);
1637 }
1638 #endif /* ICL_KERNEL_PROXY */
1639 
1640 static void
1641 iscsi_sanitize_session_conf(struct iscsi_session_conf *isc)
1642 {
1643 	/*
1644 	 * Just make sure all the fields are null-terminated.
1645 	 *
1646 	 * XXX: This is not particularly secure.  We should
1647 	 * 	create our own conf and then copy in relevant
1648 	 * 	fields.
1649 	 */
1650 	isc->isc_initiator[ISCSI_NAME_LEN - 1] = '\0';
1651 	isc->isc_initiator_addr[ISCSI_ADDR_LEN - 1] = '\0';
1652 	isc->isc_initiator_alias[ISCSI_ALIAS_LEN - 1] = '\0';
1653 	isc->isc_target[ISCSI_NAME_LEN - 1] = '\0';
1654 	isc->isc_target_addr[ISCSI_ADDR_LEN - 1] = '\0';
1655 	isc->isc_user[ISCSI_NAME_LEN - 1] = '\0';
1656 	isc->isc_secret[ISCSI_SECRET_LEN - 1] = '\0';
1657 	isc->isc_mutual_user[ISCSI_NAME_LEN - 1] = '\0';
1658 	isc->isc_mutual_secret[ISCSI_SECRET_LEN - 1] = '\0';
1659 }
1660 
1661 static bool
1662 iscsi_valid_session_conf(const struct iscsi_session_conf *isc)
1663 {
1664 
1665 	if (isc->isc_initiator[0] == '\0') {
1666 		ISCSI_DEBUG("empty isc_initiator");
1667 		return (false);
1668 	}
1669 
1670 	if (isc->isc_target_addr[0] == '\0') {
1671 		ISCSI_DEBUG("empty isc_target_addr");
1672 		return (false);
1673 	}
1674 
1675 	if (isc->isc_discovery != 0 && isc->isc_target[0] != 0) {
1676 		ISCSI_DEBUG("non-empty isc_target for discovery session");
1677 		return (false);
1678 	}
1679 
1680 	if (isc->isc_discovery == 0 && isc->isc_target[0] == 0) {
1681 		ISCSI_DEBUG("empty isc_target for non-discovery session");
1682 		return (false);
1683 	}
1684 
1685 	return (true);
1686 }
1687 
1688 static int
1689 iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
1690 {
1691 	struct iscsi_session *is;
1692 	const struct iscsi_session *is2;
1693 	int error;
1694 
1695 	iscsi_sanitize_session_conf(&isa->isa_conf);
1696 	if (iscsi_valid_session_conf(&isa->isa_conf) == false)
1697 		return (EINVAL);
1698 
1699 	is = malloc(sizeof(*is), M_ISCSI, M_ZERO | M_WAITOK);
1700 	memcpy(&is->is_conf, &isa->isa_conf, sizeof(is->is_conf));
1701 
1702 	sx_xlock(&sc->sc_lock);
1703 
1704 	/*
1705 	 * Prevent duplicates.
1706 	 */
1707 	TAILQ_FOREACH(is2, &sc->sc_sessions, is_next) {
1708 		if (!!is->is_conf.isc_discovery !=
1709 		    !!is2->is_conf.isc_discovery)
1710 			continue;
1711 
1712 		if (strcmp(is->is_conf.isc_target_addr,
1713 		    is2->is_conf.isc_target_addr) != 0)
1714 			continue;
1715 
1716 		if (is->is_conf.isc_discovery == 0 &&
1717 		    strcmp(is->is_conf.isc_target,
1718 		    is2->is_conf.isc_target) != 0)
1719 			continue;
1720 
1721 		sx_xunlock(&sc->sc_lock);
1722 		free(is, M_ISCSI);
1723 		return (EBUSY);
1724 	}
1725 
1726 	is->is_conn = icl_conn_new("iscsi", &is->is_lock);
1727 	is->is_conn->ic_receive = iscsi_receive_callback;
1728 	is->is_conn->ic_error = iscsi_error_callback;
1729 	is->is_conn->ic_prv0 = is;
1730 	TAILQ_INIT(&is->is_outstanding);
1731 	STAILQ_INIT(&is->is_postponed);
1732 	mtx_init(&is->is_lock, "iscsi_lock", NULL, MTX_DEF);
1733 	cv_init(&is->is_maintenance_cv, "iscsi_mt");
1734 #ifdef ICL_KERNEL_PROXY
1735 	cv_init(&is->is_login_cv, "iscsi_login");
1736 #endif
1737 
1738 	is->is_softc = sc;
1739 	sc->sc_last_session_id++;
1740 	is->is_id = sc->sc_last_session_id;
1741 	is->is_isid[0] = 0x80; /* RFC 3720, 10.12.5: 10b, "Random" ISID. */
1742 	arc4rand(&is->is_isid[1], 5, 0);
1743 	is->is_tsih = 0;
1744 	callout_init(&is->is_callout, 1);
1745 	callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is);
1746 	TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
1747 
1748 	error = kthread_add(iscsi_maintenance_thread, is, NULL, NULL, 0, 0, "iscsimt");
1749 	if (error != 0) {
1750 		ISCSI_SESSION_WARN(is, "kthread_add(9) failed with error %d", error);
1751 		return (error);
1752 	}
1753 
1754 	/*
1755 	 * Trigger immediate reconnection.
1756 	 */
1757 	ISCSI_SESSION_LOCK(is);
1758 	is->is_waiting_for_iscsid = true;
1759 	strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
1760 	ISCSI_SESSION_UNLOCK(is);
1761 	cv_signal(&sc->sc_cv);
1762 
1763 	sx_xunlock(&sc->sc_lock);
1764 
1765 	return (0);
1766 }
1767 
1768 static bool
1769 iscsi_session_conf_matches(unsigned int id1, const struct iscsi_session_conf *c1,
1770     unsigned int id2, const struct iscsi_session_conf *c2)
1771 {
1772 
1773 	if (id2 != 0 && id2 != id1)
1774 		return (false);
1775 	if (c2->isc_target[0] != '\0' &&
1776 	    strcmp(c1->isc_target, c2->isc_target) != 0)
1777 		return (false);
1778 	if (c2->isc_target_addr[0] != '\0' &&
1779 	    strcmp(c1->isc_target_addr, c2->isc_target_addr) != 0)
1780 		return (false);
1781 	return (true);
1782 }
1783 
1784 static int
1785 iscsi_ioctl_session_remove(struct iscsi_softc *sc,
1786     struct iscsi_session_remove *isr)
1787 {
1788 	struct iscsi_session *is, *tmp;
1789 	bool found = false;
1790 
1791 	iscsi_sanitize_session_conf(&isr->isr_conf);
1792 
1793 	sx_xlock(&sc->sc_lock);
1794 	TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp) {
1795 		ISCSI_SESSION_LOCK(is);
1796 		if (iscsi_session_conf_matches(is->is_id, &is->is_conf,
1797 		    isr->isr_session_id, &isr->isr_conf)) {
1798 			found = true;
1799 			iscsi_session_logout(is);
1800 			iscsi_session_terminate(is);
1801 		}
1802 		ISCSI_SESSION_UNLOCK(is);
1803 	}
1804 	sx_xunlock(&sc->sc_lock);
1805 
1806 	if (!found)
1807 		return (ESRCH);
1808 
1809 	return (0);
1810 }
1811 
1812 static int
1813 iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl)
1814 {
1815 	int error;
1816 	unsigned int i = 0;
1817 	struct iscsi_session *is;
1818 	struct iscsi_session_state iss;
1819 
1820 	sx_slock(&sc->sc_lock);
1821 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1822 		if (i >= isl->isl_nentries) {
1823 			sx_sunlock(&sc->sc_lock);
1824 			return (EMSGSIZE);
1825 		}
1826 		memset(&iss, 0, sizeof(iss));
1827 		memcpy(&iss.iss_conf, &is->is_conf, sizeof(iss.iss_conf));
1828 		iss.iss_id = is->is_id;
1829 		strlcpy(iss.iss_target_alias, is->is_target_alias, sizeof(iss.iss_target_alias));
1830 		strlcpy(iss.iss_reason, is->is_reason, sizeof(iss.iss_reason));
1831 
1832 		if (is->is_conn->ic_header_crc32c)
1833 			iss.iss_header_digest = ISCSI_DIGEST_CRC32C;
1834 		else
1835 			iss.iss_header_digest = ISCSI_DIGEST_NONE;
1836 
1837 		if (is->is_conn->ic_data_crc32c)
1838 			iss.iss_data_digest = ISCSI_DIGEST_CRC32C;
1839 		else
1840 			iss.iss_data_digest = ISCSI_DIGEST_NONE;
1841 
1842 		iss.iss_max_data_segment_length = is->is_max_data_segment_length;
1843 		iss.iss_immediate_data = is->is_immediate_data;
1844 		iss.iss_connected = is->is_connected;
1845 
1846 		error = copyout(&iss, isl->isl_pstates + i, sizeof(iss));
1847 		if (error != 0) {
1848 			sx_sunlock(&sc->sc_lock);
1849 			return (error);
1850 		}
1851 		i++;
1852 	}
1853 	sx_sunlock(&sc->sc_lock);
1854 
1855 	isl->isl_nentries = i;
1856 
1857 	return (0);
1858 }
1859 
1860 static int
1861 iscsi_ioctl_session_modify(struct iscsi_softc *sc,
1862     struct iscsi_session_modify *ism)
1863 {
1864 	struct iscsi_session *is;
1865 
1866 	iscsi_sanitize_session_conf(&ism->ism_conf);
1867 	if (iscsi_valid_session_conf(&ism->ism_conf) == false)
1868 		return (EINVAL);
1869 
1870 	sx_xlock(&sc->sc_lock);
1871 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1872 		ISCSI_SESSION_LOCK(is);
1873 		if (is->is_id == ism->ism_session_id)
1874 			break;
1875 		ISCSI_SESSION_UNLOCK(is);
1876 	}
1877 	if (is == NULL) {
1878 		sx_xunlock(&sc->sc_lock);
1879 		return (ESRCH);
1880 	}
1881 	sx_xunlock(&sc->sc_lock);
1882 
1883 	memcpy(&is->is_conf, &ism->ism_conf, sizeof(is->is_conf));
1884 	ISCSI_SESSION_UNLOCK(is);
1885 
1886 	iscsi_session_reconnect(is);
1887 
1888 	return (0);
1889 }
1890 
1891 static int
1892 iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
1893     struct thread *td)
1894 {
1895 	struct iscsi_softc *sc;
1896 
1897 	sc = dev->si_drv1;
1898 
1899 	switch (cmd) {
1900 	case ISCSIDWAIT:
1901 		return (iscsi_ioctl_daemon_wait(sc,
1902 		    (struct iscsi_daemon_request *)arg));
1903 	case ISCSIDHANDOFF:
1904 		return (iscsi_ioctl_daemon_handoff(sc,
1905 		    (struct iscsi_daemon_handoff *)arg));
1906 	case ISCSIDFAIL:
1907 		return (iscsi_ioctl_daemon_fail(sc,
1908 		    (struct iscsi_daemon_fail *)arg));
1909 #ifdef ICL_KERNEL_PROXY
1910 	case ISCSIDCONNECT:
1911 		return (iscsi_ioctl_daemon_connect(sc,
1912 		    (struct iscsi_daemon_connect *)arg));
1913 	case ISCSIDSEND:
1914 		return (iscsi_ioctl_daemon_send(sc,
1915 		    (struct iscsi_daemon_send *)arg));
1916 	case ISCSIDRECEIVE:
1917 		return (iscsi_ioctl_daemon_receive(sc,
1918 		    (struct iscsi_daemon_receive *)arg));
1919 #endif /* ICL_KERNEL_PROXY */
1920 	case ISCSISADD:
1921 		return (iscsi_ioctl_session_add(sc,
1922 		    (struct iscsi_session_add *)arg));
1923 	case ISCSISREMOVE:
1924 		return (iscsi_ioctl_session_remove(sc,
1925 		    (struct iscsi_session_remove *)arg));
1926 	case ISCSISLIST:
1927 		return (iscsi_ioctl_session_list(sc,
1928 		    (struct iscsi_session_list *)arg));
1929 	case ISCSISMODIFY:
1930 		return (iscsi_ioctl_session_modify(sc,
1931 		    (struct iscsi_session_modify *)arg));
1932 	default:
1933 		return (EINVAL);
1934 	}
1935 }
1936 
1937 static struct iscsi_outstanding *
1938 iscsi_outstanding_find(struct iscsi_session *is, uint32_t initiator_task_tag)
1939 {
1940 	struct iscsi_outstanding *io;
1941 
1942 	ISCSI_SESSION_LOCK_ASSERT(is);
1943 
1944 	TAILQ_FOREACH(io, &is->is_outstanding, io_next) {
1945 		if (io->io_initiator_task_tag == initiator_task_tag)
1946 			return (io);
1947 	}
1948 	return (NULL);
1949 }
1950 
1951 static struct iscsi_outstanding *
1952 iscsi_outstanding_find_ccb(struct iscsi_session *is, union ccb *ccb)
1953 {
1954 	struct iscsi_outstanding *io;
1955 
1956 	ISCSI_SESSION_LOCK_ASSERT(is);
1957 
1958 	TAILQ_FOREACH(io, &is->is_outstanding, io_next) {
1959 		if (io->io_ccb == ccb)
1960 			return (io);
1961 	}
1962 	return (NULL);
1963 }
1964 
1965 static struct iscsi_outstanding *
1966 iscsi_outstanding_add(struct iscsi_session *is,
1967     uint32_t initiator_task_tag, union ccb *ccb)
1968 {
1969 	struct iscsi_outstanding *io;
1970 
1971 	ISCSI_SESSION_LOCK_ASSERT(is);
1972 
1973 	KASSERT(iscsi_outstanding_find(is, initiator_task_tag) == NULL,
1974 	    ("initiator_task_tag 0x%x already added", initiator_task_tag));
1975 
1976 	io = uma_zalloc(iscsi_outstanding_zone, M_NOWAIT | M_ZERO);
1977 	if (io == NULL) {
1978 		ISCSI_SESSION_WARN(is, "failed to allocate %zd bytes", sizeof(*io));
1979 		return (NULL);
1980 	}
1981 	io->io_initiator_task_tag = initiator_task_tag;
1982 	io->io_ccb = ccb;
1983 	TAILQ_INSERT_TAIL(&is->is_outstanding, io, io_next);
1984 	return (io);
1985 }
1986 
1987 static void
1988 iscsi_outstanding_remove(struct iscsi_session *is, struct iscsi_outstanding *io)
1989 {
1990 
1991 	ISCSI_SESSION_LOCK_ASSERT(is);
1992 
1993 	TAILQ_REMOVE(&is->is_outstanding, io, io_next);
1994 	uma_zfree(iscsi_outstanding_zone, io);
1995 }
1996 
1997 static void
1998 iscsi_action_abort(struct iscsi_session *is, union ccb *ccb)
1999 {
2000 	struct icl_pdu *request;
2001 	struct iscsi_bhs_task_management_request *bhstmr;
2002 	struct ccb_abort *cab = &ccb->cab;
2003 	struct iscsi_outstanding *io, *aio;
2004 
2005 	ISCSI_SESSION_LOCK_ASSERT(is);
2006 
2007 #if 0
2008 	KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__));
2009 #else
2010 	if (is->is_login_phase) {
2011 		ccb->ccb_h.status = CAM_REQ_ABORTED;
2012 		xpt_done(ccb);
2013 		return;
2014 	}
2015 #endif
2016 
2017 	aio = iscsi_outstanding_find_ccb(is, cab->abort_ccb);
2018 	if (aio == NULL) {
2019 		ccb->ccb_h.status = CAM_REQ_CMP;
2020 		xpt_done(ccb);
2021 		return;
2022 	}
2023 
2024 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
2025 	if (request == NULL) {
2026 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2027 		xpt_done(ccb);
2028 		return;
2029 	}
2030 
2031 	bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
2032 	bhstmr->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_REQUEST;
2033 	bhstmr->bhstmr_function = 0x80 | BHSTMR_FUNCTION_ABORT_TASK;
2034 
2035 	bhstmr->bhstmr_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
2036 	bhstmr->bhstmr_initiator_task_tag = is->is_initiator_task_tag;
2037 	is->is_initiator_task_tag++;
2038 	bhstmr->bhstmr_referenced_task_tag = aio->io_initiator_task_tag;
2039 
2040 	io = iscsi_outstanding_add(is, bhstmr->bhstmr_initiator_task_tag, NULL);
2041 	if (io == NULL) {
2042 		icl_pdu_free(request);
2043 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2044 		xpt_done(ccb);
2045 		return;
2046 	}
2047 	io->io_datasn = aio->io_initiator_task_tag;
2048 	iscsi_pdu_queue_locked(request);
2049 }
2050 
2051 static void
2052 iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
2053 {
2054 	struct icl_pdu *request;
2055 	struct iscsi_bhs_scsi_command *bhssc;
2056 	struct ccb_scsiio *csio;
2057 	struct iscsi_outstanding *io;
2058 	size_t len;
2059 	int error;
2060 
2061 	ISCSI_SESSION_LOCK_ASSERT(is);
2062 
2063 #if 0
2064 	KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__));
2065 #else
2066 	if (is->is_login_phase) {
2067 		ISCSI_SESSION_DEBUG(is, "called during login phase");
2068 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2069 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2070 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2071 		}
2072 		ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_DEV_QFRZN;
2073 		xpt_done(ccb);
2074 		return;
2075 	}
2076 #endif
2077 
2078 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
2079 	if (request == NULL) {
2080 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2081 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2082 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2083 		}
2084 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2085 		xpt_done(ccb);
2086 		return;
2087 	}
2088 
2089 	csio = &ccb->csio;
2090 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
2091 	bhssc->bhssc_opcode = ISCSI_BHS_OPCODE_SCSI_COMMAND;
2092 	bhssc->bhssc_flags |= BHSSC_FLAGS_F;
2093 	switch (csio->ccb_h.flags & CAM_DIR_MASK) {
2094 	case CAM_DIR_IN:
2095 		bhssc->bhssc_flags |= BHSSC_FLAGS_R;
2096 		break;
2097 	case CAM_DIR_OUT:
2098 		bhssc->bhssc_flags |= BHSSC_FLAGS_W;
2099 		break;
2100 	}
2101 
2102 	if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
2103 		switch (csio->tag_action) {
2104 		case MSG_HEAD_OF_Q_TAG:
2105 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_HOQ;
2106 			break;
2107 		case MSG_ORDERED_Q_TAG:
2108 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ORDERED;
2109 			break;
2110 		case MSG_ACA_TASK:
2111 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ACA;
2112 			break;
2113 		case MSG_SIMPLE_Q_TAG:
2114 		default:
2115 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_SIMPLE;
2116 			break;
2117 		}
2118 	} else
2119 		bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_UNTAGGED;
2120 
2121 	bhssc->bhssc_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
2122 	bhssc->bhssc_initiator_task_tag = is->is_initiator_task_tag;
2123 	is->is_initiator_task_tag++;
2124 	bhssc->bhssc_expected_data_transfer_length = htonl(csio->dxfer_len);
2125 	KASSERT(csio->cdb_len <= sizeof(bhssc->bhssc_cdb),
2126 	    ("unsupported CDB size %zd", (size_t)csio->cdb_len));
2127 
2128 	if (csio->ccb_h.flags & CAM_CDB_POINTER)
2129 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_ptr, csio->cdb_len);
2130 	else
2131 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_bytes, csio->cdb_len);
2132 
2133 	io = iscsi_outstanding_add(is, bhssc->bhssc_initiator_task_tag, ccb);
2134 	if (io == NULL) {
2135 		icl_pdu_free(request);
2136 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2137 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2138 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2139 		}
2140 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2141 		xpt_done(ccb);
2142 		return;
2143 	}
2144 
2145 	if (is->is_immediate_data &&
2146 	    (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
2147 		len = csio->dxfer_len;
2148 		//ISCSI_SESSION_DEBUG(is, "adding %zd of immediate data", len);
2149 		if (len > is->is_first_burst_length) {
2150 			ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_first_burst_length);
2151 			len = is->is_first_burst_length;
2152 		}
2153 
2154 		error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT);
2155 		if (error != 0) {
2156 			icl_pdu_free(request);
2157 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2158 				xpt_freeze_devq(ccb->ccb_h.path, 1);
2159 				ISCSI_SESSION_DEBUG(is, "freezing devq");
2160 			}
2161 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2162 			xpt_done(ccb);
2163 			return;
2164 		}
2165 	}
2166 	iscsi_pdu_queue_locked(request);
2167 }
2168 
2169 static void
2170 iscsi_action(struct cam_sim *sim, union ccb *ccb)
2171 {
2172 	struct iscsi_session *is;
2173 
2174 	is = cam_sim_softc(sim);
2175 
2176 	ISCSI_SESSION_LOCK_ASSERT(is);
2177 
2178 	if (is->is_terminating ||
2179 	    (is->is_connected == false && fail_on_disconnection)) {
2180 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2181 		xpt_done(ccb);
2182 		return;
2183 	}
2184 
2185 	switch (ccb->ccb_h.func_code) {
2186 	case XPT_PATH_INQ:
2187 	{
2188 		struct ccb_pathinq *cpi = &ccb->cpi;
2189 
2190 		cpi->version_num = 1;
2191 		cpi->hba_inquiry = PI_TAG_ABLE;
2192 		cpi->target_sprt = 0;
2193 		cpi->hba_misc = PIM_EXTLUNS;
2194 		cpi->hba_eng_cnt = 0;
2195 		cpi->max_target = 0;
2196 		/*
2197 		 * Note that the variable below is only relevant for targets
2198 		 * that don't claim compliance with anything above SPC2, which
2199 		 * means they don't support REPORT_LUNS.
2200 		 */
2201 		cpi->max_lun = 255;
2202 		cpi->initiator_id = ~0;
2203 		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2204 		strlcpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
2205 		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2206 		cpi->unit_number = cam_sim_unit(sim);
2207 		cpi->bus_id = cam_sim_bus(sim);
2208 		cpi->base_transfer_speed = 150000; /* XXX */
2209 		cpi->transport = XPORT_ISCSI;
2210 		cpi->transport_version = 0;
2211 		cpi->protocol = PROTO_SCSI;
2212 		cpi->protocol_version = SCSI_REV_SPC3;
2213 		cpi->maxio = MAXPHYS;
2214 		cpi->ccb_h.status = CAM_REQ_CMP;
2215 		break;
2216 	}
2217 	case XPT_GET_TRAN_SETTINGS:
2218 	{
2219 		struct ccb_trans_settings	*cts;
2220 		struct ccb_trans_settings_scsi	*scsi;
2221 
2222 		cts = &ccb->cts;
2223 		scsi = &cts->proto_specific.scsi;
2224 
2225 		cts->protocol = PROTO_SCSI;
2226 		cts->protocol_version = SCSI_REV_SPC3;
2227 		cts->transport = XPORT_ISCSI;
2228 		cts->transport_version = 0;
2229 		scsi->valid = CTS_SCSI_VALID_TQ;
2230 		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2231 		cts->ccb_h.status = CAM_REQ_CMP;
2232 		break;
2233 	}
2234 	case XPT_CALC_GEOMETRY:
2235 		cam_calc_geometry(&ccb->ccg, /*extended*/1);
2236 		ccb->ccb_h.status = CAM_REQ_CMP;
2237 		break;
2238 #if 0
2239 	/*
2240 	 * XXX: What's the point?
2241 	 */
2242 	case XPT_RESET_BUS:
2243 	case XPT_TERM_IO:
2244 		ISCSI_SESSION_DEBUG(is, "faking success for reset, abort, or term_io");
2245 		ccb->ccb_h.status = CAM_REQ_CMP;
2246 		break;
2247 #endif
2248 	case XPT_ABORT:
2249 		iscsi_action_abort(is, ccb);
2250 		return;
2251 	case XPT_SCSI_IO:
2252 		iscsi_action_scsiio(is, ccb);
2253 		return;
2254 	default:
2255 #if 0
2256 		ISCSI_SESSION_DEBUG(is, "got unsupported code 0x%x", ccb->ccb_h.func_code);
2257 #endif
2258 		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2259 		break;
2260 	}
2261 	xpt_done(ccb);
2262 }
2263 
2264 static void
2265 iscsi_poll(struct cam_sim *sim)
2266 {
2267 
2268 	KASSERT(0, ("%s: you're not supposed to be here", __func__));
2269 }
2270 
2271 static void
2272 iscsi_shutdown(struct iscsi_softc *sc)
2273 {
2274 	struct iscsi_session *is;
2275 
2276 	ISCSI_DEBUG("removing all sessions due to shutdown");
2277 
2278 	sx_slock(&sc->sc_lock);
2279 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next)
2280 		iscsi_session_terminate(is);
2281 	sx_sunlock(&sc->sc_lock);
2282 }
2283 
2284 static int
2285 iscsi_load(void)
2286 {
2287 	int error;
2288 
2289 	sc = malloc(sizeof(*sc), M_ISCSI, M_ZERO | M_WAITOK);
2290 	sx_init(&sc->sc_lock, "iscsi");
2291 	TAILQ_INIT(&sc->sc_sessions);
2292 	cv_init(&sc->sc_cv, "iscsi_cv");
2293 
2294 	iscsi_outstanding_zone = uma_zcreate("iscsi_outstanding",
2295 	    sizeof(struct iscsi_outstanding), NULL, NULL, NULL, NULL,
2296 	    UMA_ALIGN_PTR, 0);
2297 
2298 	error = make_dev_p(MAKEDEV_CHECKNAME, &sc->sc_cdev, &iscsi_cdevsw,
2299 	    NULL, UID_ROOT, GID_WHEEL, 0600, "iscsi");
2300 	if (error != 0) {
2301 		ISCSI_WARN("failed to create device node, error %d", error);
2302 		return (error);
2303 	}
2304 	sc->sc_cdev->si_drv1 = sc;
2305 
2306 	/*
2307 	 * Note that this needs to get run before dashutdown().  Otherwise,
2308 	 * when rebooting with iSCSI session with outstanding requests,
2309 	 * but disconnected, dashutdown() will hang on cam_periph_runccb().
2310 	 */
2311 	sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
2312 	    iscsi_shutdown, sc, SHUTDOWN_PRI_FIRST);
2313 
2314 	return (0);
2315 }
2316 
2317 static int
2318 iscsi_unload(void)
2319 {
2320 	struct iscsi_session *is, *tmp;
2321 
2322 	if (sc->sc_cdev != NULL) {
2323 		ISCSI_DEBUG("removing device node");
2324 		destroy_dev(sc->sc_cdev);
2325 		ISCSI_DEBUG("device node removed");
2326 	}
2327 
2328 	if (sc->sc_shutdown_eh != NULL)
2329 		EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_eh);
2330 
2331 	sx_slock(&sc->sc_lock);
2332 	TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp)
2333 		iscsi_session_terminate(is);
2334 	while(!TAILQ_EMPTY(&sc->sc_sessions)) {
2335 		ISCSI_DEBUG("waiting for sessions to terminate");
2336 		cv_wait(&sc->sc_cv, &sc->sc_lock);
2337 	}
2338 	ISCSI_DEBUG("all sessions terminated");
2339 	sx_sunlock(&sc->sc_lock);
2340 
2341 	uma_zdestroy(iscsi_outstanding_zone);
2342 	sx_destroy(&sc->sc_lock);
2343 	cv_destroy(&sc->sc_cv);
2344 	free(sc, M_ISCSI);
2345 	return (0);
2346 }
2347 
2348 static int
2349 iscsi_quiesce(void)
2350 {
2351 	sx_slock(&sc->sc_lock);
2352 	if (!TAILQ_EMPTY(&sc->sc_sessions)) {
2353 		sx_sunlock(&sc->sc_lock);
2354 		return (EBUSY);
2355 	}
2356 	sx_sunlock(&sc->sc_lock);
2357 	return (0);
2358 }
2359 
2360 static int
2361 iscsi_modevent(module_t mod, int what, void *arg)
2362 {
2363 	int error;
2364 
2365 	switch (what) {
2366 	case MOD_LOAD:
2367 		error = iscsi_load();
2368 		break;
2369 	case MOD_UNLOAD:
2370 		error = iscsi_unload();
2371 		break;
2372 	case MOD_QUIESCE:
2373 		error = iscsi_quiesce();
2374 		break;
2375 	default:
2376 		error = EINVAL;
2377 		break;
2378 	}
2379 	return (error);
2380 }
2381 
2382 moduledata_t iscsi_data = {
2383 	"iscsi",
2384 	iscsi_modevent,
2385 	0
2386 };
2387 
2388 DECLARE_MODULE(iscsi, iscsi_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
2389 MODULE_DEPEND(iscsi, cam, 1, 1, 1);
2390 MODULE_DEPEND(iscsi, icl, 1, 1, 1);
2391