2 * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 | $Id: iscsi.c 752 2009-08-20 11:23:28Z danny $
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include "opt_iscsi_initiator.h"
36 #include <sys/param.h>
37 #include <sys/capability.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
44 #include <sys/ctype.h>
45 #include <sys/errno.h>
46 #include <sys/sysctl.h>
49 #include <sys/socketvar.h>
50 #include <sys/socket.h>
51 #include <sys/protosw.h>
53 #include <sys/ioccom.h>
54 #include <sys/queue.h>
55 #include <sys/kthread.h>
57 #include <sys/syslog.h>
61 #include <dev/iscsi/initiator/iscsi.h>
62 #include <dev/iscsi/initiator/iscsivar.h>
63 static char *iscsi_driver_version = "2.2.4.2";
65 static struct isc_softc *isc;
67 MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI driver");
68 MALLOC_DEFINE(M_ISCSIBUF, "iSCbuf", "iSCSI buffers");
69 MALLOC_DEFINE(M_TMP, "iSCtmp", "iSCSI tmp");
71 #ifdef ISCSI_INITIATOR_DEBUG
72 int iscsi_debug = ISCSI_INITIATOR_DEBUG;
73 SYSCTL_INT(_debug, OID_AUTO, iscsi_initiator, CTLFLAG_RW, &iscsi_debug, 0,
74 "iSCSI driver debug flag");
76 struct mtx iscsi_dbg_mtx;
79 static int max_sessions = MAX_SESSIONS;
80 SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_sessions, CTLFLAG_RDTUN, &max_sessions, MAX_SESSIONS,
81 "Max sessions allowed");
82 static int max_pdus = MAX_PDUS;
83 SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_pdus, CTLFLAG_RDTUN, &max_pdus, MAX_PDUS,
86 static char isid[6+1] = {
96 static int i_create_session(struct cdev *dev, int *ndev);
98 static int i_ping(struct cdev *dev);
99 static int i_send(struct cdev *dev, caddr_t arg, struct thread *td);
100 static int i_recv(struct cdev *dev, caddr_t arg, struct thread *td);
101 static int i_setsoc(isc_session_t *sp, int fd, struct thread *td);
102 static int i_fullfeature(struct cdev *dev, int flag);
104 static d_open_t iscsi_open;
105 static d_close_t iscsi_close;
106 static d_ioctl_t iscsi_ioctl;
107 #ifdef ISCSI_INITIATOR_DEBUG
108 static d_read_t iscsi_read;
111 static struct cdevsw iscsi_cdevsw = {
112 .d_version = D_VERSION,
113 .d_open = iscsi_open,
114 .d_close = iscsi_close,
115 .d_ioctl = iscsi_ioctl,
116 #ifdef ISCSI_INITIATOR_DEBUG
117 .d_read = iscsi_read,
123 iscsi_open(struct cdev *dev, int flags, int otype, struct thread *td)
127 debug(7, "dev=%d", dev2unit(dev));
129 if(dev2unit(dev) > max_sessions) {
137 iscsi_close(struct cdev *dev, int flag, int otyp, struct thread *td)
143 debug(3, "session=%d flag=%x", dev2unit(dev), flag);
145 if(dev2unit(dev) == max_sessions) {
150 sdebug(3, "sp->flags=%x", sp->flags );
152 | if still in full phase, this probably means
153 | that something went realy bad.
154 | it could be a result from 'shutdown', in which case
155 | we will ignore it (so buffers can be flushed).
156 | the problem is that there is no way of differentiating
157 | between a shutdown procedure and 'iscontrol' dying.
159 if(sp->flags & ISC_FFPHASE)
160 // delay in case this is a shutdown.
161 tsleep(sp, PRIBIO, "isc-cls", 60*hz);
169 iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
171 struct isc_softc *sc;
179 if(dev2unit(dev) == max_sessions) {
181 | non Session commands
189 error = i_create_session(dev, (int *)arg);
205 sdebug(6, "dev=%d cmd=%d", dev2unit(dev), (int)(cmd & 0xff));
209 error = i_setsoc(sp, *(u_int *)arg, td);
213 opt = (isc_opt_t *)arg;
214 error = i_setopt(sp, opt);
218 error = i_send(dev, arg, td);
222 error = i_recv(dev, arg, td);
230 error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 1);
232 sp->proc = td->td_proc;
233 SYSCTL_ADD_INT(&sp->clist, SYSCTL_CHILDREN(sp->oid),
234 OID_AUTO, "pid", CTLFLAG_RD,
235 &sp->proc->p_pid, sizeof(pid_t), "control process id");
240 error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 2);
244 error = i_fullfeature(dev, 0);
248 int sig = *(int *)arg;
250 if(sig < 0 || sig > _SIG_MAXSIG)
258 iscsi_cam_t *cp = (iscsi_cam_t *)arg;
260 error = ic_getCamVals(sp, cp);
272 iscsi_read(struct cdev *dev, struct uio *uio, int ioflag)
274 #ifdef ISCSI_INITIATOR_DEBUG
275 struct isc_softc *sc;
282 if(dev2unit(dev) == max_sessions) {
283 sprintf(buf, "/----- Session ------/\n");
284 uiomove(buf, strlen(buf), uio);
287 TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) {
288 if(uio->uio_resid == 0)
290 sprintf(buf, "%03d] '%s' '%s'\n", i++, sp->opt.targetAddress, sp->opt.targetName);
291 uiomove(buf, strlen(buf), uio);
293 sprintf(buf, "%d/%d /---- free -----/\n", sc->npdu_alloc, sc->npdu_max);
295 uiomove(buf, strlen(buf), uio);
299 struct socket *so = sp->soc;
300 #define pukeit(i, pq) do {\
301 sprintf(buf, "%03d] %06x %02x %06x %06x %jd\n",\
302 i, ntohl(pq->pdu.ipdu.bhs.CmdSN),\
303 pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\
304 ntohl(pq->pdu.ipdu.bhs.ExpStSN),\
305 (intmax_t)pq->ts.sec);\
308 sprintf(buf, "%d/%d /---- hld -----/\n", sp->stats.nhld, sp->stats.max_hld);
309 uiomove(buf, strlen(buf), uio);
310 TAILQ_FOREACH(pq, &sp->hld, pq_link) {
311 if(uio->uio_resid == 0)
314 uiomove(buf, strlen(buf), uio);
316 sprintf(buf, "%d/%d /---- rsp -----/\n", sp->stats.nrsp, sp->stats.max_rsp);
317 uiomove(buf, strlen(buf), uio);
319 TAILQ_FOREACH(pq, &sp->rsp, pq_link) {
320 if(uio->uio_resid == 0)
323 uiomove(buf, strlen(buf), uio);
325 sprintf(buf, "%d/%d /---- csnd -----/\n", sp->stats.ncsnd, sp->stats.max_csnd);
327 uiomove(buf, strlen(buf), uio);
328 TAILQ_FOREACH(pq, &sp->csnd, pq_link) {
329 if(uio->uio_resid == 0)
332 uiomove(buf, strlen(buf), uio);
334 sprintf(buf, "%d/%d /---- wsnd -----/\n", sp->stats.nwsnd, sp->stats.max_wsnd);
336 uiomove(buf, strlen(buf), uio);
337 TAILQ_FOREACH(pq, &sp->wsnd, pq_link) {
338 if(uio->uio_resid == 0)
341 uiomove(buf, strlen(buf), uio);
343 sprintf(buf, "%d/%d /---- isnd -----/\n", sp->stats.nisnd, sp->stats.max_isnd);
345 uiomove(buf, strlen(buf), uio);
346 TAILQ_FOREACH(pq, &sp->isnd, pq_link) {
347 if(uio->uio_resid == 0)
350 uiomove(buf, strlen(buf), uio);
353 sprintf(buf, "/---- Stats ---/\n");
354 uiomove(buf, strlen(buf), uio);
356 sprintf(buf, "recv=%d sent=%d\n", sp->stats.nrecv, sp->stats.nsent);
357 uiomove(buf, strlen(buf), uio);
359 sprintf(buf, "flags=%x pdus: alloc=%d max=%d\n",
360 sp->flags, sc->npdu_alloc, sc->npdu_max);
361 uiomove(buf, strlen(buf), uio);
363 sprintf(buf, "cws=%d last cmd=%x exp=%x max=%x stat=%x itt=%x\n",
364 sp->cws, sp->sn.cmd, sp->sn.expCmd, sp->sn.maxCmd, sp->sn.stat, sp->sn.itt);
365 uiomove(buf, strlen(buf), uio);
367 sprintf(buf, "/---- socket -----/\nso_count=%d so_state=%x\n", so->so_count, so->so_state);
368 uiomove(buf, strlen(buf), uio);
376 i_ping(struct cdev *dev)
384 i_setsoc(isc_session_t *sp, int fd, struct thread *td)
389 isc_stop_receiver(sp);
391 error = fget(td, fd, CAP_SOCK_ALL, &sp->fp);
395 if((error = fgetsock(td, fd, CAP_SOCK_ALL, &sp->soc, 0)) == 0) {
397 isc_start_receiver(sp);
408 i_send(struct cdev *dev, caddr_t arg, struct thread *td)
410 isc_session_t *sp = dev->si_drv2;
421 if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL)
424 pq->pdu = *(pdu_t *)arg;
425 if((error = i_prepPDU(sp, pq)) != 0)
429 if((pq->len - sizeof(union ipdu_u)) > 0) {
430 pq->buf = bp = malloc(pq->len - sizeof(union ipdu_u), M_ISCSIBUF, M_NOWAIT);
431 if(pq->buf == NULL) {
437 pq->buf = NULL; // just in case?
439 sdebug(2, "len=%d ahs_len=%d ds_len=%d buf=%zu@%p",
440 pq->len, pp->ahs_len, pp->ds_len, pq->len - sizeof(union ipdu_u), bp);
443 // XXX: never tested, looks suspicious
445 error = copyin(pp->ahs_addr, bp, n);
447 sdebug(3, "copyin ahs: error=%d", error);
450 pp->ahs_addr = (ahs_t *)bp;
455 error = copyin(pp->ds_addr, bp, n);
457 sdebug(3, "copyin ds: error=%d", error);
468 error = isc_qout(sp, pq);
470 wakeup(&sp->flags); // XXX: to 'push' proc_out ...
473 pdu_free(sp->isc, pq);
479 i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
481 isc_session_t *sp = dev->si_drv2;
485 int error, mustfree, cnt;
486 size_t need, have, n;
495 cnt = 6; // XXX: maybe the user can request a time out?
496 mtx_lock(&sp->rsp_mtx);
497 while((pq = TAILQ_FIRST(&sp->rsp)) == NULL) {
498 msleep(&sp->rsp, &sp->rsp_mtx, PRIBIO, "isc_rsp", hz*10);
499 if(cnt-- == 0) break; // XXX: for now, needs work
503 TAILQ_REMOVE(&sp->rsp, pq, pq_link);
505 mtx_unlock(&sp->rsp_mtx);
507 sdebug(6, "cnt=%d", cnt);
511 sdebug(3, "error=%d sp->flags=%x ", error, sp->flags);
535 if(len > pq->mp->m_len) {
537 bp = malloc(len, M_TMP, M_WAITOK);
538 sdebug(4, "need mbufcopy: %d", len);
539 i_mbufcopy(pq->mp, bp, len);
542 bp = mtod(pq->mp, caddr_t);
546 n = MIN(up->ahs_size, need);
547 error = copyout(bp, (caddr_t)up->ahs_addr, n);
551 if(!error && pp->ds_len) {
553 if((have = up->ds_size) == 0) {
554 have = up->ahs_size - n;
555 up->ds_addr = (caddr_t)up->ahs_addr + n;
558 error = copyout(bp, (caddr_t)up->ds_addr, n);
566 sdebug(6, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len);
568 pdu_free(sp->isc, pq);
574 i_fullfeature(struct cdev *dev, int flag)
576 isc_session_t *sp = dev->si_drv2;
579 sdebug(2, "flag=%d", flag);
584 sp->flags &= ~ISC_FFPHASE;
587 sp->flags |= ISC_FFPHASE;
591 sp->flags |= ISC_FFPHASE;
599 i_create_session(struct cdev *dev, int *ndev)
601 struct isc_softc *sc = dev->si_drv1;
607 sp = malloc(sizeof(isc_session_t), M_ISCSI, M_WAITOK | M_ZERO);
611 sx_xlock(&sc->unit_sx);
612 if((n = alloc_unr(sc->unit)) < 0) {
613 sx_unlock(&sc->unit_sx);
615 xdebug("too many sessions!");
618 sx_unlock(&sc->unit_sx);
620 mtx_lock(&sc->isc_mtx);
621 TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link);
623 mtx_unlock(&sc->isc_mtx);
625 sp->dev = make_dev(&iscsi_cdevsw, n, UID_ROOT, GID_WHEEL, 0600, "iscsi%d", n);
628 sp->dev->si_drv1 = sc;
629 sp->dev->si_drv2 = sp;
631 sp->opt.maxRecvDataSegmentLength = 8192;
632 sp->opt.maxXmitDataSegmentLength = 8192;
633 sp->opt.maxBurstLength = 65536; // 64k
634 sp->opt.maxluns = ISCSI_MAX_LUNS;
636 error = ism_start(sp);
643 iscsi_counters(isc_session_t *sp)
648 #define _puke(i, pq) do {\
649 debug(2, "%03d] %06x %02x %x %ld %jd %x\n",\
650 i, ntohl( pq->pdu.ipdu.bhs.CmdSN), \
651 pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\
652 (long)pq->ts.sec, pq->ts.frac, pq->flags);\
656 TAILQ_FOREACH(pq, &sp->hld, pq_link) {
660 TAILQ_FOREACH(pq, &sp->rsp, pq_link) r++;
661 TAILQ_FOREACH(pq, &sp->csnd, pq_link) s++;
662 TAILQ_FOREACH(pq, &sp->wsnd, pq_link) s++;
663 TAILQ_FOREACH(pq, &sp->isnd, pq_link) s++;
664 debug(2, "hld=%d rsp=%d snd=%d", h, r, s);
669 iscsi_shutdown(void *v)
671 struct isc_softc *sc = v;
677 xdebug("sc is NULL!");
680 #ifdef DO_EVENTHANDLER
682 debug(2, "sc->eh is NULL");
684 EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->eh);
685 debug(2, "done n=%d", sc->nsess);
689 TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) {
690 debug(2, "%2d] sp->flags=0x%08x", n, sp->flags);
697 free_pdus(struct isc_softc *sc)
702 if(sc->pdu_zone != NULL) {
703 uma_zdestroy(sc->pdu_zone);
713 TUNABLE_INT_FETCH("net.iscsi_initiator.max_sessions", &max_sessions);
714 TUNABLE_INT_FETCH("net.iscsi_initiator.max_pdus", &max_pdus);
716 isc = malloc(sizeof(struct isc_softc), M_ISCSI, M_ZERO|M_WAITOK);
717 isc->dev = make_dev(&iscsi_cdevsw, max_sessions, UID_ROOT, GID_WHEEL, 0600, "iscsi");
718 isc->dev->si_drv1 = isc;
719 mtx_init(&isc->isc_mtx, "iscsi", NULL, MTX_DEF);
721 TAILQ_INIT(&isc->isc_sess);
723 | now init the free pdu list
725 isc->pdu_zone = uma_zcreate("pdu", sizeof(pduq_t),
726 NULL, NULL, NULL, NULL,
728 if(isc->pdu_zone == NULL) {
729 xdebug("iscsi_initiator: uma_zcreate failed");
730 // XXX: should fail...
732 uma_zone_set_max(isc->pdu_zone, max_pdus);
733 isc->unit = new_unrhdr(0, max_sessions-1, NULL);
734 sx_init(&isc->unit_sx, "iscsi sx");
736 #ifdef DO_EVENTHANDLER
737 if((isc->eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, iscsi_shutdown,
738 sc, SHUTDOWN_PRI_DEFAULT-1)) == NULL)
739 xdebug("shutdown event registration failed\n");
744 sysctl_ctx_init(&isc->clist);
745 isc->oid = SYSCTL_ADD_NODE(&isc->clist,
746 SYSCTL_STATIC_CHILDREN(_net),
753 SYSCTL_ADD_STRING(&isc->clist,
754 SYSCTL_CHILDREN(isc->oid),
758 iscsi_driver_version,
760 "iscsi driver version");
762 SYSCTL_ADD_STRING(&isc->clist,
763 SYSCTL_CHILDREN(isc->oid),
769 "initiator part of the Session Identifier");
771 SYSCTL_ADD_INT(&isc->clist,
772 SYSCTL_CHILDREN(isc->oid),
778 "number of active session");
780 printf("iscsi: version %s\n", iscsi_driver_version);
785 | unload SHOULD fail if there is activity
786 | activity: there is/are active session/s
791 isc_session_t *sp, *sp_tmp;
796 | go through all the sessions
797 | Note: close should have done this ...
799 TAILQ_FOREACH_SAFE(sp, &isc->isc_sess, sp_link, sp_tmp) {
800 //XXX: check for activity ...
802 if(sp->cam_sim != NULL)
805 mtx_destroy(&isc->isc_mtx);
806 sx_destroy(&isc->unit_sx);
811 destroy_dev(isc->dev);
813 if(sysctl_ctx_free(&isc->clist))
814 xdebug("sysctl_ctx_free failed");
816 iscsi_shutdown(isc); // XXX: check EVENTHANDLER_ ...
821 iscsi_modevent(module_t mod, int what, void *arg)
832 xdebug("iscsi module busy(nsess=%d), cannot unload", isc->nsess);
833 log(LOG_ERR, "iscsi module busy, cannot unload");
850 moduledata_t iscsi_mod = {
852 (modeventhand_t) iscsi_modevent,
861 nfs_setup_diskless();
862 if (nfs_diskless_valid)
863 rootdevnames[0] = "nfs:";
865 printf("** iscsi_rootconf **\n");
868 SYSINIT(cpu_rootconf1, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, iscsi_rootconf, NULL)
871 DECLARE_MODULE(iscsi, iscsi_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
872 MODULE_DEPEND(iscsi, cam, 1, 1, 1);