xref: /freebsd/sys/dev/iscsi/iscsi.c (revision c215ad3aa893ea1e2cd3c874801e3cf4982292d7)
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 	struct ccb_scsiio *csio;
842 	size_t data_segment_len;
843 	uint16_t sense_len;
844 
845 	is = PDU_SESSION(response);
846 
847 	bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs;
848 	io = iscsi_outstanding_find(is, bhssr->bhssr_initiator_task_tag);
849 	if (io == NULL || io->io_ccb == NULL) {
850 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhssr->bhssr_initiator_task_tag);
851 		icl_pdu_free(response);
852 		iscsi_session_reconnect(is);
853 		ISCSI_SESSION_UNLOCK(is);
854 		return;
855 	}
856 
857 	iscsi_outstanding_remove(is, io);
858 	ISCSI_SESSION_UNLOCK(is);
859 
860 	if (bhssr->bhssr_response != BHSSR_RESPONSE_COMMAND_COMPLETED) {
861 		ISCSI_SESSION_WARN(is, "service response 0x%x", bhssr->bhssr_response);
862  		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
863  			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
864 			ISCSI_SESSION_DEBUG(is, "freezing devq");
865 		}
866  		io->io_ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
867 	} else if (bhssr->bhssr_status == 0) {
868 		io->io_ccb->ccb_h.status = CAM_REQ_CMP;
869 	} else {
870  		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
871  			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
872 			ISCSI_SESSION_DEBUG(is, "freezing devq");
873 		}
874  		io->io_ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
875 		io->io_ccb->csio.scsi_status = bhssr->bhssr_status;
876 	}
877 
878 	csio = &io->io_ccb->csio;
879 	data_segment_len = icl_pdu_data_segment_length(response);
880 	if (data_segment_len > 0) {
881 		if (data_segment_len < sizeof(sense_len)) {
882 			ISCSI_SESSION_WARN(is, "truncated data segment (%zd bytes)",
883 			    data_segment_len);
884 			if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
885 				xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
886 				ISCSI_SESSION_DEBUG(is, "freezing devq");
887 			}
888 			io->io_ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
889 			goto out;
890 		}
891 		icl_pdu_get_data(response, 0, &sense_len, sizeof(sense_len));
892 		sense_len = ntohs(sense_len);
893 #if 0
894 		ISCSI_SESSION_DEBUG(is, "sense_len %d, data len %zd",
895 		    sense_len, data_segment_len);
896 #endif
897 		if (sizeof(sense_len) + sense_len > data_segment_len) {
898 			ISCSI_SESSION_WARN(is, "truncated data segment "
899 			    "(%zd bytes, should be %zd)",
900 			    data_segment_len, sizeof(sense_len) + sense_len);
901 			if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
902 				xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
903 				ISCSI_SESSION_DEBUG(is, "freezing devq");
904 			}
905 			io->io_ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN;
906 			goto out;
907 		} else if (sizeof(sense_len) + sense_len < data_segment_len)
908 			ISCSI_SESSION_WARN(is, "oversize data segment "
909 			    "(%zd bytes, should be %zd)",
910 			    data_segment_len, sizeof(sense_len) + sense_len);
911 		if (sense_len > csio->sense_len) {
912 			ISCSI_SESSION_DEBUG(is, "truncating sense from %d to %d",
913 			    sense_len, csio->sense_len);
914 			sense_len = csio->sense_len;
915 		}
916 		icl_pdu_get_data(response, sizeof(sense_len), &csio->sense_data, sense_len);
917 		csio->sense_resid = csio->sense_len - sense_len;
918 		io->io_ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
919 	}
920 
921 out:
922 	if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_UNDERFLOW)
923 		csio->resid = ntohl(bhssr->bhssr_residual_count);
924 
925 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
926 		KASSERT(io->io_received <= csio->dxfer_len,
927 		    ("io->io_received > csio->dxfer_len"));
928 		if (io->io_received < csio->dxfer_len) {
929 			if (csio->resid != csio->dxfer_len - io->io_received) {
930 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
931 				    "target indicates %d, we calculated %zd",
932 				    csio->resid,
933 				    csio->dxfer_len - io->io_received);
934 			}
935 			csio->resid = csio->dxfer_len - io->io_received;
936 		}
937 	}
938 
939 	xpt_done(io->io_ccb);
940 	icl_pdu_free(response);
941 }
942 
943 static void
944 iscsi_pdu_handle_task_response(struct icl_pdu *response)
945 {
946 	struct iscsi_bhs_task_management_response *bhstmr;
947 	struct iscsi_outstanding *io, *aio;
948 	struct iscsi_session *is;
949 
950 	is = PDU_SESSION(response);
951 
952 	bhstmr = (struct iscsi_bhs_task_management_response *)response->ip_bhs;
953 	io = iscsi_outstanding_find(is, bhstmr->bhstmr_initiator_task_tag);
954 	if (io == NULL || io->io_ccb != NULL) {
955 		ISCSI_SESSION_WARN(is, "bad itt 0x%x",
956 		    bhstmr->bhstmr_initiator_task_tag);
957 		icl_pdu_free(response);
958 		iscsi_session_reconnect(is);
959 		return;
960 	}
961 
962 	if (bhstmr->bhstmr_response != BHSTMR_RESPONSE_FUNCTION_COMPLETE) {
963 		ISCSI_SESSION_WARN(is, "task response 0x%x",
964 		    bhstmr->bhstmr_response);
965 	} else {
966 		aio = iscsi_outstanding_find(is, io->io_datasn);
967 		if (aio != NULL && aio->io_ccb != NULL)
968 			iscsi_session_terminate_task(is, aio, false);
969 	}
970 
971 	iscsi_outstanding_remove(is, io);
972 	icl_pdu_free(response);
973 }
974 
975 static void
976 iscsi_pdu_handle_data_in(struct icl_pdu *response)
977 {
978 	struct iscsi_bhs_data_in *bhsdi;
979 	struct iscsi_outstanding *io;
980 	struct iscsi_session *is;
981 	struct ccb_scsiio *csio;
982 	size_t data_segment_len, received;
983 
984 	is = PDU_SESSION(response);
985 	bhsdi = (struct iscsi_bhs_data_in *)response->ip_bhs;
986 	io = iscsi_outstanding_find(is, bhsdi->bhsdi_initiator_task_tag);
987 	if (io == NULL || io->io_ccb == NULL) {
988 		ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhsdi->bhsdi_initiator_task_tag);
989 		icl_pdu_free(response);
990 		iscsi_session_reconnect(is);
991 		ISCSI_SESSION_UNLOCK(is);
992 		return;
993 	}
994 
995 	data_segment_len = icl_pdu_data_segment_length(response);
996 	if (data_segment_len == 0) {
997 		/*
998 		 * "The sending of 0 length data segments should be avoided,
999 		 * but initiators and targets MUST be able to properly receive
1000 		 * 0 length data segments."
1001 		 */
1002 		ISCSI_SESSION_UNLOCK(is);
1003 		icl_pdu_free(response);
1004 		return;
1005 	}
1006 
1007 	/*
1008 	 * We need to track this for security reasons - without it, malicious target
1009 	 * could respond to SCSI READ without sending Data-In PDUs, which would result
1010 	 * in read operation on the initiator side returning random kernel data.
1011 	 */
1012 	if (ntohl(bhsdi->bhsdi_buffer_offset) != io->io_received) {
1013 		ISCSI_SESSION_WARN(is, "data out of order; expected offset %zd, got %zd",
1014 		    io->io_received, (size_t)ntohl(bhsdi->bhsdi_buffer_offset));
1015 		icl_pdu_free(response);
1016 		iscsi_session_reconnect(is);
1017 		ISCSI_SESSION_UNLOCK(is);
1018 		return;
1019 	}
1020 
1021 	csio = &io->io_ccb->csio;
1022 
1023 	if (io->io_received + data_segment_len > csio->dxfer_len) {
1024 		ISCSI_SESSION_WARN(is, "oversize data segment (%zd bytes "
1025 		    "at offset %zd, buffer is %d)",
1026 		    data_segment_len, io->io_received, csio->dxfer_len);
1027 		icl_pdu_free(response);
1028 		iscsi_session_reconnect(is);
1029 		ISCSI_SESSION_UNLOCK(is);
1030 		return;
1031 	}
1032 
1033 	received = io->io_received;
1034 	io->io_received += data_segment_len;
1035 	if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0)
1036 		iscsi_outstanding_remove(is, io);
1037 	ISCSI_SESSION_UNLOCK(is);
1038 
1039 	icl_pdu_get_data(response, 0, csio->data_ptr + received, data_segment_len);
1040 
1041 	/*
1042 	 * XXX: Check DataSN.
1043 	 * XXX: Check F.
1044 	 */
1045 	if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) == 0) {
1046 		/*
1047 		 * Nothing more to do.
1048 		 */
1049 		icl_pdu_free(response);
1050 		return;
1051 	}
1052 
1053 	//ISCSI_SESSION_DEBUG(is, "got S flag; status 0x%x", bhsdi->bhsdi_status);
1054 	if (bhsdi->bhsdi_status == 0) {
1055 		io->io_ccb->ccb_h.status = CAM_REQ_CMP;
1056 	} else {
1057 		if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
1058 			xpt_freeze_devq(io->io_ccb->ccb_h.path, 1);
1059 			ISCSI_SESSION_DEBUG(is, "freezing devq");
1060 		}
1061 		io->io_ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN;
1062 		csio->scsi_status = bhsdi->bhsdi_status;
1063 	}
1064 
1065 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1066 		KASSERT(io->io_received <= csio->dxfer_len,
1067 		    ("io->io_received > csio->dxfer_len"));
1068 		if (io->io_received < csio->dxfer_len) {
1069 			csio->resid = ntohl(bhsdi->bhsdi_residual_count);
1070 			if (csio->resid != csio->dxfer_len - io->io_received) {
1071 				ISCSI_SESSION_WARN(is, "underflow mismatch: "
1072 				    "target indicates %d, we calculated %zd",
1073 				    csio->resid,
1074 				    csio->dxfer_len - io->io_received);
1075 			}
1076 			csio->resid = csio->dxfer_len - io->io_received;
1077 		}
1078 	}
1079 
1080 	xpt_done(io->io_ccb);
1081 	icl_pdu_free(response);
1082 }
1083 
1084 static void
1085 iscsi_pdu_handle_logout_response(struct icl_pdu *response)
1086 {
1087 
1088 	ISCSI_SESSION_DEBUG(PDU_SESSION(response), "logout response");
1089 	icl_pdu_free(response);
1090 }
1091 
1092 static void
1093 iscsi_pdu_handle_r2t(struct icl_pdu *response)
1094 {
1095 	struct icl_pdu *request;
1096 	struct iscsi_session *is;
1097 	struct iscsi_bhs_r2t *bhsr2t;
1098 	struct iscsi_bhs_data_out *bhsdo;
1099 	struct iscsi_outstanding *io;
1100 	struct ccb_scsiio *csio;
1101 	size_t off, len, total_len;
1102 	int error;
1103 
1104 	is = PDU_SESSION(response);
1105 
1106 	bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs;
1107 	io = iscsi_outstanding_find(is, bhsr2t->bhsr2t_initiator_task_tag);
1108 	if (io == NULL || io->io_ccb == NULL) {
1109 		ISCSI_SESSION_WARN(is, "bad itt 0x%x; reconnecting",
1110 		    bhsr2t->bhsr2t_initiator_task_tag);
1111 		icl_pdu_free(response);
1112 		iscsi_session_reconnect(is);
1113 		return;
1114 	}
1115 
1116 	csio = &io->io_ccb->csio;
1117 
1118 	if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_OUT) {
1119 		ISCSI_SESSION_WARN(is, "received R2T for read command; reconnecting");
1120 		icl_pdu_free(response);
1121 		iscsi_session_reconnect(is);
1122 		return;
1123 	}
1124 
1125 	/*
1126 	 * XXX: Verify R2TSN.
1127 	 */
1128 
1129 	io->io_datasn = 0;
1130 
1131 	off = ntohl(bhsr2t->bhsr2t_buffer_offset);
1132 	if (off > csio->dxfer_len) {
1133 		ISCSI_SESSION_WARN(is, "target requested invalid offset "
1134 		    "%zd, buffer is is %d; reconnecting", off, csio->dxfer_len);
1135 		icl_pdu_free(response);
1136 		iscsi_session_reconnect(is);
1137 		return;
1138 	}
1139 
1140 	total_len = ntohl(bhsr2t->bhsr2t_desired_data_transfer_length);
1141 	if (total_len == 0 || total_len > csio->dxfer_len) {
1142 		ISCSI_SESSION_WARN(is, "target requested invalid length "
1143 		    "%zd, buffer is %d; reconnecting", total_len, csio->dxfer_len);
1144 		icl_pdu_free(response);
1145 		iscsi_session_reconnect(is);
1146 		return;
1147 	}
1148 
1149 	//ISCSI_SESSION_DEBUG(is, "r2t; off %zd, len %zd", off, total_len);
1150 
1151 	for (;;) {
1152 		len = total_len;
1153 
1154 		if (len > is->is_max_data_segment_length)
1155 			len = is->is_max_data_segment_length;
1156 
1157 		if (off + len > csio->dxfer_len) {
1158 			ISCSI_SESSION_WARN(is, "target requested invalid "
1159 			    "length/offset %zd, buffer is %d; reconnecting",
1160 			    off + len, csio->dxfer_len);
1161 			icl_pdu_free(response);
1162 			iscsi_session_reconnect(is);
1163 			return;
1164 		}
1165 
1166 		request = icl_pdu_new(response->ip_conn, M_NOWAIT);
1167 		if (request == NULL) {
1168 			icl_pdu_free(response);
1169 			iscsi_session_reconnect(is);
1170 			return;
1171 		}
1172 
1173 		bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs;
1174 		bhsdo->bhsdo_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_OUT;
1175 		bhsdo->bhsdo_lun = bhsr2t->bhsr2t_lun;
1176 		bhsdo->bhsdo_initiator_task_tag =
1177 		    bhsr2t->bhsr2t_initiator_task_tag;
1178 		bhsdo->bhsdo_target_transfer_tag =
1179 		    bhsr2t->bhsr2t_target_transfer_tag;
1180 		bhsdo->bhsdo_datasn = htonl(io->io_datasn++);
1181 		bhsdo->bhsdo_buffer_offset = htonl(off);
1182 		error = icl_pdu_append_data(request, csio->data_ptr + off, len,
1183 		    M_NOWAIT);
1184 		if (error != 0) {
1185 			ISCSI_SESSION_WARN(is, "failed to allocate memory; "
1186 			    "reconnecting");
1187 			icl_pdu_free(request);
1188 			icl_pdu_free(response);
1189 			iscsi_session_reconnect(is);
1190 			return;
1191 		}
1192 
1193 		off += len;
1194 		total_len -= len;
1195 
1196 		if (total_len == 0) {
1197 			bhsdo->bhsdo_flags |= BHSDO_FLAGS_F;
1198 			//ISCSI_SESSION_DEBUG(is, "setting F, off %zd", off);
1199 		} else {
1200 			//ISCSI_SESSION_DEBUG(is, "not finished, off %zd", off);
1201 		}
1202 
1203 		iscsi_pdu_queue_locked(request);
1204 
1205 		if (total_len == 0)
1206 			break;
1207 	}
1208 
1209 	icl_pdu_free(response);
1210 }
1211 
1212 static void
1213 iscsi_pdu_handle_async_message(struct icl_pdu *response)
1214 {
1215 	struct iscsi_bhs_asynchronous_message *bhsam;
1216 	struct iscsi_session *is;
1217 
1218 	is = PDU_SESSION(response);
1219 	bhsam = (struct iscsi_bhs_asynchronous_message *)response->ip_bhs;
1220 	switch (bhsam->bhsam_async_event) {
1221 	case BHSAM_EVENT_TARGET_REQUESTS_LOGOUT:
1222 		ISCSI_SESSION_WARN(is, "target requests logout; removing session");
1223 		iscsi_session_logout(is);
1224 		iscsi_session_terminate(is);
1225 		break;
1226 	case BHSAM_EVENT_TARGET_TERMINATES_CONNECTION:
1227 		ISCSI_SESSION_WARN(is, "target indicates it will drop drop the connection");
1228 		break;
1229 	case BHSAM_EVENT_TARGET_TERMINATES_SESSION:
1230 		ISCSI_SESSION_WARN(is, "target indicates it will drop drop the session");
1231 		break;
1232 	default:
1233 		/*
1234 		 * XXX: Technically, we're obligated to also handle
1235 		 * 	parameter renegotiation.
1236 		 */
1237 		ISCSI_SESSION_WARN(is, "ignoring AsyncEvent %d", bhsam->bhsam_async_event);
1238 		break;
1239 	}
1240 
1241 	icl_pdu_free(response);
1242 }
1243 
1244 static void
1245 iscsi_pdu_handle_reject(struct icl_pdu *response)
1246 {
1247 	struct iscsi_bhs_reject *bhsr;
1248 	struct iscsi_session *is;
1249 
1250 	is = PDU_SESSION(response);
1251 	bhsr = (struct iscsi_bhs_reject *)response->ip_bhs;
1252 	ISCSI_SESSION_WARN(is, "received Reject PDU, reason 0x%x; protocol error?",
1253 	    bhsr->bhsr_reason);
1254 
1255 	icl_pdu_free(response);
1256 }
1257 
1258 static int
1259 iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
1260     struct iscsi_daemon_request *request)
1261 {
1262 	struct iscsi_session *is;
1263 	int error;
1264 
1265 	sx_slock(&sc->sc_lock);
1266 	for (;;) {
1267 		TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1268 			ISCSI_SESSION_LOCK(is);
1269 			if (is->is_waiting_for_iscsid)
1270 				break;
1271 			ISCSI_SESSION_UNLOCK(is);
1272 		}
1273 
1274 		if (is == NULL) {
1275 			/*
1276 			 * No session requires attention from iscsid(8); wait.
1277 			 */
1278 			error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
1279 			if (error != 0) {
1280 				sx_sunlock(&sc->sc_lock);
1281 				return (error);
1282 			}
1283 			continue;
1284 		}
1285 
1286 		is->is_waiting_for_iscsid = false;
1287 		is->is_login_phase = true;
1288 		is->is_reason[0] = '\0';
1289 		ISCSI_SESSION_UNLOCK(is);
1290 
1291 		request->idr_session_id = is->is_id;
1292 		memcpy(&request->idr_isid, &is->is_isid,
1293 		    sizeof(request->idr_isid));
1294 		request->idr_tsih = 0;	/* New or reinstated session. */
1295 		memcpy(&request->idr_conf, &is->is_conf,
1296 		    sizeof(request->idr_conf));
1297 
1298 		sx_sunlock(&sc->sc_lock);
1299 		return (0);
1300 	}
1301 }
1302 
1303 static int
1304 iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc,
1305     struct iscsi_daemon_handoff *handoff)
1306 {
1307 	struct iscsi_session *is;
1308 	int error;
1309 
1310 	sx_slock(&sc->sc_lock);
1311 
1312 	/*
1313 	 * Find the session to hand off socket to.
1314 	 */
1315 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1316 		if (is->is_id == handoff->idh_session_id)
1317 			break;
1318 	}
1319 	if (is == NULL) {
1320 		sx_sunlock(&sc->sc_lock);
1321 		return (ESRCH);
1322 	}
1323 	ISCSI_SESSION_LOCK(is);
1324 	if (is->is_conf.isc_discovery || is->is_terminating) {
1325 		ISCSI_SESSION_UNLOCK(is);
1326 		sx_sunlock(&sc->sc_lock);
1327 		return (EINVAL);
1328 	}
1329 	if (is->is_connected) {
1330 		/*
1331 		 * This might have happened because another iscsid(8)
1332 		 * instance handed off the connection in the meantime.
1333 		 * Just return.
1334 		 */
1335 		ISCSI_SESSION_WARN(is, "handoff on already connected "
1336 		    "session");
1337 		ISCSI_SESSION_UNLOCK(is);
1338 		sx_sunlock(&sc->sc_lock);
1339 		return (EBUSY);
1340 	}
1341 
1342 	strlcpy(is->is_target_alias, handoff->idh_target_alias,
1343 	    sizeof(is->is_target_alias));
1344 	is->is_tsih = handoff->idh_tsih;
1345 	is->is_statsn = handoff->idh_statsn;
1346 	is->is_initial_r2t = handoff->idh_initial_r2t;
1347 	is->is_immediate_data = handoff->idh_immediate_data;
1348 	is->is_max_data_segment_length = handoff->idh_max_data_segment_length;
1349 	is->is_max_burst_length = handoff->idh_max_burst_length;
1350 	is->is_first_burst_length = handoff->idh_first_burst_length;
1351 
1352 	if (handoff->idh_header_digest == ISCSI_DIGEST_CRC32C)
1353 		is->is_conn->ic_header_crc32c = true;
1354 	else
1355 		is->is_conn->ic_header_crc32c = false;
1356 	if (handoff->idh_data_digest == ISCSI_DIGEST_CRC32C)
1357 		is->is_conn->ic_data_crc32c = true;
1358 	else
1359 		is->is_conn->ic_data_crc32c = false;
1360 
1361 	is->is_cmdsn = 0;
1362 	is->is_expcmdsn = 0;
1363 	is->is_maxcmdsn = 0;
1364 	is->is_waiting_for_iscsid = false;
1365 	is->is_login_phase = false;
1366 	is->is_timeout = 0;
1367 	is->is_connected = true;
1368 	is->is_reason[0] = '\0';
1369 
1370 	ISCSI_SESSION_UNLOCK(is);
1371 
1372 #ifdef ICL_KERNEL_PROXY
1373 	if (handoff->idh_socket != 0) {
1374 #endif
1375 		/*
1376 		 * Handoff without using ICL proxy.
1377 		 */
1378 		error = icl_conn_handoff(is->is_conn, handoff->idh_socket);
1379 		if (error != 0) {
1380 			sx_sunlock(&sc->sc_lock);
1381 			iscsi_session_terminate(is);
1382 			return (error);
1383 		}
1384 #ifdef ICL_KERNEL_PROXY
1385 	}
1386 #endif
1387 
1388 	sx_sunlock(&sc->sc_lock);
1389 
1390 	if (is->is_sim != NULL) {
1391 		/*
1392 		 * When reconnecting, there already is SIM allocated for the session.
1393 		 */
1394 		KASSERT(is->is_simq_frozen, ("reconnect without frozen simq"));
1395 		ISCSI_SESSION_LOCK(is);
1396 		ISCSI_SESSION_DEBUG(is, "releasing");
1397 		xpt_release_simq(is->is_sim, 1);
1398 		is->is_simq_frozen = false;
1399 		ISCSI_SESSION_UNLOCK(is);
1400 
1401 	} else {
1402 		ISCSI_SESSION_LOCK(is);
1403 		is->is_devq = cam_simq_alloc(maxtags);
1404 		if (is->is_devq == NULL) {
1405 			ISCSI_SESSION_WARN(is, "failed to allocate simq");
1406 			iscsi_session_terminate(is);
1407 			return (ENOMEM);
1408 		}
1409 
1410 		is->is_sim = cam_sim_alloc(iscsi_action, iscsi_poll, "iscsi",
1411 		    is, is->is_id /* unit */, &is->is_lock,
1412 		    1, maxtags, is->is_devq);
1413 		if (is->is_sim == NULL) {
1414 			ISCSI_SESSION_UNLOCK(is);
1415 			ISCSI_SESSION_WARN(is, "failed to allocate SIM");
1416 			cam_simq_free(is->is_devq);
1417 			iscsi_session_terminate(is);
1418 			return (ENOMEM);
1419 		}
1420 
1421 		error = xpt_bus_register(is->is_sim, NULL, 0);
1422 		if (error != 0) {
1423 			ISCSI_SESSION_UNLOCK(is);
1424 			ISCSI_SESSION_WARN(is, "failed to register bus");
1425 			iscsi_session_terminate(is);
1426 			return (ENOMEM);
1427 		}
1428 
1429 		error = xpt_create_path(&is->is_path, /*periph*/NULL,
1430 		    cam_sim_path(is->is_sim), CAM_TARGET_WILDCARD,
1431 		    CAM_LUN_WILDCARD);
1432 		if (error != CAM_REQ_CMP) {
1433 			ISCSI_SESSION_UNLOCK(is);
1434 			ISCSI_SESSION_WARN(is, "failed to create path");
1435 			iscsi_session_terminate(is);
1436 			return (ENOMEM);
1437 		}
1438 		ISCSI_SESSION_UNLOCK(is);
1439 	}
1440 
1441 	return (0);
1442 }
1443 
1444 static int
1445 iscsi_ioctl_daemon_fail(struct iscsi_softc *sc,
1446     struct iscsi_daemon_fail *fail)
1447 {
1448 	struct iscsi_session *is;
1449 
1450 	sx_slock(&sc->sc_lock);
1451 
1452 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1453 		if (is->is_id == fail->idf_session_id)
1454 			break;
1455 	}
1456 	if (is == NULL) {
1457 		sx_sunlock(&sc->sc_lock);
1458 		return (ESRCH);
1459 	}
1460 	ISCSI_SESSION_LOCK(is);
1461 	ISCSI_SESSION_DEBUG(is, "iscsid(8) failed: %s",
1462 	    fail->idf_reason);
1463 	strlcpy(is->is_reason, fail->idf_reason, sizeof(is->is_reason));
1464 	//is->is_waiting_for_iscsid = false;
1465 	//is->is_login_phase = true;
1466 	//iscsi_session_reconnect(is);
1467 	ISCSI_SESSION_UNLOCK(is);
1468 	sx_sunlock(&sc->sc_lock);
1469 
1470 	return (0);
1471 }
1472 
1473 #ifdef ICL_KERNEL_PROXY
1474 static int
1475 iscsi_ioctl_daemon_connect(struct iscsi_softc *sc,
1476     struct iscsi_daemon_connect *idc)
1477 {
1478 	struct iscsi_session *is;
1479 	struct sockaddr *from_sa, *to_sa;
1480 	int error;
1481 
1482 	sx_slock(&sc->sc_lock);
1483 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1484 		if (is->is_id == idc->idc_session_id)
1485 			break;
1486 	}
1487 	if (is == NULL) {
1488 		sx_sunlock(&sc->sc_lock);
1489 		return (ESRCH);
1490 	}
1491 	sx_sunlock(&sc->sc_lock);
1492 
1493 	if (idc->idc_from_addrlen > 0) {
1494 		error = getsockaddr(&from_sa, (void *)idc->idc_from_addr, idc->idc_from_addrlen);
1495 		if (error != 0) {
1496 			ISCSI_SESSION_WARN(is,
1497 			    "getsockaddr failed with error %d", error);
1498 			return (error);
1499 		}
1500 	} else {
1501 		from_sa = NULL;
1502 	}
1503 	error = getsockaddr(&to_sa, (void *)idc->idc_to_addr, idc->idc_to_addrlen);
1504 	if (error != 0) {
1505 		ISCSI_SESSION_WARN(is, "getsockaddr failed with error %d",
1506 		    error);
1507 		free(from_sa, M_SONAME);
1508 		return (error);
1509 	}
1510 
1511 	ISCSI_SESSION_LOCK(is);
1512 	is->is_waiting_for_iscsid = false;
1513 	is->is_login_phase = true;
1514 	is->is_timeout = 0;
1515 	ISCSI_SESSION_UNLOCK(is);
1516 
1517 	error = icl_conn_connect(is->is_conn, idc->idc_iser, idc->idc_domain,
1518 	    idc->idc_socktype, idc->idc_protocol, from_sa, to_sa);
1519 	free(from_sa, M_SONAME);
1520 	free(to_sa, M_SONAME);
1521 
1522 	/*
1523 	 * Digests are always disabled during login phase.
1524 	 */
1525 	is->is_conn->ic_header_crc32c = false;
1526 	is->is_conn->ic_data_crc32c = false;
1527 
1528 	return (error);
1529 }
1530 
1531 static int
1532 iscsi_ioctl_daemon_send(struct iscsi_softc *sc,
1533     struct iscsi_daemon_send *ids)
1534 {
1535 	struct iscsi_session *is;
1536 	struct icl_pdu *ip;
1537 	size_t datalen;
1538 	void *data;
1539 	int error;
1540 
1541 	sx_slock(&sc->sc_lock);
1542 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1543 		if (is->is_id == ids->ids_session_id)
1544 			break;
1545 	}
1546 	if (is == NULL) {
1547 		sx_sunlock(&sc->sc_lock);
1548 		return (ESRCH);
1549 	}
1550 	sx_sunlock(&sc->sc_lock);
1551 
1552 	if (is->is_login_phase == false)
1553 		return (EBUSY);
1554 
1555 	if (is->is_terminating || is->is_reconnecting)
1556 		return (EIO);
1557 
1558 	datalen = ids->ids_data_segment_len;
1559 	if (datalen > ISCSI_MAX_DATA_SEGMENT_LENGTH)
1560 		return (EINVAL);
1561 	if (datalen > 0) {
1562 		data = malloc(datalen, M_ISCSI, M_WAITOK);
1563 		error = copyin(ids->ids_data_segment, data, datalen);
1564 		if (error != 0) {
1565 			free(data, M_ISCSI);
1566 			return (error);
1567 		}
1568 	}
1569 
1570 	ip = icl_pdu_new(is->is_conn, M_WAITOK);
1571 	memcpy(ip->ip_bhs, ids->ids_bhs, sizeof(*ip->ip_bhs));
1572 	if (datalen > 0) {
1573 		error = icl_pdu_append_data(ip, data, datalen, M_WAITOK);
1574 		KASSERT(error == 0, ("icl_pdu_append_data(..., M_WAITOK) failed"));
1575 		free(data, M_ISCSI);
1576 	}
1577 	icl_pdu_queue(ip);
1578 
1579 	return (0);
1580 }
1581 
1582 static int
1583 iscsi_ioctl_daemon_receive(struct iscsi_softc *sc,
1584     struct iscsi_daemon_receive *idr)
1585 {
1586 	struct iscsi_session *is;
1587 	struct icl_pdu *ip;
1588 	void *data;
1589 
1590 	sx_slock(&sc->sc_lock);
1591 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1592 		if (is->is_id == idr->idr_session_id)
1593 			break;
1594 	}
1595 	if (is == NULL) {
1596 		sx_sunlock(&sc->sc_lock);
1597 		return (ESRCH);
1598 	}
1599 	sx_sunlock(&sc->sc_lock);
1600 
1601 	if (is->is_login_phase == false)
1602 		return (EBUSY);
1603 
1604 	ISCSI_SESSION_LOCK(is);
1605 	while (is->is_login_pdu == NULL &&
1606 	    is->is_terminating == false &&
1607 	    is->is_reconnecting == false)
1608 		cv_wait(&is->is_login_cv, &is->is_lock);
1609 	if (is->is_terminating || is->is_reconnecting) {
1610 		ISCSI_SESSION_UNLOCK(is);
1611 		return (EIO);
1612 	}
1613 	ip = is->is_login_pdu;
1614 	is->is_login_pdu = NULL;
1615 	ISCSI_SESSION_UNLOCK(is);
1616 
1617 	if (ip->ip_data_len > idr->idr_data_segment_len) {
1618 		icl_pdu_free(ip);
1619 		return (EMSGSIZE);
1620 	}
1621 
1622 	copyout(ip->ip_bhs, idr->idr_bhs, sizeof(*ip->ip_bhs));
1623 	if (ip->ip_data_len > 0) {
1624 		data = malloc(ip->ip_data_len, M_ISCSI, M_WAITOK);
1625 		icl_pdu_get_data(ip, 0, data, ip->ip_data_len);
1626 		copyout(data, idr->idr_data_segment, ip->ip_data_len);
1627 		free(data, M_ISCSI);
1628 	}
1629 
1630 	icl_pdu_free(ip);
1631 
1632 	return (0);
1633 }
1634 #endif /* ICL_KERNEL_PROXY */
1635 
1636 static void
1637 iscsi_sanitize_session_conf(struct iscsi_session_conf *isc)
1638 {
1639 	/*
1640 	 * Just make sure all the fields are null-terminated.
1641 	 *
1642 	 * XXX: This is not particularly secure.  We should
1643 	 * 	create our own conf and then copy in relevant
1644 	 * 	fields.
1645 	 */
1646 	isc->isc_initiator[ISCSI_NAME_LEN - 1] = '\0';
1647 	isc->isc_initiator_addr[ISCSI_ADDR_LEN - 1] = '\0';
1648 	isc->isc_initiator_alias[ISCSI_ALIAS_LEN - 1] = '\0';
1649 	isc->isc_target[ISCSI_NAME_LEN - 1] = '\0';
1650 	isc->isc_target_addr[ISCSI_ADDR_LEN - 1] = '\0';
1651 	isc->isc_user[ISCSI_NAME_LEN - 1] = '\0';
1652 	isc->isc_secret[ISCSI_SECRET_LEN - 1] = '\0';
1653 	isc->isc_mutual_user[ISCSI_NAME_LEN - 1] = '\0';
1654 	isc->isc_mutual_secret[ISCSI_SECRET_LEN - 1] = '\0';
1655 }
1656 
1657 static bool
1658 iscsi_valid_session_conf(const struct iscsi_session_conf *isc)
1659 {
1660 
1661 	if (isc->isc_initiator[0] == '\0') {
1662 		ISCSI_DEBUG("empty isc_initiator");
1663 		return (false);
1664 	}
1665 
1666 	if (isc->isc_target_addr[0] == '\0') {
1667 		ISCSI_DEBUG("empty isc_target_addr");
1668 		return (false);
1669 	}
1670 
1671 	if (isc->isc_discovery != 0 && isc->isc_target[0] != 0) {
1672 		ISCSI_DEBUG("non-empty isc_target for discovery session");
1673 		return (false);
1674 	}
1675 
1676 	if (isc->isc_discovery == 0 && isc->isc_target[0] == 0) {
1677 		ISCSI_DEBUG("empty isc_target for non-discovery session");
1678 		return (false);
1679 	}
1680 
1681 	return (true);
1682 }
1683 
1684 static int
1685 iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
1686 {
1687 	struct iscsi_session *is;
1688 	const struct iscsi_session *is2;
1689 	int error;
1690 
1691 	iscsi_sanitize_session_conf(&isa->isa_conf);
1692 	if (iscsi_valid_session_conf(&isa->isa_conf) == false)
1693 		return (EINVAL);
1694 
1695 	is = malloc(sizeof(*is), M_ISCSI, M_ZERO | M_WAITOK);
1696 	memcpy(&is->is_conf, &isa->isa_conf, sizeof(is->is_conf));
1697 
1698 	sx_xlock(&sc->sc_lock);
1699 
1700 	/*
1701 	 * Prevent duplicates.
1702 	 */
1703 	TAILQ_FOREACH(is2, &sc->sc_sessions, is_next) {
1704 		if (!!is->is_conf.isc_discovery !=
1705 		    !!is2->is_conf.isc_discovery)
1706 			continue;
1707 
1708 		if (strcmp(is->is_conf.isc_target_addr,
1709 		    is2->is_conf.isc_target_addr) != 0)
1710 			continue;
1711 
1712 		if (is->is_conf.isc_discovery == 0 &&
1713 		    strcmp(is->is_conf.isc_target,
1714 		    is2->is_conf.isc_target) != 0)
1715 			continue;
1716 
1717 		sx_xunlock(&sc->sc_lock);
1718 		free(is, M_ISCSI);
1719 		return (EBUSY);
1720 	}
1721 
1722 	is->is_conn = icl_conn_new("iscsi", &is->is_lock);
1723 	is->is_conn->ic_receive = iscsi_receive_callback;
1724 	is->is_conn->ic_error = iscsi_error_callback;
1725 	is->is_conn->ic_prv0 = is;
1726 	TAILQ_INIT(&is->is_outstanding);
1727 	STAILQ_INIT(&is->is_postponed);
1728 	mtx_init(&is->is_lock, "iscsi_lock", NULL, MTX_DEF);
1729 	cv_init(&is->is_maintenance_cv, "iscsi_mt");
1730 #ifdef ICL_KERNEL_PROXY
1731 	cv_init(&is->is_login_cv, "iscsi_login");
1732 #endif
1733 
1734 	is->is_softc = sc;
1735 	sc->sc_last_session_id++;
1736 	is->is_id = sc->sc_last_session_id;
1737 	is->is_isid[0] = 0x80; /* RFC 3720, 10.12.5: 10b, "Random" ISID. */
1738 	arc4rand(&is->is_isid[1], 5, 0);
1739 	is->is_tsih = 0;
1740 	callout_init(&is->is_callout, 1);
1741 	callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is);
1742 	TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
1743 
1744 	error = kthread_add(iscsi_maintenance_thread, is, NULL, NULL, 0, 0, "iscsimt");
1745 	if (error != 0) {
1746 		ISCSI_SESSION_WARN(is, "kthread_add(9) failed with error %d", error);
1747 		return (error);
1748 	}
1749 
1750 	/*
1751 	 * Trigger immediate reconnection.
1752 	 */
1753 	ISCSI_SESSION_LOCK(is);
1754 	is->is_waiting_for_iscsid = true;
1755 	strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
1756 	ISCSI_SESSION_UNLOCK(is);
1757 	cv_signal(&sc->sc_cv);
1758 
1759 	sx_xunlock(&sc->sc_lock);
1760 
1761 	return (0);
1762 }
1763 
1764 static bool
1765 iscsi_session_conf_matches(unsigned int id1, const struct iscsi_session_conf *c1,
1766     unsigned int id2, const struct iscsi_session_conf *c2)
1767 {
1768 
1769 	if (id2 != 0 && id2 != id1)
1770 		return (false);
1771 	if (c2->isc_target[0] != '\0' &&
1772 	    strcmp(c1->isc_target, c2->isc_target) != 0)
1773 		return (false);
1774 	if (c2->isc_target_addr[0] != '\0' &&
1775 	    strcmp(c1->isc_target_addr, c2->isc_target_addr) != 0)
1776 		return (false);
1777 	return (true);
1778 }
1779 
1780 static int
1781 iscsi_ioctl_session_remove(struct iscsi_softc *sc,
1782     struct iscsi_session_remove *isr)
1783 {
1784 	struct iscsi_session *is, *tmp;
1785 	bool found = false;
1786 
1787 	iscsi_sanitize_session_conf(&isr->isr_conf);
1788 
1789 	sx_xlock(&sc->sc_lock);
1790 	TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp) {
1791 		ISCSI_SESSION_LOCK(is);
1792 		if (iscsi_session_conf_matches(is->is_id, &is->is_conf,
1793 		    isr->isr_session_id, &isr->isr_conf)) {
1794 			found = true;
1795 			iscsi_session_logout(is);
1796 			iscsi_session_terminate(is);
1797 		}
1798 		ISCSI_SESSION_UNLOCK(is);
1799 	}
1800 	sx_xunlock(&sc->sc_lock);
1801 
1802 	if (!found)
1803 		return (ESRCH);
1804 
1805 	return (0);
1806 }
1807 
1808 static int
1809 iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl)
1810 {
1811 	int error;
1812 	unsigned int i = 0;
1813 	struct iscsi_session *is;
1814 	struct iscsi_session_state iss;
1815 
1816 	sx_slock(&sc->sc_lock);
1817 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1818 		if (i >= isl->isl_nentries) {
1819 			sx_sunlock(&sc->sc_lock);
1820 			return (EMSGSIZE);
1821 		}
1822 		memset(&iss, 0, sizeof(iss));
1823 		memcpy(&iss.iss_conf, &is->is_conf, sizeof(iss.iss_conf));
1824 		iss.iss_id = is->is_id;
1825 		strlcpy(iss.iss_target_alias, is->is_target_alias, sizeof(iss.iss_target_alias));
1826 		strlcpy(iss.iss_reason, is->is_reason, sizeof(iss.iss_reason));
1827 
1828 		if (is->is_conn->ic_header_crc32c)
1829 			iss.iss_header_digest = ISCSI_DIGEST_CRC32C;
1830 		else
1831 			iss.iss_header_digest = ISCSI_DIGEST_NONE;
1832 
1833 		if (is->is_conn->ic_data_crc32c)
1834 			iss.iss_data_digest = ISCSI_DIGEST_CRC32C;
1835 		else
1836 			iss.iss_data_digest = ISCSI_DIGEST_NONE;
1837 
1838 		iss.iss_max_data_segment_length = is->is_max_data_segment_length;
1839 		iss.iss_immediate_data = is->is_immediate_data;
1840 		iss.iss_connected = is->is_connected;
1841 
1842 		error = copyout(&iss, isl->isl_pstates + i, sizeof(iss));
1843 		if (error != 0) {
1844 			sx_sunlock(&sc->sc_lock);
1845 			return (error);
1846 		}
1847 		i++;
1848 	}
1849 	sx_sunlock(&sc->sc_lock);
1850 
1851 	isl->isl_nentries = i;
1852 
1853 	return (0);
1854 }
1855 
1856 static int
1857 iscsi_ioctl_session_modify(struct iscsi_softc *sc,
1858     struct iscsi_session_modify *ism)
1859 {
1860 	struct iscsi_session *is;
1861 
1862 	iscsi_sanitize_session_conf(&ism->ism_conf);
1863 	if (iscsi_valid_session_conf(&ism->ism_conf) == false)
1864 		return (EINVAL);
1865 
1866 	sx_xlock(&sc->sc_lock);
1867 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
1868 		ISCSI_SESSION_LOCK(is);
1869 		if (is->is_id == ism->ism_session_id)
1870 			break;
1871 		ISCSI_SESSION_UNLOCK(is);
1872 	}
1873 	if (is == NULL) {
1874 		sx_xunlock(&sc->sc_lock);
1875 		return (ESRCH);
1876 	}
1877 	sx_xunlock(&sc->sc_lock);
1878 
1879 	memcpy(&is->is_conf, &ism->ism_conf, sizeof(is->is_conf));
1880 	ISCSI_SESSION_UNLOCK(is);
1881 
1882 	iscsi_session_reconnect(is);
1883 
1884 	return (0);
1885 }
1886 
1887 static int
1888 iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode,
1889     struct thread *td)
1890 {
1891 	struct iscsi_softc *sc;
1892 
1893 	sc = dev->si_drv1;
1894 
1895 	switch (cmd) {
1896 	case ISCSIDWAIT:
1897 		return (iscsi_ioctl_daemon_wait(sc,
1898 		    (struct iscsi_daemon_request *)arg));
1899 	case ISCSIDHANDOFF:
1900 		return (iscsi_ioctl_daemon_handoff(sc,
1901 		    (struct iscsi_daemon_handoff *)arg));
1902 	case ISCSIDFAIL:
1903 		return (iscsi_ioctl_daemon_fail(sc,
1904 		    (struct iscsi_daemon_fail *)arg));
1905 #ifdef ICL_KERNEL_PROXY
1906 	case ISCSIDCONNECT:
1907 		return (iscsi_ioctl_daemon_connect(sc,
1908 		    (struct iscsi_daemon_connect *)arg));
1909 	case ISCSIDSEND:
1910 		return (iscsi_ioctl_daemon_send(sc,
1911 		    (struct iscsi_daemon_send *)arg));
1912 	case ISCSIDRECEIVE:
1913 		return (iscsi_ioctl_daemon_receive(sc,
1914 		    (struct iscsi_daemon_receive *)arg));
1915 #endif /* ICL_KERNEL_PROXY */
1916 	case ISCSISADD:
1917 		return (iscsi_ioctl_session_add(sc,
1918 		    (struct iscsi_session_add *)arg));
1919 	case ISCSISREMOVE:
1920 		return (iscsi_ioctl_session_remove(sc,
1921 		    (struct iscsi_session_remove *)arg));
1922 	case ISCSISLIST:
1923 		return (iscsi_ioctl_session_list(sc,
1924 		    (struct iscsi_session_list *)arg));
1925 	case ISCSISMODIFY:
1926 		return (iscsi_ioctl_session_modify(sc,
1927 		    (struct iscsi_session_modify *)arg));
1928 	default:
1929 		return (EINVAL);
1930 	}
1931 }
1932 
1933 static struct iscsi_outstanding *
1934 iscsi_outstanding_find(struct iscsi_session *is, uint32_t initiator_task_tag)
1935 {
1936 	struct iscsi_outstanding *io;
1937 
1938 	ISCSI_SESSION_LOCK_ASSERT(is);
1939 
1940 	TAILQ_FOREACH(io, &is->is_outstanding, io_next) {
1941 		if (io->io_initiator_task_tag == initiator_task_tag)
1942 			return (io);
1943 	}
1944 	return (NULL);
1945 }
1946 
1947 static struct iscsi_outstanding *
1948 iscsi_outstanding_find_ccb(struct iscsi_session *is, union ccb *ccb)
1949 {
1950 	struct iscsi_outstanding *io;
1951 
1952 	ISCSI_SESSION_LOCK_ASSERT(is);
1953 
1954 	TAILQ_FOREACH(io, &is->is_outstanding, io_next) {
1955 		if (io->io_ccb == ccb)
1956 			return (io);
1957 	}
1958 	return (NULL);
1959 }
1960 
1961 static struct iscsi_outstanding *
1962 iscsi_outstanding_add(struct iscsi_session *is,
1963     uint32_t initiator_task_tag, union ccb *ccb)
1964 {
1965 	struct iscsi_outstanding *io;
1966 
1967 	ISCSI_SESSION_LOCK_ASSERT(is);
1968 
1969 	KASSERT(iscsi_outstanding_find(is, initiator_task_tag) == NULL,
1970 	    ("initiator_task_tag 0x%x already added", initiator_task_tag));
1971 
1972 	io = uma_zalloc(iscsi_outstanding_zone, M_NOWAIT | M_ZERO);
1973 	if (io == NULL) {
1974 		ISCSI_SESSION_WARN(is, "failed to allocate %zd bytes", sizeof(*io));
1975 		return (NULL);
1976 	}
1977 	io->io_initiator_task_tag = initiator_task_tag;
1978 	io->io_ccb = ccb;
1979 	TAILQ_INSERT_TAIL(&is->is_outstanding, io, io_next);
1980 	return (io);
1981 }
1982 
1983 static void
1984 iscsi_outstanding_remove(struct iscsi_session *is, struct iscsi_outstanding *io)
1985 {
1986 
1987 	ISCSI_SESSION_LOCK_ASSERT(is);
1988 
1989 	TAILQ_REMOVE(&is->is_outstanding, io, io_next);
1990 	uma_zfree(iscsi_outstanding_zone, io);
1991 }
1992 
1993 static void
1994 iscsi_action_abort(struct iscsi_session *is, union ccb *ccb)
1995 {
1996 	struct icl_pdu *request;
1997 	struct iscsi_bhs_task_management_request *bhstmr;
1998 	struct ccb_abort *cab = &ccb->cab;
1999 	struct iscsi_outstanding *io, *aio;
2000 
2001 	ISCSI_SESSION_LOCK_ASSERT(is);
2002 
2003 #if 0
2004 	KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__));
2005 #else
2006 	if (is->is_login_phase) {
2007 		ccb->ccb_h.status = CAM_REQ_ABORTED;
2008 		xpt_done(ccb);
2009 		return;
2010 	}
2011 #endif
2012 
2013 	aio = iscsi_outstanding_find_ccb(is, cab->abort_ccb);
2014 	if (aio == NULL) {
2015 		ccb->ccb_h.status = CAM_REQ_CMP;
2016 		xpt_done(ccb);
2017 		return;
2018 	}
2019 
2020 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
2021 	if (request == NULL) {
2022 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2023 		xpt_done(ccb);
2024 		return;
2025 	}
2026 
2027 	bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs;
2028 	bhstmr->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_REQUEST;
2029 	bhstmr->bhstmr_function = 0x80 | BHSTMR_FUNCTION_ABORT_TASK;
2030 
2031 	bhstmr->bhstmr_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
2032 	bhstmr->bhstmr_initiator_task_tag = is->is_initiator_task_tag;
2033 	is->is_initiator_task_tag++;
2034 	bhstmr->bhstmr_referenced_task_tag = aio->io_initiator_task_tag;
2035 
2036 	io = iscsi_outstanding_add(is, bhstmr->bhstmr_initiator_task_tag, NULL);
2037 	if (io == NULL) {
2038 		icl_pdu_free(request);
2039 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
2040 		xpt_done(ccb);
2041 		return;
2042 	}
2043 	io->io_datasn = aio->io_initiator_task_tag;
2044 	iscsi_pdu_queue_locked(request);
2045 }
2046 
2047 static void
2048 iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
2049 {
2050 	struct icl_pdu *request;
2051 	struct iscsi_bhs_scsi_command *bhssc;
2052 	struct ccb_scsiio *csio;
2053 	struct iscsi_outstanding *io;
2054 	size_t len;
2055 	int error;
2056 
2057 	ISCSI_SESSION_LOCK_ASSERT(is);
2058 
2059 #if 0
2060 	KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__));
2061 #else
2062 	if (is->is_login_phase) {
2063 		ISCSI_SESSION_DEBUG(is, "called during login phase");
2064 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2065 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2066 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2067 		}
2068 		ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_DEV_QFRZN;
2069 		xpt_done(ccb);
2070 		return;
2071 	}
2072 #endif
2073 
2074 	request = icl_pdu_new(is->is_conn, M_NOWAIT);
2075 	if (request == NULL) {
2076 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2077 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2078 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2079 		}
2080 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2081 		xpt_done(ccb);
2082 		return;
2083 	}
2084 
2085 	csio = &ccb->csio;
2086 	bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs;
2087 	bhssc->bhssc_opcode = ISCSI_BHS_OPCODE_SCSI_COMMAND;
2088 	bhssc->bhssc_flags |= BHSSC_FLAGS_F;
2089 	switch (csio->ccb_h.flags & CAM_DIR_MASK) {
2090 	case CAM_DIR_IN:
2091 		bhssc->bhssc_flags |= BHSSC_FLAGS_R;
2092 		break;
2093 	case CAM_DIR_OUT:
2094 		bhssc->bhssc_flags |= BHSSC_FLAGS_W;
2095 		break;
2096 	}
2097 
2098 	if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
2099 		switch (csio->tag_action) {
2100 		case MSG_HEAD_OF_Q_TAG:
2101 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_HOQ;
2102 			break;
2103 		case MSG_ORDERED_Q_TAG:
2104 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ORDERED;
2105 			break;
2106 		case MSG_ACA_TASK:
2107 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ACA;
2108 			break;
2109 		case MSG_SIMPLE_Q_TAG:
2110 		default:
2111 			bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_SIMPLE;
2112 			break;
2113 		}
2114 	} else
2115 		bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_UNTAGGED;
2116 
2117 	bhssc->bhssc_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun));
2118 	bhssc->bhssc_initiator_task_tag = is->is_initiator_task_tag;
2119 	is->is_initiator_task_tag++;
2120 	bhssc->bhssc_expected_data_transfer_length = htonl(csio->dxfer_len);
2121 	KASSERT(csio->cdb_len <= sizeof(bhssc->bhssc_cdb),
2122 	    ("unsupported CDB size %zd", (size_t)csio->cdb_len));
2123 
2124 	if (csio->ccb_h.flags & CAM_CDB_POINTER)
2125 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_ptr, csio->cdb_len);
2126 	else
2127 		memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_bytes, csio->cdb_len);
2128 
2129 	io = iscsi_outstanding_add(is, bhssc->bhssc_initiator_task_tag, ccb);
2130 	if (io == NULL) {
2131 		icl_pdu_free(request);
2132 		if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2133 			xpt_freeze_devq(ccb->ccb_h.path, 1);
2134 			ISCSI_SESSION_DEBUG(is, "freezing devq");
2135 		}
2136 		ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2137 		xpt_done(ccb);
2138 		return;
2139 	}
2140 
2141 	if (is->is_immediate_data &&
2142 	    (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
2143 		len = csio->dxfer_len;
2144 		//ISCSI_SESSION_DEBUG(is, "adding %zd of immediate data", len);
2145 		if (len > is->is_first_burst_length) {
2146 			ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_first_burst_length);
2147 			len = is->is_first_burst_length;
2148 		}
2149 
2150 		error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT);
2151 		if (error != 0) {
2152 			icl_pdu_free(request);
2153 			if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
2154 				xpt_freeze_devq(ccb->ccb_h.path, 1);
2155 				ISCSI_SESSION_DEBUG(is, "freezing devq");
2156 			}
2157 			ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN;
2158 			xpt_done(ccb);
2159 			return;
2160 		}
2161 	}
2162 	iscsi_pdu_queue_locked(request);
2163 }
2164 
2165 static void
2166 iscsi_action(struct cam_sim *sim, union ccb *ccb)
2167 {
2168 	struct iscsi_session *is;
2169 
2170 	is = cam_sim_softc(sim);
2171 
2172 	ISCSI_SESSION_LOCK_ASSERT(is);
2173 
2174 	if (is->is_terminating ||
2175 	    (is->is_connected == false && fail_on_disconnection)) {
2176 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
2177 		xpt_done(ccb);
2178 		return;
2179 	}
2180 
2181 	switch (ccb->ccb_h.func_code) {
2182 	case XPT_PATH_INQ:
2183 	{
2184 		struct ccb_pathinq *cpi = &ccb->cpi;
2185 
2186 		cpi->version_num = 1;
2187 		cpi->hba_inquiry = PI_TAG_ABLE;
2188 		cpi->target_sprt = 0;
2189 		cpi->hba_misc = PIM_EXTLUNS;
2190 		cpi->hba_eng_cnt = 0;
2191 		cpi->max_target = 0;
2192 		/*
2193 		 * Note that the variable below is only relevant for targets
2194 		 * that don't claim compliance with anything above SPC2, which
2195 		 * means they don't support REPORT_LUNS.
2196 		 */
2197 		cpi->max_lun = 255;
2198 		cpi->initiator_id = ~0;
2199 		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2200 		strlcpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
2201 		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2202 		cpi->unit_number = cam_sim_unit(sim);
2203 		cpi->bus_id = cam_sim_bus(sim);
2204 		cpi->base_transfer_speed = 150000; /* XXX */
2205 		cpi->transport = XPORT_ISCSI;
2206 		cpi->transport_version = 0;
2207 		cpi->protocol = PROTO_SCSI;
2208 		cpi->protocol_version = SCSI_REV_SPC3;
2209 		cpi->maxio = MAXPHYS;
2210 		cpi->ccb_h.status = CAM_REQ_CMP;
2211 		break;
2212 	}
2213 	case XPT_GET_TRAN_SETTINGS:
2214 	{
2215 		struct ccb_trans_settings	*cts;
2216 		struct ccb_trans_settings_scsi	*scsi;
2217 
2218 		cts = &ccb->cts;
2219 		scsi = &cts->proto_specific.scsi;
2220 
2221 		cts->protocol = PROTO_SCSI;
2222 		cts->protocol_version = SCSI_REV_SPC3;
2223 		cts->transport = XPORT_ISCSI;
2224 		cts->transport_version = 0;
2225 		scsi->valid = CTS_SCSI_VALID_TQ;
2226 		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
2227 		cts->ccb_h.status = CAM_REQ_CMP;
2228 		break;
2229 	}
2230 	case XPT_CALC_GEOMETRY:
2231 		cam_calc_geometry(&ccb->ccg, /*extended*/1);
2232 		ccb->ccb_h.status = CAM_REQ_CMP;
2233 		break;
2234 #if 0
2235 	/*
2236 	 * XXX: What's the point?
2237 	 */
2238 	case XPT_RESET_BUS:
2239 	case XPT_TERM_IO:
2240 		ISCSI_SESSION_DEBUG(is, "faking success for reset, abort, or term_io");
2241 		ccb->ccb_h.status = CAM_REQ_CMP;
2242 		break;
2243 #endif
2244 	case XPT_ABORT:
2245 		iscsi_action_abort(is, ccb);
2246 		return;
2247 	case XPT_SCSI_IO:
2248 		iscsi_action_scsiio(is, ccb);
2249 		return;
2250 	default:
2251 #if 0
2252 		ISCSI_SESSION_DEBUG(is, "got unsupported code 0x%x", ccb->ccb_h.func_code);
2253 #endif
2254 		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2255 		break;
2256 	}
2257 	xpt_done(ccb);
2258 }
2259 
2260 static void
2261 iscsi_poll(struct cam_sim *sim)
2262 {
2263 
2264 	KASSERT(0, ("%s: you're not supposed to be here", __func__));
2265 }
2266 
2267 static void
2268 iscsi_shutdown(struct iscsi_softc *sc)
2269 {
2270 	struct iscsi_session *is;
2271 
2272 	ISCSI_DEBUG("removing all sessions due to shutdown");
2273 
2274 	sx_slock(&sc->sc_lock);
2275 	TAILQ_FOREACH(is, &sc->sc_sessions, is_next)
2276 		iscsi_session_terminate(is);
2277 	sx_sunlock(&sc->sc_lock);
2278 }
2279 
2280 static int
2281 iscsi_load(void)
2282 {
2283 	int error;
2284 
2285 	sc = malloc(sizeof(*sc), M_ISCSI, M_ZERO | M_WAITOK);
2286 	sx_init(&sc->sc_lock, "iscsi");
2287 	TAILQ_INIT(&sc->sc_sessions);
2288 	cv_init(&sc->sc_cv, "iscsi_cv");
2289 
2290 	iscsi_outstanding_zone = uma_zcreate("iscsi_outstanding",
2291 	    sizeof(struct iscsi_outstanding), NULL, NULL, NULL, NULL,
2292 	    UMA_ALIGN_PTR, 0);
2293 
2294 	error = make_dev_p(MAKEDEV_CHECKNAME, &sc->sc_cdev, &iscsi_cdevsw,
2295 	    NULL, UID_ROOT, GID_WHEEL, 0600, "iscsi");
2296 	if (error != 0) {
2297 		ISCSI_WARN("failed to create device node, error %d", error);
2298 		return (error);
2299 	}
2300 	sc->sc_cdev->si_drv1 = sc;
2301 
2302 	/*
2303 	 * Note that this needs to get run before dashutdown().  Otherwise,
2304 	 * when rebooting with iSCSI session with outstanding requests,
2305 	 * but disconnected, dashutdown() will hang on cam_periph_runccb().
2306 	 */
2307 	sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
2308 	    iscsi_shutdown, sc, SHUTDOWN_PRI_FIRST);
2309 
2310 	return (0);
2311 }
2312 
2313 static int
2314 iscsi_unload(void)
2315 {
2316 	struct iscsi_session *is, *tmp;
2317 
2318 	if (sc->sc_cdev != NULL) {
2319 		ISCSI_DEBUG("removing device node");
2320 		destroy_dev(sc->sc_cdev);
2321 		ISCSI_DEBUG("device node removed");
2322 	}
2323 
2324 	if (sc->sc_shutdown_eh != NULL)
2325 		EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_eh);
2326 
2327 	sx_slock(&sc->sc_lock);
2328 	TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp)
2329 		iscsi_session_terminate(is);
2330 	while(!TAILQ_EMPTY(&sc->sc_sessions)) {
2331 		ISCSI_DEBUG("waiting for sessions to terminate");
2332 		cv_wait(&sc->sc_cv, &sc->sc_lock);
2333 	}
2334 	ISCSI_DEBUG("all sessions terminated");
2335 	sx_sunlock(&sc->sc_lock);
2336 
2337 	uma_zdestroy(iscsi_outstanding_zone);
2338 	sx_destroy(&sc->sc_lock);
2339 	cv_destroy(&sc->sc_cv);
2340 	free(sc, M_ISCSI);
2341 	return (0);
2342 }
2343 
2344 static int
2345 iscsi_quiesce(void)
2346 {
2347 	sx_slock(&sc->sc_lock);
2348 	if (!TAILQ_EMPTY(&sc->sc_sessions)) {
2349 		sx_sunlock(&sc->sc_lock);
2350 		return (EBUSY);
2351 	}
2352 	sx_sunlock(&sc->sc_lock);
2353 	return (0);
2354 }
2355 
2356 static int
2357 iscsi_modevent(module_t mod, int what, void *arg)
2358 {
2359 	int error;
2360 
2361 	switch (what) {
2362 	case MOD_LOAD:
2363 		error = iscsi_load();
2364 		break;
2365 	case MOD_UNLOAD:
2366 		error = iscsi_unload();
2367 		break;
2368 	case MOD_QUIESCE:
2369 		error = iscsi_quiesce();
2370 		break;
2371 	default:
2372 		error = EINVAL;
2373 		break;
2374 	}
2375 	return (error);
2376 }
2377 
2378 moduledata_t iscsi_data = {
2379 	"iscsi",
2380 	iscsi_modevent,
2381 	0
2382 };
2383 
2384 DECLARE_MODULE(iscsi, iscsi_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
2385 MODULE_DEPEND(iscsi, cam, 1, 1, 1);
2386 MODULE_DEPEND(iscsi, icl, 1, 1, 1);
2387