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