iscsi_send.c revision 1.10.2.3 1 /* $NetBSD: iscsi_send.c,v 1.10.2.3 2016/07/09 20:25:03 skrll 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 cv_broadcast(&conn->conn_cv);
412
413 /* wake up any waiting CCBs */
414 while ((ccb = TAILQ_FIRST(&conn->ccbs_waiting)) != NULL) {
415 KASSERT(ccb->disp >= CCBDISP_NOWAIT);
416 wake_ccb(ccb, conn->terminating);
417 /* NOTE: wake_ccb will remove the CCB from the queue */
418 }
419
420 if (conn->in_session) {
421 conn->in_session = FALSE;
422 TAILQ_REMOVE(&sess->conn_list, conn, connections);
423 sess->mru_connection = TAILQ_FIRST(&sess->conn_list);
424 }
425
426 add_connection_cleanup(conn);
427
428 conn->sendproc = NULL;
429 DEBC(conn, 1, ("Send thread exits\n"));
430 iscsi_num_send_threads--;
431 kthread_exit(0);
432 }
433
434
435 /*
436 * send_pdu:
437 * Enqueue a PDU to be sent, and handle its disposition as well as
438 * the disposition of its associated CCB.
439 *
440 * Parameter:
441 * ccb The associated CCB. May be NULL if cdisp is CCBDISP_NOWAIT
442 * and pdisp is not PDUDISP_WAIT
443 * cdisp The CCB's disposition
444 * pdu The PDU
445 * pdisp The PDU's disposition
446 */
447
448 STATIC void
449 send_pdu(ccb_t *ccb, pdu_t *pdu, ccb_disp_t cdisp, pdu_disp_t pdisp)
450 {
451 connection_t *conn = pdu->connection;
452 ccb_disp_t prev_cdisp = 0;
453
454 if (ccb != NULL) {
455 prev_cdisp = ccb->disp;
456 pdu->pdu.InitiatorTaskTag = ccb->ITT;
457 pdu->owner = ccb;
458 if (cdisp != CCBDISP_NOWAIT)
459 ccb->disp = cdisp;
460 }
461
462 pdu->disp = pdisp;
463
464 DEBC(conn, 10, ("Send_pdu: CmdSN=%u ExpStatSN~%u ccb=%p, pdu=%p\n",
465 ntohl(pdu->pdu.p.command.CmdSN),
466 conn->StatSN_buf.ExpSN,
467 ccb, pdu));
468
469 mutex_enter(&conn->lock);
470 if (pdisp == PDUDISP_WAIT) {
471 ccb->pdu_waiting = pdu;
472
473 /* save UIO and IOVEC for retransmit */
474 pdu->save_uio = pdu->uio;
475 memcpy(pdu->save_iovec, pdu->io_vec, sizeof(pdu->save_iovec));
476
477 pdu->flags |= PDUF_BUSY;
478 }
479 /* Enqueue for sending */
480 pdu->flags |= PDUF_INQUEUE;
481
482 if (pdu->flags & PDUF_PRIORITY)
483 TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
484 else
485 TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
486 mutex_exit(&conn->lock);
487
488 cv_broadcast(&conn->conn_cv);
489
490 if (cdisp != CCBDISP_NOWAIT) {
491 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
492
493 mutex_enter(&conn->lock);
494 if (prev_cdisp <= CCBDISP_NOWAIT)
495 suspend_ccb(ccb, TRUE);
496 while (ccb->disp == CCBDISP_WAIT) {
497 DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d waiting\n",
498 ccb, ccb->disp));
499 cv_wait(&conn->ccb_cv, &conn->lock);
500 DEBC(conn, 15, ("Send_pdu: ccb=%p cdisp=%d returned\n",
501 ccb, ccb->disp));
502 }
503 mutex_exit(&conn->lock);
504 }
505 }
506
507
508 /*
509 * resend_pdu:
510 * Re-Enqueue a PDU that has apparently gotten lost.
511 *
512 * Parameter:
513 * ccb The associated CCB.
514 */
515
516 void
517 resend_pdu(ccb_t *ccb)
518 {
519 connection_t *conn = ccb->connection;
520 pdu_t *pdu = ccb->pdu_waiting;
521
522 mutex_enter(&conn->lock);
523 if (pdu == NULL || (pdu->flags & PDUF_BUSY)) {
524 mutex_exit(&conn->lock);
525 return;
526 }
527 pdu->flags |= PDUF_BUSY;
528 mutex_exit(&conn->lock);
529
530 /* restore UIO and IOVEC */
531 pdu->uio = pdu->save_uio;
532 memcpy(pdu->io_vec, pdu->save_iovec, sizeof(pdu->io_vec));
533
534 DEBC(conn, 8, ("ReSend_pdu: CmdSN=%u ExpStatSN~%u ccb=%p, pdu=%p\n",
535 ntohl(pdu->pdu.p.command.CmdSN),
536 conn->StatSN_buf.ExpSN,
537 ccb, pdu));
538
539 mutex_enter(&conn->lock);
540 /* Enqueue for sending */
541 pdu->flags |= PDUF_INQUEUE;
542
543 if (pdu->flags & PDUF_PRIORITY) {
544 TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
545 } else {
546 TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain);
547 }
548 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
549 mutex_exit(&conn->lock);
550
551 cv_broadcast(&conn->conn_cv);
552 }
553
554
555 /*
556 * setup_tx_uio:
557 * Initialize the uio structure for sending, including header,
558 * data (if present), padding, and Data Digest.
559 * Header Digest is generated in send thread.
560 *
561 * Parameter:
562 * pdu The PDU
563 * dsl The Data Segment Length
564 * data The data pointer
565 * read TRUE if this is a read operation
566 */
567
568 STATIC void
569 setup_tx_uio(pdu_t *pdu, uint32_t dsl, void *data, bool read)
570 {
571 static uint8_t pad_bytes[4] = { 0 };
572 struct uio *uio;
573 int i, pad, hlen;
574 connection_t *conn = pdu->connection;
575
576 DEB(99, ("SetupTxUio: dlen = %d, dptr: %p, read: %d\n",
577 dsl, data, read));
578
579 if (!read && dsl) {
580 hton3(dsl, pdu->pdu.DataSegmentLength);
581 }
582 hlen = (conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE;
583
584 pdu->io_vec[0].iov_base = &pdu->pdu;
585 pdu->io_vec[0].iov_len = hlen;
586
587 uio = &pdu->uio;
588
589 uio->uio_iov = pdu->io_vec;
590 uio->uio_iovcnt = 1;
591 uio->uio_rw = UIO_WRITE;
592 uio->uio_resid = hlen;
593 UIO_SETUP_SYSSPACE(uio);
594
595 if (!read && dsl) {
596 uio->uio_iovcnt++;
597 pdu->io_vec[1].iov_base = data;
598 pdu->io_vec[1].iov_len = dsl;
599 uio->uio_resid += dsl;
600
601 /* Pad to next multiple of 4 */
602 pad = uio->uio_resid & 0x03;
603 if (pad) {
604 i = uio->uio_iovcnt++;
605 pad = 4 - pad;
606 pdu->io_vec[i].iov_base = pad_bytes;
607 pdu->io_vec[i].iov_len = pad;
608 uio->uio_resid += pad;
609 }
610
611 if (conn->DataDigest) {
612 pdu->data_digest = gen_digest_2(data, dsl, pad_bytes, pad);
613 i = uio->uio_iovcnt++;
614 pdu->io_vec[i].iov_base = &pdu->data_digest;
615 pdu->io_vec[i].iov_len = 4;
616 uio->uio_resid += 4;
617 }
618 }
619 }
620
621 /*
622 * init_login_pdu:
623 * Initialize the login PDU.
624 *
625 * Parameter:
626 * conn The connection
627 * ccb The CCB
628 * pdu The PDU
629 */
630
631 STATIC void
632 init_login_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, bool next)
633 {
634 pdu_header_t *pdu = &ppdu->pdu;
635 login_isid_t *isid = (login_isid_t *) & pdu->LUN;
636 uint8_t c_phase;
637
638 pdu->Opcode = IOP_Login_Request | OP_IMMEDIATE;
639
640 mutex_enter(&conn->session->lock);
641 ccb->CmdSN = get_sernum(conn->session, ppdu);
642 mutex_exit(&conn->session->lock);
643
644 if (next) {
645 c_phase = (pdu->Flags >> CSG_SHIFT) & SG_MASK;
646 pdu->Flags = FLAG_TRANSIT | (c_phase << CSG_SHIFT) |
647 NEXT_PHASE(c_phase);
648 }
649
650 memcpy(isid, &iscsi_InitiatorISID, 6);
651 isid->TSIH = conn->session->TSIH;
652
653 pdu->p.login_req.CID = htons(conn->id);
654 pdu->p.login_req.CmdSN = htonl(ccb->CmdSN);
655 }
656
657
658 /*
659 * negotiate_login:
660 * Control login negotiation.
661 *
662 * Parameter:
663 * conn The connection
664 * rx_pdu The received login response PDU
665 * tx_ccb The originally sent login CCB
666 */
667
668 void
669 negotiate_login(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
670 {
671 int rc;
672 bool next = TRUE;
673 pdu_t *tx_pdu;
674 uint8_t c_phase;
675
676 if (rx_pdu->pdu.Flags & FLAG_TRANSIT)
677 c_phase = rx_pdu->pdu.Flags & SG_MASK;
678 else
679 c_phase = (rx_pdu->pdu.Flags >> CSG_SHIFT) & SG_MASK;
680
681 DEB(99, ("NegotiateLogin: Flags=%x Phase=%x\n",
682 rx_pdu->pdu.Flags, c_phase));
683
684 if (c_phase == SG_FULL_FEATURE_PHASE) {
685 session_t *sess = conn->session;
686
687 if (!sess->TSIH)
688 sess->TSIH = ((login_isid_t *) &rx_pdu->pdu.LUN)->TSIH;
689
690 if (rx_pdu->temp_data != NULL)
691 assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, NULL);
692
693 /* negotiated values are now valid */
694 set_negotiated_parameters(tx_ccb);
695
696 DEBC(conn, 5, ("Login Successful!\n"));
697 wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
698 return;
699 }
700
701 tx_pdu = get_pdu(conn, TRUE);
702 if (tx_pdu == NULL)
703 return;
704
705 tx_pdu->pdu.Flags = c_phase << CSG_SHIFT;
706
707 switch (c_phase) {
708 case SG_SECURITY_NEGOTIATION:
709 rc = assemble_security_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
710 if (rc < 0)
711 next = FALSE;
712 break;
713
714 case SG_LOGIN_OPERATIONAL_NEGOTIATION:
715 rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
716 break;
717
718 default:
719 DEBOUT(("Invalid phase %x in negotiate_login\n", c_phase));
720 rc = ISCSI_STATUS_TARGET_ERROR;
721 break;
722 }
723
724 if (rc > 0) {
725 wake_ccb(tx_ccb, rc);
726 free_pdu(tx_pdu);
727 } else {
728 init_login_pdu(conn, tx_ccb, tx_pdu, next);
729 setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data, FALSE);
730 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
731 }
732 }
733
734
735 /*
736 * init_text_pdu:
737 * Initialize the text PDU.
738 *
739 * Parameter:
740 * conn The connection
741 * ccb The transmit CCB
742 * ppdu The transmit PDU
743 * rx_pdu The received PDU if this is an unsolicited negotiation
744 */
745
746 STATIC void
747 init_text_pdu(connection_t *conn, ccb_t *ccb, pdu_t *ppdu, pdu_t *rx_pdu)
748 {
749 pdu_header_t *pdu = &ppdu->pdu;
750
751 pdu->Opcode = IOP_Text_Request | OP_IMMEDIATE;
752 pdu->Flags = FLAG_FINAL;
753
754 mutex_enter(&conn->session->lock);
755 ccb->CmdSN = get_sernum(conn->session, ppdu);
756 mutex_exit(&conn->session->lock);
757
758 if (rx_pdu != NULL) {
759 pdu->p.text_req.TargetTransferTag =
760 rx_pdu->pdu.p.text_rsp.TargetTransferTag;
761 pdu->LUN = rx_pdu->pdu.LUN;
762 } else
763 pdu->p.text_req.TargetTransferTag = 0xffffffff;
764
765 pdu->p.text_req.CmdSN = htonl(ccb->CmdSN);
766 }
767
768
769 /*
770 * acknowledge_text:
771 * Acknowledge a continued login or text response.
772 *
773 * Parameter:
774 * conn The connection
775 * rx_pdu The received login/text response PDU
776 * tx_ccb The originally sent login/text request CCB
777 */
778
779 void
780 acknowledge_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
781 {
782 pdu_t *tx_pdu;
783
784 tx_pdu = get_pdu(conn, TRUE);
785 if (tx_pdu == NULL)
786 return;
787
788 if (rx_pdu != NULL &&
789 (rx_pdu->pdu.Opcode & OPCODE_MASK) == IOP_Login_Request)
790 init_login_pdu(conn, tx_ccb, tx_pdu, FALSE);
791 else
792 init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
793
794 setup_tx_uio(tx_pdu, 0, NULL, FALSE);
795 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
796 }
797
798
799 /*
800 * start_text_negotiation:
801 * Handle target request to negotiate (via asynch event)
802 *
803 * Parameter:
804 * conn The connection
805 */
806
807 void
808 start_text_negotiation(connection_t *conn)
809 {
810 pdu_t *pdu;
811 ccb_t *ccb;
812
813 ccb = get_ccb(conn, TRUE);
814 if (ccb == NULL)
815 return;
816 pdu = get_pdu(conn, TRUE);
817 if (pdu == NULL) {
818 free_ccb(ccb);
819 return;
820 }
821
822 if (init_text_parameters(conn, ccb)) {
823 free_ccb(ccb);
824 free_pdu(pdu);
825 return;
826 }
827
828 init_text_pdu(conn, ccb, pdu, NULL);
829 setup_tx_uio(pdu, 0, NULL, FALSE);
830 send_pdu(ccb, pdu, CCBDISP_FREE, PDUDISP_WAIT);
831 }
832
833
834 /*
835 * negotiate_text:
836 * Handle received text negotiation.
837 *
838 * Parameter:
839 * conn The connection
840 * rx_pdu The received text response PDU
841 * tx_ccb The original CCB
842 */
843
844 void
845 negotiate_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb)
846 {
847 int rc;
848 pdu_t *tx_pdu;
849
850 if (tx_ccb->flags & CCBF_SENDTARGET) {
851 if (!(rx_pdu->pdu.Flags & FLAG_FINAL)) {
852 handle_connection_error(conn, ISCSI_STATUS_PROTOCOL_ERROR,
853 LOGOUT_CONNECTION);
854 return;
855 }
856 /* transfer ownership of text to CCB */
857 tx_ccb->text_data = rx_pdu->temp_data;
858 tx_ccb->text_len = rx_pdu->temp_data_len;
859 rx_pdu->temp_data = NULL;
860 wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
861 } else {
862 if (!(rx_pdu->pdu.Flags & FLAG_FINAL))
863 tx_pdu = get_pdu(conn, TRUE);
864 else
865 tx_pdu = NULL;
866
867 rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu);
868 if (rc) {
869 if (tx_pdu != NULL)
870 free_pdu(tx_pdu);
871
872 handle_connection_error(conn, rc, LOGOUT_CONNECTION);
873 } else if (tx_pdu != NULL) {
874 init_text_pdu(conn, tx_ccb, tx_pdu, rx_pdu);
875 setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data,
876 FALSE);
877 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
878 } else {
879 set_negotiated_parameters(tx_ccb);
880 wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
881 }
882 }
883 }
884
885
886 /*
887 * send_send_targets:
888 * Send out a SendTargets text request.
889 * The result is stored in the fields in the session structure.
890 *
891 * Parameter:
892 * session The session
893 * key The text key to use
894 *
895 * Returns: 0 on success, else an error code.
896 */
897
898 int
899 send_send_targets(session_t *session, uint8_t *key)
900 {
901 ccb_t *ccb;
902 pdu_t *pdu;
903 int rc = 0;
904 connection_t *conn;
905
906 DEB(9, ("Send_send_targets\n"));
907
908 conn = assign_connection(session, TRUE);
909 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE)
910 return (conn != NULL && conn->terminating) ? conn->terminating
911 : ISCSI_STATUS_CONNECTION_FAILED;
912
913 ccb = get_ccb(conn, TRUE);
914 if (ccb == NULL)
915 return conn->terminating;
916 pdu = get_pdu(conn, TRUE);
917 if (pdu == NULL) {
918 free_ccb(ccb);
919 return conn->terminating;
920 }
921
922 ccb->flags |= CCBF_SENDTARGET;
923
924 if ((rc = assemble_send_targets(pdu, key)) != 0) {
925 free_ccb(ccb);
926 free_pdu(pdu);
927 return rc;
928 }
929
930 init_text_pdu(conn, ccb, pdu, NULL);
931
932 setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
933 send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_WAIT);
934
935 rc = ccb->status;
936 if (!rc) {
937 /* transfer ownership of data */
938 session->target_list = ccb->text_data;
939 session->target_list_len = ccb->text_len;
940 ccb->text_data = NULL;
941 }
942 free_ccb(ccb);
943 return rc;
944 }
945
946
947 /*
948 * send_nop_out:
949 * Send nop out request.
950 *
951 * Parameter:
952 * conn The connection
953 * rx_pdu The received Nop-In PDU
954 *
955 * Returns: 0 on success, else an error code.
956 */
957
958 int
959 send_nop_out(connection_t *conn, pdu_t *rx_pdu)
960 {
961 session_t *sess;
962 ccb_t *ccb;
963 pdu_t *ppdu;
964 pdu_header_t *pdu;
965 uint32_t sn;
966
967 if (rx_pdu != NULL) {
968 ccb = NULL;
969 ppdu = get_pdu(conn, TRUE);
970 if (ppdu == NULL)
971 return 1;
972 } else {
973 ccb = get_ccb(conn, FALSE);
974 if (ccb == NULL) {
975 DEBOUT(("Can't get CCB in send_nop_out\n"));
976 return 1;
977 }
978 ppdu = get_pdu(conn, FALSE);
979 if (ppdu == NULL) {
980 free_ccb(ccb);
981 DEBOUT(("Can't get PDU in send_nop_out\n"));
982 return 1;
983 }
984 }
985
986 pdu = &ppdu->pdu;
987 pdu->Flags = FLAG_FINAL;
988 pdu->Opcode = IOP_NOP_Out | OP_IMMEDIATE;
989
990 sess = conn->session;
991
992 mutex_enter(&sess->lock);
993 sn = get_sernum(sess, ppdu);
994 mutex_exit(&sess->lock);
995
996 if (rx_pdu != NULL) {
997 pdu->p.nop_out.TargetTransferTag =
998 rx_pdu->pdu.p.nop_in.TargetTransferTag;
999 pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
1000 pdu->p.nop_out.CmdSN = htonl(sn);
1001 pdu->LUN = rx_pdu->pdu.LUN;
1002 } else {
1003 pdu->p.nop_out.TargetTransferTag = 0xffffffff;
1004 pdu->InitiatorTaskTag = 0xffffffff;
1005 ccb->CmdSN = sn;
1006 pdu->p.nop_out.CmdSN = htonl(sn);
1007 }
1008
1009 DEBC(conn, 10, ("Send NOP_Out CmdSN=%d, rx_pdu=%p\n", sn, rx_pdu));
1010
1011 setup_tx_uio(ppdu, 0, NULL, FALSE);
1012 send_pdu(ccb, ppdu, (rx_pdu != NULL) ? CCBDISP_NOWAIT : CCBDISP_FREE,
1013 PDUDISP_FREE);
1014 return 0;
1015 }
1016
1017
1018 /*
1019 * snack_missing:
1020 * Send SNACK request for missing data.
1021 *
1022 * Parameter:
1023 * conn The connection
1024 * ccb The task's CCB (for Data NAK only)
1025 * type The SNACK type
1026 * BegRun The BegRun field
1027 * RunLength The RunLength field
1028 */
1029
1030 void
1031 snack_missing(connection_t *conn, ccb_t *ccb, uint8_t type,
1032 uint32_t BegRun, uint32_t RunLength)
1033 {
1034 pdu_t *ppdu;
1035 pdu_header_t *pdu;
1036
1037 ppdu = get_pdu(conn, TRUE);
1038 if (ppdu == NULL)
1039 return;
1040 pdu = &ppdu->pdu;
1041 pdu->Opcode = IOP_SNACK_Request;
1042 pdu->Flags = FLAG_FINAL | type;
1043
1044 pdu->InitiatorTaskTag = (type == SNACK_DATA_NAK) ? ccb->ITT : 0xffffffff;
1045 pdu->p.snack.TargetTransferTag = 0xffffffff;
1046 pdu->p.snack.BegRun = htonl(BegRun);
1047 pdu->p.snack.RunLength = htonl(RunLength);
1048
1049 ppdu->flags = PDUF_PRIORITY;
1050
1051 setup_tx_uio(ppdu, 0, NULL, FALSE);
1052 send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
1053 }
1054
1055
1056 /*
1057 * send_snack:
1058 * Send SNACK request.
1059 *
1060 * Parameter:
1061 * conn The connection
1062 * rx_pdu The received data in PDU
1063 * tx_ccb The original command CCB (required for Data ACK only)
1064 * type The SNACK type
1065 *
1066 * Returns: 0 on success, else an error code.
1067 */
1068
1069 void
1070 send_snack(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb, uint8_t type)
1071 {
1072 pdu_t *ppdu;
1073 pdu_header_t *pdu;
1074
1075 ppdu = get_pdu(conn, TRUE);
1076 if (ppdu == NULL)
1077 return;
1078 pdu = &ppdu->pdu;
1079 pdu->Opcode = IOP_SNACK_Request;
1080 pdu->Flags = FLAG_FINAL | type;
1081
1082 switch (type) {
1083 case SNACK_DATA_NAK:
1084 pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag;
1085 pdu->p.snack.TargetTransferTag = 0xffffffff;
1086 pdu->p.snack.BegRun = rx_pdu->pdu.p.data_in.DataSN;
1087 pdu->p.snack.RunLength = htonl(1);
1088 break;
1089
1090 case SNACK_STATUS_NAK:
1091 pdu->InitiatorTaskTag = 0xffffffff;
1092 pdu->p.snack.TargetTransferTag = 0xffffffff;
1093 pdu->p.snack.BegRun = rx_pdu->pdu.p.response.StatSN;
1094 pdu->p.snack.RunLength = htonl(1);
1095 break;
1096
1097 case SNACK_DATA_ACK:
1098 pdu->InitiatorTaskTag = 0xffffffff;
1099 pdu->p.snack.TargetTransferTag =
1100 rx_pdu->pdu.p.data_in.TargetTransferTag;
1101 pdu->p.snack.BegRun = tx_ccb->DataSN_buf.ExpSN;
1102 pdu->p.snack.RunLength = 0;
1103 break;
1104
1105 default:
1106 DEBOUT(("Invalid type %d in send_snack\n", type));
1107 return;
1108 }
1109
1110 pdu->LUN = rx_pdu->pdu.LUN;
1111
1112 ppdu->flags = PDUF_PRIORITY;
1113
1114 setup_tx_uio(ppdu, 0, NULL, FALSE);
1115 send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE);
1116 }
1117
1118
1119 /*
1120 * send_login:
1121 * Send login request.
1122 *
1123 * Parameter:
1124 * conn The connection
1125 * par The login parameters (for negotiation)
1126 *
1127 * Returns: 0 on success, else an error code.
1128 */
1129
1130 int
1131 send_login(connection_t *conn)
1132 {
1133 ccb_t *ccb;
1134 pdu_t *pdu;
1135 int rc;
1136
1137 DEBC(conn, 9, ("Send_login\n"));
1138 ccb = get_ccb(conn, TRUE);
1139 /* only if terminating (which couldn't possibly happen here, but...) */
1140 if (ccb == NULL)
1141 return conn->terminating;
1142 pdu = get_pdu(conn, TRUE);
1143 if (pdu == NULL) {
1144 free_ccb(ccb);
1145 return conn->terminating;
1146 }
1147
1148 if ((rc = assemble_login_parameters(conn, ccb, pdu)) <= 0) {
1149 init_login_pdu(conn, ccb, pdu, !rc);
1150 setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
1151 send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_FREE);
1152 rc = ccb->status;
1153 } else {
1154 free_pdu(pdu);
1155 }
1156 free_ccb(ccb);
1157 return rc;
1158 }
1159
1160
1161 /*
1162 * send_logout:
1163 * Send logout request.
1164 * NOTE: This function does not wait for the logout to complete.
1165 *
1166 * Parameter:
1167 * conn The connection
1168 * refconn The referenced connection
1169 * reason The reason code
1170 * wait Wait for completion if TRUE
1171 *
1172 * Returns: 0 on success (logout sent), else an error code.
1173 */
1174
1175 int
1176 send_logout(connection_t *conn, connection_t *refconn, int reason,
1177 bool wait)
1178 {
1179 ccb_t *ccb;
1180 pdu_t *ppdu;
1181 pdu_header_t *pdu;
1182
1183 DEBC(conn, 5, ("Send_logout\n"));
1184 ccb = get_ccb(conn, TRUE);
1185 /* can only happen if terminating... */
1186 if (ccb == NULL)
1187 return conn->terminating;
1188 ppdu = get_pdu(conn, TRUE);
1189 if (ppdu == NULL) {
1190 free_ccb(ccb);
1191 return conn->terminating;
1192 }
1193
1194 pdu = &ppdu->pdu;
1195 pdu->Opcode = IOP_Logout_Request | OP_IMMEDIATE;
1196
1197 pdu->Flags = FLAG_FINAL | reason;
1198 ccb->CmdSN = conn->session->CmdSN;
1199 pdu->p.logout_req.CmdSN = htonl(ccb->CmdSN);
1200 if (reason > 0)
1201 pdu->p.logout_req.CID = htons(refconn->id);
1202
1203 ccb->par = refconn;
1204 if (refconn != conn) {
1205 ccb->flags |= CCBF_OTHERCONN;
1206 } else {
1207 conn->state = ST_LOGOUT_SENT;
1208 conn->loggedout = LOGOUT_SENT;
1209 }
1210
1211 setup_tx_uio(ppdu, 0, NULL, FALSE);
1212
1213 send_pdu(ccb, ppdu, (wait) ? CCBDISP_WAIT : CCBDISP_FREE, PDUDISP_FREE);
1214
1215 if (wait) {
1216 int rc = ccb->status;
1217 free_ccb (ccb);
1218 return rc;
1219 }
1220 return 0;
1221 }
1222
1223
1224 /*
1225 * send_task_management:
1226 * Send task management request.
1227 *
1228 * Parameter:
1229 * conn The connection
1230 * ref_ccb The referenced command (NULL if none)
1231 * xs The scsipi command structure (NULL if not a scsipi request)
1232 * function The function code
1233 *
1234 * Returns: 0 on success, else an error code.
1235 */
1236
1237 int
1238 send_task_management(connection_t *conn, ccb_t *ref_ccb, struct scsipi_xfer *xs,
1239 int function)
1240 {
1241 ccb_t *ccb;
1242 pdu_t *ppdu;
1243 pdu_header_t *pdu;
1244
1245 DEBC(conn, 5, ("Send_task_management, ref_ccb=%p, func = %d\n",
1246 ref_ccb, function));
1247
1248 if (function == TASK_REASSIGN && conn->session->ErrorRecoveryLevel < 2)
1249 return ISCSI_STATUS_CANT_REASSIGN;
1250
1251 ccb = get_ccb(conn, xs == NULL);
1252 /* can only happen if terminating... */
1253 if (ccb == NULL)
1254 return conn->terminating;
1255 ppdu = get_pdu(conn, xs == NULL);
1256 if (ppdu == NULL) {
1257 free_ccb(ccb);
1258 return conn->terminating;
1259 }
1260
1261 ccb->xs = xs;
1262
1263 pdu = &ppdu->pdu;
1264 pdu->Opcode = IOP_SCSI_Task_Management | OP_IMMEDIATE;
1265 pdu->Flags = FLAG_FINAL | function;
1266
1267 ccb->CmdSN = conn->session->CmdSN;
1268 pdu->p.task_req.CmdSN = htonl(ccb->CmdSN);
1269
1270 if (ref_ccb != NULL) {
1271 pdu->p.task_req.ReferencedTaskTag = ref_ccb->ITT;
1272 pdu->p.task_req.RefCmdSN = htonl(ref_ccb->CmdSN);
1273 pdu->p.task_req.ExpDataSN = htonl(ref_ccb->DataSN_buf.ExpSN);
1274 } else
1275 pdu->p.task_req.ReferencedTaskTag = 0xffffffff;
1276
1277 ppdu->flags |= PDUF_PRIORITY;
1278
1279 setup_tx_uio(ppdu, 0, NULL, FALSE);
1280 send_pdu(ccb, ppdu, (xs) ? CCBDISP_SCSIPI : CCBDISP_WAIT, PDUDISP_FREE);
1281
1282 if (xs == NULL) {
1283 int rc = ccb->status;
1284 free_ccb(ccb);
1285 return rc;
1286 }
1287 return 0;
1288 }
1289
1290
1291 /*
1292 * send_data_out:
1293 * Send data to target in response to an R2T or as unsolicited data.
1294 *
1295 * Parameter:
1296 * conn The connection
1297 * rx_pdu The received R2T PDU (NULL if unsolicited)
1298 * tx_ccb The originally sent command CCB
1299 * waitok Whether it's OK to wait for an available PDU or not
1300 */
1301
1302 int
1303 send_data_out(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb,
1304 ccb_disp_t disp, bool waitok)
1305 {
1306 pdu_header_t *pdu;
1307 uint32_t totlen, len, offs, sn;
1308 pdu_t *tx_pdu;
1309
1310 KASSERT(conn->max_transfer != 0);
1311
1312 if (rx_pdu) {
1313 offs = ntohl(rx_pdu->pdu.p.r2t.BufferOffset);
1314 totlen = ntohl(rx_pdu->pdu.p.r2t.DesiredDataTransferLength);
1315 } else {
1316 offs = conn->max_firstimmed;
1317 totlen = min(conn->max_firstdata - offs, tx_ccb->data_len - offs);
1318 }
1319 sn = 0;
1320
1321 while (totlen) {
1322 len = min(totlen, conn->max_transfer);
1323
1324 tx_pdu = get_pdu(conn, waitok);
1325 if (tx_pdu == NULL) {
1326 DEBC(conn, 5, ("No PDU in send_data_out\n"));
1327
1328 tx_ccb->disp = disp;
1329 tx_ccb->status = ISCSI_STATUS_NO_RESOURCES;
1330 handle_connection_error(conn, ISCSI_STATUS_NO_RESOURCES, NO_LOGOUT);
1331
1332 return ISCSI_STATUS_NO_RESOURCES;
1333 }
1334
1335 totlen -= len;
1336 pdu = &tx_pdu->pdu;
1337 pdu->Opcode = IOP_SCSI_Data_out;
1338 if (!totlen)
1339 pdu->Flags = FLAG_FINAL;
1340
1341 if (rx_pdu != NULL)
1342 pdu->p.data_out.TargetTransferTag =
1343 rx_pdu->pdu.p.r2t.TargetTransferTag;
1344 else
1345 pdu->p.data_out.TargetTransferTag = 0xffffffff;
1346 pdu->p.data_out.BufferOffset = htonl(offs);
1347 pdu->p.data_out.DataSN = htonl(sn);
1348
1349 DEBC(conn, 10, ("Send DataOut: DataSN %d, len %d offs %x totlen %d\n",
1350 sn, len, offs, totlen));
1351
1352 setup_tx_uio(tx_pdu, len, tx_ccb->data_ptr + offs, FALSE);
1353
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 return;
1487 }
1488
1489 if (xs->xs_control & XS_CTL_RESET) {
1490 if (send_task_management(conn, NULL, xs, TARGET_WARM_RESET)) {
1491 xs->error = XS_SELTIMEOUT;
1492 scsipi_done(xs);
1493 }
1494 return;
1495 }
1496
1497 ccb = get_ccb(conn, waitok);
1498 if (ccb == NULL) {
1499 xs->error = XS_BUSY;
1500 DEBC(conn, 5, ("No CCB in run_xfer, %d in use.\n", conn->usecount));
1501 scsipi_done(xs);
1502 return;
1503 }
1504 /* copy parameters into CCB for easier access */
1505 ccb->xs = xs;
1506
1507 ccb->data_in = (xs->xs_control & XS_CTL_DATA_IN) != 0;
1508 ccb->data_len = (uint32_t) xs->datalen;
1509 ccb->data_ptr = xs->data;
1510
1511 ccb->sense_len_req = sizeof(xs->sense.scsi_sense);
1512 ccb->sense_ptr = &xs->sense;
1513
1514 ccb->lun = ((uint64_t) (uint8_t) xs->xs_periph->periph_lun) << 48;
1515 ccb->cmd = (uint8_t *) xs->cmd;
1516 ccb->cmdlen = xs->cmdlen;
1517 DEB(10, ("RunXfer: Periph_lun = %d, cmd[1] = %x, cmdlen = %d\n",
1518 xs->xs_periph->periph_lun, ccb->cmd[1], xs->cmdlen));
1519
1520 ccb->ITT |= xs->xs_tag_id << 24;
1521 switch (xs->xs_tag_type) {
1522 case MSG_ORDERED_Q_TAG:
1523 ccb->tag = ATTR_ORDERED;
1524 break;
1525 case MSG_SIMPLE_Q_TAG:
1526 ccb->tag = ATTR_SIMPLE;
1527 break;
1528 case MSG_HEAD_OF_Q_TAG:
1529 ccb->tag = ATTR_HEAD_OF_QUEUE;
1530 break;
1531 default:
1532 ccb->tag = 0;
1533 break;
1534 }
1535
1536 #ifdef LUN_1
1537 ccb->lun += 0x1000000000000LL;
1538 ccb->cmd[1] += 0x10;
1539 #endif
1540 send_command(ccb, CCBDISP_SCSIPI, waitok, FALSE);
1541 }
1542
1543
1544 #ifndef ISCSI_MINIMAL
1545 /*
1546 * send_io_command:
1547 * Handle a SCSI io command request from user space.
1548 *
1549 * Parameter:
1550 * session The session
1551 * lun The LUN to use
1552 * req The SCSI request block
1553 * immed Immediate command if TRUE
1554 * conn_id Assign to this connection ID if nonzero
1555 */
1556
1557 int
1558 send_io_command(session_t *session, uint64_t lun, scsireq_t *req,
1559 bool immed, uint32_t conn_id)
1560 {
1561 ccb_t *ccb;
1562 connection_t *conn;
1563 int rc;
1564
1565 DEB(9, ("IoCommand: lun=%x, datalen=%d, cmdlen=%d, immed=%d, cid=%d\n",
1566 (int) lun, (int) req->datalen, (int) req->cmdlen, immed, conn_id));
1567
1568 conn = (conn_id) ? find_connection(session, conn_id)
1569 : assign_connection(session, TRUE);
1570
1571 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
1572 DEBOUT(("io_command on dead connection (state = %d)\n",
1573 (conn != NULL) ? conn->state : -1));
1574 return ISCSI_STATUS_INVALID_CONNECTION_ID;
1575 }
1576
1577 ccb = get_ccb(conn, TRUE);
1578 if (ccb == NULL) {
1579 DEBOUT(("No CCB in io_command\n"));
1580 return ISCSI_STATUS_NO_RESOURCES;
1581 }
1582
1583 ccb->data_in = (req->flags & SCCMD_READ) != 0;
1584 ccb->data_len = (uint32_t) req->datalen;
1585 ccb->data_ptr = req->databuf;
1586
1587 ccb->sense_len_req = req->senselen;
1588 ccb->sense_ptr = &req->sense;
1589
1590 ccb->lun = lun;
1591 ccb->cmd = (uint8_t *) req->cmd;
1592 ccb->cmdlen = req->cmdlen;
1593 DEBC(conn, 10, ("IoCommand: cmd[1] = %x, cmdlen = %d\n",
1594 ccb->cmd[1], ccb->cmdlen));
1595
1596 send_command(ccb, CCBDISP_WAIT, TRUE, immed);
1597
1598 rc = ccb->status;
1599
1600 req->senselen_used = ccb->sense_len_got;
1601 req->datalen_used = req->datalen - ccb->residual;
1602
1603 free_ccb(ccb);
1604
1605 return rc;
1606 }
1607 #endif
1608
1609
1610 /*****************************************************************************
1611 * Timeout handlers
1612 *****************************************************************************/
1613 /*
1614 * connection_timeout:
1615 * Handle prolonged silence on a connection by checking whether
1616 * it's still alive.
1617 * This has the side effect of discovering missing status or lost commands
1618 * before those time out.
1619 *
1620 * Parameter:
1621 * conn The connection
1622 */
1623
1624 void
1625 connection_timeout(connection_t *conn)
1626 {
1627
1628 if (++conn->num_timeouts > MAX_CONN_TIMEOUTS)
1629 handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, NO_LOGOUT);
1630 else {
1631 if (conn->state == ST_FULL_FEATURE)
1632 send_nop_out(conn, NULL);
1633
1634 connection_timeout_start(conn, CONNECTION_TIMEOUT);
1635 }
1636 }
1637
1638 /*
1639 * ccb_timeout:
1640 * Handle timeout of a sent command.
1641 *
1642 * Parameter:
1643 * ccb The CCB
1644 */
1645
1646 void
1647 ccb_timeout(ccb_t *ccb)
1648 {
1649 connection_t *conn = ccb->connection;
1650
1651 ccb->total_tries++;
1652
1653 DEBC(conn, 0, ("ccb_timeout: num=%d total=%d disp=%d\n",
1654 ccb->num_timeouts+1, ccb->total_tries, ccb->disp));
1655
1656 if (++ccb->num_timeouts > MAX_CCB_TIMEOUTS ||
1657 ccb->total_tries > MAX_CCB_TRIES ||
1658 ccb->disp <= CCBDISP_FREE ||
1659 !ccb->session->ErrorRecoveryLevel) {
1660
1661 wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
1662 handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION);
1663 } else {
1664 if (ccb->data_in && ccb->xfer_len < ccb->data_len) {
1665 /* request resend of all missing data */
1666 snack_missing(conn, ccb, SNACK_DATA_NAK, 0, 0);
1667 } else {
1668 /* request resend of all missing status */
1669 snack_missing(conn, NULL, SNACK_STATUS_NAK, 0, 0);
1670 }
1671 ccb_timeout_start(ccb, COMMAND_TIMEOUT);
1672 }
1673 }
1674
1675