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