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