1 /*-
2 * Copyright (c) 2005-2011 Daniel Braniss <danny@cs.huji.ac.il>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: releng/10.0/sys/dev/iscsi_initiator/iscsivar.h 234233 2012-04-13 18:21:56Z jpaetzel $
27 */
28
29 /*
30 | $Id: iscsivar.h 743 2009-08-08 10:54:53Z danny $
31 */
32 #define ISCSI_MAX_LUNS 128 // don't touch this
33 #if ISCSI_MAX_LUNS > 8
34 /*
35 | for this to work
36 | sysctl kern.cam.cam_srch_hi=1
37 */
38 #endif
39
40 #ifndef ISCSI_INITIATOR_DEBUG
41 #define ISCSI_INITIATOR_DEBUG 1
42 #endif
43
44 #ifdef ISCSI_INITIATOR_DEBUG
45 extern int iscsi_debug;
46 #define debug(level, fmt, args...) do {if(level <= iscsi_debug)\
47 printf("%s: " fmt "\n", __func__ , ##args);} while(0)
48 #define sdebug(level, fmt, args...) do {if(level <= iscsi_debug)\
49 printf("%d] %s: " fmt "\n", sp->sid, __func__ , ##args);} while(0)
50 #define debug_called(level) do {if(level <= iscsi_debug)\
51 printf("%s: called\n", __func__);} while(0)
52 #else
53 #define debug(level, fmt, args...)
54 #define debug_called(level)
55 #define sdebug(level, fmt, args...)
56 #endif /* ISCSI_INITIATOR_DEBUG */
57
58 #define xdebug(fmt, args...) printf(">>> %s: " fmt "\n", __func__ , ##args)
59
60 #define MAX_SESSIONS ISCSI_MAX_TARGETS
61 #define MAX_PDUS (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary
62
63 typedef uint32_t digest_t(const void *, int len, uint32_t ocrc);
64
65 MALLOC_DECLARE(M_ISCSI);
66 MALLOC_DECLARE(M_ISCSIBUF);
67
68 #define ISOK2DIG(dig, pp) ((dig != NULL) && ((pp->ipdu.bhs.opcode & 0x1f) != ISCSI_LOGIN_CMD))
69
70 #ifndef BIT
71 #define BIT(n) (1 <<(n))
72 #endif
73
74 #define ISC_SM_RUN BIT(0)
75 #define ISC_SM_RUNNING BIT(1)
76
77 #define ISC_LINK_UP BIT(2)
78 #define ISC_CON_RUN BIT(3)
79 #define ISC_CON_RUNNING BIT(4)
80 #define ISC_KILL BIT(5)
81 #define ISC_OQNOTEMPTY BIT(6)
82 #define ISC_OWAITING BIT(7)
83 #define ISC_FFPHASE BIT(8)
84
85 #define ISC_CAMDEVS BIT(9)
86 #define ISC_SCANWAIT BIT(10)
87
88 #define ISC_MEMWAIT BIT(11)
89 #define ISC_SIGNALED BIT(12)
90
91 #define ISC_HOLD BIT(15)
92 #define ISC_HOLDED BIT(16)
93
94 #define ISC_SHUTDOWN BIT(31)
95
96 /*
97 | some stats
98 */
99 struct i_stats {
100 int npdu; // number of pdus malloc'ed.
101 int nrecv; // unprocessed received pdus
102 int nsent; // sent pdus
103
104 int nrsp, max_rsp;
105 int nrsv, max_rsv;
106 int ncsnd, max_csnd;
107 int nisnd, max_isnd;
108 int nwsnd, max_wsnd;
109 int nhld, max_hld;
110
111 struct bintime t_sent;
112 struct bintime t_recv;
113 };
114
115 /*
116 | one per 'session'
117 */
118
119 typedef TAILQ_HEAD(, pduq) queue_t;
120
121 typedef struct isc_session {
122 TAILQ_ENTRY(isc_session) sp_link;
123 int flags;
124 struct cdev *dev;
125 struct socket *soc;
126 struct file *fp;
127 struct thread *td;
128
129 struct proc *proc; // the userland process
130 int signal;
131 struct proc *soc_proc;
132 struct proc *stp; // the sm thread
133
134 struct isc_softc *isc;
135
136 digest_t *hdrDigest; // the digest alg. if any
137 digest_t *dataDigest; // the digest alg. if any
138
139 int sid; // Session ID
140 sn_t sn; // sequence number stuff;
141 int cws; // current window size
142
143 int target_nluns; // this and target_lun are
144 // hopefully temporal till I
145 // figure out a better way.
146 int target_lun[ISCSI_MAX_LUNS/(sizeof(int)*8) + 1];
147
148 struct mtx rsp_mtx;
149 struct mtx rsv_mtx;
150 struct mtx snd_mtx;
151 struct mtx hld_mtx;
152 struct mtx io_mtx;
153 queue_t rsp;
154 queue_t rsv;
155 queue_t csnd;
156 queue_t isnd;
157 queue_t wsnd;
158 queue_t hld;
159
160 isc_opt_t opt; // negotiable values
161
162 struct i_stats stats;
163 bhs_t bhs;
164 struct uio uio;
165 struct iovec iov;
166 /*
167 | cam stuff
168 */
169 struct cam_sim *cam_sim;
170 struct cam_path *cam_path;
171 struct mtx cam_mtx;
172 /*
173 | sysctl stuff
174 */
175 struct sysctl_ctx_list clist;
176 struct sysctl_oid *oid;
177 int douio; //XXX: turn on/off uio on read
178 } isc_session_t;
179
180 typedef struct pduq {
181 TAILQ_ENTRY(pduq) pq_link;
182
183 caddr_t buf;
184 u_int len; // the total length of the pdu
185 pdu_t pdu;
186 union ccb *ccb;
187
188 struct uio uio;
189 struct iovec iov[5]; // XXX: careful ...
190 struct mbuf *mp;
191 struct bintime ts;
192 queue_t *pduq;
193 } pduq_t;
194 /*
195 */
196 struct isc_softc {
197 struct mtx isc_mtx;
198 TAILQ_HEAD(,isc_session) isc_sess;
199 int nsess;
200 struct cdev *dev;
201 char isid[6]; // Initiator Session ID (48 bits)
202 struct unrhdr *unit;
203 struct sx unit_sx;
204
205 uma_zone_t pdu_zone; // pool of free pdu's
206 TAILQ_HEAD(,pduq) freepdu;
207
208 #ifdef ISCSI_INITIATOR_DEBUG
209 int npdu_alloc, npdu_max; // for instrumentation
210 #endif
211 #ifdef DO_EVENTHANDLER
212 eventhandler_tag eh;
213 #endif
214 /*
215 | sysctl stuff
216 */
217 struct sysctl_ctx_list clist;
218 struct sysctl_oid *oid;
219 };
220
221 #ifdef ISCSI_INITIATOR_DEBUG
222 extern struct mtx iscsi_dbg_mtx;
223 #endif
224
225 void isc_start_receiver(isc_session_t *sp);
226 void isc_stop_receiver(isc_session_t *sp);
227
228 int isc_sendPDU(isc_session_t *sp, pduq_t *pq);
229 int isc_qout(isc_session_t *sp, pduq_t *pq);
230 int i_prepPDU(isc_session_t *sp, pduq_t *pq);
231
232 int ism_fullfeature(struct cdev *dev, int flag);
233
234 int i_pdu_flush(isc_session_t *sc);
235 int i_setopt(isc_session_t *sp, isc_opt_t *opt);
236 void i_freeopt(isc_opt_t *opt);
237
238 int ic_init(isc_session_t *sp);
239 void ic_destroy(isc_session_t *sp);
240 void ic_lost_target(isc_session_t *sp, int target);
241 int ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp);
242
243 void ism_recv(isc_session_t *sp, pduq_t *pq);
244 int ism_start(isc_session_t *sp);
245 void ism_restart(isc_session_t *sp);
246 void ism_stop(isc_session_t *sp);
247
248 int scsi_encap(struct cam_sim *sim, union ccb *ccb);
249 int scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
250 void iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
251 void iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
252 void iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq);
253 void iscsi_async(isc_session_t *sp, pduq_t *pq);
254 void iscsi_cleanup(isc_session_t *sp);
255 int iscsi_requeue(isc_session_t *sp);
256
257 // Serial Number Arithmetic
258 #define _MAXINCR 0x7FFFFFFF // 2 ^ 31 - 1
259 #define SNA_GT(i1, i2) ((i1 != i2) && (\
260 (i1 < i2 && i2 - i1 > _MAXINCR) ||\
261 (i1 > i2 && i1 - i2 < _MAXINCR))?1: 0)
262
263 /*
264 | inlines
265 */
266 #ifdef _CAM_CAM_XPT_SIM_H
267
268 #if __FreeBSD_version < 600000
269 #define CAM_LOCK(arg)
270 #define CAM_ULOCK(arg)
271
272 static __inline void
273 XPT_DONE(isc_session_t *sp, union ccb *ccb)
274 {
275 mtx_lock(&Giant);
276 xpt_done(ccb);
277 mtx_unlock(&Giant);
278 }
279 #elif __FreeBSD_version >= 700000
280 #define CAM_LOCK(arg) mtx_lock(&arg->cam_mtx)
281 #define CAM_UNLOCK(arg) mtx_unlock(&arg->cam_mtx)
282
283 static __inline void
284 XPT_DONE(isc_session_t *sp, union ccb *ccb)
285 {
286 CAM_LOCK(sp);
287 xpt_done(ccb);
288 CAM_UNLOCK(sp);
289 }
290 #else
291 //__FreeBSD_version >= 600000
292 #define CAM_LOCK(arg)
293 #define CAM_UNLOCK(arg)
294 #define XPT_DONE(ignore, arg) xpt_done(arg)
295 #endif
296
297 #endif /* _CAM_CAM_XPT_SIM_H */
298
299 static __inline pduq_t *
300 pdu_alloc(struct isc_softc *isc, int wait)
301 {
302 pduq_t *pq;
303
304 pq = (pduq_t *)uma_zalloc(isc->pdu_zone, wait /* M_WAITOK or M_NOWAIT*/);
305 if(pq == NULL) {
306 debug(7, "out of mem");
307 return NULL;
308 }
309 #ifdef ISCSI_INITIATOR_DEBUG
310 mtx_lock(&iscsi_dbg_mtx);
311 isc->npdu_alloc++;
312 if(isc->npdu_alloc > isc->npdu_max)
313 isc->npdu_max = isc->npdu_alloc;
314 mtx_unlock(&iscsi_dbg_mtx);
315 #endif
316 memset(pq, 0, sizeof(pduq_t));
317
318 return pq;
319 }
320
321 static __inline void
322 pdu_free(struct isc_softc *isc, pduq_t *pq)
323 {
324 if(pq->mp)
325 m_freem(pq->mp);
326 #ifdef NO_USE_MBUF
327 if(pq->buf != NULL)
328 free(pq->buf, M_ISCSIBUF);
329 #endif
330 uma_zfree(isc->pdu_zone, pq);
331 #ifdef ISCSI_INITIATOR_DEBUG
332 mtx_lock(&iscsi_dbg_mtx);
333 isc->npdu_alloc--;
334 mtx_unlock(&iscsi_dbg_mtx);
335 #endif
336 }
337
338 static __inline void
339 i_nqueue_rsp(isc_session_t *sp, pduq_t *pq)
340 {
341 mtx_lock(&sp->rsp_mtx);
342 if(++sp->stats.nrsp > sp->stats.max_rsp)
343 sp->stats.max_rsp = sp->stats.nrsp;
344 TAILQ_INSERT_TAIL(&sp->rsp, pq, pq_link);
345 mtx_unlock(&sp->rsp_mtx);
346 }
347
348 static __inline pduq_t *
349 i_dqueue_rsp(isc_session_t *sp)
350 {
351 pduq_t *pq;
352
353 mtx_lock(&sp->rsp_mtx);
354 if((pq = TAILQ_FIRST(&sp->rsp)) != NULL) {
355 sp->stats.nrsp--;
356 TAILQ_REMOVE(&sp->rsp, pq, pq_link);
357 }
358 mtx_unlock(&sp->rsp_mtx);
359
360 return pq;
361 }
362
363 static __inline void
364 i_nqueue_rsv(isc_session_t *sp, pduq_t *pq)
365 {
366 mtx_lock(&sp->rsv_mtx);
367 if(++sp->stats.nrsv > sp->stats.max_rsv)
368 sp->stats.max_rsv = sp->stats.nrsv;
369 TAILQ_INSERT_TAIL(&sp->rsv, pq, pq_link);
370 mtx_unlock(&sp->rsv_mtx);
371 }
372
373 static __inline pduq_t *
374 i_dqueue_rsv(isc_session_t *sp)
375 {
376 pduq_t *pq;
377
378 mtx_lock(&sp->rsv_mtx);
379 if((pq = TAILQ_FIRST(&sp->rsv)) != NULL) {
380 sp->stats.nrsv--;
381 TAILQ_REMOVE(&sp->rsv, pq, pq_link);
382 }
383 mtx_unlock(&sp->rsv_mtx);
384
385 return pq;
386 }
387
388 static __inline void
389 i_nqueue_csnd(isc_session_t *sp, pduq_t *pq)
390 {
391 mtx_lock(&sp->snd_mtx);
392 if(++sp->stats.ncsnd > sp->stats.max_csnd)
393 sp->stats.max_csnd = sp->stats.ncsnd;
394 TAILQ_INSERT_TAIL(&sp->csnd, pq, pq_link);
395 mtx_unlock(&sp->snd_mtx);
396 }
397
398 static __inline pduq_t *
399 i_dqueue_csnd(isc_session_t *sp)
400 {
401 pduq_t *pq;
402
403 mtx_lock(&sp->snd_mtx);
404 if((pq = TAILQ_FIRST(&sp->csnd)) != NULL) {
405 sp->stats.ncsnd--;
406 TAILQ_REMOVE(&sp->csnd, pq, pq_link);
407 }
408 mtx_unlock(&sp->snd_mtx);
409
410 return pq;
411 }
412
413 static __inline void
414 i_nqueue_isnd(isc_session_t *sp, pduq_t *pq)
415 {
416 mtx_lock(&sp->snd_mtx);
417 if(++sp->stats.nisnd > sp->stats.max_isnd)
418 sp->stats.max_isnd = sp->stats.nisnd;
419 TAILQ_INSERT_TAIL(&sp->isnd, pq, pq_link);
420 mtx_unlock(&sp->snd_mtx);
421 }
422
423 static __inline pduq_t *
424 i_dqueue_isnd(isc_session_t *sp)
425 {
426 pduq_t *pq;
427
428 mtx_lock(&sp->snd_mtx);
429 if((pq = TAILQ_FIRST(&sp->isnd)) != NULL) {
430 sp->stats.nisnd--;
431 TAILQ_REMOVE(&sp->isnd, pq, pq_link);
432 }
433 mtx_unlock(&sp->snd_mtx);
434
435 return pq;
436 }
437
438 static __inline void
439 i_nqueue_wsnd(isc_session_t *sp, pduq_t *pq)
440 {
441 mtx_lock(&sp->snd_mtx);
442 if(++sp->stats.nwsnd > sp->stats.max_wsnd)
443 sp->stats.max_wsnd = sp->stats.nwsnd;
444 TAILQ_INSERT_TAIL(&sp->wsnd, pq, pq_link);
445 mtx_unlock(&sp->snd_mtx);
446 }
447
448 static __inline pduq_t *
449 i_dqueue_wsnd(isc_session_t *sp)
450 {
451 pduq_t *pq;
452
453 mtx_lock(&sp->snd_mtx);
454 if((pq = TAILQ_FIRST(&sp->wsnd)) != NULL) {
455 sp->stats.nwsnd--;
456 TAILQ_REMOVE(&sp->wsnd, pq, pq_link);
457 }
458 mtx_unlock(&sp->snd_mtx);
459
460 return pq;
461 }
462
463 static __inline pduq_t *
464 i_dqueue_snd(isc_session_t *sp, int which)
465 {
466 pduq_t *pq;
467
468 pq = NULL;
469 mtx_lock(&sp->snd_mtx);
470 if((which & BIT(0)) && (pq = TAILQ_FIRST(&sp->isnd)) != NULL) {
471 sp->stats.nisnd--;
472 TAILQ_REMOVE(&sp->isnd, pq, pq_link);
473 pq->pduq = &sp->isnd; // remember where you came from
474 } else
475 if((which & BIT(1)) && (pq = TAILQ_FIRST(&sp->wsnd)) != NULL) {
476 sp->stats.nwsnd--;
477 TAILQ_REMOVE(&sp->wsnd, pq, pq_link);
478 pq->pduq = &sp->wsnd; // remember where you came from
479 } else
480 if((which & BIT(2)) && (pq = TAILQ_FIRST(&sp->csnd)) != NULL) {
481 sp->stats.ncsnd--;
482 TAILQ_REMOVE(&sp->csnd, pq, pq_link);
483 pq->pduq = &sp->csnd; // remember where you came from
484 }
485 mtx_unlock(&sp->snd_mtx);
486
487 return pq;
488 }
489
490 static __inline void
491 i_rqueue_pdu(isc_session_t *sp, pduq_t *pq)
492 {
493 mtx_lock(&sp->snd_mtx);
494 KASSERT(pq->pduq != NULL, ("pq->pduq is NULL"));
495 TAILQ_INSERT_TAIL(pq->pduq, pq, pq_link);
496 mtx_unlock(&sp->snd_mtx);
497 }
498
499 /*
500 | Waiting for ACK (or something :-)
501 */
502 static __inline void
503 i_nqueue_hld(isc_session_t *sp, pduq_t *pq)
504 {
505 getbintime(&pq->ts);
506 mtx_lock(&sp->hld_mtx);
507 if(++sp->stats.nhld > sp->stats.max_hld)
508 sp->stats.max_hld = sp->stats.nhld;
509 TAILQ_INSERT_TAIL(&sp->hld, pq, pq_link);
510 mtx_unlock(&sp->hld_mtx);
511 return;
512 }
513
514 static __inline void
515 i_remove_hld(isc_session_t *sp, pduq_t *pq)
516 {
517 mtx_lock(&sp->hld_mtx);
518 sp->stats.nhld--;
519 TAILQ_REMOVE(&sp->hld, pq, pq_link);
520 mtx_unlock(&sp->hld_mtx);
521 }
522
523 static __inline pduq_t *
524 i_dqueue_hld(isc_session_t *sp)
525 {
526 pduq_t *pq;
527
528 mtx_lock(&sp->hld_mtx);
529 if((pq = TAILQ_FIRST(&sp->hld)) != NULL) {
530 sp->stats.nhld--;
531 TAILQ_REMOVE(&sp->hld, pq, pq_link);
532 }
533 mtx_unlock(&sp->hld_mtx);
534
535 return pq;
536 }
537
538 static __inline pduq_t *
539 i_search_hld(isc_session_t *sp, int itt, int keep)
540 {
541 pduq_t *pq, *tmp;
542
543 pq = NULL;
544
545 mtx_lock(&sp->hld_mtx);
546 TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) {
547 if(pq->pdu.ipdu.bhs.itt == itt) {
548 if(!keep) {
549 sp->stats.nhld--;
550 TAILQ_REMOVE(&sp->hld, pq, pq_link);
551 }
552 break;
553 }
554 }
555 mtx_unlock(&sp->hld_mtx);
556
557 return pq;
558 }
559
560 static __inline void
561 i_acked_hld(isc_session_t *sp, pdu_t *op)
562 {
563 pduq_t *pq, *tmp;
564 u_int exp = sp->sn.expCmd;
565
566 pq = NULL;
567 mtx_lock(&sp->hld_mtx);
568 TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) {
569 if((op && op->ipdu.bhs.itt == pq->pdu.ipdu.bhs.itt)
570 || (pq->ccb == NULL
571 && (pq->pdu.ipdu.bhs.opcode != ISCSI_WRITE_DATA)
572 && SNA_GT(exp, ntohl(pq->pdu.ipdu.bhs.ExpStSN)))) {
573 sp->stats.nhld--;
574 TAILQ_REMOVE(&sp->hld, pq, pq_link);
575 pdu_free(sp->isc, pq);
576 }
577 }
578 mtx_unlock(&sp->hld_mtx);
579 }
580
581 static __inline void
582 i_mbufcopy(struct mbuf *mp, caddr_t dp, int len)
583 {
584 struct mbuf *m;
585 caddr_t bp;
586
587 for(m = mp; m != NULL; m = m->m_next) {
588 bp = mtod(m, caddr_t);
589 /*
590 | the pdu is word (4 octed) aligned
591 | so len <= packet
592 */
593 memcpy(dp, bp, MIN(len, m->m_len));
594 dp += m->m_len;
595 len -= m->m_len;
596 if(len <= 0)
597 break;
598 }
599 }
Cache object: ccef6cfba2c0dbfcb39c4f33a747db96
|