1 /*-
2 * Copyright (c) 2005-2008 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: src/sys/dev/iscsi/initiator/iscsi.c,v 1.4 2008/11/25 07:17:11 scottl Exp $
27 */
28 /*
29 | iSCSI
30 | $Id: iscsi.c,v 1.35 2007/04/22 08:58:29 danny Exp danny $
31 */
32
33 #include "opt_iscsi_initiator.h"
34
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/conf.h>
39 #include <sys/bus.h>
40 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/ctype.h>
43 #include <sys/errno.h>
44 #include <sys/sysctl.h>
45 #include <sys/file.h>
46 #include <sys/uio.h>
47 #include <sys/socketvar.h>
48 #include <sys/socket.h>
49 #include <sys/protosw.h>
50 #include <sys/proc.h>
51 #include <sys/queue.h>
52 #include <sys/kthread.h>
53 #include <sys/mbuf.h>
54 #include <sys/syslog.h>
55 #include <sys/eventhandler.h>
56 #include <sys/devfs.h>
57 #include <sys/udev.h>
58 #include <sys/objcache.h>
59
60 #include <bus/cam/cam.h>
61 #include <dev/disk/iscsi/initiator/iscsi.h>
62 #include <dev/disk/iscsi/initiator/iscsivar.h>
63
64 static char *iscsi_driver_version = "2.1.0";
65
66 static struct isc_softc isc;
67
68 MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI driver");
69
70 struct objcache_malloc_args iscsi_malloc_args = {
71 sizeof(pduq_t), M_ISCSI
72 };
73
74 #ifdef ISCSI_INITIATOR_DEBUG
75 int iscsi_debug = ISCSI_INITIATOR_DEBUG;
76 SYSCTL_INT(_debug, OID_AUTO, iscsi_initiator, CTLFLAG_RW, &iscsi_debug, 0, "iSCSI driver debug flag");
77
78 struct lock iscsi_dbg_lock;
79 #endif
80
81
82 static char isid[6+1] = {
83 0x80,
84 'D',
85 'I',
86 'B',
87 '0',
88 '0',
89 0
90 };
91
92 static int i_create_session(struct cdev *dev, int *ndev);
93
94 static int i_ping(struct cdev *dev);
95 static int i_send(struct cdev *dev, caddr_t arg, struct thread *td);
96 static int i_recv(struct cdev *dev, caddr_t arg, struct thread *td);
97 static int i_setsoc(isc_session_t *sp, int fd, struct thread *td);
98
99 static void free_pdus(struct isc_softc *sc);
100
101 static d_open_t iscsi_open;
102 static d_close_t iscsi_close;
103 static d_ioctl_t iscsi_ioctl;
104 #ifdef ISCSI_INITIATOR_DEBUG
105 static d_read_t iscsi_read;
106 #endif
107
108 static struct dev_ops iscsi_ops = {
109 .head = { "iscsi", 0, D_DISK},
110 .d_open = iscsi_open,
111 .d_close = iscsi_close,
112 .d_ioctl = iscsi_ioctl,
113 #ifdef ISCSI_INITIATOR_DEBUG
114 .d_read = iscsi_read,
115 #endif
116 };
117
118 static int
iscsi_open(struct dev_open_args * ap)119 iscsi_open(struct dev_open_args *ap)
120 {
121 cdev_t dev = ap->a_head.a_dev;
122
123 debug_called(8);
124
125 debug(7, "dev=%d", dev->si_uminor);
126
127 if(minor(dev) > MAX_SESSIONS) {
128 // should not happen
129 return ENODEV;
130 }
131
132 /* Make sure the device is passed */
133 if (dev->si_drv1 == NULL)
134 dev->si_drv1 = (struct isc *)isc.dev->si_drv1;
135
136 if(minor(dev) == MAX_SESSIONS) {
137 #if 1
138 struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
139
140 // this should be in iscsi_start
141 if(sc->cam_sim == NULL)
142 ic_init(sc);
143 #endif
144 }
145 return 0;
146 }
147
148 static int
iscsi_close(struct dev_close_args * ap)149 iscsi_close(struct dev_close_args *ap)
150 {
151 cdev_t dev = ap->a_head.a_dev;
152 int flag = ap->a_fflag;
153 isc_session_t *sp;
154
155 debug_called(8);
156
157 debug(3, "flag=%x", flag);
158
159 if(minor(dev) == MAX_SESSIONS) {
160 return 0;
161 }
162 sp = (isc_session_t *)dev->si_drv2;
163 if(sp != NULL) {
164 sdebug(2, "session=%d flags=%x", minor(dev), sp->flags );
165 /*
166 | if still in full phase, this probably means
167 | that something went realy bad.
168 | it could be a result from 'shutdown', in which case
169 | we will ignore it (so buffers can be flushed).
170 | the problem is that there is no way of differentiating
171 | between a shutdown procedure and 'iscontrol' dying.
172 */
173 if(sp->flags & ISC_FFPHASE)
174 // delay in case this is a shutdown.
175 tsleep(sp, 0, "isc-cls", 60*hz);
176 ism_stop(sp);
177 }
178 debug(2, "done");
179 return 0;
180 }
181
182 static int
iscsi_ioctl(struct dev_ioctl_args * ap)183 iscsi_ioctl(struct dev_ioctl_args *ap)
184 {
185 struct isc *sc;
186 cdev_t dev = ap->a_head.a_dev;
187 caddr_t arg = ap->a_data;
188 isc_session_t *sp;
189 isc_opt_t *opt;
190 int error;
191
192 sc = (struct isc *)dev->si_drv1;
193 debug_called(8);
194
195 error = 0;
196 if(minor(dev) == MAX_SESSIONS) {
197 /*
198 | non Session commands
199 */
200 if(sc == NULL)
201 return ENXIO;
202
203 switch(ap->a_cmd) {
204 case ISCSISETSES:
205 error = i_create_session(dev, (int *)arg);
206 if(error == 0)
207
208 break;
209
210 default:
211 error = ENXIO; // XXX:
212 }
213 return error;
214 }
215 sp = (isc_session_t *)dev->si_drv2;
216 /*
217 | session commands
218 */
219 if(sp == NULL)
220 return ENXIO;
221
222 sdebug(6, "dev=%d cmd=%d", minor(dev), (int)(ap->a_cmd & 0xff));
223
224 switch(ap->a_cmd) {
225 case ISCSISETSOC:
226 error = i_setsoc(sp, *(u_int *)arg, curthread);
227 break;
228
229 case ISCSISETOPT:
230 opt = (isc_opt_t *)arg;
231 error = i_setopt(sp, opt);
232 break;
233
234 case ISCSISEND:
235 error = i_send(dev, arg, curthread);
236 break;
237
238 case ISCSIRECV:
239 error = i_recv(dev, arg, curthread);
240 break;
241
242 case ISCSIPING:
243 error = i_ping(dev);
244 break;
245
246 case ISCSISTART:
247 error = sp->soc == NULL? ENOTCONN: ism_fullfeature(dev, 1);
248 if(error == 0) {
249 sp->proc = curthread->td_proc;
250 SYSCTL_ADD_UINT(&sp->clist,
251 SYSCTL_CHILDREN(sp->oid),
252 OID_AUTO,
253 "pid",
254 CTLFLAG_RD,
255 &sp->proc->p_pid, sizeof(pid_t), "control process id");
256 }
257 break;
258
259 case ISCSIRESTART:
260 error = sp->soc == NULL? ENOTCONN: ism_fullfeature(dev, 2);
261 break;
262
263 case ISCSISTOP:
264 error = ism_fullfeature(dev, 0);
265 break;
266
267 case ISCSISIGNAL: {
268 int sig = *(int *)arg;
269
270 if(sig < 0 || sig >= _SIG_MAXSIG)
271 error = EINVAL;
272 else
273 sp->signal = sig;
274 break;
275 }
276
277 case ISCSIGETCAM: {
278 iscsi_cam_t *cp = (iscsi_cam_t *)arg;
279
280 error = ic_getCamVals(sp, cp);
281 break;
282 }
283
284 default:
285 error = ENOIOCTL;
286 }
287
288 return error;
289 }
290
291 static int
iscsi_read(struct dev_read_args * ra)292 iscsi_read(struct dev_read_args *ra)
293 {
294 #ifdef ISCSI_INITIATOR_DEBUG
295 struct isc_softc *sc;
296 cdev_t dev = ra->a_head.a_dev;
297 struct uio *uio = ra->a_uio;
298 isc_session_t *sp;
299 pduq_t *pq;
300 char buf[1024];
301
302 sc = (struct isc_softc *)dev->si_drv1;
303 sp = (isc_session_t *)dev->si_drv2;
304
305 if(minor(dev) == MAX_SESSIONS) {
306 ksprintf(buf, "/----- Session ------/\n");
307 uiomove(buf, strlen(buf), uio);
308 int i = 0;
309
310 TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) {
311 if(uio->uio_resid == 0)
312 return 0;
313 ksprintf(buf, "%03d] '%s' '%s'\n", i++, sp->opt.targetAddress, sp->opt.targetName);
314 uiomove(buf, strlen(buf), uio);
315 }
316 ksprintf(buf, "%d/%d /---- free -----/\n", sc->npdu_alloc, sc->npdu_max);
317 i = 0;
318 uiomove(buf, strlen(buf), uio);
319 TAILQ_FOREACH(pq, &sc->freepdu, pq_link) {
320 if(uio->uio_resid == 0)
321 return 0;
322 ksprintf(buf, "%03d] %06x\n", i++, ntohl(pq->pdu.ipdu.bhs.itt));
323 uiomove(buf, strlen(buf), uio);
324 }
325 }
326 else {
327 int i = 0;
328 struct socket *so = sp->soc;
329 #define pukeit(i, pq) do {\
330 ksprintf(buf, "%03d] %06x %02x %x %ld\n",\
331 i, ntohl( pq->pdu.ipdu.bhs.CmdSN), \
332 pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\
333 (long)pq->ts.tv_sec);\
334 } while(0)
335
336 ksprintf(buf, "%d/%d /---- hld -----/\n", sp->stats.nhld, sp->stats.max_hld);
337 uiomove(buf, strlen(buf), uio);
338 TAILQ_FOREACH(pq, &sp->hld, pq_link) {
339 if(uio->uio_resid == 0)
340 return 0;
341 pukeit(i, pq); i++;
342 uiomove(buf, strlen(buf), uio);
343 }
344 ksprintf(buf, "%d/%d /---- rsp -----/\n", sp->stats.nrsp, sp->stats.max_rsp);
345 uiomove(buf, strlen(buf), uio);
346 i = 0;
347 TAILQ_FOREACH(pq, &sp->rsp, pq_link) {
348 if(uio->uio_resid == 0)
349 return 0;
350 pukeit(i, pq); i++;
351 uiomove(buf, strlen(buf), uio);
352 }
353 ksprintf(buf, "%d/%d /---- csnd -----/\n", sp->stats.ncsnd, sp->stats.max_csnd);
354 i = 0;
355 uiomove(buf, strlen(buf), uio);
356 TAILQ_FOREACH(pq, &sp->csnd, pq_link) {
357 if(uio->uio_resid == 0)
358 return 0;
359 pukeit(i, pq); i++;
360 uiomove(buf, strlen(buf), uio);
361 }
362 ksprintf(buf, "%d/%d /---- wsnd -----/\n", sp->stats.nwsnd, sp->stats.max_wsnd);
363 i = 0;
364 uiomove(buf, strlen(buf), uio);
365 TAILQ_FOREACH(pq, &sp->wsnd, pq_link) {
366 if(uio->uio_resid == 0)
367 return 0;
368 pukeit(i, pq); i++;
369 uiomove(buf, strlen(buf), uio);
370 }
371 ksprintf(buf, "%d/%d /---- isnd -----/\n", sp->stats.nisnd, sp->stats.max_isnd);
372 i = 0;
373 uiomove(buf, strlen(buf), uio);
374 TAILQ_FOREACH(pq, &sp->isnd, pq_link) {
375 if(uio->uio_resid == 0)
376 return 0;
377 pukeit(i, pq); i++;
378 uiomove(buf, strlen(buf), uio);
379 }
380
381 ksprintf(buf, "/---- Stats ---/\n");
382 uiomove(buf, strlen(buf), uio);
383
384 ksprintf(buf, "recv=%d sent=%d\n", sp->stats.nrecv, sp->stats.nsent);
385 uiomove(buf, strlen(buf), uio);
386
387 ksprintf(buf, "flags=%x pdus: alloc=%d max=%d\n",
388 sp->flags, sc->npdu_alloc, sc->npdu_max);
389 uiomove(buf, strlen(buf), uio);
390
391 ksprintf(buf, "cws=%d last cmd=%x exp=%x max=%x stat=%x itt=%x\n",
392 sp->cws, sp->sn.cmd, sp->sn.expCmd, sp->sn.maxCmd, sp->sn.stat, sp->sn.itt);
393 uiomove(buf, strlen(buf), uio);
394
395 if (so)
396 ksprintf(buf, "/---- socket -----/\nso_state=%x\n", so->so_state);
397 uiomove(buf, strlen(buf), uio);
398
399 }
400 #endif
401 return 0;
402 }
403
404 static int
i_ping(struct cdev * dev)405 i_ping(struct cdev *dev)
406 {
407 return 0;
408 }
409 /*
410 | low level I/O
411 */
412 static int
i_setsoc(isc_session_t * sp,int fd,thread_t td)413 i_setsoc(isc_session_t *sp, int fd, thread_t td)
414 {
415 int error = 0;
416 struct file *fp;
417
418 if (sp->soc != NULL)
419 isc_stop_receiver(sp);
420 if (sp->fp) {
421 fdrop(sp->fp);
422 sp->fp = NULL;
423 }
424
425 debug_called(8);
426
427 if ((error = holdsock(td, fd, &fp)) == 0) {
428 sp->soc = fp->f_data;
429 sp->fp = fp;
430 isc_start_receiver(sp);
431 }
432
433 return error;
434 }
435
436 static int
i_send(struct cdev * dev,caddr_t arg,struct thread * td)437 i_send(struct cdev *dev, caddr_t arg, struct thread *td)
438 {
439 isc_session_t *sp = (isc_session_t *)dev->si_drv2;
440 struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
441 caddr_t bp;
442 pduq_t *pq;
443 pdu_t *pp;
444 int n, error;
445
446 debug_called(8);
447
448 if(sp->soc == NULL)
449 return ENOTCONN;
450
451 if((pq = pdu_alloc(sc, M_NOWAIT)) == NULL)
452 return EAGAIN;
453 pp = &pq->pdu;
454 pq->pdu = *(pdu_t *)arg;
455 pq->refcnt = 0;
456 if((error = i_prepPDU(sp, pq)) != 0)
457 goto out;
458
459 sdebug(3, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len);
460
461 pq->buf = bp = kmalloc(pq->len - sizeof(union ipdu_u), M_ISCSI, M_NOWAIT);
462 if(pq->buf == NULL) {
463 error = EAGAIN;
464 goto out;
465 }
466
467 if(pp->ahs_len) {
468 n = pp->ahs_len;
469 error = copyin(pp->ahs, bp, n);
470 if(error != 0) {
471 sdebug(3, "copyin ahs: error=%d", error);
472 goto out;
473 }
474 pp->ahs = (ahs_t *)bp;
475 bp += n;
476 }
477 if(pp->ds_len) {
478 n = pp->ds_len;
479 error = copyin(pp->ds, bp, n);
480 if(error != 0) {
481 sdebug(3, "copyin ds: error=%d", error);
482 goto out;
483 }
484 pp->ds = bp;
485 bp += n;
486 while(n & 03) {
487 n++;
488 *bp++ = 0;
489 }
490 }
491
492 error = isc_qout(sp, pq);
493 #if 1
494 if(error == 0)
495 wakeup(&sp->flags); // XXX: to 'push' proc_out ...
496 #endif
497 out:
498 if(error)
499 pdu_free(sc, pq);
500
501 return error;
502 }
503
504 /*
505 | NOTE: must calculate digest if requiered.
506 */
507 static int
i_recv(struct cdev * dev,caddr_t arg,struct thread * td)508 i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
509 {
510 isc_session_t *sp = (isc_session_t *)dev->si_drv2;
511 pduq_t *pq;
512 pdu_t *pp, *up;
513 caddr_t bp;
514 int error, mustfree, cnt;
515 size_t need, have, n;
516
517 debug_called(8);
518
519 if(sp == NULL)
520 return EIO;
521
522 if(sp->soc == NULL)
523 return ENOTCONN;
524 sdebug(3, "");
525 cnt = 6; // XXX: maybe the user can request a time out?
526 iscsi_lock_ex(&sp->rsp_mtx);
527 while((pq = TAILQ_FIRST(&sp->rsp)) == NULL) {
528 issleep(&sp->rsp, &sp->rsp_mtx, 0, "isc_rsp", hz*10);
529 if(cnt-- == 0) break; // XXX: for now, needs work
530
531 }
532 if(pq != NULL) {
533 sp->stats.nrsp--;
534 TAILQ_REMOVE(&sp->rsp, pq, pq_link);
535 }
536 iscsi_unlock_ex(&sp->rsp_mtx);
537
538 sdebug(4, "cnt=%d", cnt);
539
540 if(pq == NULL) {
541 error = ENOTCONN;
542 sdebug(3, "error=%d sp->flags=%x ", error, sp->flags);
543 return error;
544 }
545 up = (pdu_t *)arg;
546 pp = &pq->pdu;
547 up->ipdu = pp->ipdu;
548 n = 0;
549 up->ds_len = 0;
550 up->ahs_len = 0;
551 error = 0;
552
553 if(pq->mp) {
554 u_int len;
555
556 // Grr...
557 len = 0;
558 if(pp->ahs_len) {
559 len += pp->ahs_len;
560 if(sp->hdrDigest)
561 len += 4;
562 }
563 if(pp->ds_len) {
564 len += pp->ds_len;
565 if(sp->hdrDigest)
566 len += 4;
567 }
568
569 mustfree = 0;
570 if(len > pq->mp->m_len) {
571 mustfree++;
572 bp = kmalloc(len, M_ISCSI, M_INTWAIT);
573 sdebug(4, "need mbufcopy: %d", len);
574 i_mbufcopy(pq->mp, bp, len);
575 }
576 else
577 bp = mtod(pq->mp, caddr_t);
578
579 if(pp->ahs_len) {
580 need = pp->ahs_len;
581 if(sp->hdrDigest)
582 need += 4;
583 n = MIN(up->ahs_size, need);
584 error = copyout(bp, (caddr_t)up->ahs, n);
585 up->ahs_len = n;
586 bp += need;
587 }
588 if(!error && pp->ds_len) {
589 need = pp->ds_len;
590 if(sp->hdrDigest)
591 need += 4;
592 if((have = up->ds_size) == 0) {
593 have = up->ahs_size - n;
594 up->ds = (caddr_t)up->ahs + n;
595 }
596 n = MIN(have, need);
597 error = copyout(bp, (caddr_t)up->ds, n);
598 up->ds_len = n;
599 }
600
601 if(mustfree)
602 kfree(bp, M_ISCSI);
603 }
604
605 sdebug(6, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len);
606
607 pdu_free(sp->isc, pq);
608
609 return error;
610 }
611
612 static int
i_create_session(struct cdev * dev,int * ndev)613 i_create_session(struct cdev *dev, int *ndev)
614 {
615 struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
616 isc_session_t *sp;
617 int error, n;
618
619 debug_called(8);
620 sp = (isc_session_t *)kmalloc(sizeof *sp, M_ISCSI, M_WAITOK | M_ZERO);
621 if(sp == NULL)
622 return ENOMEM;
623 lockmgr(&sc->lock, LK_EXCLUSIVE);
624 /*
625 | search for the lowest unused sid
626 */
627 for(n = 0; n < MAX_SESSIONS; n++)
628 if(sc->sessions[n] == NULL)
629 break;
630 if(n == MAX_SESSIONS) {
631 lockmgr(&sc->lock, LK_RELEASE);
632 kfree(sp, M_ISCSI);
633 return EPERM;
634 }
635 TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link);
636 sc->nsess++;
637 lockmgr(&sc->lock, LK_RELEASE);
638
639 sc->sessions[n] = sp;
640 debug(8, "n is %d", n);
641 sp->dev = make_dev(&iscsi_ops, n, UID_ROOT, GID_WHEEL, 0600, "iscsi%d", n);
642 devfs_config();
643 reference_dev(sp->dev);
644 udev_dict_set_cstr(sp->dev, "subsystem", "disk");
645 udev_dict_set_cstr(sp->dev, "disk-type", "network");
646
647 *ndev = sp->sid = n;
648 sp->isc = sc;
649 sp->dev->si_drv1 = sc;
650 sp->dev->si_drv2 = sp;
651
652 sp->opt.maxRecvDataSegmentLength = 8192;
653 sp->opt.maxXmitDataSegmentLength = 8192;
654
655 sp->opt.maxBurstLength = 65536; // 64k
656
657 sdebug(2, "sessionID=%d sp=%p", n, sp);
658 error = ism_start(sp);
659
660 return error;
661 }
662
663 #ifdef notused
664 static void
iscsi_counters(isc_session_t * sp)665 iscsi_counters(isc_session_t *sp)
666 {
667 int h, r, s;
668 pduq_t *pq;
669
670 #define _puke(i, pq) do {\
671 debug(2, "%03d] %06x %02x %x %ld %jd %x\n",\
672 i, ntohl( pq->pdu.ipdu.bhs.CmdSN), \
673 pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\
674 (long)pq->ts.sec, pq->ts.frac, pq->flags);\
675 } while(0)
676
677 h = r = s = 0;
678 TAILQ_FOREACH(pq, &sp->hld, pq_link) {
679 _puke(h, pq);
680 h++;
681 }
682 TAILQ_FOREACH(pq, &sp->rsp, pq_link) r++;
683 TAILQ_FOREACH(pq, &sp->csnd, pq_link) s++;
684 TAILQ_FOREACH(pq, &sp->wsnd, pq_link) s++;
685 TAILQ_FOREACH(pq, &sp->isnd, pq_link) s++;
686 debug(2, "hld=%d rsp=%d snd=%d", h, r, s);
687 }
688 #endif
689
690 static void
iscsi_shutdown(void * v)691 iscsi_shutdown(void *v)
692 {
693 struct isc_softc *sc = (struct isc_softc *)v;
694 isc_session_t *sp;
695 int n;
696
697 debug_called(8);
698 if(sc == NULL) {
699 xdebug("sc is NULL!");
700 return;
701 }
702 if(sc->eh == NULL)
703 debug(2, "sc->eh is NULL");
704 else {
705 EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->eh);
706 debug(2, "done n=%d", sc->nsess);
707 }
708 n = 0;
709 TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) {
710 debug(2, "%2d] sp->flags=0x%08x", n, sp->flags);
711 n++;
712 }
713 debug(2, "done");
714 }
715
716 static int
init_pdus(struct isc_softc * sc)717 init_pdus(struct isc_softc *sc)
718 {
719 debug_called(8);
720
721 sc->pdu_zone = objcache_create("pdu", 0, 0,
722 NULL, NULL, NULL,
723 objcache_malloc_alloc,
724 objcache_malloc_free,
725 &iscsi_malloc_args);
726
727 if(sc->pdu_zone == NULL) {
728 kprintf("iscsi_initiator: objcache_create failed");
729 return -1;
730 }
731 TAILQ_INIT(&sc->freepdu);
732
733 return 0;
734 }
735
736 static void
free_pdus(struct isc_softc * sc)737 free_pdus(struct isc_softc *sc)
738 {
739 pduq_t *pq;
740
741 debug_called(8);
742
743 if(sc->pdu_zone != NULL) {
744 TAILQ_FOREACH(pq, &sc->freepdu, pq_link) {
745 TAILQ_REMOVE(&sc->freepdu, pq, pq_link);
746 objcache_put(sc->pdu_zone, pq);
747 }
748 objcache_destroy(sc->pdu_zone);
749 sc->pdu_zone = NULL;
750 }
751 }
752
753 static void
iscsi_start(void)754 iscsi_start(void)
755 {
756 struct isc_softc *sc = &isc;
757
758 debug_called(8);
759
760 memset(sc, 0, sizeof(struct isc_softc));
761
762 sc->dev = make_dev(&iscsi_ops, MAX_SESSIONS, UID_ROOT, GID_WHEEL, 0600, "iscsi");
763 devfs_config();
764
765 sc->dev->si_drv1 = sc;
766
767 reference_dev(sc->dev);
768
769 TAILQ_INIT(&sc->isc_sess);
770 if(init_pdus(sc) != 0)
771 xdebug("pdu zone init failed!"); // XXX: should cause terminal failure ...
772
773 lockinit(&sc->lock, "iscsi", 0, LK_CANRECURSE);
774 lockinit(&sc->pdu_lock, "iscsi pdu pool", 0, LK_CANRECURSE);
775
776 #if 0
777 // XXX: this will cause a panic if the
778 // module is loaded too early
779 if(ic_init(sc) != 0)
780 return;
781 #else
782 sc->cam_sim = NULL;
783 #endif
784
785 #ifdef DO_EVENTHANDLER
786 if((sc->eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, iscsi_shutdown,
787 sc, SHUTDOWN_PRI_DEFAULT-1)) == NULL)
788 xdebug("shutdown event registration failed\n");
789 #endif
790 /*
791 | sysctl stuff
792 */
793 sysctl_ctx_init(&sc->clist);
794 sc->oid = SYSCTL_ADD_NODE(&sc->clist,
795 SYSCTL_STATIC_CHILDREN(_net),
796 OID_AUTO,
797 "iscsi",
798 CTLFLAG_RD,
799 0,
800 "iSCSI Subsystem");
801
802 SYSCTL_ADD_STRING(&sc->clist,
803 SYSCTL_CHILDREN(sc->oid),
804 OID_AUTO,
805 "driver_version",
806 CTLFLAG_RD,
807 iscsi_driver_version,
808 0,
809 "iscsi driver version");
810
811 SYSCTL_ADD_STRING(&sc->clist,
812 SYSCTL_CHILDREN(sc->oid),
813 OID_AUTO,
814 "isid",
815 CTLFLAG_RW,
816 isid,
817 6+1,
818 "initiator part of the Session Identifier");
819
820 SYSCTL_ADD_INT(&sc->clist,
821 SYSCTL_CHILDREN(sc->oid),
822 OID_AUTO,
823 "sessions",
824 CTLFLAG_RD,
825 &sc->nsess,
826 sizeof(sc->nsess),
827 "number of active session");
828
829 kprintf("iscsi: version %s\n", iscsi_driver_version);
830 }
831
832 /*
833 | Notes:
834 | unload SHOULD fail if there is activity
835 | activity: there is/are active session/s
836 */
837 static void
iscsi_stop(void)838 iscsi_stop(void)
839 {
840 struct isc_softc *sc = &isc;
841 isc_session_t *sp, *sp_tmp;
842
843 debug_called(8);
844
845 /*
846 | go through all the sessions
847 | Note: close should have done this ...
848 */
849 TAILQ_FOREACH_MUTABLE(sp, &sc->isc_sess, sp_link, sp_tmp) {
850 //XXX: check for activity ...
851 ism_stop(sp);
852 }
853 if(sc->cam_sim != NULL)
854 ic_destroy(sc);
855
856 lockuninit(&sc->lock);
857 lockuninit(&sc->pdu_lock);
858 free_pdus(sc);
859
860 if(sc->dev) {
861 release_dev(sc->dev);
862 destroy_dev(sc->dev);
863 //dev_ops_remove(&sc->dev, -1, 0);
864 }
865
866 if(sysctl_ctx_free(&sc->clist))
867 xdebug("sysctl_ctx_free failed");
868
869 iscsi_shutdown(sc); // XXX: check EVENTHANDLER_ ...
870 }
871
872 static int
iscsi_modevent(module_t mod,int what,void * arg)873 iscsi_modevent(module_t mod, int what, void *arg)
874 {
875 debug_called(8);
876
877 switch(what) {
878 case MOD_LOAD:
879 iscsi_start();
880 break;
881
882 case MOD_SHUTDOWN:
883 break;
884
885 case MOD_UNLOAD:
886 iscsi_stop();
887 break;
888
889 default:
890 break;
891 }
892 return 0;
893 }
894
895 moduledata_t iscsi_mod = {
896 "iscsi_initiator",
897 (modeventhand_t) iscsi_modevent,
898 0
899 };
900
901 #ifdef ISCSI_ROOT
902 static void
iscsi_rootconf(void)903 iscsi_rootconf(void)
904 {
905 #if 0
906 nfs_setup_diskless();
907 if (nfs_diskless_valid)
908 rootdevnames[0] = "nfs:";
909 #endif
910 kprintf("** iscsi_rootconf **\n");
911 }
912
913 SYSINIT(cpu_rootconf1, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, iscsi_rootconf, NULL);
914 #endif
915
916 DECLARE_MODULE(iscsi_initiator, iscsi_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
917 MODULE_DEPEND(iscsi_initiator, cam, 1, 1, 1);
918