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