summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2010-08-09 12:36:36 +0000
committerdes <des@FreeBSD.org>2010-08-09 12:36:36 +0000
commit9f1a6fc5a691fe47d9f9667fa2a112ee7e4bbdf0 (patch)
tree43342de6f254d6434829cb76dee008ac438a8d6d /sys/dev
parent855b4d34cabdc84251dc2751ba1a4d13588bc04e (diff)
downloadFreeBSD-src-9f1a6fc5a691fe47d9f9667fa2a112ee7e4bbdf0.zip
FreeBSD-src-9f1a6fc5a691fe47d9f9667fa2a112ee7e4bbdf0.tar.gz
- Add full support for header / data digests.
- Increase target limit from 4 to 64; this limit will be removed entirely at a later time. - Improve recovery from lost network connections. - Fix some potential deadlocks and a serious memory leak. - Fix incorrect use of MH_ALIGN (instead of M_ALIGN), which makes no practical difference, but triggers a KASSERT with INVARIANTS. - Fix some warnings in iscontrol(8) and improve the man page somewhat. Submitted by: Daniel Braniss <danny@cs.huji.ac.il> Sponsored by: Dansk Scanning A/S, Data Robotics Inc.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/iscsi/initiator/isc_cam.c356
-rw-r--r--sys/dev/iscsi/initiator/isc_sm.c146
-rw-r--r--sys/dev/iscsi/initiator/isc_soc.c443
-rw-r--r--sys/dev/iscsi/initiator/isc_subr.c45
-rw-r--r--sys/dev/iscsi/initiator/iscsi.c311
-rw-r--r--sys/dev/iscsi/initiator/iscsi.h18
-rw-r--r--sys/dev/iscsi/initiator/iscsi_subr.c102
-rw-r--r--sys/dev/iscsi/initiator/iscsivar.h126
8 files changed, 767 insertions, 780 deletions
diff --git a/sys/dev/iscsi/initiator/isc_cam.c b/sys/dev/iscsi/initiator/isc_cam.c
index 0d87823..706ea4f 100644
--- a/sys/dev/iscsi/initiator/isc_cam.c
+++ b/sys/dev/iscsi/initiator/isc_cam.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,9 @@
* SUCH DAMAGE.
*
*/
-
+/*
+ | $Id: isc_cam.c 998 2009-12-20 10:32:45Z danny $
+ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -43,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/uio.h>
#include <sys/sysctl.h>
+#include <sys/sx.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -53,52 +56,70 @@ __FBSDID("$FreeBSD$");
#include <dev/iscsi/initiator/iscsi.h>
#include <dev/iscsi/initiator/iscsivar.h>
-// XXX: untested/incomplete
-void
-ic_freeze(isc_session_t *sp)
+static void
+_inq(struct cam_sim *sim, union ccb *ccb)
{
+ struct ccb_pathinq *cpi = &ccb->cpi;
+ isc_session_t *sp = cam_sim_softc(sim);
+
debug_called(8);
-#if 0
- sdebug(2, "freezing path=%p", sp->cam_path == NULL? 0: sp->cam_path);
- if((sp->cam_path != NULL) && !(sp->flags & ISC_FROZEN)) {
- xpt_freeze_devq(sp->cam_path, 1);
- }
+ debug(3, "sid=%d target=%d lun=%d", sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
+
+ cpi->version_num = 1; /* XXX??? */
+ cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32;
+ cpi->target_sprt = 0;
+ cpi->hba_misc = 0;
+ cpi->hba_eng_cnt = 0;
+ cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1;
+ cpi->initiator_id = ISCSI_MAX_TARGETS;
+ cpi->max_lun = sp->opt.maxluns - 1;
+ cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300; // 40000; // XXX:
+ strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+ strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
+ strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+ cpi->unit_number = cam_sim_unit(sim);
+ cpi->ccb_h.status = CAM_REQ_CMP;
+#if defined(KNOB_VALID_ADDRESS)
+ cpi->transport = XPORT_ISCSI;
+ cpi->transport_version = 0;
#endif
- sp->flags |= ISC_FROZEN;
}
-// XXX: untested/incomplete
-void
-ic_release(isc_session_t *sp)
+static __inline int
+_scsi_encap(struct cam_sim *sim, union ccb *ccb)
{
- debug_called(8);
-#if 0
- sdebug(2, "release path=%p", sp->cam_path == NULL? 0: sp->cam_path);
- if((sp->cam_path != NULL) && (sp->flags & ISC_FROZEN)) {
- xpt_release_devq(sp->cam_path, 1, TRUE);
- }
+ int ret;
+
+#if __FreeBSD_version < 700000
+ ret = scsi_encap(sim, ccb);
+#else
+ isc_session_t *sp = cam_sim_softc(sim);
+
+ mtx_unlock(&sp->cam_mtx);
+ ret = scsi_encap(sim, ccb);
+ mtx_lock(&sp->cam_mtx);
#endif
- sp->flags &= ~ISC_FROZEN;
+ return ret;
}
void
ic_lost_target(isc_session_t *sp, int target)
{
- struct isc_softc *isp = sp->isc;
-
debug_called(8);
- sdebug(2, "target=%d", target);
+ sdebug(2, "lost target=%d", target);
+
if(sp->cam_path != NULL) {
- mtx_lock(&isp->cam_mtx);
+ mtx_lock(&sp->cam_mtx);
xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL);
xpt_free_path(sp->cam_path);
- mtx_unlock(&isp->cam_mtx);
+ mtx_unlock(&sp->cam_mtx);
sp->cam_path = 0; // XXX
}
}
static void
-_scan_callback(struct cam_periph *periph, union ccb *ccb)
+scan_callback(struct cam_periph *periph, union ccb *ccb)
{
isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0;
@@ -106,63 +127,52 @@ _scan_callback(struct cam_periph *periph, union ccb *ccb)
free(ccb, M_TEMP);
- if(sp->flags & ISC_FFPWAIT) {
- sp->flags &= ~ISC_FFPWAIT;
+ if(sp->flags & ISC_SCANWAIT) {
+ sp->flags &= ~ISC_SCANWAIT;
wakeup(sp);
}
}
-static void
-_scan_target(isc_session_t *sp, int target)
+static int
+ic_scan(isc_session_t *sp)
{
- union ccb *ccb;
+ union ccb *ccb;
debug_called(8);
- sdebug(2, "target=%d", target);
+ sdebug(2, "scanning sid=%d", sp->sid);
if((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
xdebug("scan failed (can't allocate CCB)");
- return;
+ return ENOMEM; // XXX
}
- CAM_LOCK(sp->isc);
- xpt_setup_ccb(&ccb->ccb_h, sp->cam_path, 5/*priority (low)*/);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = _scan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- ccb->ccb_h.spriv_ptr0 = sp;
- xpt_action(ccb);
- CAM_UNLOCK(sp->isc);
-}
-
-int
-ic_fullfeature(struct cdev *dev)
-{
- struct isc_softc *isp = dev->si_drv1;
- isc_session_t *sp = (isc_session_t *)dev->si_drv2;
+ sp->flags &= ~ISC_CAMDEVS;
+ sp->flags |= ISC_SCANWAIT;
- debug_called(8);
- sdebug(3, "dev=%d sc=%p", dev2unit(dev), isp);
-
- sp->flags &= ~ISC_FFPHASE;
- sp->flags |= ISC_FFPWAIT;
-
- CAM_LOCK(isp);
- if(xpt_create_path(&sp->cam_path, xpt_periph, cam_sim_path(sp->isc->cam_sim),
- sp->sid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ CAM_LOCK(sp);
+ if(xpt_create_path(&sp->cam_path, xpt_periph, cam_sim_path(sp->cam_sim),
+ 0, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xdebug("can't create cam path");
- CAM_UNLOCK(isp);
+ CAM_UNLOCK(sp);
+ free(ccb, M_TEMP);
return ENODEV; // XXX
}
- CAM_UNLOCK(isp);
+ xpt_setup_ccb(&ccb->ccb_h, sp->cam_path, 5/*priority (low)*/);
+ ccb->ccb_h.func_code = XPT_SCAN_BUS;
+ ccb->ccb_h.cbfcnp = scan_callback;
+ ccb->crcn.flags = CAM_FLAG_NONE;
+ ccb->ccb_h.spriv_ptr0 = sp;
- _scan_target(sp, sp->sid);
+ xpt_action(ccb);
+ CAM_UNLOCK(sp);
- while(sp->flags & ISC_FFPWAIT)
+ while(sp->flags & ISC_SCANWAIT)
tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should
// be configurable
+ sdebug(2, "# of luns=%d", sp->target_nluns);
+
if(sp->target_nluns > 0) {
- sp->flags |= ISC_FFPHASE;
+ sp->flags |= ISC_CAMDEVS;
return 0;
}
@@ -170,110 +180,25 @@ ic_fullfeature(struct cdev *dev)
}
static void
-_inq(struct cam_sim *sim, union ccb *ccb, int maxluns)
-{
- struct ccb_pathinq *cpi = &ccb->cpi;
-
- debug_called(4);
-
- cpi->version_num = 1; /* XXX??? */
- cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32;
- cpi->target_sprt = 0;
- cpi->hba_misc = 0;
- cpi->hba_eng_cnt = 0;
- cpi->max_target = ISCSI_MAX_TARGETS - 1;
- cpi->initiator_id = ISCSI_MAX_TARGETS;
- cpi->max_lun = maxluns;
- cpi->bus_id = cam_sim_bus(sim);
- cpi->base_transfer_speed = 3300;
- strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
- strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
- strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
- cpi->unit_number = cam_sim_unit(sim);
- cpi->transport = XPORT_ISCSI;
- cpi->transport_version = 0;
- cpi->ccb_h.status = CAM_REQ_CMP;
-}
-
-static __inline int
-_scsi_encap(struct cam_sim *sim, union ccb *ccb)
-{
- int ret;
-
-#if __FreeBSD_version < 700000
- ret = scsi_encap(sim, ccb);
-#else
- struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim);
-
- mtx_unlock(&isp->cam_mtx);
- ret = scsi_encap(sim, ccb);
- mtx_lock(&isp->cam_mtx);
-#endif
- return ret;
-}
-
-static void
ic_action(struct cam_sim *sim, union ccb *ccb)
{
+ isc_session_t *sp = cam_sim_softc(sim);
struct ccb_hdr *ccb_h = &ccb->ccb_h;
- struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim);
- isc_session_t *sp;
debug_called(8);
- if((ccb_h->target_id != CAM_TARGET_WILDCARD) && (ccb_h->target_id < MAX_SESSIONS))
- sp = isp->sessions[ccb_h->target_id];
- else
- sp = NULL;
-
ccb_h->spriv_ptr0 = sp;
-
- debug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d",
+ sdebug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d",
ccb_h->func_code, ccb->ccb_h.flags, ccb->ccb_h.status,
ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
ccb->ccb_h.retry_count, ccb_h->timeout);
- /*
- | first quick check
- */
- switch(ccb_h->func_code) {
- default:
- // XXX: maybe check something else?
- break;
-
- case XPT_SCSI_IO:
- case XPT_RESET_DEV:
- case XPT_GET_TRAN_SETTINGS:
- case XPT_SET_TRAN_SETTINGS:
- case XPT_CALC_GEOMETRY:
- if(sp == NULL) {
- ccb->ccb_h.status = CAM_DEV_NOT_THERE;
-#if __FreeBSD_version < 700000
- XPT_DONE(isp, ccb);
-#else
- xpt_done(ccb);
-#endif
- return;
- }
- break;
-
- case XPT_PATH_INQ:
- case XPT_NOOP:
- if(sp == NULL && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
- ccb->ccb_h.status = CAM_DEV_NOT_THERE;
-#if __FreeBSD_version < 700000
- XPT_DONE(isp, ccb);
-#else
- xpt_done(ccb);
-#endif
- debug(4, "status = CAM_DEV_NOT_THERE");
- return;
- }
- }
-
+ if(sp == NULL) {
+ xdebug("sp == NULL! cannot happen");
+ return;
+ }
switch(ccb_h->func_code) {
-
case XPT_PATH_INQ:
- _inq(sim, ccb, (sp? sp->opt.maxluns: ISCSI_MAX_LUNS) - 1);
+ _inq(sim, ccb);
break;
case XPT_RESET_BUS: // (can just be a stub that does nothing and completes)
@@ -310,14 +235,35 @@ ic_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_calc_geometry *ccg;
ccg = &ccb->ccg;
- debug(6, "XPT_CALC_GEOMETRY vsize=%jd bsize=%d", ccg->volume_size, ccg->block_size);
+ debug(4, "sid=%d target=%d lun=%d XPT_CALC_GEOMETRY vsize=%jd bsize=%d",
+ sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
+ ccg->volume_size, ccg->block_size);
if(ccg->block_size == 0 ||
(ccg->volume_size < ccg->block_size)) {
// print error message ...
/* XXX: what error is appropiate? */
break;
- } else
+ }
+ else {
+ int lun, *off, boff;
+
+ lun = ccb->ccb_h.target_lun;
+ if(lun > ISCSI_MAX_LUNS) {
+ // XXX:
+ xdebug("lun %d > ISCSI_MAX_LUNS!\n", lun);
+ lun %= ISCSI_MAX_LUNS;
+ }
+ off = &sp->target_lun[lun / (sizeof(int)*8)];
+ boff = BIT(lun % (sizeof(int)*8));
+ debug(4, "sp->target_nluns=%d *off=%x boff=%x",
+ sp->target_nluns, *off, boff);
+
+ if((*off & boff) == 0) {
+ sp->target_nluns++;
+ *off |= boff;
+ }
cam_calc_geometry(ccg, /*extended*/1);
+ }
break;
}
@@ -327,7 +273,7 @@ ic_action(struct cam_sim *sim, union ccb *ccb)
break;
}
#if __FreeBSD_version < 700000
- XPT_DONE(isp, ccb);
+ XPT_DONE(sp, ccb);
#else
xpt_done(ccb);
#endif
@@ -337,102 +283,102 @@ ic_action(struct cam_sim *sim, union ccb *ccb)
static void
ic_poll(struct cam_sim *sim)
{
- debug_called(8);
+ debug_called(4);
}
int
ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp)
{
- int i;
-
debug_called(8);
- if(sp && sp->isc->cam_sim) {
- cp->path_id = cam_sim_path(sp->isc->cam_sim);
- cp->target_id = sp->sid;
- cp->target_nluns = sp->target_nluns; // XXX: -1?
- for(i = 0; i < cp->target_nluns; i++)
- cp->target_lun[i] = sp->target_lun[i];
+ if(sp && sp->cam_sim) {
+ cp->path_id = cam_sim_path(sp->cam_sim);
+ cp->target_id = 0;
+ cp->target_nluns = ISCSI_MAX_LUNS; // XXX: -1?
return 0;
}
return ENXIO;
}
void
-ic_destroy(struct isc_softc *isp)
+ic_destroy(isc_session_t *sp )
{
debug_called(8);
- CAM_LOCK(isp); // can't harm :-)
-
- xpt_async(AC_LOST_DEVICE, isp->cam_path, NULL);
- xpt_free_path(isp->cam_path);
-
- xpt_bus_deregister(cam_sim_path(isp->cam_sim));
- cam_sim_free(isp->cam_sim, TRUE /*free_devq*/);
+ if(sp->cam_path != NULL) {
+ sdebug(2, "name=%s unit=%d",
+ cam_sim_name(sp->cam_sim), cam_sim_unit(sp->cam_sim));
+ CAM_LOCK(sp);
+#if 0
+ xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL);
+#else
+ xpt_async(XPT_RESET_BUS, sp->cam_path, NULL);
+#endif
+ xpt_free_path(sp->cam_path);
+ xpt_bus_deregister(cam_sim_path(sp->cam_sim));
+ cam_sim_free(sp->cam_sim, TRUE /*free_devq*/);
- CAM_UNLOCK(isp);
+ CAM_UNLOCK(sp);
+ sdebug(2, "done");
+ }
}
int
-ic_init(struct isc_softc *isp)
+ic_init(isc_session_t *sp)
{
struct cam_sim *sim;
struct cam_devq *devq;
- struct cam_path *path;
+
+ debug_called(8);
if((devq = cam_simq_alloc(256)) == NULL)
return ENOMEM;
#if __FreeBSD_version >= 700000
- mtx_init(&isp->cam_mtx, "isc-cam", NULL, MTX_DEF);
+ mtx_init(&sp->cam_mtx, "isc-cam", NULL, MTX_DEF);
#else
isp->cam_mtx = Giant;
#endif
- sim = cam_sim_alloc(ic_action, ic_poll,
- "iscsi", isp, 0/*unit*/,
+ sim = cam_sim_alloc(ic_action,
+ ic_poll,
+ "iscsi",
+ sp,
+ sp->sid, // unit
#if __FreeBSD_version >= 700000
- &isp->cam_mtx,
+ &sp->cam_mtx,
#endif
- 1/*max_dev_transactions*/,
- 100/*max_tagged_dev_transactions*/,
+ 1, // max_dev_transactions
+ 0, // max_tagged_dev_transactions
devq);
if(sim == NULL) {
cam_simq_free(devq);
#if __FreeBSD_version >= 700000
- mtx_destroy(&isp->cam_mtx);
+ mtx_destroy(&sp->cam_mtx);
#endif
return ENXIO;
}
- CAM_LOCK(isp);
+
+ CAM_LOCK(sp);
if(xpt_bus_register(sim,
#if __FreeBSD_version >= 700000
NULL,
#endif
- 0/*bus_number*/) != CAM_SUCCESS)
- goto bad;
+ 0/*bus_number*/) != CAM_SUCCESS) {
- if(xpt_create_path(&path, xpt_periph, cam_sim_path(sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- xpt_bus_deregister(cam_sim_path(sim));
- goto bad;
+ cam_sim_free(sim, /*free_devq*/TRUE);
+ CAM_UNLOCK(sp);
+#if __FreeBSD_version >= 700000
+ mtx_destroy(&sp->cam_mtx);
+#endif
+ return ENXIO;
}
+ sp->cam_sim = sim;
+ CAM_UNLOCK(sp);
- CAM_UNLOCK(isp);
+ sdebug(1, "cam subsystem initialized");
- isp->cam_sim = sim;
- isp->cam_path = path;
+ ic_scan(sp);
- debug(2, "cam subsystem initialized"); // XXX: add dev ...
- debug(4, "sim=%p path=%p", sim, path);
return 0;
-
- bad:
- cam_sim_free(sim, /*free_devq*/TRUE);
- CAM_UNLOCK(isp);
-#if __FreeBSD_version >= 700000
- mtx_destroy(&isp->cam_mtx);
-#endif
- return ENXIO;
}
diff --git a/sys/dev/iscsi/initiator/isc_sm.c b/sys/dev/iscsi/initiator/isc_sm.c
index ec9d346..25a0919 100644
--- a/sys/dev/iscsi/initiator/isc_sm.c
+++ b/sys/dev/iscsi/initiator/isc_sm.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
*/
/*
| iSCSI - Session Manager
- | $Id: isc_sm.c,v 1.30 2007/04/22 09:53:09 danny Exp danny $
+ | $Id: isc_sm.c 743 2009-08-08 10:54:53Z danny $
*/
#include <sys/cdefs.h>
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/mbuf.h>
#include <sys/bus.h>
+#include <sys/sx.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -131,8 +132,10 @@ _scsi_rsp(isc_session_t *sp, pduq_t *pq)
debug_called(8);
opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 0);
debug(5, "itt=%x pq=%p opq=%p", ntohl(pq->pdu.ipdu.bhs.itt), pq, opq);
- if(opq != NULL)
+ if(opq != NULL) {
iscsi_done(sp, opq, pq);
+ i_acked_hld(sp, &pq->pdu);
+ }
else
xdebug("%d] we lost something itt=%x",
sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
@@ -267,7 +270,7 @@ i_prepPDU(isc_session_t *sp, pduq_t *pq)
len += pp->ahs_len;
bhp->AHSLength = pp->ahs_len / 4;
}
- if(sp->hdrDigest)
+ if(ISOK2DIG(sp->hdrDigest, pp))
len += 4;
if(pp->ds_len) {
n = pp->ds_len;
@@ -283,7 +286,7 @@ i_prepPDU(isc_session_t *sp, pduq_t *pq)
n = 4 - (len & 03);
len += n;
}
- if(sp->dataDigest)
+ if(ISOK2DIG(sp->dataDigest, pp))
len += 4;
}
@@ -321,7 +324,7 @@ isc_qout(isc_session_t *sp, pduq_t *pq)
mtx_lock(&sp->io_mtx);
sp->flags |= ISC_OQNOTEMPTY;
if(sp->flags & ISC_OWAITING)
- wakeup(&sp->flags);
+ wakeup(&sp->flags);
mtx_unlock(&sp->io_mtx);
return error;
@@ -329,7 +332,7 @@ isc_qout(isc_session_t *sp, pduq_t *pq)
/*
| called when a fullPhase is restarted
*/
-static void
+void
ism_restart(isc_session_t *sp)
{
int lastcmd;
@@ -348,30 +351,7 @@ ism_restart(isc_session_t *sp)
}
mtx_unlock(&sp->io_mtx);
- sdebug(2, "restarted lastcmd=0x%x", lastcmd);
-}
-
-int
-ism_fullfeature(struct cdev *dev, int flag)
-{
- isc_session_t *sp = (isc_session_t *)dev->si_drv2;
- int error;
-
- sdebug(2, "flag=%d", flag);
-
- error = 0;
- switch(flag) {
- case 0: // stop
- sp->flags &= ~ISC_FFPHASE;
- break;
- case 1: // start
- error = ic_fullfeature(dev);
- break;
- case 2: // restart
- ism_restart(sp);
- break;
- }
- return error;
+ sdebug(2, "restarted sn.cmd=0x%x lastcmd=0x%x", sp->sn.cmd, lastcmd);
}
void
@@ -384,26 +364,6 @@ ism_recv(isc_session_t *sp, pduq_t *pq)
bhs = &pq->pdu.ipdu.bhs;
statSN = ntohl(bhs->OpcodeSpecificFields[1]);
-#if 0
- {
- /*
- | this code is only for debugging.
- */
- sn_t *sn = &sp->sn;
- if(sp->cws == 0) {
- if((sp->flags & ISC_STALLED) == 0) {
- sdebug(4, "window closed: max=0x%x exp=0x%x opcode=0x%x cmd=0x%x cws=%d.",
- sn->maxCmd, sn->expCmd, bhs->opcode, sn->cmd, sp->cws);
- sp->flags |= ISC_STALLED;
- } else
- if(sp->flags & ISC_STALLED) {
- sdebug(4, "window opened: max=0x%x exp=0x%x opcode=0x%x cmd=0x%x cws=%d.",
- sn->maxCmd, sn->expCmd, bhs->opcode, sn->cmd, sp->cws);
- sp->flags &= ~ISC_STALLED;
- }
- }
- }
-#endif
#ifdef notyet
if(sp->sn.expCmd != sn->cmd) {
@@ -454,7 +414,7 @@ ism_recv(isc_session_t *sp, pduq_t *pq)
break;
}
}
-
+
/*
| go through the out queues looking for work
| if either nothing to do, or window is closed
@@ -465,11 +425,10 @@ proc_out(isc_session_t *sp)
{
sn_t *sn = &sp->sn;
pduq_t *pq;
- int error, ndone;
- int which;
+ int error, which;
debug_called(8);
- error = ndone = 0;
+ error = 0;
while(sp->flags & ISC_LINK_UP) {
pdu_t *pp;
@@ -508,7 +467,7 @@ proc_out(isc_session_t *sp)
sn->cmd++;
case ISCSI_WRITE_DATA:
- bhs->ExpStSN = htonl(sn->stat);
+ bhs->ExpStSN = htonl(sn->stat + 1);
break;
default:
@@ -523,19 +482,21 @@ proc_out(isc_session_t *sp)
bhs->opcode,
sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt);
- if(pq->ccb)
+ if(bhs->opcode != ISCSI_NOP_OUT)
+ /*
+ | enqued till ack is received
+ | note: sosend(...) does not mean the packet left
+ | the host so that freeing resources has to wait
+ */
i_nqueue_hld(sp, pq);
- if((error = isc_sendPDU(sp, pq)) == 0) {
- ndone++;
- if(pq->ccb == NULL)
- pdu_free(sp->isc, pq);
- }
- else {
- xdebug("error=%d ndone=%d opcode=0x%x ccb=%p itt=%x",
- error, ndone, bhs->opcode, pq->ccb, ntohl(bhs->itt));
- if(pq->ccb)
- i_remove_hld(sp, pq);
+ error = isc_sendPDU(sp, pq);
+ if(bhs->opcode == ISCSI_NOP_OUT)
+ pdu_free(sp->isc, pq);
+ if(error) {
+ xdebug("error=%d opcode=0x%x ccb=%p itt=%x",
+ error, bhs->opcode, pq->ccb, ntohl(bhs->itt));
+ i_remove_hld(sp, pq);
switch(error) {
case EPIPE:
sp->flags &= ~ISC_LINK_UP;
@@ -546,12 +507,12 @@ proc_out(isc_session_t *sp)
break;
default:
- if(pq->ccb) {
+ if(pq->ccb) {
xdebug("back to cam");
pq->ccb->ccb_h.status |= CAM_REQUEUE_REQ; // some better error?
- XPT_DONE(sp->isc, pq->ccb);
+ XPT_DONE(sp, pq->ccb);
pdu_free(sp->isc, pq);
- }
+ }
else
xdebug("we lost it!");
}
@@ -559,12 +520,12 @@ proc_out(isc_session_t *sp)
}
return error;
}
-
+
/*
| survives link breakdowns.
*/
static void
-ism_proc(void *vp)
+ism_out(void *vp)
{
isc_session_t *sp = (isc_session_t *)vp;
int error;
@@ -580,8 +541,11 @@ ism_proc(void *vp)
sdebug(3, "error=%d", error);
}
}
- mtx_lock(&sp->io_mtx);
+ mtx_lock(&sp->io_mtx);
if((sp->flags & ISC_LINK_UP) == 0) {
+ sdebug(3, "ISC_LINK_UP==0, sp->flags=%x ", sp->flags);
+ if(sp->soc != NULL)
+ sdebug(3, "so_state=%x", sp->soc->so_state);
wakeup(&sp->soc);
}
@@ -589,7 +553,7 @@ ism_proc(void *vp)
sp->flags |= ISC_OWAITING;
if(msleep(&sp->flags, &sp->io_mtx, PRIBIO, "isc_proc", hz*30) == EWOULDBLOCK) {
if(sp->flags & ISC_CON_RUNNING)
- _nop_out(sp);
+ _nop_out(sp);
}
sp->flags &= ~ISC_OWAITING;
}
@@ -600,14 +564,20 @@ ism_proc(void *vp)
sp->flags &= ~ISC_SM_RUNNING;
sdebug(3, "dropped ISC_SM_RUNNING");
+ wakeup(&sp->soc);
+ wakeup(sp); // XXX: do we need this one?
+
#if __FreeBSD_version >= 700000
destroy_dev(sp->dev);
#endif
- wakeup(sp);
debug(3, "terminated sp=%p sp->sid=%d", sp, sp->sid);
+#if __FreeBSD_version >= 800000
kproc_exit(0);
+#else
+ kthread_exit(0);
+#endif
}
#if 0
@@ -753,12 +723,16 @@ ism_stop(isc_session_t *sp)
(void)i_pdu_flush(sp);
- ic_lost_target(sp, sp->sid);
+ ic_destroy(sp);
- mtx_lock(&sc->mtx);
+ sx_xlock(&sc->unit_sx);
+ free_unr(sc->unit, sp->sid);
+ sx_xunlock(&sc->unit_sx);
+
+ mtx_lock(&sc->isc_mtx);
TAILQ_REMOVE(&sc->isc_sess, sp, sp_link);
sc->nsess--;
- mtx_unlock(&sc->mtx);
+ mtx_unlock(&sc->isc_mtx);
#if __FreeBSD_version < 700000
destroy_dev(sp->dev);
@@ -771,7 +745,6 @@ ism_stop(isc_session_t *sp)
mtx_destroy(&sp->io_mtx);
i_freeopt(&sp->opt);
- sc->sessions[sp->sid] = NULL;
if(sysctl_ctx_free(&sp->clist))
xdebug("sysctl_ctx_free failed");
@@ -792,17 +765,11 @@ ism_start(isc_session_t *sp)
TAILQ_INIT(&sp->isnd);
TAILQ_INIT(&sp->wsnd);
TAILQ_INIT(&sp->hld);
-#if 1
+
mtx_init(&sp->rsv_mtx, "iscsi-rsv", NULL, MTX_DEF);
mtx_init(&sp->rsp_mtx, "iscsi-rsp", NULL, MTX_DEF);
mtx_init(&sp->snd_mtx, "iscsi-snd", NULL, MTX_DEF);
mtx_init(&sp->hld_mtx, "iscsi-hld", NULL, MTX_DEF);
-#else
- mtx_init(&sp->rsv_mtx, "iscsi-rsv", NULL, MTX_SPIN);
- mtx_init(&sp->rsp_mtx, "iscsi-rsp", NULL, MTX_SPIN);
- mtx_init(&sp->snd_mtx, "iscsi-snd", NULL, MTX_SPIN);
- mtx_init(&sp->hld_mtx, "iscsi-hld", NULL, MTX_SPIN);
-#endif
mtx_init(&sp->io_mtx, "iscsi-io", NULL, MTX_DEF);
isc_add_sysctls(sp);
@@ -810,5 +777,10 @@ ism_start(isc_session_t *sp)
sp->flags |= ISC_SM_RUN;
debug(4, "starting ism_proc: sp->sid=%d", sp->sid);
- return kproc_create(ism_proc, sp, &sp->stp, 0, 0, "ism_%d", sp->sid);
+
+#if __FreeBSD_version >= 800000
+ return kproc_create(ism_out, sp, &sp->stp, 0, 0, "isc_out %d", sp->sid);
+#else
+ return kthread_create(ism_out, sp, &sp->stp, 0, 0, "isc_out %d", sp->sid);
+#endif
}
diff --git a/sys/dev/iscsi/initiator/isc_soc.c b/sys/dev/iscsi/initiator/isc_soc.c
index ef32e63..329f830 100644
--- a/sys/dev/iscsi/initiator/isc_soc.c
+++ b/sys/dev/iscsi/initiator/isc_soc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,10 +25,8 @@
*
*/
/*
- | iSCSI
- | $Id: isc_soc.c,v 1.26 2007/05/19 06:09:01 danny Exp danny $
+ | $Id: isc_soc.c 998 2009-12-20 10:32:45Z danny $
*/
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -66,9 +64,7 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef USE_MBUF
-
static int ou_refcnt = 0;
-
/*
| function for freeing external storage for mbuf
*/
@@ -79,7 +75,7 @@ ext_free(void *a, void *b)
if(pq->buf != NULL) {
debug(3, "ou_refcnt=%d a=%p b=%p", ou_refcnt, a, pq->buf);
- free(pq->buf, M_ISCSI);
+ free(pq->buf, M_ISCSIBUF);
pq->buf = NULL;
}
}
@@ -88,84 +84,96 @@ int
isc_sendPDU(isc_session_t *sp, pduq_t *pq)
{
struct mbuf *mh, **mp;
- pdu_t *pp = &pq->pdu;
- int len, error;
+ pdu_t *pp = &pq->pdu;
+ int len, error;
debug_called(8);
/*
| mbuf for the iSCSI header
*/
MGETHDR(mh, M_TRYWAIT, MT_DATA);
- mh->m_len = mh->m_pkthdr.len = sizeof(union ipdu_u);
mh->m_pkthdr.rcvif = NULL;
- MH_ALIGN(mh, sizeof(union ipdu_u));
- bcopy(&pp->ipdu, mh->m_data, sizeof(union ipdu_u));
mh->m_next = NULL;
-
- if(sp->hdrDigest)
- pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
+ mh->m_len = sizeof(union ipdu_u);
+
+ if(ISOK2DIG(sp->hdrDigest, pp)) {
+ pp->hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
+ mh->m_len += sizeof(pp->hdr_dig);
+ if(pp->ahs_len) {
+ debug(2, "ahs_len=%d", pp->ahs_len);
+ pp->hdr_dig = sp->hdrDigest(&pp->ahs_addr, pp->ahs_len, pp->hdr_dig);
+ }
+ debug(3, "pp->hdr_dig=%04x", htonl(pp->hdr_dig));
+ }
if(pp->ahs_len) {
/*
| Add any AHS to the iSCSI hdr mbuf
- | XXX Assert: (mh->m_pkthdr.len + pp->ahs_len) < MHLEN
*/
- bcopy(pp->ahs, (mh->m_data + mh->m_len), pp->ahs_len);
- mh->m_len += pp->ahs_len;
- mh->m_pkthdr.len += pp->ahs_len;
-
- if(sp->hdrDigest)
- pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig);
+ if((mh->m_len + pp->ahs_len) < MHLEN) {
+ MH_ALIGN(mh, mh->m_len + pp->ahs_len);
+ bcopy(&pp->ipdu, mh->m_data, mh->m_len);
+ bcopy(pp->ahs_addr, mh->m_data + mh->m_len, pp->ahs_len);
+ mh->m_len += pp->ahs_len;
+ }
+ else
+ panic("len AHS=%d too big, not impleneted yet", pp->ahs_len);
}
- if(sp->hdrDigest) {
- debug(2, "hdr_dig=%x", pq->pdu.hdr_dig);
- /*
- | Add header digest to the iSCSI hdr mbuf
- | XXX Assert: (mh->m_pkthdr.len + 4) < MHLEN
- */
- bcopy(&pp->hdr_dig, (mh->m_data + mh->m_len), sizeof(int));
- mh->m_len += sizeof(int);
- mh->m_pkthdr.len += sizeof(int);
+ else {
+ MH_ALIGN(mh, mh->m_len);
+ bcopy(&pp->ipdu, mh->m_data, mh->m_len);
}
+ mh->m_pkthdr.len = mh->m_len;
mp = &mh->m_next;
- if(pq->pdu.ds) {
- struct mbuf *md;
- int off = 0;
+ if(pp->ds_len && pq->pdu.ds_addr) {
+ struct mbuf *md;
+ int off = 0;
len = pp->ds_len;
- while(len & 03) // the specs say it must be int alligned
- len++;
while(len > 0) {
- int l;
-
+ int l;
+
MGET(md, M_TRYWAIT, MT_DATA);
md->m_ext.ref_cnt = &ou_refcnt;
- l = min(MCLBYTES, len);
- debug(5, "setting ext_free(arg=%p len/l=%d/%d)", pq->buf, len, l);
- MEXTADD(md, pp->ds + off, l, ext_free, pp->ds + off, pq, 0, EXT_EXTREF);
- md->m_len = l;
- md->m_next = NULL;
- mh->m_pkthdr.len += l;
- *mp = md;
- mp = &md->m_next;
- len -= l;
- off += l;
- }
- }
- if(sp->dataDigest) {
- struct mbuf *me;
-
- pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
-
- MGET(me, M_TRYWAIT, MT_DATA);
- me->m_len = sizeof(int);
- MH_ALIGN(mh, sizeof(int));
- bcopy(&pp->ds_dig, me->m_data, sizeof(int));
- me->m_next = NULL;
- mh->m_pkthdr.len += sizeof(int);
- *mp = me;
+ l = min(MCLBYTES, len);
+ debug(4, "setting ext_free(arg=%p len/l=%d/%d)", pq->buf, len, l);
+ MEXTADD(md, pp->ds_addr + off, l, ext_free,
+#if __FreeBSD_version >= 800000
+ pp->ds_addr + off,
+#endif
+ pq, 0, EXT_EXTREF);
+ md->m_len = l;
+ md->m_next = NULL;
+ mh->m_pkthdr.len += l;
+ *mp = md;
+ mp = &md->m_next;
+ len -= l;
+ off += l;
+ }
+ if(((pp->ds_len & 03) != 0) || ISOK2DIG(sp->dataDigest, pp)) {
+ MGET(md, M_TRYWAIT, MT_DATA);
+ if(pp->ds_len & 03)
+ len = 4 - (pp->ds_len & 03);
+ else
+ len = 0;
+ md->m_len = len;
+ if(ISOK2DIG(sp->dataDigest, pp))
+ md->m_len += sizeof(pp->ds_dig);
+ M_ALIGN(md, md->m_len);
+ if(ISOK2DIG(sp->dataDigest, pp)) {
+ pp->ds_dig = sp->dataDigest(pp->ds_addr, pp->ds_len, 0);
+ if(len) {
+ bzero(md->m_data, len); // RFC says SHOULD be 0
+ pp->ds_dig = sp->dataDigest(md->m_data, len, pp->ds_dig);
+ }
+ bcopy(&pp->ds_dig, md->m_data+len, sizeof(pp->ds_dig));
+ }
+ md->m_next = NULL;
+ mh->m_pkthdr.len += md->m_len;
+ *mp = md;
+ }
}
if((error = sosend(sp->soc, NULL, NULL, mh, 0, 0, sp->td)) != 0) {
- sdebug(3, "error=%d", error);
+ sdebug(2, "error=%d", error);
return error;
}
sp->stats.nsent++;
@@ -191,39 +199,46 @@ isc_sendPDU(isc_session_t *sp, pduq_t *pq)
iv->iov_base = &pp->ipdu;
iv->iov_len = sizeof(union ipdu_u);
- uio->uio_resid = pq->len;
+ uio->uio_resid = iv->iov_len;
iv++;
- if(sp->hdrDigest)
+ if(ISOK2DIG(sp->hdrDigest, pp))
pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
if(pp->ahs_len) {
- iv->iov_base = pp->ahs;
+ iv->iov_base = pp->ahs_addr;
iv->iov_len = pp->ahs_len;
+ uio->uio_resid += iv->iov_len;
iv++;
-
- if(sp->hdrDigest)
- pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig);
+ if(ISOK2DIG(sp->hdrDigest, pp))
+ pp->hdr_dig = sp->hdrDigest(&pp->ahs_addr, pp->ahs_len, pp->hdr_dig);
}
- if(sp->hdrDigest) {
- debug(2, "hdr_dig=%x", pq->pdu.hdr_dig);
+ if(ISOK2DIG(sp->hdrDigest, pp)) {
+ debug(3, "hdr_dig=%04x", htonl(pp->hdr_dig));
iv->iov_base = &pp->hdr_dig;
iv->iov_len = sizeof(int);
+ uio->uio_resid += iv->iov_len ;
iv++;
}
- if(pq->pdu.ds) {
- iv->iov_base = pp->ds;
+ if(pq->pdu.ds_addr && pp->ds_len) {
+ iv->iov_base = pp->ds_addr;
iv->iov_len = pp->ds_len;
while(iv->iov_len & 03) // the specs say it must be int alligned
iv->iov_len++;
+ uio->uio_resid += iv->iov_len ;
iv++;
+ if(ISOK2DIG(sp->dataDigest, pp)) {
+ pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
+ iv->iov_base = &pp->ds_dig;
+ iv->iov_len = sizeof(pp->ds_dig);
+ uio->uio_resid += iv->iov_len ;
+ iv++;
+ }
}
- if(sp->dataDigest) {
- pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
- iv->iov_base = &pp->ds_dig;
- iv->iov_len = sizeof(int);
- iv++;
- }
- uio->uio_iovcnt = iv - pq->iov;
- sdebug(5, "opcode=%x iovcnt=%d uio_resid=%d itt=%x",
+ uio->uio_iovcnt = iv - pq->iov;
+ sdebug(4, "pq->len=%d uio->uio_resid=%d uio->uio_iovcnt=%d", pq->len,
+ uio->uio_resid,
+ uio->uio_iovcnt);
+
+ sdebug(4, "opcode=%x iovcnt=%d uio_resid=%d itt=%x",
pp->ipdu.bhs.opcode, uio->uio_iovcnt, uio->uio_resid,
ntohl(pp->ipdu.bhs.itt));
sdebug(5, "sp=%p sp->soc=%p uio=%p sp->td=%p",
@@ -244,12 +259,12 @@ isc_sendPDU(isc_session_t *sp, pduq_t *pq)
| XXX: untested code
*/
sdebug(1, "uio->uio_resid=%d uio->uio_iovcnt=%d",
- uio->uio_resid, uio->uio_iovcnt);
+ uio->uio_resid, uio->uio_iovcnt);
iv = uio->uio_iov;
len -= uio->uio_resid;
while(uio->uio_iovcnt > 0) {
if(iv->iov_len > len) {
- caddr_t bp = (caddr_t)iv->iov_base;
+ caddr_t bp = (caddr_t)iv->iov_base;
iv->iov_len -= len;
iv->iov_base = (void *)&bp[len];
@@ -265,7 +280,6 @@ isc_sendPDU(isc_session_t *sp, pduq_t *pq)
if(error == 0) {
sp->stats.nsent++;
getbintime(&sp->stats.t_sent);
-
}
return error;
@@ -322,159 +336,197 @@ so_getbhs(isc_session_t *sp)
error = soreceive(sp->soc, NULL, uio, 0, 0, &flags);
if(error)
- debug(2, "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd",
+ debug(2,
+#if __FreeBSD_version > 800000
+ "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd",
+#else
+ "error=%d so_error=%d uio->uio_resid=%d iov.iov_len=%zd",
+#endif
error,
sp->soc->so_error, uio->uio_resid, iov->iov_len);
if(!error && (uio->uio_resid > 0)) {
error = EPIPE; // was EAGAIN
- debug(2, "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd so_state=%x",
+ debug(2,
+#if __FreeBSD_version > 800000
+ "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd so_state=%x",
+#else
+ "error=%d so_error=%d uio->uio_resid=%d iov.iov_len=%zd so_state=%x",
+#endif
error,
sp->soc->so_error, uio->uio_resid, iov->iov_len, sp->soc->so_state);
}
-
return error;
}
/*
- | so_recv gets called when there is at least
- | an iSCSI header in the queue
+ | so_recv gets called when
+ | an iSCSI header has been received.
+ | Note: the designers had no intentions
+ | in making programmer's life easy.
*/
static int
so_recv(isc_session_t *sp, pduq_t *pq)
{
- struct socket *so = sp->soc;
sn_t *sn = &sp->sn;
struct uio *uio = &pq->uio;
- pdu_t *pp;
+ pdu_t *pp = &pq->pdu;
+ bhs_t *bhs = &pp->ipdu.bhs;
+ struct iovec *iov = pq->iov;
int error;
- size_t n, len;
- bhs_t *bhs;
+ u_int len;
u_int max, exp;
+ int flags = MSG_WAITALL;
debug_called(8);
/*
| now calculate how much data should be in the buffer
- | NOTE: digest is not verified/calculated - yet
*/
- pp = &pq->pdu;
- bhs = &pp->ipdu.bhs;
-
+ uio->uio_iov = iov;
+ uio->uio_iovcnt = 0;
len = 0;
if(bhs->AHSLength) {
+ debug(2, "bhs->AHSLength=%d", bhs->AHSLength);
pp->ahs_len = bhs->AHSLength * 4;
len += pp->ahs_len;
+ pp->ahs_addr = malloc(pp->ahs_len, M_TEMP, M_WAITOK); // XXX: could get stuck here
+ iov->iov_base = pp->ahs_addr;
+ iov->iov_len = pp->ahs_len;
+ uio->uio_iovcnt++;
+ iov++;
+ }
+ if(ISOK2DIG(sp->hdrDigest, pp)) {
+ len += sizeof(pp->hdr_dig);
+ iov->iov_base = &pp->hdr_dig;
+ iov->iov_len = sizeof(pp->hdr_dig);
+ uio->uio_iovcnt++;
}
- if(sp->hdrDigest)
- len += 4;
+ if(len) {
+ uio->uio_rw = UIO_READ;
+ uio->uio_segflg = UIO_SYSSPACE;
+ uio->uio_resid = len;
+ uio->uio_td = sp->td; // why ...
+ error = soreceive(sp->soc, NULL, uio, NULL, NULL, &flags);
+ //if(error == EAGAIN)
+ // XXX: this needs work! it hangs iscontrol
+ if(error || uio->uio_resid) {
+ debug(2,
+#if __FreeBSD_version > 800000
+ "len=%d error=%d uio->uio_resid=%zd",
+#else
+ "len=%d error=%d uio->uio_resid=%d",
+#endif
+ len, error, uio->uio_resid);
+ goto out;
+ }
+ if(ISOK2DIG(sp->hdrDigest, pp)) {
+ bhs_t *bhs;
+ u_int digest;
+
+ bhs = (bhs_t *)&pp->ipdu;
+ digest = sp->hdrDigest(bhs, sizeof(bhs_t), 0);
+ if(pp->ahs_len)
+ digest = sp->hdrDigest(pp->ahs_addr, pp->ahs_len, digest);
+ if(pp->hdr_dig != digest) {
+ debug(2, "bad header digest: received=%x calculated=%x", pp->hdr_dig, digest);
+ // XXX: now what?
+ error = EIO;
+ goto out;
+ }
+ }
+ if(pp->ahs_len) {
+ debug(2, "ahs len=%x type=%x spec=%x",
+ pp->ahs_addr->len, pp->ahs_addr->type, pp->ahs_addr->spec);
+ // XXX: till I figure out what to do with this
+ free(pp->ahs_addr, M_TEMP);
+ }
+ pq->len += len; // XXX: who needs this?
+ bzero(uio, sizeof(struct uio));
+ len = 0;
+ }
+
if(bhs->DSLength) {
- n = bhs->DSLength;
+ len = bhs->DSLength;
#if BYTE_ORDER == LITTLE_ENDIAN
- pp->ds_len = ((n & 0x00ff0000) >> 16)
- | (n & 0x0000ff00)
- | ((n & 0x000000ff) << 16);
-#else
- pp->ds_len = n;
+ len = ((len & 0x00ff0000) >> 16)
+ | (len & 0x0000ff00)
+ | ((len & 0x000000ff) << 16);
#endif
- len += pp->ds_len;
+ pp->ds_len = len;
+ if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) {
+ xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d",
+ len, sp->opt.maxRecvDataSegmentLength);
+ log(LOG_ERR,
+ "so_recv: impossible PDU length(%d) from iSCSI %s/%s\n",
+ len, sp->opt.targetAddress, sp->opt.targetName);
+ /*
+ | XXX: this will really screwup the stream.
+ | should clear up the buffer till a valid header
+ | is found, or just close connection ...
+ | should read the RFC.
+ */
+ error = E2BIG;
+ goto out;
+ }
while(len & 03)
len++;
- if(sp->dataDigest)
+ if(ISOK2DIG(sp->dataDigest, pp))
len += 4;
- }
-
- if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) {
-#if 0
- xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d",
- len, sp->opt.maxRecvDataSegmentLength);
- // deep trouble here, probably all we can do is
- // force a disconnect, XXX: check RFC ...
- log(LOG_ERR,
- "so_recv: impossible PDU length(%ld) from iSCSI %s/%s\n",
- len, sp->opt.targetAddress, sp->opt.targetName);
-#endif
- /*
- | XXX: this will really screwup the stream.
- | should clear up the buffer till a valid header
- | is found, or just close connection ...
- | should read the RFC.
- */
- error = E2BIG;
- goto out;
- }
- if(len) {
- int flags = MSG_WAITALL;
- struct mbuf **mp;
-
- mp = &pq->mp;
-
uio->uio_resid = len;
- uio->uio_td = curthread; // why ...
- if(sp->douio) {
- // it's more efficient to use mbufs -- why?
- if(bhs->opcode == ISCSI_READ_DATA) {
- pduq_t *opq;
-
- opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1);
- if(opq != NULL) {
- union ccb *ccb = opq->ccb;
- struct ccb_scsiio *csio = &ccb->csio;
- pdu_t *opp = &opq->pdu;
- scsi_req_t *cmd = &opp->ipdu.scsi_req;
- data_in_t *rcmd = &pq->pdu.ipdu.data_in;
- bhs_t *bhp = &opp->ipdu.bhs;
- int r;
-
- if(bhp->opcode == ISCSI_SCSI_CMD
- && cmd->R
- && (ntohl(cmd->edtlen) >= pq->pdu.ds_len)) {
- struct iovec *iov = pq->iov;
- iov->iov_base = csio->data_ptr + ntohl(rcmd->bo);
- iov->iov_len = pq->pdu.ds_len;
-
- uio->uio_rw = UIO_READ;
- uio->uio_segflg = UIO_SYSSPACE;
- uio->uio_iov = iov;
- uio->uio_iovcnt = 1;
- if(len > pq->pdu.ds_len) {
- pq->iov[1].iov_base = &r;
- pq->iov[1].iov_len = len - pq->pdu.ds_len;
- uio->uio_iovcnt++;
- }
- mp = NULL;
-
- sdebug(4, "uio_resid=0x%zx itt=0x%x bp=%p bo=%x len=%x/%x",
- uio->uio_resid,
- ntohl(pq->pdu.ipdu.bhs.itt),
- csio->data_ptr, ntohl(rcmd->bo), ntohl(cmd->edtlen), pq->pdu.ds_len);
- }
- }
- }
- }
- error = soreceive(so, NULL, uio, mp, NULL, &flags);
+ uio->uio_td = sp->td; // why ...
+ pq->len += len; // XXX: do we need this?
+ error = soreceive(sp->soc, NULL, uio, &pq->mp, NULL, &flags);
//if(error == EAGAIN)
// XXX: this needs work! it hangs iscontrol
if(error || uio->uio_resid)
goto out;
+ if(ISOK2DIG(sp->dataDigest, pp)) {
+ struct mbuf *m;
+ u_int digest, ds_len, cnt;
+
+ // get the received digest
+ m_copydata(pq->mp,
+ len - sizeof(pp->ds_dig),
+ sizeof(pp->ds_dig),
+ (caddr_t)&pp->ds_dig);
+ // calculate all mbufs
+ digest = 0;
+ ds_len = len - sizeof(pp->ds_dig);
+ for(m = pq->mp; m != NULL; m = m->m_next) {
+ cnt = MIN(ds_len, m->m_len);
+ digest = sp->dataDigest(mtod(m, char *), cnt, digest);
+ ds_len -= cnt;
+ if(ds_len == 0)
+ break;
+ }
+ if(digest != pp->ds_dig) {
+ sdebug(1, "bad data digest: received=%x calculated=%x", pp->ds_dig, digest);
+ error = EIO; // XXX: find a better error
+ goto out;
+ }
+ KASSERT(ds_len == 0, ("ds_len not zero"));
+ }
}
- pq->len += len;
sdebug(6, "len=%d] opcode=0x%x ahs_len=0x%x ds_len=0x%x",
pq->len, bhs->opcode, pp->ahs_len, pp->ds_len);
max = ntohl(bhs->MaxCmdSN);
exp = ntohl(bhs->ExpStSN);
-
if(max < exp - 1 &&
max > exp - _MAXINCR) {
sdebug(2, "bad cmd window size");
error = EIO; // XXX: for now;
goto out; // error
}
-
if(SNA_GT(max, sn->maxCmd))
sn->maxCmd = max;
-
if(SNA_GT(exp, sn->expCmd))
sn->expCmd = exp;
+ /*
+ | remove from the holding queue packets
+ | that have been acked and don't need
+ | further processing.
+ */
+ i_acked_hld(sp, NULL);
sp->cws = sn->maxCmd - sn->expCmd + 1;
@@ -482,6 +534,10 @@ so_recv(isc_session_t *sp, pduq_t *pq)
out:
// XXX: need some work here
+ if(pp->ahs_len) {
+ // XXX: till I figure out what to do with this
+ free(pp->ahs_addr, M_TEMP);
+ }
xdebug("have a problem, error=%d", error);
pdu_free(sp->isc, pq);
if(!error && uio->uio_resid > 0)
@@ -510,8 +566,8 @@ so_input(isc_session_t *sp)
*/
pq = pdu_alloc(sp->isc, M_NOWAIT);
if(pq == NULL) { // XXX: might cause a deadlock ...
- debug(3, "out of pdus, wait");
- pq = pdu_alloc(sp->isc, M_NOWAIT); // OK to WAIT
+ debug(2, "out of pdus, wait");
+ pq = pdu_alloc(sp->isc, M_WAITOK); // OK to WAIT
}
pq->pdu.ipdu.bhs = sp->bhs;
pq->len = sizeof(bhs_t); // so far only the header was read
@@ -536,7 +592,7 @@ so_input(isc_session_t *sp)
| in packets from the target.
*/
static void
-isc_soc(void *vp)
+isc_in(void *vp)
{
isc_session_t *sp = (isc_session_t *)vp;
struct socket *so = sp->soc;
@@ -545,9 +601,6 @@ isc_soc(void *vp)
debug_called(8);
sp->flags |= ISC_CON_RUNNING;
- if(sp->cam_path)
- ic_release(sp);
-
error = 0;
while((sp->flags & (ISC_CON_RUN | ISC_LINK_UP)) == (ISC_CON_RUN | ISC_LINK_UP)) {
// XXX: hunting ...
@@ -559,7 +612,7 @@ isc_soc(void *vp)
if(error == 0) {
mtx_lock(&sp->io_mtx);
if(sp->flags & ISC_OWAITING) {
- wakeup(&sp->flags);
+ wakeup(&sp->flags);
}
mtx_unlock(&sp->io_mtx);
} else if(error == EPIPE) {
@@ -594,8 +647,11 @@ isc_soc(void *vp)
mtx_unlock(&sp->io_mtx);
sdebug(2, "dropped ISC_CON_RUNNING");
-
+#if __FreeBSD_version >= 800000
kproc_exit(0);
+#else
+ kthread_exit(0);
+#endif
}
void
@@ -621,7 +677,6 @@ isc_stop_receiver(isc_session_t *sp)
}
mtx_unlock(&sp->io_mtx);
-
if(sp->fp != NULL)
fdrop(sp->fp, sp->td);
fputsock(sp->soc);
@@ -637,6 +692,10 @@ isc_start_receiver(isc_session_t *sp)
debug_called(8);
sp->flags |= ISC_CON_RUN | ISC_LINK_UP;
-
- kproc_create(isc_soc, sp, &sp->soc_proc, 0, 0, "iscsi%d", sp->sid);
+#if __FreeBSD_version >= 800000
+ kproc_create
+#else
+ kthread_create
+#endif
+ (isc_in, sp, &sp->soc_proc, 0, 0, "isc_in %d", sp->sid);
}
diff --git a/sys/dev/iscsi/initiator/isc_subr.c b/sys/dev/iscsi/initiator/isc_subr.c
index b59516d..7a8138b 100644
--- a/sys/dev/iscsi/initiator/isc_subr.c
+++ b/sys/dev/iscsi/initiator/isc_subr.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
*/
/*
| iSCSI
- | $Id: isc_subr.c,v 1.20 2006/12/01 09:10:17 danny Exp danny $
+ | $Id: isc_subr.c 560 2009-05-07 07:37:49Z danny $
*/
#include <sys/cdefs.h>
@@ -58,20 +58,22 @@ __FBSDID("$FreeBSD$");
#include <dev/iscsi/initiator/iscsi.h>
#include <dev/iscsi/initiator/iscsivar.h>
+MALLOC_DEFINE(M_ISC, "iSC", "iSCSI driver options");
+
static char *
i_strdupin(char *s, size_t maxlen)
{
size_t len;
char *p, *q;
- p = malloc(maxlen, M_ISCSI, M_WAITOK);
+ p = malloc(maxlen, M_ISC, M_WAITOK);
if(copyinstr(s, p, maxlen, &len)) {
- free(p, M_ISCSI);
+ free(p, M_ISC);
return NULL;
}
- q = malloc(len, M_ISCSI, M_WAITOK);
+ q = malloc(len, M_ISC, M_WAITOK);
bcopy(p, q, len);
- free(p, M_ISCSI);
+ free(p, M_ISC);
return q;
}
@@ -98,50 +100,51 @@ i_setopt(isc_session_t *sp, isc_opt_t *opt)
if(opt->maxXmitDataSegmentLength > 0) {
// danny's RFC
sp->opt.maxXmitDataSegmentLength = opt->maxXmitDataSegmentLength;
- sdebug(2, "maXmitDataSegmentLength=%d", sp->opt.maxXmitDataSegmentLength);
+ sdebug(2, "opt.maXmitDataSegmentLength=%d", sp->opt.maxXmitDataSegmentLength);
}
if(opt->maxBurstLength != 0) {
sp->opt.maxBurstLength = opt->maxBurstLength;
- sdebug(2, "maxBurstLength=%d", sp->opt.maxBurstLength);
+ sdebug(2, "opt.maxBurstLength=%d", sp->opt.maxBurstLength);
}
if(opt->targetAddress != NULL) {
if(sp->opt.targetAddress != NULL)
- free(sp->opt.targetAddress, M_ISCSI);
+ free(sp->opt.targetAddress, M_ISC);
sp->opt.targetAddress = i_strdupin(opt->targetAddress, 128);
- sdebug(4, "opt.targetAddress='%s'", sp->opt.targetAddress);
+ sdebug(2, "opt.targetAddress='%s'", sp->opt.targetAddress);
}
if(opt->targetName != NULL) {
if(sp->opt.targetName != NULL)
- free(sp->opt.targetName, M_ISCSI);
+ free(sp->opt.targetName, M_ISC);
sp->opt.targetName = i_strdupin(opt->targetName, 128);
- sdebug(4, "opt.targetName='%s'", sp->opt.targetName);
+ sdebug(2, "opt.targetName='%s'", sp->opt.targetName);
}
if(opt->initiatorName != NULL) {
if(sp->opt.initiatorName != NULL)
- free(sp->opt.initiatorName, M_ISCSI);
+ free(sp->opt.initiatorName, M_ISC);
sp->opt.initiatorName = i_strdupin(opt->initiatorName, 128);
- sdebug(4, "opt.initiatorName='%s'", sp->opt.initiatorName);
+ sdebug(2, "opt.initiatorName='%s'", sp->opt.initiatorName);
}
if(opt->maxluns > 0) {
if(opt->maxluns > ISCSI_MAX_LUNS)
sp->opt.maxluns = ISCSI_MAX_LUNS; // silently chop it down ...
sp->opt.maxluns = opt->maxluns;
- sdebug(4, "opt.maxluns=%d", sp->opt.maxluns);
+ sdebug(2, "opt.maxluns=%d", sp->opt.maxluns);
}
if(opt->headerDigest != NULL) {
sdebug(2, "opt.headerDigest='%s'", opt->headerDigest);
if(strcmp(opt->headerDigest, "CRC32C") == 0) {
sp->hdrDigest = (digest_t *)i_crc32c;
- sdebug(2, "headerDigest set");
+ sdebug(2, "opt.headerDigest set");
}
}
if(opt->dataDigest != NULL) {
+ sdebug(2, "opt.dataDigest='%s'", opt->headerDigest);
if(strcmp(opt->dataDigest, "CRC32C") == 0) {
sp->dataDigest = (digest_t *)i_crc32c;
- sdebug(2, "dataDigest set");
+ sdebug(2, "opt.dataDigest set");
}
}
@@ -151,16 +154,18 @@ i_setopt(isc_session_t *sp, isc_opt_t *opt)
void
i_freeopt(isc_opt_t *opt)
{
+ debug_called(8);
+
if(opt->targetAddress != NULL) {
- free(opt->targetAddress, M_ISCSI);
+ free(opt->targetAddress, M_ISC);
opt->targetAddress = NULL;
}
if(opt->targetName != NULL) {
- free(opt->targetName, M_ISCSI);
+ free(opt->targetName, M_ISC);
opt->targetName = NULL;
}
if(opt->initiatorName != NULL) {
- free(opt->initiatorName, M_ISCSI);
+ free(opt->initiatorName, M_ISC);
opt->initiatorName = NULL;
}
}
diff --git a/sys/dev/iscsi/initiator/iscsi.c b/sys/dev/iscsi/initiator/iscsi.c
index 2296989..b44c4f7 100644
--- a/sys/dev/iscsi/initiator/iscsi.c
+++ b/sys/dev/iscsi/initiator/iscsi.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,8 +25,7 @@
*
*/
/*
- | iSCSI
- | $Id: iscsi.c,v 1.35 2007/04/22 08:58:29 danny Exp danny $
+ | $Id: iscsi.c 752 2009-08-20 11:23:28Z danny $
*/
#include <sys/cdefs.h>
@@ -56,15 +55,17 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/syslog.h>
#include <vm/uma.h>
+#include <sys/sx.h>
#include <dev/iscsi/initiator/iscsi.h>
#include <dev/iscsi/initiator/iscsivar.h>
+static char *iscsi_driver_version = "2.2.4.2";
-static char *iscsi_driver_version = "2.1.0";
-
-static struct isc_softc isc;
+static struct isc_softc *isc;
MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI driver");
+MALLOC_DEFINE(M_ISCSIBUF, "iSCbuf", "iSCSI buffers");
+MALLOC_DEFINE(M_TMP, "iSCtmp", "iSCSI tmp");
#ifdef ISCSI_INITIATOR_DEBUG
int iscsi_debug = ISCSI_INITIATOR_DEBUG;
@@ -74,6 +75,12 @@ SYSCTL_INT(_debug, OID_AUTO, iscsi_initiator, CTLFLAG_RW, &iscsi_debug, 0,
struct mtx iscsi_dbg_mtx;
#endif
+static int max_sessions = MAX_SESSIONS;
+SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_sessions, CTLFLAG_RDTUN, &max_sessions, MAX_SESSIONS,
+ "Max sessions allowed");
+static int max_pdus = MAX_PDUS;
+SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_pdus, CTLFLAG_RDTUN, &max_pdus, MAX_PDUS,
+ "Max pdu pool");
static char isid[6+1] = {
0x80,
@@ -91,6 +98,7 @@ static int i_ping(struct cdev *dev);
static int i_send(struct cdev *dev, caddr_t arg, struct thread *td);
static int i_recv(struct cdev *dev, caddr_t arg, struct thread *td);
static int i_setsoc(isc_session_t *sp, int fd, struct thread *td);
+static int i_fullfeature(struct cdev *dev, int flag);
static d_open_t iscsi_open;
static d_close_t iscsi_close;
@@ -117,39 +125,28 @@ iscsi_open(struct cdev *dev, int flags, int otype, struct thread *td)
debug(7, "dev=%d", dev2unit(dev));
- if(dev2unit(dev) > MAX_SESSIONS) {
+ if(dev2unit(dev) > max_sessions) {
// should not happen
return ENODEV;
}
- if(dev2unit(dev) == MAX_SESSIONS) {
-#if 1
- struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
-
- // this should be in iscsi_start
- if(sc->cam_sim == NULL)
- ic_init(sc);
-#endif
- }
return 0;
}
static int
iscsi_close(struct cdev *dev, int flag, int otyp, struct thread *td)
{
- struct isc *sc;
isc_session_t *sp;
debug_called(8);
- debug(3, "flag=%x", flag);
+ debug(3, "session=%d flag=%x", dev2unit(dev), flag);
- sc = (struct isc *)dev->si_drv1;
- if(dev2unit(dev) == MAX_SESSIONS) {
+ if(dev2unit(dev) == max_sessions) {
return 0;
}
- sp = (isc_session_t *)dev->si_drv2;
+ sp = dev->si_drv2;
if(sp != NULL) {
- sdebug(2, "session=%d flags=%x", dev2unit(dev), sp->flags );
+ sdebug(3, "sp->flags=%x", sp->flags );
/*
| if still in full phase, this probably means
| that something went realy bad.
@@ -170,19 +167,19 @@ iscsi_close(struct cdev *dev, int flag, int otyp, struct thread *td)
static int
iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
{
- struct isc *sc;
+ struct isc_softc *sc;
isc_session_t *sp;
isc_opt_t *opt;
int error;
- sc = (struct isc *)dev->si_drv1;
debug_called(8);
error = 0;
- if(dev2unit(dev) == MAX_SESSIONS) {
+ if(dev2unit(dev) == max_sessions) {
/*
| non Session commands
*/
+ sc = dev->si_drv1;
if(sc == NULL)
return ENXIO;
@@ -190,18 +187,17 @@ iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *
case ISCSISETSES:
error = i_create_session(dev, (int *)arg);
if(error == 0)
-
- break;
+ break;
default:
- error = ENXIO; // XXX:
+ error = ENXIO;
}
return error;
}
- sp = (isc_session_t *)dev->si_drv2;
/*
| session commands
*/
+ sp = dev->si_drv2;
if(sp == NULL)
return ENXIO;
@@ -230,7 +226,7 @@ iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *
break;
case ISCSISTART:
- error = sp->soc == NULL? ENOTCONN: ism_fullfeature(dev, 1);
+ error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 1);
if(error == 0) {
sp->proc = td->td_proc;
SYSCTL_ADD_UINT(&sp->clist,
@@ -243,11 +239,11 @@ iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *
break;
case ISCSIRESTART:
- error = sp->soc == NULL? ENOTCONN: ism_fullfeature(dev, 2);
+ error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 2);
break;
case ISCSISTOP:
- error = ism_fullfeature(dev, 0);
+ error = i_fullfeature(dev, 0);
break;
case ISCSISIGNAL: {
@@ -283,9 +279,9 @@ iscsi_read(struct cdev *dev, struct uio *uio, int ioflag)
pduq_t *pq;
char buf[1024];
- sc = (struct isc_softc *)dev->si_drv1;
- sp = (isc_session_t *)dev->si_drv2;
- if(dev2unit(dev) == MAX_SESSIONS) {
+ sc = dev->si_drv1;
+ sp = dev->si_drv2;
+ if(dev2unit(dev) == max_sessions) {
sprintf(buf, "/----- Session ------/\n");
uiomove(buf, strlen(buf), uio);
int i = 0;
@@ -310,10 +306,11 @@ iscsi_read(struct cdev *dev, struct uio *uio, int ioflag)
int i = 0;
struct socket *so = sp->soc;
#define pukeit(i, pq) do {\
- sprintf(buf, "%03d] %06x %02x %x %ld %jd\n",\
- i, ntohl( pq->pdu.ipdu.bhs.CmdSN), \
+ sprintf(buf, "%03d] %06x %02x %06x %06x %zd\n",\
+ i, ntohl(pq->pdu.ipdu.bhs.CmdSN),\
pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\
- (long)pq->ts.sec, pq->ts.frac);\
+ ntohl(pq->pdu.ipdu.bhs.ExpStSN),\
+ pq->ts.sec);\
} while(0)
sprintf(buf, "%d/%d /---- hld -----/\n", sp->stats.nhld, sp->stats.max_hld);
@@ -418,8 +415,7 @@ i_setsoc(isc_session_t *sp, int fd, struct thread *td)
static int
i_send(struct cdev *dev, caddr_t arg, struct thread *td)
{
- isc_session_t *sp = (isc_session_t *)dev->si_drv2;
- struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
+ isc_session_t *sp = dev->si_drv2;
caddr_t bp;
pduq_t *pq;
pdu_t *pp;
@@ -430,38 +426,46 @@ i_send(struct cdev *dev, caddr_t arg, struct thread *td)
if(sp->soc == NULL)
return ENOTCONN;
- if((pq = pdu_alloc(sc, M_NOWAIT)) == NULL)
+ if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL)
return EAGAIN;
pp = &pq->pdu;
pq->pdu = *(pdu_t *)arg;
if((error = i_prepPDU(sp, pq)) != 0)
goto out;
- sdebug(3, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len);
-
- pq->buf = bp = malloc(pq->len - sizeof(union ipdu_u), M_ISCSI, M_NOWAIT);
- if(pq->buf == NULL) {
- error = EAGAIN;
- goto out;
+ bp = NULL;
+ if((pq->len - sizeof(union ipdu_u)) > 0) {
+ pq->buf = bp = malloc(pq->len - sizeof(union ipdu_u), M_ISCSIBUF, M_NOWAIT);
+ if(pq->buf == NULL) {
+ error = EAGAIN;
+ goto out;
+ }
}
+ else
+ pq->buf = NULL; // just in case?
+
+ sdebug(2, "len=%d ahs_len=%d ds_len=%d buf=%zu@%p",
+ pq->len, pp->ahs_len, pp->ds_len, pq->len - sizeof(union ipdu_u), bp);
+
if(pp->ahs_len) {
+ // XXX: never tested, looks suspicious
n = pp->ahs_len;
- error = copyin(pp->ahs, bp, n);
+ error = copyin(pp->ahs_addr, bp, n);
if(error != 0) {
sdebug(3, "copyin ahs: error=%d", error);
goto out;
}
- pp->ahs = (ahs_t *)bp;
+ pp->ahs_addr = (ahs_t *)bp;
bp += n;
}
if(pp->ds_len) {
n = pp->ds_len;
- error = copyin(pp->ds, bp, n);
+ error = copyin(pp->ds_addr, bp, n);
if(error != 0) {
sdebug(3, "copyin ds: error=%d", error);
goto out;
}
- pp->ds = bp;
+ pp->ds_addr = bp;
bp += n;
while(n & 03) {
n++;
@@ -470,24 +474,19 @@ i_send(struct cdev *dev, caddr_t arg, struct thread *td)
}
error = isc_qout(sp, pq);
-#if 1
if(error == 0)
wakeup(&sp->flags); // XXX: to 'push' proc_out ...
-#endif
out:
if(error)
- pdu_free(sc, pq);
+ pdu_free(sp->isc, pq);
return error;
}
-/*
- | NOTE: must calculate digest if requiered.
- */
static int
i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
{
- isc_session_t *sp = (isc_session_t *)dev->si_drv2;
+ isc_session_t *sp = dev->si_drv2;
pduq_t *pq;
pdu_t *pp, *up;
caddr_t bp;
@@ -501,7 +500,6 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
if(sp->soc == NULL)
return ENOTCONN;
- sdebug(3, "");
cnt = 6; // XXX: maybe the user can request a time out?
mtx_lock(&sp->rsp_mtx);
while((pq = TAILQ_FIRST(&sp->rsp)) == NULL) {
@@ -514,7 +512,7 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
}
mtx_unlock(&sp->rsp_mtx);
- sdebug(4, "cnt=%d", cnt);
+ sdebug(6, "cnt=%d", cnt);
if(pq == NULL) {
error = ENOTCONN;
@@ -536,19 +534,15 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
len = 0;
if(pp->ahs_len) {
len += pp->ahs_len;
- if(sp->hdrDigest)
- len += 4;
}
if(pp->ds_len) {
len += pp->ds_len;
- if(sp->hdrDigest)
- len += 4;
}
mustfree = 0;
if(len > pq->mp->m_len) {
mustfree++;
- bp = malloc(len, M_ISCSI, M_WAITOK);
+ bp = malloc(len, M_TMP, M_WAITOK);
sdebug(4, "need mbufcopy: %d", len);
i_mbufcopy(pq->mp, bp, len);
}
@@ -557,28 +551,24 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
if(pp->ahs_len) {
need = pp->ahs_len;
- if(sp->hdrDigest)
- need += 4;
n = MIN(up->ahs_size, need);
- error = copyout(bp, (caddr_t)up->ahs, n);
+ error = copyout(bp, (caddr_t)up->ahs_addr, n);
up->ahs_len = n;
bp += need;
}
if(!error && pp->ds_len) {
need = pp->ds_len;
- if(sp->hdrDigest)
- need += 4;
if((have = up->ds_size) == 0) {
have = up->ahs_size - n;
- up->ds = (caddr_t)up->ahs + n;
+ up->ds_addr = (caddr_t)up->ahs_addr + n;
}
n = MIN(have, need);
- error = copyout(bp, (caddr_t)up->ds, n);
+ error = copyout(bp, (caddr_t)up->ds_addr, n);
up->ds_len = n;
}
if(mustfree)
- free(bp, M_ISCSI);
+ free(bp, M_TMP);
}
sdebug(6, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len);
@@ -589,33 +579,57 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td)
}
static int
+i_fullfeature(struct cdev *dev, int flag)
+{
+ isc_session_t *sp = dev->si_drv2;
+ int error;
+
+ sdebug(2, "flag=%d", flag);
+
+ error = 0;
+ switch(flag) {
+ case 0: // stop
+ sp->flags &= ~ISC_FFPHASE;
+ break;
+ case 1: // start
+ sp->flags |= ISC_FFPHASE;
+ error = ic_init(sp);
+ break;
+ case 2: // restart
+ sp->flags |= ISC_FFPHASE;
+ ism_restart(sp);
+ break;
+ }
+ return error;
+}
+
+static int
i_create_session(struct cdev *dev, int *ndev)
{
- struct isc_softc *sc = (struct isc_softc *)dev->si_drv1;
+ struct isc_softc *sc = dev->si_drv1;
isc_session_t *sp;
int error, n;
debug_called(8);
- sp = (isc_session_t *)malloc(sizeof *sp, M_ISCSI, M_WAITOK | M_ZERO);
+
+ sp = malloc(sizeof(isc_session_t), M_ISCSI, M_WAITOK | M_ZERO);
if(sp == NULL)
return ENOMEM;
- mtx_lock(&sc->mtx);
- /*
- | search for the lowest unused sid
- */
- for(n = 0; n < MAX_SESSIONS; n++)
- if(sc->sessions[n] == NULL)
- break;
- if(n == MAX_SESSIONS) {
- mtx_unlock(&sc->mtx);
+
+ sx_xlock(&sc->unit_sx);
+ if((n = alloc_unr(sc->unit)) < 0) {
+ sx_unlock(&sc->unit_sx);
free(sp, M_ISCSI);
+ xdebug("too many sessions!");
return EPERM;
}
+ sx_unlock(&sc->unit_sx);
+
+ mtx_lock(&sc->isc_mtx);
TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link);
- sc->nsess++;
- mtx_unlock(&sc->mtx);
+ isc->nsess++;
+ mtx_unlock(&sc->isc_mtx);
- sc->sessions[n] = sp;
sp->dev = make_dev(&iscsi_cdevsw, n, UID_ROOT, GID_WHEEL, 0600, "iscsi%d", n);
*ndev = sp->sid = n;
sp->isc = sc;
@@ -624,10 +638,9 @@ i_create_session(struct cdev *dev, int *ndev)
sp->opt.maxRecvDataSegmentLength = 8192;
sp->opt.maxXmitDataSegmentLength = 8192;
-
sp->opt.maxBurstLength = 65536; // 64k
+ sp->opt.maxluns = ISCSI_MAX_LUNS;
- sdebug(2, "sessionID=%d sp=%p", n, sp);
error = ism_start(sp);
return error;
@@ -663,7 +676,7 @@ iscsi_counters(isc_session_t *sp)
static void
iscsi_shutdown(void *v)
{
- struct isc_softc *sc = (struct isc_softc *)v;
+ struct isc_softc *sc = v;
isc_session_t *sp;
int n;
@@ -672,12 +685,14 @@ iscsi_shutdown(void *v)
xdebug("sc is NULL!");
return;
}
+#ifdef DO_EVENTHANDLER
if(sc->eh == NULL)
debug(2, "sc->eh is NULL");
else {
EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->eh);
debug(2, "done n=%d", sc->nsess);
}
+#endif
n = 0;
TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) {
debug(2, "%2d] sp->flags=0x%08x", n, sp->flags);
@@ -686,24 +701,6 @@ iscsi_shutdown(void *v)
debug(2, "done");
}
-static int
-init_pdus(struct isc_softc *sc)
-{
- debug_called(8);
-
- sc->pdu_zone = uma_zcreate("pdu", sizeof(pduq_t),
- NULL, NULL, NULL, NULL,
- 0, 0);
- if(sc->pdu_zone == NULL) {
- printf("iscsi_initiator: uma_zcreate failed");
- return -1;
- }
- uma_zone_set_max(sc->pdu_zone, MAX_PDUS);
- TAILQ_INIT(&sc->freepdu);
-
- return 0;
-}
-
static void
free_pdus(struct isc_softc *sc)
{
@@ -724,50 +721,52 @@ free_pdus(struct isc_softc *sc)
static void
iscsi_start(void)
{
- struct isc_softc *sc = &isc;
-
debug_called(8);
- memset(sc, 0, sizeof(struct isc_softc));
+ TUNABLE_INT_FETCH("net.iscsi_initiator.max_sessions", &max_sessions);
+ TUNABLE_INT_FETCH("net.iscsi_initiator.max_pdus", &max_pdus);
- sc->dev = make_dev(&iscsi_cdevsw, MAX_SESSIONS, UID_ROOT, GID_WHEEL, 0600, "iscsi");
- sc->dev->si_drv1 = sc;
+ isc = malloc(sizeof(struct isc_softc), M_ISCSI, M_ZERO|M_WAITOK);
+ isc->dev = make_dev(&iscsi_cdevsw, max_sessions, UID_ROOT, GID_WHEEL, 0600, "iscsi");
+ isc->dev->si_drv1 = isc;
+ mtx_init(&isc->isc_mtx, "iscsi", NULL, MTX_DEF);
+ mtx_init(&isc->pdu_mtx, "iscsi pdu pool", NULL, MTX_DEF);
- TAILQ_INIT(&sc->isc_sess);
- if(init_pdus(sc) != 0)
- xdebug("pdu zone init failed!"); // XXX: should cause terminal failure ...
-
- mtx_init(&sc->mtx, "iscsi", NULL, MTX_DEF);
- mtx_init(&sc->pdu_mtx, "iscsi pdu pool", NULL, MTX_DEF);
-
-#if 0
- // XXX: this will cause a panic if the
- // module is loaded too early
- if(ic_init(sc) != 0)
- return;
-#else
- sc->cam_sim = NULL;
-#endif
+ TAILQ_INIT(&isc->isc_sess);
+ /*
+ | now init the free pdu list
+ */
+ isc->pdu_zone = uma_zcreate("pdu", sizeof(pduq_t),
+ NULL, NULL, NULL, NULL,
+ 0, 0);
+ if(isc->pdu_zone == NULL) {
+ xdebug("iscsi_initiator: uma_zcreate failed");
+ // XXX: should fail...
+ }
+ uma_zone_set_max(isc->pdu_zone, max_pdus);
+ TAILQ_INIT(&isc->freepdu);
+ isc->unit = new_unrhdr(0, max_sessions-1, NULL);
+ sx_init(&isc->unit_sx, "iscsi sx");
#ifdef DO_EVENTHANDLER
- if((sc->eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, iscsi_shutdown,
+ if((isc->eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, iscsi_shutdown,
sc, SHUTDOWN_PRI_DEFAULT-1)) == NULL)
xdebug("shutdown event registration failed\n");
#endif
/*
| sysctl stuff
*/
- sysctl_ctx_init(&sc->clist);
- sc->oid = SYSCTL_ADD_NODE(&sc->clist,
+ sysctl_ctx_init(&isc->clist);
+ isc->oid = SYSCTL_ADD_NODE(&isc->clist,
SYSCTL_STATIC_CHILDREN(_net),
OID_AUTO,
- "iscsi",
+ "iscsi_initiator",
CTLFLAG_RD,
0,
"iSCSI Subsystem");
- SYSCTL_ADD_STRING(&sc->clist,
- SYSCTL_CHILDREN(sc->oid),
+ SYSCTL_ADD_STRING(&isc->clist,
+ SYSCTL_CHILDREN(isc->oid),
OID_AUTO,
"driver_version",
CTLFLAG_RD,
@@ -775,8 +774,8 @@ iscsi_start(void)
0,
"iscsi driver version");
- SYSCTL_ADD_STRING(&sc->clist,
- SYSCTL_CHILDREN(sc->oid),
+ SYSCTL_ADD_STRING(&isc->clist,
+ SYSCTL_CHILDREN(isc->oid),
OID_AUTO,
"isid",
CTLFLAG_RW,
@@ -784,13 +783,13 @@ iscsi_start(void)
6+1,
"initiator part of the Session Identifier");
- SYSCTL_ADD_INT(&sc->clist,
- SYSCTL_CHILDREN(sc->oid),
+ SYSCTL_ADD_INT(&isc->clist,
+ SYSCTL_CHILDREN(isc->oid),
OID_AUTO,
"sessions",
CTLFLAG_RD,
- &sc->nsess,
- sizeof(sc->nsess),
+ &isc->nsess,
+ sizeof(isc->nsess),
"number of active session");
printf("iscsi: version %s\n", iscsi_driver_version);
@@ -804,7 +803,6 @@ iscsi_start(void)
static void
iscsi_stop(void)
{
- struct isc_softc *sc = &isc;
isc_session_t *sp, *sp_tmp;
debug_called(8);
@@ -813,24 +811,26 @@ iscsi_stop(void)
| go through all the sessions
| Note: close should have done this ...
*/
- TAILQ_FOREACH_SAFE(sp, &sc->isc_sess, sp_link, sp_tmp) {
+ TAILQ_FOREACH_SAFE(sp, &isc->isc_sess, sp_link, sp_tmp) {
//XXX: check for activity ...
ism_stop(sp);
+ if(sp->cam_sim != NULL)
+ ic_destroy(sp);
}
- if(sc->cam_sim != NULL)
- ic_destroy(sc);
+ mtx_destroy(&isc->isc_mtx);
+ mtx_destroy(&isc->pdu_mtx);
+ sx_destroy(&isc->unit_sx);
- mtx_destroy(&sc->mtx);
- mtx_destroy(&sc->pdu_mtx);
- free_pdus(sc);
+ free_pdus(isc);
- if(sc->dev)
- destroy_dev(sc->dev);
+ if(isc->dev)
+ destroy_dev(isc->dev);
- if(sysctl_ctx_free(&sc->clist))
+ if(sysctl_ctx_free(&isc->clist))
xdebug("sysctl_ctx_free failed");
- iscsi_shutdown(sc); // XXX: check EVENTHANDLER_ ...
+ iscsi_shutdown(isc); // XXX: check EVENTHANDLER_ ...
+ free(isc, M_ISCSI);
}
static int
@@ -844,13 +844,12 @@ iscsi_modevent(module_t mod, int what, void *arg)
break;
case MOD_QUIESCE:
-#if 1
- if(isc.nsess) {
- xdebug("iscsi module busy(nsess=%d), cannot unload", isc.nsess);
+ if(isc->nsess) {
+ xdebug("iscsi module busy(nsess=%d), cannot unload", isc->nsess);
log(LOG_ERR, "iscsi module busy, cannot unload");
}
- return isc.nsess;
-#endif
+ return isc->nsess;
+
case MOD_SHUTDOWN:
break;
diff --git a/sys/dev/iscsi/initiator/iscsi.h b/sys/dev/iscsi/initiator/iscsi.h
index 2eace68..3142113 100644
--- a/sys/dev/iscsi/initiator/iscsi.h
+++ b/sys/dev/iscsi/initiator/iscsi.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
* $FreeBSD$
*/
/*
- | $Id: iscsi.h,v 1.17 2006/12/01 09:10:17 danny Exp danny $
+ | $Id: iscsi.h 743 2009-08-08 10:54:53Z danny $
*/
#define TRUE 1
#define FALSE 0
@@ -37,11 +37,7 @@ typedef int boolean_t;
#include <cam/cam.h>
#define ISCSIDEV "iscsi"
-
-#define ISCSI_MAX_TARGETS 4 //64
-
-#define ISCSI_MAX_LUNS 4
-
+#define ISCSI_MAX_TARGETS 64
/*
| iSCSI commands
*/
@@ -422,13 +418,13 @@ typedef struct {
*/
typedef struct {
union ipdu_u ipdu;
+ u_int hdr_dig; // header digest
- ahs_t *ahs;
+ ahs_t *ahs_addr;
u_int ahs_len;
u_int ahs_size; // the allocated size
- u_int hdr_dig; // header digest
- u_char *ds;
+ u_char *ds_addr;
u_int ds_len;
u_int ds_size; // the allocated size
u_int ds_dig; // data digest
@@ -474,6 +470,7 @@ typedef struct opvals {
u_char tgtChapID;
char *tgtChapDigest;
char *iqn;
+ char *pidfile;
} isc_opt_t;
/*
@@ -498,7 +495,6 @@ typedef struct iscsi_cam {
path_id_t path_id;
target_id_t target_id;
int target_nluns;
- lun_id_t target_lun[ISCSI_MAX_LUNS];
} iscsi_cam_t;
#define ISCSIGETCAM _IOR('i', 33, iscsi_cam_t)
diff --git a/sys/dev/iscsi/initiator/iscsi_subr.c b/sys/dev/iscsi/initiator/iscsi_subr.c
index 9ef92d5..03d9293 100644
--- a/sys/dev/iscsi/initiator/iscsi_subr.c
+++ b/sys/dev/iscsi/initiator/iscsi_subr.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
*
*/
/*
- | $Id: iscsi_subr.c,v 1.17 2006/11/26 14:50:43 danny Exp danny $
+ | $Id: iscsi_subr.c 743 2009-08-08 10:54:53Z danny $
*/
#include <sys/cdefs.h>
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/uio.h>
#include <sys/sysctl.h>
+#include <sys/sx.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -122,7 +123,7 @@ iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
bs = MIN(bs, bleft);
wpq->pdu.ds_len = bs;
- wpq->pdu.ds = bp;
+ wpq->pdu.ds_addr = bp;
error = isc_qout(sp, wpq);
sdebug(6, "bs=%x bo=%x bp=%p dsn=%x error=%d", bs, bo, bp, dsn, error);
@@ -188,16 +189,16 @@ getSenseData(u_int status, union ccb *ccb, pduq_t *pq)
| Some information is from SAM draft.
*/
static void
-_scsi_done(struct isc_softc *isp, u_int response, u_int status, union ccb *ccb, pduq_t *pq)
+_scsi_done(isc_session_t *sp, u_int response, u_int status, union ccb *ccb, pduq_t *pq)
{
struct ccb_hdr *ccb_h = &ccb->ccb_h;
debug_called(8);
if(status || response) {
- debug(3, "response=%x status=%x ccb=%p pq=%p", response, status, ccb, pq);
+ sdebug(3, "response=%x status=%x ccb=%p pq=%p", response, status, ccb, pq);
if(pq != NULL)
- debug(3, "mp=%p buf=%p len=%d", pq->mp, pq->buf, pq->len);
+ sdebug(3, "mp=%p buf=%p len=%d", pq->mp, pq->buf, pq->len);
}
ccb_h->status = 0;
switch(response) {
@@ -241,9 +242,9 @@ _scsi_done(struct isc_softc *isp, u_int response, u_int status, union ccb *ccb,
ccb_h->status = CAM_REQ_CMP_ERR; //CAM_REQ_ABORTED;
break;
}
- debug(5, "ccb_h->status=%x", ccb_h->status);
+ sdebug(5, "ccb_h->status=%x", ccb_h->status);
- XPT_DONE(isp, ccb);
+ XPT_DONE(sp, ccb);
}
/*
@@ -256,16 +257,17 @@ iscsi_requeue(isc_session_t *sp)
u_int i, n, last;
debug_called(8);
- last = -1;
- i = 0;
+ i = last = 0;
sp->flags |= ISC_HOLD;
while((pq = i_dqueue_hld(sp)) != NULL) {
i++;
- _scsi_done(sp->isc, 0, 0x28, pq->ccb, NULL);
- n = ntohl(pq->pdu.ipdu.bhs.CmdSN);
- if(last > n)
- last = n;
- sdebug(2, "last=%x n=%x", last, n);
+ if(pq->ccb != NULL) {
+ _scsi_done(sp, 0, 0x28, pq->ccb, NULL);
+ n = ntohl(pq->pdu.ipdu.bhs.CmdSN);
+ if(last==0 || (last > n))
+ last = n;
+ sdebug(2, "last=%x n=%x", last, n);
+ }
pdu_free(sp->isc, pq);
}
sp->flags &= ~ISC_HOLD;
@@ -316,14 +318,22 @@ iscsi_cleanup(isc_session_t *sp)
TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, pqtmp) {
sdebug(3, "hld pq=%p", pq);
if(pq->ccb)
- _scsi_done(sp->isc, 1, 0x40, pq->ccb, NULL);
+ _scsi_done(sp, 1, 0x40, pq->ccb, NULL);
TAILQ_REMOVE(&sp->hld, pq, pq_link);
+ if(pq->buf) {
+ free(pq->buf, M_ISCSIBUF);
+ pq->buf = NULL;
+ }
pdu_free(sp->isc, pq);
}
while((pq = i_dqueue_snd(sp, BIT(0)|BIT(1)|BIT(2))) != NULL) {
sdebug(3, "pq=%p", pq);
if(pq->ccb)
- _scsi_done(sp->isc, 1, 0x40, pq->ccb, NULL);
+ _scsi_done(sp, 1, 0x40, pq->ccb, NULL);
+ if(pq->buf) {
+ free(pq->buf, M_ISCSIBUF);
+ pq->buf = NULL;
+ }
pdu_free(sp->isc, pq);
}
@@ -338,7 +348,7 @@ iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
debug_called(8);
- _scsi_done(sp->isc, cmd->response, cmd->status, opq->ccb, pq);
+ _scsi_done(sp, cmd->response, cmd->status, opq->ccb, pq);
pdu_free(sp->isc, opq);
}
@@ -394,7 +404,7 @@ iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
debug_called(8);
//XXX: check RFC 10.17.1 (page 176)
ccb->ccb_h.status = CAM_REQ_ABORTED;
- XPT_DONE(sp->isc, ccb);
+ XPT_DONE(sp, ccb);
pdu_free(sp->isc, opq);
}
@@ -405,10 +415,8 @@ iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
static int
dwl(isc_session_t *sp, int lun, u_char *lp)
{
- int i;
-
debug_called(8);
-
+ sdebug(4, "lun=%d", lun);
/*
| mapping LUN to iSCSI LUN
| check the SAM-2 specs
@@ -429,14 +437,6 @@ dwl(isc_session_t *sp, int lun, u_char *lp)
return -1;
}
- for(i = 0; i < sp->target_nluns; i++)
- if(sp->target_lun[i] == lun)
- return 0;
- if(sp->target_nluns < ISCSI_MAX_LUNS)
- sp->target_lun[sp->target_nluns++] = lun;
-
- sdebug(3, "nluns=%d lun=%d", sp->target_nluns, lun);
-
return 0;
}
@@ -446,8 +446,7 @@ dwl(isc_session_t *sp, int lun, u_char *lp)
int
scsi_encap(struct cam_sim *sim, union ccb *ccb)
{
- struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim);
- isc_session_t *sp;
+ isc_session_t *sp = cam_sim_softc(sim);
struct ccb_scsiio *csio = &ccb->csio;
struct ccb_hdr *ccb_h = &ccb->ccb_h;
pduq_t *pq;
@@ -458,33 +457,19 @@ scsi_encap(struct cam_sim *sim, union ccb *ccb)
debug(4, "ccb->sp=%p", ccb_h->spriv_ptr0);
sp = ccb_h->spriv_ptr0;
- if((pq = pdu_alloc(isp, M_NOWAIT)) == NULL) {
+ if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) {
debug(2, "ccb->sp=%p", ccb_h->spriv_ptr0);
sdebug(1, "pdu_alloc failed sc->npdu_max=%d npdu_alloc=%d",
sp->isc->npdu_max, sp->isc->npdu_alloc);
while((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) {
- sdebug(3, "waiting...");
+ sdebug(2, "waiting...");
#if __FreeBSD_version >= 700000
pause("isc_encap", 5*hz);
#else
tsleep(sp->isc, 0, "isc_encap", 5*hz);
#endif
}
-#if 0
- sdebug(3, "freezing");
- ccb->ccb_h.status = CAM_REQUEUE_REQ;
- ic_freeze(sp);
- return 0;
-#endif
- }
-
-#if 0
- if((sp->flags & ISC_FFPHASE) == 0) {
- ccb->ccb_h.status = CAM_DEV_NOT_THERE; // CAM_NO_NEXUS;
- sdebug(3, "no active session with target %d", ccb_h->target_id);
- goto bad;
}
-#endif
cmd = &pq->pdu.ipdu.scsi_req;
cmd->opcode = ISCSI_SCSI_CMD;
cmd->F = 1;
@@ -493,8 +478,8 @@ scsi_encap(struct cam_sim *sim, union ccb *ccb)
*/
switch(csio->tag_action) {
case MSG_SIMPLE_Q_TAG: cmd->attr = iSCSI_TASK_SIMPLE; break;
- case MSG_HEAD_OF_Q_TAG: cmd->attr = iSCSI_TASK_ORDER; break;
- case MSG_ORDERED_Q_TAG: cmd->attr = iSCSI_TASK_HOFQ; break;
+ case MSG_HEAD_OF_Q_TAG: cmd->attr = iSCSI_TASK_HOFQ; break;
+ case MSG_ORDERED_Q_TAG: cmd->attr = iSCSI_TASK_ORDER; break;
case MSG_ACA_TASK: cmd->attr = iSCSI_TASK_ACA; break;
}
@@ -532,7 +517,8 @@ scsi_encap(struct cam_sim *sim, union ccb *ccb)
return 1;
invalid:
ccb->ccb_h.status = CAM_REQ_INVALID;
- pdu_free(isp, pq);
+ pdu_free(sp->isc, pq);
+
return 0;
}
@@ -573,15 +559,15 @@ scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
csio->data_ptr, bp? mtod(pq->mp, caddr_t): 0,
ntohl(cmd->edtlen), pq->pdu.ds_len, pq->mp);
if(ntohl(cmd->edtlen) >= pq->pdu.ds_len) {
- int offset, len = pq->pdu.ds_len;
+ int offset, len = pq->pdu.ds_len;
if(pq->mp != NULL) {
- caddr_t dp;
+ caddr_t dp;
- offset = ntohl(rcmd->bo);
- dp = csio->data_ptr + offset;
- i_mbufcopy(pq->mp, dp, len);
- }
+ offset = ntohl(rcmd->bo);
+ dp = csio->data_ptr + offset;
+ i_mbufcopy(pq->mp, dp, len);
+ }
}
else {
xdebug("edtlen=%d < ds_len=%d",
@@ -592,7 +578,7 @@ scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq)
/*
| contains also the SCSI Status
*/
- _scsi_done(sp->isc, 0, rcmd->status, opq->ccb, NULL);
+ _scsi_done(sp, 0, rcmd->status, opq->ccb, NULL);
return 0;
} else
return 1;
diff --git a/sys/dev/iscsi/initiator/iscsivar.h b/sys/dev/iscsi/initiator/iscsivar.h
index 128a745..a6eae21 100644
--- a/sys/dev/iscsi/initiator/iscsivar.h
+++ b/sys/dev/iscsi/initiator/iscsivar.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005-2008 Daniel Braniss <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,9 +25,18 @@
*
* $FreeBSD$
*/
+
+/*
+ | $Id: iscsivar.h 743 2009-08-08 10:54:53Z danny $
+ */
+#define ISCSI_MAX_LUNS 128 // don't touch this
+#if ISCSI_MAX_LUNS > 8
/*
- | $Id: iscsivar.h,v 1.30 2007/04/22 10:12:11 danny Exp danny $
+ | for this to work
+ | sysctl kern.cam.cam_srch_hi=1
*/
+#endif
+
#ifndef ISCSI_INITIATOR_DEBUG
#define ISCSI_INITIATOR_DEBUG 1
#endif
@@ -48,13 +57,17 @@ extern int iscsi_debug;
#define xdebug(fmt, args...) printf(">>> %s: " fmt "\n", __func__ , ##args)
-#define MAX_SESSIONS ISCSI_MAX_TARGETS
+#define MAX_SESSIONS ISCSI_MAX_TARGETS
+#define MAX_PDUS (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary
typedef uint32_t digest_t(const void *, int len, uint32_t ocrc);
MALLOC_DECLARE(M_ISCSI);
+MALLOC_DECLARE(M_ISCSIBUF);
MALLOC_DECLARE(M_PDU);
+#define ISOK2DIG(dig, pp) ((dig != NULL) && ((pp->ipdu.bhs.opcode & 0x1f) != ISCSI_LOGIN_CMD))
+
#ifndef BIT
#define BIT(n) (1 <<(n))
#endif
@@ -69,15 +82,15 @@ MALLOC_DECLARE(M_PDU);
#define ISC_OQNOTEMPTY BIT(6)
#define ISC_OWAITING BIT(7)
#define ISC_FFPHASE BIT(8)
-#define ISC_FFPWAIT BIT(9)
-#define ISC_MEMWAIT BIT(10)
-#define ISC_SIGNALED BIT(11)
-#define ISC_FROZEN BIT(12)
-#define ISC_STALLED BIT(13)
+#define ISC_CAMDEVS BIT(9)
+#define ISC_SCANWAIT BIT(10)
+
+#define ISC_MEMWAIT BIT(11)
+#define ISC_SIGNALED BIT(12)
-#define ISC_HOLD BIT(14)
-#define ISC_HOLDED BIT(15)
+#define ISC_HOLD BIT(15)
+#define ISC_HOLDED BIT(16)
#define ISC_SHUTDOWN BIT(31)
@@ -116,9 +129,7 @@ typedef struct isc_session {
struct proc *proc; // the userland process
int signal;
-
struct proc *soc_proc;
-
struct proc *stp; // the sm thread
struct isc_softc *isc;
@@ -127,16 +138,13 @@ typedef struct isc_session {
digest_t *dataDigest; // the digest alg. if any
int sid; // Session ID
- int targetid;
-// int cid; // Connection ID
-// int tsih; // target session identifier handle
sn_t sn; // sequence number stuff;
int cws; // current window size
int target_nluns; // this and target_lun are
// hopefully temporal till I
// figure out a better way.
- lun_id_t target_lun[ISCSI_MAX_LUNS];
+ int target_lun[ISCSI_MAX_LUNS/(sizeof(int)*8) + 1];
struct mtx rsp_mtx;
struct mtx rsv_mtx;
@@ -150,17 +158,19 @@ typedef struct isc_session {
queue_t wsnd;
queue_t hld;
- /*
- | negotiable values
- */
- isc_opt_t opt;
+ isc_opt_t opt; // negotiable values
struct i_stats stats;
- struct cam_path *cam_path;
bhs_t bhs;
struct uio uio;
struct iovec iov;
/*
+ | cam stuff
+ */
+ struct cam_sim *cam_sim;
+ struct cam_path *cam_path;
+ struct mtx cam_mtx;
+ /*
| sysctl stuff
*/
struct sysctl_ctx_list clist;
@@ -180,33 +190,29 @@ typedef struct pduq {
struct iovec iov[5]; // XXX: careful ...
struct mbuf *mp;
struct bintime ts;
- queue_t *pduq;
+ queue_t *pduq;
} pduq_t;
-
+/*
+ */
struct isc_softc {
- //int state;
+ struct mtx isc_mtx;
+ TAILQ_HEAD(,isc_session) isc_sess;
+ int nsess;
struct cdev *dev;
- eventhandler_tag eh;
char isid[6]; // Initiator Session ID (48 bits)
- struct mtx mtx;
+ struct unrhdr *unit;
+ struct sx unit_sx;
- int nsess;
- TAILQ_HEAD(,isc_session) isc_sess;
- isc_session_t *sessions[MAX_SESSIONS];
+ struct mtx pdu_mtx;
+ uma_zone_t pdu_zone; // pool of free pdu's
+ TAILQ_HEAD(,pduq) freepdu;
- struct mtx pdu_mtx;
#ifdef ISCSI_INITIATOR_DEBUG
- int npdu_alloc, npdu_max; // for instrumentation
+ int npdu_alloc, npdu_max; // for instrumentation
+#endif
+#ifdef DO_EVENTHANDLER
+ eventhandler_tag eh;
#endif
-#define MAX_PDUS (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary
- uma_zone_t pdu_zone; // pool of free pdu's
- TAILQ_HEAD(,pduq) freepdu;
- /*
- | cam stuff
- */
- struct cam_sim *cam_sim;
- struct cam_path *cam_path;
- struct mtx cam_mtx;
/*
| sysctl stuff
*/
@@ -231,14 +237,14 @@ int i_pdu_flush(isc_session_t *sc);
int i_setopt(isc_session_t *sp, isc_opt_t *opt);
void i_freeopt(isc_opt_t *opt);
-int ic_init(struct isc_softc *sc);
-void ic_destroy(struct isc_softc *sc);
-int ic_fullfeature(struct cdev *dev);
+int ic_init(isc_session_t *sp);
+void ic_destroy(isc_session_t *sp);
void ic_lost_target(isc_session_t *sp, int target);
int ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp);
void ism_recv(isc_session_t *sp, pduq_t *pq);
int ism_start(isc_session_t *sp);
+void ism_restart(isc_session_t *sp);
void ism_stop(isc_session_t *sp);
int scsi_encap(struct cam_sim *sim, union ccb *ccb);
@@ -250,9 +256,6 @@ void iscsi_async(isc_session_t *sp, pduq_t *pq);
void iscsi_cleanup(isc_session_t *sp);
int iscsi_requeue(isc_session_t *sp);
-void ic_freeze(isc_session_t *sp);
-void ic_release(isc_session_t *sp);
-
// Serial Number Arithmetic
#define _MAXINCR 0x7FFFFFFF // 2 ^ 31 - 1
#define SNA_GT(i1, i2) ((i1 != i2) && (\
@@ -269,7 +272,7 @@ void ic_release(isc_session_t *sp);
#define CAM_ULOCK(arg)
static __inline void
-XPT_DONE(struct isc_softc *isp, union ccb *ccb)
+XPT_DONE(isc_session_t *sp, union ccb *ccb)
{
mtx_lock(&Giant);
xpt_done(ccb);
@@ -280,11 +283,11 @@ XPT_DONE(struct isc_softc *isp, union ccb *ccb)
#define CAM_UNLOCK(arg) mtx_unlock(&arg->cam_mtx)
static __inline void
-XPT_DONE(struct isc_softc *isp, union ccb *ccb)
+XPT_DONE(isc_session_t *sp, union ccb *ccb)
{
- CAM_LOCK(isp);
+ CAM_LOCK(sp);
xpt_done(ccb);
- CAM_UNLOCK(isp);
+ CAM_UNLOCK(sp);
}
#else
//__FreeBSD_version >= 600000
@@ -332,7 +335,7 @@ pdu_free(struct isc_softc *isc, pduq_t *pq)
m_freem(pq->mp);
#ifdef NO_USE_MBUF
if(pq->buf != NULL)
- free(pq->buf, M_ISCSI);
+ free(pq->buf, M_ISCSIBUF);
#endif
mtx_lock(&isc->pdu_mtx);
TAILQ_INSERT_TAIL(&isc->freepdu, pq, pq_link);
@@ -565,6 +568,27 @@ i_search_hld(isc_session_t *sp, int itt, int keep)
}
static __inline void
+i_acked_hld(isc_session_t *sp, pdu_t *op)
+{
+ pduq_t *pq, *tmp;
+ u_int exp = sp->sn.expCmd;
+
+ pq = NULL;
+ mtx_lock(&sp->hld_mtx);
+ TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) {
+ if((op && op->ipdu.bhs.itt == pq->pdu.ipdu.bhs.itt)
+ || (pq->ccb == NULL
+ && (pq->pdu.ipdu.bhs.opcode != ISCSI_WRITE_DATA)
+ && SNA_GT(exp, ntohl(pq->pdu.ipdu.bhs.ExpStSN)))) {
+ sp->stats.nhld--;
+ TAILQ_REMOVE(&sp->hld, pq, pq_link);
+ pdu_free(sp->isc, pq);
+ }
+ }
+ mtx_unlock(&sp->hld_mtx);
+}
+
+static __inline void
i_mbufcopy(struct mbuf *mp, caddr_t dp, int len)
{
struct mbuf *m;
OpenPOWER on IntegriCloud