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