iscsi_send.c revision 1.34 1 /* $NetBSD: iscsi_send.c,v 1.34 2017/02/25 12:03:57 mlelstv Exp $ */
2
3 /*-
4 * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include "iscsi_globals.h"
32
33 #include <sys/file.h>
34 #include <sys/filedesc.h>
35 #include <sys/socket.h>
36 #include <sys/socketvar.h>
37 #include <sys/atomic.h>
38
39 /*#define LUN_1 1 */
40
41 /*****************************************************************************/
42
43 /*
44 * my_soo_write:
45 * Replacement for soo_write with flag handling.
46 *
47 * Parameter:
48 * conn The connection
49 * u The uio descriptor
50 *
51 * Returns: 0 on success, else EIO.
52 */
53
54 STATIC int
55 my_soo_write(connection_t *conn, struct uio *u)
56 {
57 struct socket *so = conn->sock->f_socket;
58 int ret;
59 #ifdef ISCSI_DEBUG
60 size_t resid = u->uio_resid;
61 #endif
62
63 KASSERT(u->uio_resid != 0);
64
65 ret = (*so->so_send)(so, NULL, u, NULL, NULL, 0, conn->threadobj);
66
67 DEB(99, ("soo_write done: len = %zu\n", u->uio_resid));
68
69 if (ret != 0 || u->uio_resid) {
70 DEBC(conn, 0, ("Write failed sock %p (ret: %d, req: %zu, resid: %zu)\n",
71 conn->sock, ret, resid, u->uio_resid));
72 handle_connection_error(conn, ISCSI_STATUS_SOCKET_ERROR, NO_LOGOUT);
73 return EIO;
74 }
75 return 0;
76 }
77
78 /*****************************************************************************/
79
80 /*
81 * assign_connection:
82 * This function returns the connection to use for the next transaction.
83 *
84 * Parameter: The session
85 *
86 * Returns: The connection
87 */
88
89 connection_t *
90 assign_connection(session_t *session, bool waitok)
91 {
92 connection_t *conn, *next;
93
94 mutex_enter(&session->lock);
95 do {
96 if (session->terminating ||
97 (conn = session->mru_connection) == NULL) {
98 mutex_exit(&session->lock);
99 return NULL;
100 }
101 next = conn;
102 do {
103 next = TAILQ_NEXT(next, connections);
104 if (next == NULL) {
105 next = TAILQ_FIRST(&session->conn_list);
106 }
107 } while (next != NULL && next != conn &&
108 next->state != ST_FULL_FEATURE);
109
110 if (next->state != ST_FULL_FEATURE) {
111 if (waitok) {
112 cv_wait(&session->sess_cv, &session->lock);
113 next = TAILQ_FIRST(&session->conn_list);
114 } else {
115 mutex_exit(&session->lock);
116 return NULL;
117 }
118 } else {
119 session->mru_connection = next;
120 }
121 } while (next != NULL && next->state != ST_FULL_FEATURE);
122 mutex_exit(&session->lock);
123
124 return next;
125 }
126
127
128 /*
129 * reassign_tasks:
130 * Reassign pending commands to one of the still existing connections
131 * of a session.
132 *
133 * Parameter:
134 * oldconn The terminating connection
135 */
136
137 STATIC void
138 reassign_tasks(connection_t *oldconn)
139 {
140 session_t *sess = oldconn->session;
141 connection_t *conn;
142 ccb_t *ccb;
143 pdu_t *pdu = NULL;
144 pdu_t *opdu;
145 int no_tm = 1;
146 int rc = 1;
147 uint32_t sn;
148
149 if ((conn = assign_connection(sess, FALSE)) == NULL) {
150 DEB(1, ("Reassign_tasks of Session %d, connection %d failed, "
151 "no active connection\n",
152 sess->id, oldconn->id));
153 /* XXX here we need to abort the waiting CCBs */
154 return;
155 }
156
157 if (sess->ErrorRecoveryLevel >= 2) {
158 if (oldconn->loggedout == NOT_LOGGED_OUT) {
159 oldconn->loggedout = LOGOUT_SENT;
160 no_tm = send_logout(conn, oldconn, RECOVER_CONNECTION, TRUE);
161 oldconn->loggedout = (rc) ? LOGOUT_FAILED : LOGOUT_SUCCESS;
162 if (!oldconn->Time2Retain) {
163 DEBC(conn, 1, ("Time2Retain is zero, setting no_tm\n"));
164 no_tm = 1;
165 }
166 } else if (oldconn->loggedout == LOGOUT_SUCCESS) {
167 no_tm = 0;
168 }
169 if (!no_tm && oldconn->Time2Wait) {
170 DEBC(conn, 1, ("Time2Wait=%d, hz=%d, waiting...\n",
171 oldconn->Time2Wait, hz));
172 kpause("Time2Wait", false, oldconn->Time2Wait * hz, NULL);
173 }
174 }
175
176 DEBC(conn, 1, ("Reassign_tasks: Session %d, conn %d -> conn %d, no_tm=%d\n",
177 sess->id, oldconn->id, conn->id, no_tm));
178
179
180 /* XXX reassign waiting CCBs to new connection */
181
182 while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) {
183 /* Copy PDU contents (PDUs are bound to connection) */
184 if ((pdu = get_pdu(conn, TRUE)) == NULL) {
185 break;
186 }
187
188 /* adjust CCB and clone PDU for new connection */
189 TAILQ_REMOVE(&oldconn->ccbs_waiting, ccb, chain);
190
191 opdu = ccb->pdu_waiting;
192 KASSERT((opdu->flags & PDUF_INQUEUE) == 0);
193
194 *pdu = *opdu;
195
196 /* restore overwritten back ptr */
197 pdu->connection = conn;
198
199 /* fixup saved UIO and IOVEC (regular one will be overwritten anyway) */
200 pdu->save_uio.uio_iov = pdu->io_vec;
201 pdu->save_iovec [0].iov_base = &pdu->pdu;
202
203 if (conn->DataDigest && pdu->save_uio.uio_iovcnt > 1) {
204 if (pdu->save_iovec [2].iov_base == NULL) {
205 pdu->save_iovec [2].iov_base = &pdu->data_digest;
206 pdu->save_uio.uio_iovcnt = 3;
207 } else {
208 pdu->save_iovec [3].iov_base = &pdu->data_digest;
209 pdu->save_uio.uio_iovcnt = 4;
210 }
211 }
212 pdu->save_iovec [0].iov_len =
213 (conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE;
214
215 /* link new PDU into old CCB */
216 ccb->pdu_waiting = pdu;
217 /* link new CCB into new connection */
218 ccb->connection = conn;
219 /* reset timeouts */
220 ccb->num_timeouts = 0;
221
222 /* fixup reference counts */
223 oldconn->usecount--;
224 atomic_inc_uint(&conn->usecount);
225
226 DEBC(conn, 1, ("CCB %p: Copied PDU %p to %p\n",
227 ccb, opdu, pdu));
228
229 /* kill temp pointer that is now referenced by the new PDU */
230 opdu->temp_data = NULL;
231
232 /* and free the old PDU */
233 free_pdu(opdu);
234
235 /* put ready CCB into waiting list of new connection */
236 mutex_enter(&conn->lock);
237 suspend_ccb(ccb, TRUE);
238 mutex_exit(&conn->lock);
239 }
240
241 if (pdu == NULL) {
242 DEBC(conn, 1, ("Error while copying PDUs in reassign_tasks!\n"));
243 /* give up recovering, the other connection is screwed up as well... */
244 while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) {
245 wake_ccb(ccb, oldconn->terminating);
246 }
247 /* XXX some CCBs might have been moved to new connection, but how is the
248 * new connection handled or killed ? */
249 return;
250 }
251
252 TAILQ_FOREACH(ccb, &conn->ccbs_waiting, chain) {
253 if (!no_tm) {
254 rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN);
255 }
256 /* if we get an error on reassign, restart the original request */
257 if (no_tm || rc) {
258 mutex_enter(&sess->lock);
259 if (ccb->CmdSN < sess->ExpCmdSN) {
260 pdu = ccb->pdu_waiting;
261 sn = get_sernum(sess, pdu);
262
263 /* update CmdSN */
264 DEBC(conn, 1, ("Resend Updating CmdSN - old %d, new %d\n",
265 ccb->CmdSN, sn));
266 ccb->CmdSN = sn;
267 pdu->pdu.p.command.CmdSN = htonl(ccb->CmdSN);
268 }
269 mutex_exit(&sess->lock);
270 resend_pdu(ccb);
271 } else {
272 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
273 }
274 DEBC(conn, 1, ("Reassign ccb %p, no_tm=%d, rc=%d\n",
275 ccb, no_tm, rc));
276 }
277 }
278
279
280 /*
281 * iscsi_send_thread:
282 * This thread services the send queue, writing the PDUs to the socket.
283 * It also handles the cleanup when the connection is terminated.
284 *
285 * Parameter:
286 * par The connection this thread services
287 */
288
289 void
290 iscsi_send_thread(void *par)
291 {
292 connection_t *conn = (connection_t *) par;
293 session_t *sess;
294 ccb_t *ccb, *nccb;
295 pdu_t *pdu;
296 struct file *fp;
297 pdu_disp_t pdisp;
298
299 sess = conn->session;
300 /* so cleanup thread knows there's someone left */
301 iscsi_num_send_threads++;
302
303 do {
304 mutex_enter(&conn->lock);
305 while (!conn->terminating) {
306 while (!conn->terminating &&
307 (pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) {
308 TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
309 pdu->flags &= ~PDUF_INQUEUE;
310 mutex_exit(&conn->lock);
311
312 /* update ExpStatSN here to avoid discontinuities */
313 /* and delays in updating target */
314 pdu->pdu.p.command.ExpStatSN = htonl(conn->StatSN_buf.ExpSN);
315
316 if (conn->HeaderDigest)
317 pdu->pdu.HeaderDigest = gen_digest(&pdu->pdu, BHS_SIZE);
318
319 DEBC(conn, 99, ("Transmitting PDU CmdSN = %u, ExpStatSN = %u\n",
320 ntohl(pdu->pdu.p.command.CmdSN),
321 ntohl(pdu->pdu.p.command.ExpStatSN)));
322 my_soo_write(conn, &pdu->uio);
323
324 mutex_enter(&conn->lock);
325 pdisp = pdu->disp;
326 if (pdisp > PDUDISP_FREE)
327 pdu->flags &= ~PDUF_BUSY;
328 mutex_exit(&conn->lock);
329 if (pdisp <= PDUDISP_FREE)
330 free_pdu(pdu);
331
332 mutex_enter(&conn->lock);
333 }
334
335 if (!conn->terminating)
336 cv_wait(&conn->conn_cv, &conn->lock);
337 }
338 mutex_exit(&conn->lock);
339
340 /* ------------------------------------------------------------------------
341 * Here this thread takes over cleanup of the terminating connection.
342 * ------------------------------------------------------------------------
343 */
344 connection_timeout_stop(conn);
345 conn->idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
346
347 fp = conn->sock;
348
349 /*
350 * We shutdown the socket here to force the receive
351 * thread to wake up
352 */
353 DEBC(conn, 1, ("Closing Socket %p\n", conn->sock));
354 solock(fp->f_socket);
355 soshutdown(fp->f_socket, SHUT_RDWR);
356 sounlock(fp->f_socket);
357
358 /* wake up any non-reassignable waiting CCBs */
359 TAILQ_FOREACH_SAFE(ccb, &conn->ccbs_waiting, chain, nccb) {
360 if (!(ccb->flags & CCBF_REASSIGN) || ccb->pdu_waiting == NULL) {
361 DEBC(conn, 1, ("Terminating CCB %p (t=%p)\n",
362 ccb,&ccb->timeout));
363 wake_ccb(ccb, conn->terminating);
364 } else {
365 ccb_timeout_stop(ccb);
366 ccb->num_timeouts = 0;
367 }
368 }
369
370 /* clean out anything left in send queue */
371 mutex_enter(&conn->lock);
372 while ((pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) {
373 TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain);
374 pdu->flags &= ~(PDUF_INQUEUE | PDUF_BUSY);
375 mutex_exit(&conn->lock);
376 /* if it's not attached to a waiting CCB, free it */
377 if (pdu->owner == NULL ||
378 pdu->owner->pdu_waiting != pdu) {
379 free_pdu(pdu);
380 }
381 mutex_enter(&conn->lock);
382 }
383 mutex_exit(&conn->lock);
384
385 /* If there's another connection available, transfer pending tasks */
386 if (sess->active_connections &&
387 TAILQ_FIRST(&conn->ccbs_waiting) != NULL) {
388
389 reassign_tasks(conn);
390 } else if (!conn->destroy && conn->Time2Wait) {
391 DEBC(conn, 1, ("Time2Wait\n"));
392 kpause("Time2Wait", false, conn->Time2Wait * hz, NULL);
393 DEBC(conn, 1, ("Time2Wait\n"));
394 }
395 /* notify event handlers of connection shutdown */
396 DEBC(conn, 1, ("%s\n", (conn->destroy) ? "TERMINATED" : "RECOVER"));
397 add_event((conn->destroy) ? ISCSI_CONNECTION_TERMINATED
398 : ISCSI_RECOVER_CONNECTION,
399 sess->id, conn->id, conn->terminating);
400
401 DEBC(conn, 1, ("Waiting for conn_idle\n"));
402 mutex_enter(&conn->lock);
403 if (!conn->destroy)
404 cv_timedwait(&conn->idle_cv, &conn->lock, CONNECTION_IDLE_TIMEOUT);
405 mutex_exit(&conn->lock);
406 DEBC(conn, 1, ("Waited for conn_idle, destroy = %d\n", conn->destroy));
407
408 } while (!conn->destroy);
409
410 /* wake up anyone waiting for a PDU */
411 mutex_enter(&conn->lock);
412 cv_broadcast(&conn->conn_cv);
413 mutex_exit(&conn->lock);
414
415 /* wake up any waiting CCBs */
416 while ((ccb = TAILQ_FIRST(&conn->ccbs_waiting)) != NULL) {
417 KASSERT(ccb->disp >= CCBDISP_NOWAIT);
418 wake_ccb(ccb, conn->terminating);
419 /* NOTE: wake_ccb will remove the CCB from the queue */
420 }
421
422 add_connection_cleanup(conn);
423
424 conn->sendproc = NULL;
425 DEBC(conn, 1, ("Send thread exits\n"));
426 iscsi_num_send_threads--;
427 kthread_exit(0);
428 }
429
430
431 /*
432 * send_pdu:
433 * Enqueue a PDU to be sent, and handle its disposition as well as
434 * the disposition of its associated CCB.
435 *
436 * Parameter:
437 * ccb The associated CCB. May be NULL if cdisp is CCBDISP_NOWAIT
438 * and pdisp is not PDUDISP_WAIT
439 * cdisp The CCB's disposition
440 * pdu The PDU
441 * pdisp The PDU's disposition
442 */
443
444 STATIC void
445 send_pdu(ccb_t *ccb, pdu_t *pdu, ccb_disp_t cdisp, pdu_disp_t pdisp)
446 {
447 connection_t *conn = pdu->connection;
448 ccb_disp_t prev_cdisp = 0;
449
450 if (ccb != NULL) {
451 prev_cdisp = ccb->disp;
452 pdu->pdu.InitiatorTaskTag = ccb->ITT;
453 pdu->owner = ccb;
454 if (cdisp != CCBDISP_NOWAIT)
455 ccb->disp = cdisp;
456 }
457
458 pdu->disp = pdisp;
459
460 DEBC(conn, 10, ("Send_pdu: CmdSN=%u ExpStatSN~%u ccb=%p, pdu=%p\n",
461 ntohl(pdu->pdu.p.command.CmdSN),
462 conn->StatSN_buf.ExpSN,
463 ccb, pdu));
464
465 mutex_enter(&conn->lock);
466 if (pdisp == PDUDISP_WAIT) {
467 KASSERT(ccb != NULL);
468
469 ccb->pdu_waiting = pdu;
470
471 /* save UIO and IOVEC for retransmit */
472 pdu->save_uio = pdu->uio;
473 memcpy(pdu->save_iovec, pdu->io_vec, sizeof(pdu->save_iovec));
474
475 pdu->flags |= PDUF_BUSY;
476 }
477 /* Enqueue for sending */
478 pdu->flags |= PDUF_INQUEUE;
479
480 if (pdu->flags & PDUF_PRIORITY)
481 TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
482 else
483 TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
484
485 cv_broadcast(&conn->conn_cv);
486
487 if (cdisp != CCBDISP_NOWAIT) {
488 KASSERT(ccb != NULL);
489 KASSERTMSG(ccb->connection == conn, "conn mismatch %p != %p\n", ccb->connection, conn);
490
491 if (prev_cdisp <= CCBDISP_NOWAIT)
492 suspend_ccb(ccb, TRUE);
493
494 mutex_exit(&conn->lock);
495 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
496 mutex_enter(&conn->lock);
497
498 while (ccb->disp == CCBDISP_WAIT) {
499 DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d waiting\n",
500 ccb, ccb->disp));
501 cv_wait(&conn->ccb_cv, &conn->lock);
502 DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d returned\n",
503 ccb, ccb->disp));
504 }
505 }
506
507 mutex_exit(&conn->lock);
508 }
509
510
511 /*
512 * resend_pdu:
513 * Re-Enqueue a PDU that has apparently gotten lost.
514 *
515 * Parameter:
516 * ccb The associated CCB.
517 */
518
519 void
520 resend_pdu(ccb_t *ccb)
521 {
522 connection_t *conn = ccb->connection;
523 pdu_t *pdu = ccb->pdu_waiting;
524
525 mutex_enter(&conn->lock);
526 if (pdu == NULL || (pdu->flags & PDUF_BUSY)) {
527 mutex_exit(&conn->lock);
528 return;
529 }
530 pdu->flags |= PDUF_BUSY;
531 mutex_exit(&conn->lock);
532
533 /* restore UIO and IOVEC */
534 pdu->uio = pdu->save_uio;
535 memcpy(pdu->io_vec, pdu->save_iovec, sizeof(pdu->io_vec));
536
537 DEBC(conn, 8, ("ReSend_pdu: CmdSN=%u ExpStatSN~%u ccb=%p, pdu=%p\n",
538 ntohl(pdu->pdu.p.command.CmdSN),
539 conn->StatSN_buf.ExpSN,
540 ccb, pdu));
541
542 mutex_enter(&conn->lock);
543 /* Enqueue for sending */
544 pdu->flags |= PDUF_INQUEUE;
545
546 if (pdu->flags & PDUF_PRIORITY) {
547 TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
548 } else {
549 TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
550 }
551 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
552 cv_broadcast(&conn->conn_cv);
553 mutex_exit(&conn->lock);
554 }
555
556
557 /*
558 * setup_tx_uio:
559 * Initialize the uio structure for sending, including header,
560 * data (if present), padding, and Data Digest.
561 * Header Digest is generated in send thread.
562 *
563 * Parameter:
564 * pdu The PDU
565 * dsl The Data Segment Length
566 * data The data pointer
567 * read TRUE if this is a read operation
568 */
569
570 STATIC void
571 setup_tx_uio(pdu_t *pdu, uint32_t dsl, void *data, bool read)
572 {
573 static uint8_t pad_bytes[4] = { 0 };
574 struct uio *uio;
575 int i, pad, hlen;
576 connection_t *conn = pdu->connection;
577
578 DEB(99, ("SetupTxUio: dlen = %d, dptr: %p, read: %d\n",
579 dsl, data, read));
580
581 if (!read && dsl) {
582 hton3(dsl, pdu->pdu.DataSegmentLength);
583 }
584 hlen = (conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE;
585
586 pdu->io_vec[0].iov_base = &pdu->pdu;
587 pdu->io_vec[0].iov_len = hlen;
588
589 uio = &pdu->uio;
590
591 uio->uio_iov = pdu->io_vec;
592 uio->uio_iovcnt = 1;
593 uio->uio_rw = UIO_WRITE;
594 uio->uio_resid = hlen;
595 UIO_SETUP_SYSSPACE(uio);
596
597 if (!read && dsl) {
598 uio->uio_iovcnt++;
599 pdu->io_vec[1].iov_base = data;
600 pdu->io_vec[1].iov_len = dsl;
601 uio->uio_resid += dsl;
602
603 /* Pad to next multiple of 4 */
604 pad = uio->uio_resid & 0x03;
605 if (pad) {
606 i = uio->uio_iovcnt++;
607 pad = 4 - pad;
608 pdu->io_vec[i].iov_base = pad_bytes;
609 pdu->io_vec[i].iov_len = pad;
610 uio->uio_resid += pad;
611 }
612
613 if (conn->DataDigest) {
614 pdu->data_digest = gen_digest_2(data, dsl, pad_bytes, pad);
615 i = uio->uio_iovcnt++;
616 pdu->io_vec[i].iov_base = &pdu->data_digest;
617 pdu->io_vec[i].iov_len = 4;
618 uio->uio_resid += 4;
619 }
620 }
621 }
622
623 /*
624 * init_login_pdu:
625 * Initialize the login PDU.
626 *
627 * Parameter:
628 * conn The connection
629 * ccb The CCB
630 * pdu The PDU
631 */
632
633 STATIC void
634 init_login_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, bool next)
635 {
636 pdu_header_t *pdu = &ppdu->pdu;
637 login_isid_t *isid = (login_isid_t *) & pdu->LUN;
638 uint8_t c_phase;
639
640 pdu->Opcode = IOP_Login_Request | OP_IMMEDIATE;
641
642 mutex_enter(&conn->session->lock);
643 ccb->CmdSN = get_sernum(conn->session, ppdu);
644 mutex_exit(&conn->session->lock);
645
646 if (next) {
647 c_phase = (pdu->Flags >> CSG_SHIFT) & SG_MASK;
648 pdu->Flags = FLAG_TRANSIT | (c_phase << CSG_SHIFT) |
649 NEXT_PHASE(c_phase);
650 }
651
652 memcpy(isid, &iscsi_InitiatorISID, 6);
653 isid->TSIH = conn->session->TSIH;
654
655 pdu->p.login_req.CID = htons(conn->id);
656 pdu->p.login_req.CmdSN = htonl(ccb->CmdSN);
657 }
658
659
660 /*
661 * negotiate_login:
662 * Control login negotiation.
663 *
664 * Parameter:
665 * conn The connection
666 * rx_pdu The received login response PDU
667 * tx_ccb The originally sent login CCB
668 */
669
670 void
671 negotiate_login(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
672 {
673 int rc;
674 bool next = TRUE;
675 pdu_t *tx_pdu;
676 uint8_t c_phase;
677
678 if (rx_pdu->pdu.Flags & FLAG_TRANSIT)
679 c_phase = rx_pdu->pdu.Flags & SG_MASK;
680 else
681 c_phase = (rx_pdu->pdu.Flags >> CSG_SHIFT) & SG_MASK;
682
683 DEB(99, ("NegotiateLogin: Flags=%x Phase=%x\n",
684 rx_pdu->pdu.Flags, c_phase));
685
686 if (c_phase == SG_FULL_FEATURE_PHASE) {
687 session_t *sess = conn->session;
688
689 if (!sess->TSIH)
690 sess->TSIH = ((login_isid_t *) &rx_pdu->pdu.LUN)->TSIH;
691
692 if (rx_pdu->temp_data != NULL)
693 assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, NULL);
694
695 /* negotiated values are now valid */
696 set_negotiated_parameters(tx_ccb);
697
698 DEBC(conn, 5, ("Login Successful!\n"));
699 wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
700 return;
701 }
702
703 tx_pdu = get_pdu(conn, TRUE);
704 if (tx_pdu == NULL)
705 return;
706
707 tx_pdu->pdu.Flags = c_phase << CSG_SHIFT;
708
709 switch (c_phase) {
710 case SG_SECURITY_NEGOTIATION:
711 rc = assemble_security_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
712 if (rc < 0)
713 next = FALSE;
714 break;
715
716 case SG_LOGIN_OPERATIONAL_NEGOTIATION:
717 rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
718 break;
719
720 default:
721 DEBOUT(("Invalid phase %x in negotiate_login\n", c_phase));
722 rc = ISCSI_STATUS_TARGET_ERROR;
723 break;
724 }
725
726 if (rc > 0) {
727 wake_ccb(tx_ccb, rc);
728 free_pdu(tx_pdu);
729 } else {
730 init_login_pdu(conn, tx_ccb, tx_pdu, next);
731 setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data, FALSE);
732 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
733 }
734 }
735
736
737 /*
738 * init_text_pdu:
739 * Initialize the text PDU.
740 *
741 * Parameter:
742 * conn The connection
743 * ccb The transmit CCB
744 * ppdu The transmit PDU
745 * rx_pdu The received PDU if this is an unsolicited negotiation
746 */
747
748 STATIC void
749 init_text_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, pdu_t *rx_pdu)
750 {
751 pdu_header_t *pdu = &ppdu->pdu;
752
753 pdu->Opcode = IOP_Text_Request | OP_IMMEDIATE;
754 pdu->Flags = FLAG_FINAL;
755
756 mutex_enter(&conn->session->lock);
757 ccb->CmdSN = get_sernum(conn->session, ppdu);
758 mutex_exit(&conn->session->lock);
759
760 if (rx_pdu != NULL) {
761 pdu->p.text_req.TargetTransferTag =
762 rx_pdu->pdu.p.text_rsp.TargetTransferTag;
763 pdu->LUN = rx_pdu->pdu.LUN;
764 } else
765 pdu->p.text_req.TargetTransferTag = 0xffffffff;
766
767 pdu->p.text_req.CmdSN = htonl(ccb->CmdSN);
768 }
769
770
771 /*
772 * acknowledge_text:
773 * Acknowledge a continued login or text response.
774 *
775 * Parameter:
776 * conn The connection
777 * rx_pdu The received login/text response PDU
778 * tx_ccb The originally sent login/text request CCB
779 */
780
781 void
782 acknowledge_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
783 {
784 pdu_t *tx_pdu;
785
786 tx_pdu = get_pdu(conn, TRUE);
787 if (tx_pdu == NULL)
788 return;
789
790 if (rx_pdu != NULL &&
791 (rx_pdu->pdu.Opcode & OPCODE_MASK) == IOP_Login_Request)
792 init_login_pdu(conn, tx_ccb, tx_pdu, FALSE);
793 else
794 init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
795
796 setup_tx_uio(tx_pdu, 0, NULL, FALSE);
797 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
798 }
799
800
801 /*
802 * start_text_negotiation:
803 * Handle target request to negotiate (via asynch event)
804 *
805 * Parameter:
806 * conn The connection
807 */
808
809 void
810 start_text_negotiation(connection_t *conn)
811 {
812 pdu_t *pdu;
813 ccb_t *ccb;
814
815 ccb = get_ccb(conn, TRUE);
816 if (ccb == NULL)
817 return;
818 pdu = get_pdu(conn, TRUE);
819 if (pdu == NULL) {
820 free_ccb(ccb);
821 return;
822 }
823
824 if (init_text_parameters(conn, ccb)) {
825 free_ccb(ccb);
826 free_pdu(pdu);
827 return;
828 }
829
830 init_text_pdu(conn, ccb, pdu, NULL);
831 setup_tx_uio(pdu, 0, NULL, FALSE);
832 send_pdu(ccb, pdu, CCBDISP_FREE, PDUDISP_WAIT);
833 }
834
835
836 /*
837 * negotiate_text:
838 * Handle received text negotiation.
839 *
840 * Parameter:
841 * conn The connection
842 * rx_pdu The received text response PDU
843 * tx_ccb The original CCB
844 */
845
846 void
847 negotiate_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
848 {
849 int rc;
850 pdu_t *tx_pdu;
851
852 if (tx_ccb->flags & CCBF_SENDTARGET) {
853 if (!(rx_pdu->pdu.Flags & FLAG_FINAL)) {
854 handle_connection_error(conn, ISCSI_STATUS_PROTOCOL_ERROR,
855 LOGOUT_CONNECTION);
856 return;
857 }
858 /* transfer ownership of text to CCB */
859 tx_ccb->text_data = rx_pdu->temp_data;
860 tx_ccb->text_len = rx_pdu->temp_data_len;
861 rx_pdu->temp_data = NULL;
862 wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
863 } else {
864 if (!(rx_pdu->pdu.Flags & FLAG_FINAL))
865 tx_pdu = get_pdu(conn, TRUE);
866 else
867 tx_pdu = NULL;
868
869 rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
870 if (rc) {
871 if (tx_pdu != NULL)
872 free_pdu(tx_pdu);
873
874 handle_connection_error(conn, rc, LOGOUT_CONNECTION);
875 } else if (tx_pdu != NULL) {
876 init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
877 setup_tx_uio(tx_pdu, tx_pdu->temp_data_len,
878 tx_pdu->temp_data, FALSE);
879 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
880 } else {
881 set_negotiated_parameters(tx_ccb);
882 wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
883 }
884 }
885 }
886
887
888 /*
889 * send_send_targets:
890 * Send out a SendTargets text request.
891 * The result is stored in the fields in the session structure.
892 *
893 * Parameter:
894 * session The session
895 * key The text key to use
896 *
897 * Returns: 0 on success, else an error code.
898 */
899
900 int
901 send_send_targets(session_t *session, uint8_t *key)
902 {
903 ccb_t *ccb;
904 pdu_t *pdu;
905 int rc = 0;
906 connection_t *conn;
907
908 DEB(9, ("Send_send_targets\n"));
909
910 conn = assign_connection(session, TRUE);
911 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE)
912 return (conn != NULL && conn->terminating) ? conn->terminating
913 : ISCSI_STATUS_CONNECTION_FAILED;
914
915 ccb = get_ccb(conn, TRUE);
916 if (ccb == NULL)
917 return conn->terminating;
918 pdu = get_pdu(conn, TRUE);
919 if (pdu == NULL) {
920 free_ccb(ccb);
921 return conn->terminating;
922 }
923
924 ccb->flags |= CCBF_SENDTARGET;
925
926 if ((rc = assemble_send_targets(pdu, key)) != 0) {
927 free_ccb(ccb);
928 free_pdu(pdu);
929 return rc;
930 }
931
932 init_text_pdu(conn, ccb, pdu, NULL);
933
934 setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
935 send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_WAIT);
936
937 rc = ccb->status;
938 if (!rc) {
939 /* transfer ownership of data */
940 session->target_list = ccb->text_data;
941 session->target_list_len = ccb->text_len;
942 ccb->text_data = NULL;
943 }
944 free_ccb(ccb);
945 return rc;
946 }
947
948
949 /*
950 * send_nop_out:
951 * Send nop out request.
952 *
953 * Parameter:
954 * conn The connection
955 * rx_pdu The received Nop-In PDU
956 *
957 * Returns: 0 on success, else an error code.
958 */
959
960 int
961 send_nop_out(connection_t *conn, pdu_t *rx_pdu)
962 {
963 session_t *sess;
964 ccb_t *ccb;
965 pdu_t *ppdu;
966 pdu_header_t *pdu;
967 uint32_t sn;
968
969 if (rx_pdu != NULL) {
970 ccb = NULL;
971 ppdu = get_pdu(conn, TRUE);
972 if (ppdu == NULL)
973 return 1;
974 } else {
975 ccb = get_ccb(conn, FALSE);
976 if (ccb == NULL) {
977 DEBOUT(("Can't get CCB in send_nop_out\n"));
978 return 1;
979 }
980 ppdu = get_pdu(conn, FALSE);
981 if (ppdu == NULL) {
982 free_ccb(ccb);
983 DEBOUT(("Can't get PDU in send_nop_out\n"));
984 return 1;
985 }
986 }
987
988 pdu = &ppdu->pdu;
989 pdu->Flags = FLAG_FINAL;
990 pdu->Opcode = IOP_NOP_Out | OP_IMMEDIATE;
991
992 sess = conn->session;
993
994 mutex_enter(&sess->lock);
995 sn = get_sernum(sess, ppdu);
996 mutex_exit(&sess->lock);
997
998 if (rx_pdu != NULL) {
999 pdu->p.nop_out.TargetTransferTag =
1000 rx_pdu->pdu.p.nop_in.TargetTransferTag;
1001 pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
1002 pdu->p.nop_out.CmdSN = htonl(sn);
1003 pdu->LUN = rx_pdu->pdu.LUN;
1004 } else {
1005 pdu->p.nop_out.TargetTransferTag = 0xffffffff;
1006 pdu->InitiatorTaskTag = 0xffffffff;
1007 ccb->CmdSN = sn;
1008 pdu->p.nop_out.CmdSN = htonl(sn);
1009 }
1010
1011 DEBC(conn, 10, ("Send NOP_Out CmdSN=%d, rx_pdu=%p\n", sn, rx_pdu));
1012
1013 setup_tx_uio(ppdu, 0, NULL, FALSE);
1014 send_pdu(ccb, ppdu, (rx_pdu != NULL) ? CCBDISP_NOWAIT : CCBDISP_FREE,
1015 PDUDISP_FREE);
1016 return 0;
1017 }
1018
1019
1020 /*
1021 * snack_missing:
1022 * Send SNACK request for missing data.
1023 *
1024 * Parameter:
1025 * conn The connection
1026 * ccb The task's CCB (for Data NAK only)
1027 * type The SNACK type
1028 * BegRun The BegRun field
1029 * RunLength The RunLength field
1030 */
1031
1032 void
1033 snack_missing(connection_t *conn, ccb_t *ccb, uint8_t type,
1034 uint32_t BegRun, uint32_t RunLength)
1035 {
1036 pdu_t *ppdu;
1037 pdu_header_t *pdu;
1038
1039 ppdu = get_pdu(conn, TRUE);
1040 if (ppdu == NULL)
1041 return;
1042 pdu = &ppdu->pdu;
1043 pdu->Opcode = IOP_SNACK_Request;
1044 pdu->Flags = FLAG_FINAL | type;
1045
1046 pdu->InitiatorTaskTag = (type == SNACK_DATA_NAK) ? ccb->ITT : 0xffffffff;
1047 pdu->p.snack.TargetTransferTag = 0xffffffff;
1048 pdu->p.snack.BegRun = htonl(BegRun);
1049 pdu->p.snack.RunLength = htonl(RunLength);
1050
1051 ppdu->flags = PDUF_PRIORITY;
1052
1053 setup_tx_uio(ppdu, 0, NULL, FALSE);
1054 send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
1055 }
1056
1057
1058 /*
1059 * send_snack:
1060 * Send SNACK request.
1061 *
1062 * Parameter:
1063 * conn The connection
1064 * rx_pdu The received data in PDU
1065 * tx_ccb The original command CCB (required for Data ACK only)
1066 * type The SNACK type
1067 *
1068 * Returns: 0 on success, else an error code.
1069 */
1070
1071 void
1072 send_snack(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb, uint8_t type)
1073 {
1074 pdu_t *ppdu;
1075 pdu_header_t *pdu;
1076
1077 ppdu = get_pdu(conn, TRUE);
1078 if (ppdu == NULL)
1079 return;
1080 pdu = &ppdu->pdu;
1081 pdu->Opcode = IOP_SNACK_Request;
1082 pdu->Flags = FLAG_FINAL | type;
1083
1084 switch (type) {
1085 case SNACK_DATA_NAK:
1086 pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
1087 pdu->p.snack.TargetTransferTag = 0xffffffff;
1088 pdu->p.snack.BegRun = rx_pdu->pdu.p.data_in.DataSN;
1089 pdu->p.snack.RunLength = htonl(1);
1090 break;
1091
1092 case SNACK_STATUS_NAK:
1093 pdu->InitiatorTaskTag = 0xffffffff;
1094 pdu->p.snack.TargetTransferTag = 0xffffffff;
1095 pdu->p.snack.BegRun = rx_pdu->pdu.p.response.StatSN;
1096 pdu->p.snack.RunLength = htonl(1);
1097 break;
1098
1099 case SNACK_DATA_ACK:
1100 pdu->InitiatorTaskTag = 0xffffffff;
1101 pdu->p.snack.TargetTransferTag =
1102 rx_pdu->pdu.p.data_in.TargetTransferTag;
1103 pdu->p.snack.BegRun = tx_ccb->DataSN_buf.ExpSN;
1104 pdu->p.snack.RunLength = 0;
1105 break;
1106
1107 default:
1108 DEBOUT(("Invalid type %d in send_snack\n", type));
1109 return;
1110 }
1111
1112 pdu->LUN = rx_pdu->pdu.LUN;
1113
1114 ppdu->flags = PDUF_PRIORITY;
1115
1116 setup_tx_uio(ppdu, 0, NULL, FALSE);
1117 send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
1118 }
1119
1120
1121 /*
1122 * send_login:
1123 * Send login request.
1124 *
1125 * Parameter:
1126 * conn The connection
1127 * par The login parameters (for negotiation)
1128 *
1129 * Returns: 0 on success, else an error code.
1130 */
1131
1132 int
1133 send_login(connection_t *conn)
1134 {
1135 ccb_t *ccb;
1136 pdu_t *pdu;
1137 int rc;
1138
1139 DEBC(conn, 9, ("Send_login\n"));
1140 ccb = get_ccb(conn, TRUE);
1141 /* only if terminating (which couldn't possibly happen here, but...) */
1142 if (ccb == NULL)
1143 return conn->terminating;
1144 pdu = get_pdu(conn, TRUE);
1145 if (pdu == NULL) {
1146 free_ccb(ccb);
1147 return conn->terminating;
1148 }
1149
1150 if ((rc = assemble_login_parameters(conn, ccb, pdu)) <= 0) {
1151 init_login_pdu(conn, ccb, pdu, !rc);
1152 setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
1153 send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_FREE);
1154 rc = ccb->status;
1155 } else {
1156 free_pdu(pdu);
1157 }
1158 free_ccb(ccb);
1159 return rc;
1160 }
1161
1162
1163 /*
1164 * send_logout:
1165 * Send logout request.
1166 * NOTE: This function does not wait for the logout to complete.
1167 *
1168 * Parameter:
1169 * conn The connection
1170 * refconn The referenced connection
1171 * reason The reason code
1172 * wait Wait for completion if TRUE
1173 *
1174 * Returns: 0 on success (logout sent), else an error code.
1175 */
1176
1177 int
1178 send_logout(connection_t *conn, connection_t *refconn, int reason,
1179 bool wait)
1180 {
1181 ccb_t *ccb;
1182 pdu_t *ppdu;
1183 pdu_header_t *pdu;
1184
1185 DEBC(conn, 5, ("Send_logout\n"));
1186 ccb = get_ccb(conn, TRUE);
1187 /* can only happen if terminating... */
1188 if (ccb == NULL)
1189 return conn->terminating;
1190 ppdu = get_pdu(conn, TRUE);
1191 if (ppdu == NULL) {
1192 free_ccb(ccb);
1193 return conn->terminating;
1194 }
1195
1196 pdu = &ppdu->pdu;
1197 pdu->Opcode = IOP_Logout_Request | OP_IMMEDIATE;
1198
1199 pdu->Flags = FLAG_FINAL | reason;
1200 ccb->CmdSN = conn->session->CmdSN;
1201 pdu->p.logout_req.CmdSN = htonl(ccb->CmdSN);
1202 if (reason > 0)
1203 pdu->p.logout_req.CID = htons(refconn->id);
1204
1205 ccb->par = refconn;
1206 if (refconn != conn) {
1207 ccb->flags |= CCBF_OTHERCONN;
1208 } else {
1209 conn->state = ST_LOGOUT_SENT;
1210 conn->loggedout = LOGOUT_SENT;
1211 }
1212
1213 setup_tx_uio(ppdu, 0, NULL, FALSE);
1214 send_pdu(ccb, ppdu, (wait) ? CCBDISP_WAIT : CCBDISP_FREE, PDUDISP_FREE);
1215
1216 if (wait) {
1217 int rc = ccb->status;
1218 free_ccb (ccb);
1219 return rc;
1220 }
1221 return 0;
1222 }
1223
1224
1225 /*
1226 * send_task_management:
1227 * Send task management request.
1228 *
1229 * Parameter:
1230 * conn The connection
1231 * ref_ccb The referenced command (NULL if none)
1232 * xs The scsipi command structure (NULL if not a scsipi request)
1233 * function The function code
1234 *
1235 * Returns: 0 on success, else an error code.
1236 */
1237
1238 int
1239 send_task_management(connection_t *conn, ccb_t *ref_ccb, struct scsipi_xfer *xs,
1240 int function)
1241 {
1242 ccb_t *ccb;
1243 pdu_t *ppdu;
1244 pdu_header_t *pdu;
1245
1246 DEBC(conn, 5, ("Send_task_management, ref_ccb=%p, func = %d\n",
1247 ref_ccb, function));
1248
1249 if (function == TASK_REASSIGN && conn->session->ErrorRecoveryLevel < 2)
1250 return ISCSI_STATUS_CANT_REASSIGN;
1251
1252 ccb = get_ccb(conn, xs == NULL);
1253 /* can only happen if terminating... */
1254 if (ccb == NULL)
1255 return conn->terminating;
1256 ppdu = get_pdu(conn, xs == NULL);
1257 if (ppdu == NULL) {
1258 free_ccb(ccb);
1259 return conn->terminating;
1260 }
1261
1262 ccb->xs = xs;
1263
1264 pdu = &ppdu->pdu;
1265 pdu->Opcode = IOP_SCSI_Task_Management | OP_IMMEDIATE;
1266 pdu->Flags = FLAG_FINAL | function;
1267
1268 ccb->CmdSN = conn->session->CmdSN;
1269 pdu->p.task_req.CmdSN = htonl(ccb->CmdSN);
1270
1271 if (ref_ccb != NULL) {
1272 pdu->p.task_req.ReferencedTaskTag = ref_ccb->ITT;
1273 pdu->p.task_req.RefCmdSN = htonl(ref_ccb->CmdSN);
1274 pdu->p.task_req.ExpDataSN = htonl(ref_ccb->DataSN_buf.ExpSN);
1275 } else
1276 pdu->p.task_req.ReferencedTaskTag = 0xffffffff;
1277
1278 ppdu->flags |= PDUF_PRIORITY;
1279
1280 setup_tx_uio(ppdu, 0, NULL, FALSE);
1281 send_pdu(ccb, ppdu, (xs) ? CCBDISP_SCSIPI : CCBDISP_WAIT, PDUDISP_FREE);
1282
1283 if (xs == NULL) {
1284 int rc = ccb->status;
1285 free_ccb(ccb);
1286 return rc;
1287 }
1288 return 0;
1289 }
1290
1291
1292 /*
1293 * send_data_out:
1294 * Send data to target in response to an R2T or as unsolicited data.
1295 *
1296 * Parameter:
1297 * conn The connection
1298 * rx_pdu The received R2T PDU (NULL if unsolicited)
1299 * tx_ccb The originally sent command CCB
1300 * waitok Whether it's OK to wait for an available PDU or not
1301 */
1302
1303 int
1304 send_data_out(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb,
1305 ccb_disp_t disp, bool waitok)
1306 {
1307 pdu_header_t *pdu;
1308 uint32_t totlen, len, offs, sn;
1309 pdu_t *tx_pdu;
1310
1311 KASSERT(conn->max_transfer != 0);
1312
1313 if (rx_pdu) {
1314 offs = ntohl(rx_pdu->pdu.p.r2t.BufferOffset);
1315 totlen = ntohl(rx_pdu->pdu.p.r2t.DesiredDataTransferLength);
1316 } else {
1317 offs = conn->max_firstimmed;
1318 totlen = min(conn->max_firstdata - offs, tx_ccb->data_len - offs);
1319 }
1320 sn = 0;
1321
1322 while (totlen) {
1323 len = min(totlen, conn->max_transfer);
1324
1325 tx_pdu = get_pdu(conn, waitok);
1326 if (tx_pdu == NULL) {
1327 DEBC(conn, 5, ("No PDU in send_data_out\n"));
1328
1329 tx_ccb->disp = disp;
1330 tx_ccb->status = ISCSI_STATUS_NO_RESOURCES;
1331 handle_connection_error(conn, ISCSI_STATUS_NO_RESOURCES, NO_LOGOUT);
1332
1333 return ISCSI_STATUS_NO_RESOURCES;
1334 }
1335
1336 totlen -= len;
1337 pdu = &tx_pdu->pdu;
1338 pdu->Opcode = IOP_SCSI_Data_out;
1339 if (!totlen)
1340 pdu->Flags = FLAG_FINAL;
1341
1342 if (rx_pdu != NULL)
1343 pdu->p.data_out.TargetTransferTag =
1344 rx_pdu->pdu.p.r2t.TargetTransferTag;
1345 else
1346 pdu->p.data_out.TargetTransferTag = 0xffffffff;
1347 pdu->p.data_out.BufferOffset = htonl(offs);
1348 pdu->p.data_out.DataSN = htonl(sn);
1349
1350 DEBC(conn, 10, ("Send DataOut: DataSN %d, len %d offs %x totlen %d\n",
1351 sn, len, offs, totlen));
1352
1353 setup_tx_uio(tx_pdu, len, tx_ccb->data_ptr + offs, FALSE);
1354 send_pdu(tx_ccb, tx_pdu, (totlen) ? CCBDISP_NOWAIT : disp, PDUDISP_FREE);
1355
1356 sn++;
1357 offs += len;
1358 }
1359 return 0;
1360 }
1361
1362
1363 /*
1364 * send_command:
1365 * Send a SCSI command request.
1366 *
1367 * Parameter:
1368 * CCB The CCB
1369 * disp The CCB disposition
1370 */
1371
1372 void
1373 send_command(ccb_t *ccb, ccb_disp_t disp, bool waitok, bool immed)
1374 {
1375 uint32_t totlen, len;
1376 connection_t *conn = ccb->connection;
1377 session_t *sess = ccb->session;
1378 pdu_t *ppdu;
1379 pdu_header_t *pdu;
1380
1381 mutex_enter(&sess->lock);
1382 while (!sernum_in_window(sess)) {
1383 mutex_exit(&sess->lock);
1384 ccb->disp = disp;
1385 wake_ccb(ccb, ISCSI_STATUS_QUEUE_FULL);
1386 return;
1387 }
1388 mutex_exit(&sess->lock);
1389
1390 /* Don't confuse targets during (re-)negotations */
1391 if (conn->state != ST_FULL_FEATURE) {
1392 DEBOUT(("Invalid connection for send_command, ccb = %p\n",ccb));
1393 ccb->disp = disp;
1394 wake_ccb(ccb, ISCSI_STATUS_TARGET_BUSY);
1395 return;
1396 }
1397
1398 ppdu = get_pdu(conn, waitok);
1399 if (ppdu == NULL) {
1400 DEBOUT(("No PDU for send_command, ccb = %p\n",ccb));
1401 ccb->disp = disp;
1402 wake_ccb(ccb, ISCSI_STATUS_NO_RESOURCES);
1403 return;
1404 }
1405
1406 totlen = len = ccb->data_len;
1407
1408 pdu = &ppdu->pdu;
1409 pdu->LUN = htonq(ccb->lun);
1410 memcpy(pdu->p.command.SCSI_CDB, ccb->cmd, ccb->cmdlen);
1411 pdu->Opcode = IOP_SCSI_Command;
1412 if (immed)
1413 pdu->Opcode |= OP_IMMEDIATE;
1414 pdu->p.command.ExpectedDataTransferLength = htonl(totlen);
1415
1416 if (totlen) {
1417 if (ccb->data_in) {
1418 pdu->Flags = FLAG_READ;
1419 totlen = 0;
1420 } else {
1421 pdu->Flags = FLAG_WRITE;
1422 /* immediate data we can send */
1423 len = min(totlen, conn->max_firstimmed);
1424
1425 /* can we send more unsolicited data ? */
1426 totlen = conn->max_firstdata ? totlen - len : 0;
1427 }
1428 }
1429 if (!totlen)
1430 pdu->Flags |= FLAG_FINAL;
1431 pdu->Flags |= ccb->tag;
1432
1433 if (ccb->data_in)
1434 init_sernum(&ccb->DataSN_buf);
1435
1436 ccb->sense_len_got = 0;
1437 ccb->xfer_len = 0;
1438 ccb->residual = 0;
1439 ccb->flags |= CCBF_REASSIGN;
1440
1441 mutex_enter(&sess->lock);
1442 ccb->CmdSN = get_sernum(sess, ppdu);
1443 mutex_exit(&sess->lock);
1444
1445 pdu->p.command.CmdSN = htonl(ccb->CmdSN);
1446
1447 DEBC(conn, 10, ("Send Command: CmdSN %d (%d), data_in %d, len %d, totlen %d\n",
1448 ccb->CmdSN, sess->MaxCmdSN, ccb->data_in, len, totlen));
1449
1450 setup_tx_uio(ppdu, len, ccb->data_ptr, ccb->data_in);
1451 send_pdu(ccb, ppdu, (totlen) ? CCBDISP_DEFER : disp, PDUDISP_WAIT);
1452
1453 if (totlen)
1454 send_data_out(conn, NULL, ccb, disp, waitok);
1455 }
1456
1457
1458 /*
1459 * send_run_xfer:
1460 * Handle a SCSI command transfer request from scsipi.
1461 *
1462 * Parameter:
1463 * session The session
1464 * xs The transfer parameters
1465 */
1466
1467 void
1468 send_run_xfer(session_t *session, struct scsipi_xfer *xs)
1469 {
1470 ccb_t *ccb;
1471 connection_t *conn;
1472 bool waitok;
1473
1474 waitok = !(xs->xs_control & XS_CTL_NOSLEEP);
1475
1476 DEB(10, ("RunXfer: flags=%x, data=%p, datalen=%d, resid=%d, cmdlen=%d, "
1477 "waitok=%d\n", xs->xs_control, xs->data, xs->datalen,
1478 xs->resid, xs->cmdlen, waitok));
1479
1480 conn = assign_connection(session, waitok);
1481
1482 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
1483 xs->error = XS_SELTIMEOUT;
1484 DEBC(conn, 10, ("run_xfer on dead connection\n"));
1485 scsipi_done(xs);
1486 unref_session(session);
1487 return;
1488 }
1489
1490 if (xs->xs_control & XS_CTL_RESET) {
1491 if (send_task_management(conn, NULL, xs, TARGET_WARM_RESET)) {
1492 xs->error = XS_SELTIMEOUT;
1493 scsipi_done(xs);
1494 unref_session(session);
1495 }
1496 return;
1497 }
1498
1499 ccb = get_ccb(conn, waitok);
1500 if (ccb == NULL) {
1501 xs->error = XS_BUSY;
1502 DEBC(conn, 5, ("No CCB in run_xfer, %d in use.\n", conn->usecount));
1503 scsipi_done(xs);
1504 unref_session(session);
1505 return;
1506 }
1507 /* copy parameters into CCB for easier access */
1508 ccb->xs = xs;
1509
1510 ccb->data_in = (xs->xs_control & XS_CTL_DATA_IN) != 0;
1511 ccb->data_len = (uint32_t) xs->datalen;
1512 ccb->data_ptr = xs->data;
1513
1514 ccb->sense_len_req = sizeof(xs->sense.scsi_sense);
1515 ccb->sense_ptr = &xs->sense;
1516
1517 ccb->lun = ((uint64_t) (uint8_t) xs->xs_periph->periph_lun) << 48;
1518 ccb->cmd = (uint8_t *) xs->cmd;
1519 ccb->cmdlen = xs->cmdlen;
1520 DEB(10, ("RunXfer: Periph_lun = %d, cmd[1] = %x, cmdlen = %d\n",
1521 xs->xs_periph->periph_lun, ccb->cmd[1], xs->cmdlen));
1522
1523 ccb->ITT |= xs->xs_tag_id << 24;
1524 switch (xs->xs_tag_type) {
1525 case MSG_ORDERED_Q_TAG:
1526 ccb->tag = ATTR_ORDERED;
1527 break;
1528 case MSG_SIMPLE_Q_TAG:
1529 ccb->tag = ATTR_SIMPLE;
1530 break;
1531 case MSG_HEAD_OF_Q_TAG:
1532 ccb->tag = ATTR_HEAD_OF_QUEUE;
1533 break;
1534 default:
1535 ccb->tag = 0;
1536 break;
1537 }
1538
1539 #ifdef LUN_1
1540 ccb->lun += 0x1000000000000LL;
1541 ccb->cmd[1] += 0x10;
1542 #endif
1543 send_command(ccb, CCBDISP_SCSIPI, waitok, FALSE);
1544 }
1545
1546
1547 #ifndef ISCSI_MINIMAL
1548 /*
1549 * send_io_command:
1550 * Handle a SCSI io command request from user space.
1551 *
1552 * Parameter:
1553 * session The session
1554 * lun The LUN to use
1555 * req The SCSI request block
1556 * immed Immediate command if TRUE
1557 * conn_id Assign to this connection ID if nonzero
1558 */
1559
1560 int
1561 send_io_command(session_t *session, uint64_t lun, scsireq_t *req,
1562 bool immed, uint32_t conn_id)
1563 {
1564 ccb_t *ccb;
1565 connection_t *conn;
1566 int rc;
1567
1568 DEB(9, ("IoCommand: lun=%x, datalen=%d, cmdlen=%d, immed=%d, cid=%d\n",
1569 (int) lun, (int) req->datalen, (int) req->cmdlen, immed, conn_id));
1570
1571 conn = (conn_id) ? find_connection(session, conn_id)
1572 : assign_connection(session, TRUE);
1573
1574 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
1575 DEBOUT(("io_command on dead connection (state = %d)\n",
1576 (conn != NULL) ? conn->state : -1));
1577 return ISCSI_STATUS_INVALID_CONNECTION_ID;
1578 }
1579
1580 ccb = get_ccb(conn, TRUE);
1581 if (ccb == NULL) {
1582 DEBOUT(("No CCB in io_command\n"));
1583 return ISCSI_STATUS_NO_RESOURCES;
1584 }
1585
1586 ccb->data_in = (req->flags & SCCMD_READ) != 0;
1587 ccb->data_len = (uint32_t) req->datalen;
1588 ccb->data_ptr = req->databuf;
1589
1590 ccb->sense_len_req = req->senselen;
1591 ccb->sense_ptr = &req->sense;
1592
1593 ccb->lun = lun;
1594 ccb->cmd = (uint8_t *) req->cmd;
1595 ccb->cmdlen = req->cmdlen;
1596 DEBC(conn, 10, ("IoCommand: cmd[1] = %x, cmdlen = %d\n",
1597 ccb->cmd[1], ccb->cmdlen));
1598
1599 send_command(ccb, CCBDISP_WAIT, TRUE, immed);
1600
1601 rc = ccb->status;
1602
1603 req->senselen_used = ccb->sense_len_got;
1604 req->datalen_used = req->datalen - ccb->residual;
1605
1606 free_ccb(ccb);
1607
1608 return rc;
1609 }
1610 #endif
1611
1612
1613 /*****************************************************************************
1614 * Timeout handlers
1615 *****************************************************************************/
1616 /*
1617 * connection_timeout:
1618 * Handle prolonged silence on a connection by checking whether
1619 * it's still alive.
1620 * This has the side effect of discovering missing status or lost commands
1621 * before those time out.
1622 *
1623 * Parameter:
1624 * conn The connection
1625 */
1626
1627 void
1628 connection_timeout(connection_t *conn)
1629 {
1630
1631 if (++conn->num_timeouts > MAX_CONN_TIMEOUTS)
1632 handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, NO_LOGOUT);
1633 else {
1634 if (conn->state == ST_FULL_FEATURE)
1635 send_nop_out(conn, NULL);
1636
1637 connection_timeout_start(conn, CONNECTION_TIMEOUT);
1638 }
1639 }
1640
1641 /*
1642 * ccb_timeout:
1643 * Handle timeout of a sent command.
1644 *
1645 * Parameter:
1646 * ccb The CCB
1647 */
1648
1649 void
1650 ccb_timeout(ccb_t *ccb)
1651 {
1652 connection_t *conn = ccb->connection;
1653
1654 ccb->total_tries++;
1655
1656 DEBC(conn, 0, ("ccb_timeout: num=%d total=%d disp=%d\n",
1657 ccb->num_timeouts+1, ccb->total_tries, ccb->disp));
1658
1659 if (++ccb->num_timeouts > MAX_CCB_TIMEOUTS ||
1660 ccb->total_tries > MAX_CCB_TRIES ||
1661 ccb->disp <= CCBDISP_FREE ||
1662 !ccb->session->ErrorRecoveryLevel) {
1663
1664 wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
1665 handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION);
1666 } else {
1667 if (ccb->data_in && ccb->xfer_len < ccb->data_len) {
1668 /* request resend of all missing data */
1669 snack_missing(conn, ccb, SNACK_DATA_NAK, 0, 0);
1670 } else {
1671 /* request resend of all missing status */
1672 snack_missing(conn, NULL, SNACK_STATUS_NAK, 0, 0);
1673 }
1674 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
1675 }
1676 }
1677
1678