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