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