From c201d4532c499221abc67df4802b7095b1017674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Mon, 9 Aug 2010 12:36:36 +0000 Subject: [PATCH] - 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 Sponsored by: Dansk Scanning A/S, Data Robotics Inc. --- sbin/iscontrol/Makefile | 5 +- sbin/iscontrol/auth_subr.c | 6 +- sbin/iscontrol/config.c | 23 +- sbin/iscontrol/fsm.c | 117 ++++--- sbin/iscontrol/iscontrol.8 | 32 +- sbin/iscontrol/iscontrol.c | 24 +- sbin/iscontrol/iscontrol.h | 4 +- sbin/iscontrol/iscsi.conf.5 | 3 +- sbin/iscontrol/login.c | 10 +- sbin/iscontrol/misc.c | 5 +- sbin/iscontrol/pdu.c | 22 +- sbin/iscontrol/pdu.h | 134 -------- sys/dev/iscsi/initiator/isc_cam.c | 404 +++++++++++------------- sys/dev/iscsi/initiator/isc_sm.c | 146 ++++----- sys/dev/iscsi/initiator/isc_soc.c | 447 +++++++++++++++------------ sys/dev/iscsi/initiator/isc_subr.c | 45 +-- sys/dev/iscsi/initiator/iscsi.c | 313 ++++++++++--------- sys/dev/iscsi/initiator/iscsi.h | 22 +- sys/dev/iscsi/initiator/iscsi_subr.c | 102 +++--- sys/dev/iscsi/initiator/iscsivar.h | 130 ++++---- 20 files changed, 940 insertions(+), 1054 deletions(-) delete mode 100644 sbin/iscontrol/pdu.h diff --git a/sbin/iscontrol/Makefile b/sbin/iscontrol/Makefile index 446a5f48ab54..1830ad935a7a 100644 --- a/sbin/iscontrol/Makefile +++ b/sbin/iscontrol/Makefile @@ -4,9 +4,10 @@ SRCS= iscontrol.c pdu.c fsm.c config.c login.c auth_subr.c misc.c PROG= iscontrol DPADD= ${LIBCAM} ${LIBMD} LDADD= -lcam -lmd +S= ${.CURDIR}/../../sys -WARNS?= 2 -CFLAGS += -I${.CURDIR}/../../sys/dev/iscsi/initiator +WARNS?= 3 +CFLAGS += -I$S #CFLAGS += -g -DDEBUG MAN= iscsi.conf.5 iscontrol.8 diff --git a/sbin/iscontrol/auth_subr.c b/sbin/iscontrol/auth_subr.c index 06c0ee57fd73..375d06dbae40 100644 --- a/sbin/iscontrol/auth_subr.c +++ b/sbin/iscontrol/auth_subr.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "iscsi.h" +#include #include "iscontrol.h" static int @@ -152,7 +152,7 @@ chapDigest(char *ap, char id, char *cp, char *chapSecret) } char * -genChapChallenge(char *encoding, int len) +genChapChallenge(char *encoding, uint len) { int fd; unsigned char tmp[1024]; diff --git a/sbin/iscontrol/config.c b/sbin/iscontrol/config.c index df3a4900f0a4..197f178debe0 100644 --- a/sbin/iscontrol/config.c +++ b/sbin/iscontrol/config.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2009 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "iscsi.h" +#include #include "iscontrol.h" /* @@ -94,6 +94,11 @@ __FBSDID("$FreeBSD$"); #define OPT_iqn 34 #define OPT_sockbufsize 35 +/* + | sentinel + */ +#define OPT_end 0 + #define _OFF(v) ((int)&((isc_opt_t *)NULL)->v) #define _E(u, s, v) {.usage=u, .scope=s, .name=#v, .tokenID=OPT_##v} @@ -145,7 +150,7 @@ textkey_t keyMap[] = { _E(U_LO, S_SW, sessionType), - {0} + _E(0, 0, end) }; #define _OPT_INT(w) strtol((char *)w, NULL, 0) @@ -154,7 +159,7 @@ textkey_t keyMap[] = { static __inline int _OPT_BOOL(char *w) { - if(isalpha(*w)) + if(isalpha((unsigned char)*w)) return strcasecmp(w, "TRUE") == 0; else return _OPT_INT(w); @@ -244,12 +249,12 @@ getConfig(FILE *fd, char *key, char **Ar, int *nargs) len = 0; state = 0; while((lp = getline(fd)) != NULL) { - for(; isspace(*lp); lp++) + for(; isspace((unsigned char)*lp); lp++) ; switch(state) { case 0: if((p = strchr(lp, '{')) != NULL) { - while((--p > lp) && *p && isspace(*p)); + while((--p > lp) && *p && isspace((unsigned char)*p)); n = p - lp; if(len && strncmp(lp, key, MAX(n, len)) == 0) state = 2; @@ -272,7 +277,7 @@ getConfig(FILE *fd, char *key, char **Ar, int *nargs) } - for(p = &lp[strlen(lp)-1]; isspace(*p); p--) + for(p = &lp[strlen(lp)-1]; isspace((unsigned char)*p); p--) *p = 0; if((*nargs)-- > 0) *ar++ = strdup(lp); @@ -351,9 +356,9 @@ parseArgs(int nargs, char **args, isc_opt_t *op) continue; *p = 0; v = p + 1; - while(isspace(*--p)) + while(isspace((unsigned char)*--p)) *p = 0; - while(isspace(*v)) + while(isspace((unsigned char)*v)) v++; if((tk = keyLookup(*ar)) == NULL) continue; diff --git a/sbin/iscontrol/fsm.c b/sbin/iscontrol/fsm.c index 443ebcac6b2e..ec71931d5848 100644 --- a/sbin/iscontrol/fsm.c +++ b/sbin/iscontrol/fsm.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "iscsi.h" +#include #include "iscontrol.h" typedef enum { @@ -99,26 +99,26 @@ tcpConnect(isess_t *sess) #ifdef notyet { time_t sec; - // make sure we are not in a loop - // XXX: this code has to be tested - sec = time(0) - sess->reconnect_time; - if(sec > (5*60)) { - // if we've been connected for more that 5 minutes - // then just reconnect - sess->reconnect_time = sec; - sess->reconnect_cnt1 = 0; - } - else { - // - sess->reconnect_cnt1++; - if((sec / sess->reconnect_cnt1) < 2) { - // if less that 2 seconds from the last reconnect - // we are most probably looping - syslog(LOG_CRIT, "too many reconnects %d", sess->reconnect_cnt1); - return 0; + // make sure we are not in a loop + // XXX: this code has to be tested + sec = time(0) - sess->reconnect_time; + if(sec > (5*60)) { + // if we've been connected for more that 5 minutes + // then just reconnect + sess->reconnect_time = sec; + sess->reconnect_cnt1 = 0; + } + else { + // + sess->reconnect_cnt1++; + if((sec / sess->reconnect_cnt1) < 2) { + // if less that 2 seconds from the last reconnect + // we are most probably looping + syslog(LOG_CRIT, "too many reconnects %d", sess->reconnect_cnt1); + return 0; + } } } - } #endif sess->reconnect_cnt++; } @@ -140,13 +140,13 @@ tcpConnect(isess_t *sess) if (soc == -1) continue; - // from Patrick.Guelat@imp.ch: - // iscontrol can be called without waiting for the socket entry to time out - val = 1; + // from Patrick.Guelat@imp.ch: + // iscontrol can be called without waiting for the socket entry to time out + val = 1; if(setsockopt(soc, SOL_SOCKET, SO_REUSEADDR, &val, (socklen_t)sizeof(val)) < 0) { - fprintf(stderr, "Cannot set socket SO_REUSEADDR %d: %s\n\n", - errno, strerror(errno)); - } + fprintf(stderr, "Cannot set socket SO_REUSEADDR %d: %s\n\n", + errno, strerror(errno)); + } if(connect(soc, res->ai_addr, res->ai_addrlen) == 0) break; @@ -196,7 +196,7 @@ tcpConnect(isess_t *sess) } sess->flags |= SESS_CONNECTED; return T1; - } + } fprintf(stderr, "errno=%d\n", sv_errno); perror("connect"); @@ -289,7 +289,7 @@ startSession(isess_t *sess) // XXX: this has to go size_t n; n = sizeof(sess->isid); - if(sysctlbyname("net.iscsi.isid", (void *)sess->isid, (size_t *)&n, 0, 0) != 0) + if(sysctlbyname("net.iscsi_initiator.isid", (void *)sess->isid, (size_t *)&n, 0, 0) != 0) perror("sysctlbyname"); } if(ioctl(fd, ISCSISETSES, &n)) { @@ -343,29 +343,29 @@ trap(int sig) } } -static void +static int doCAM(isess_t *sess) { char pathstr[1024]; union ccb *ccb; - int i; + int i, n; if(ioctl(sess->fd, ISCSIGETCAM, &sess->cam) != 0) { syslog(LOG_WARNING, "ISCSIGETCAM failed: %d", errno); - return; + return 0; } - debug(2, "nluns=%d", sess->cam.target_nluns); + debug(1, "nluns=%d", sess->cam.target_nluns); /* | for now will do this for each lun ... */ - for(i = 0; i < sess->cam.target_nluns; i++) { + for(n = i = 0; i < sess->cam.target_nluns; i++) { debug(2, "CAM path_id=%d target_id=%d target_lun=%d", sess->cam.path_id, sess->cam.target_id, sess->cam.target_lun[i]); sess->camdev = cam_open_btl(sess->cam.path_id, sess->cam.target_id, - sess->cam.target_lun[i], O_RDWR, NULL); + i, O_RDWR, NULL); if(sess->camdev == NULL) { - syslog(LOG_WARNING, "%s", cam_errbuf); + //syslog(LOG_WARNING, "%s", cam_errbuf); debug(3, "%s", cam_errbuf); continue; } @@ -378,20 +378,21 @@ doCAM(isess_t *sess) ccb->ccb_h.func_code = XPT_REL_SIMQ; ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS; ccb->crs.openings = sess->op->tags; - if(cam_send_ccb(sess->camdev, ccb) < 0) - syslog(LOG_WARNING, "%s", cam_errbuf); + debug(2, "%s", cam_errbuf); else if((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { syslog(LOG_WARNING, "XPT_REL_SIMQ CCB failed"); // cam_error_print(sess->camdev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); } - else + else { + n++; syslog(LOG_INFO, "%s tagged openings now %d\n", pathstr, ccb->crs.openings); - + } cam_freeccb(ccb); cam_close_device(sess->camdev); } + return n; } static trans_t @@ -417,7 +418,15 @@ supervise(isess_t *sess) perror("daemon"); exit(1); } + if(sess->op->pidfile != NULL) { + FILE *pidf; + pidf = fopen(sess->op->pidfile, "w"); + if(pidf != NULL) { + fprintf(pidf, "%d\n", getpid()); + fclose(pidf); + } + } openlog("iscontrol", LOG_CONS|LOG_PERROR|LOG_PID|LOG_NDELAY, LOG_KERN); syslog(LOG_INFO, "running"); @@ -426,7 +435,11 @@ supervise(isess_t *sess) perror("ISCSISTART"); return -1; } - doCAM(sess); + if(doCAM(sess) == 0) { + syslog(LOG_WARNING, "no device found"); + ioctl(sess->fd, ISCSISTOP); + return T15; + } } else { @@ -449,7 +462,8 @@ supervise(isess_t *sess) sess->flags |= SESS_FULLFEATURE; sess->flags &= ~(SESS_REDIRECT | SESS_RECONNECT); - printf("iscontrol: supervise starting main loop\n"); + if(vflag) + printf("iscontrol: supervise starting main loop\n"); /* | the main loop - actually do nothing | all the work is done inside the kernel @@ -468,14 +482,14 @@ supervise(isess_t *sess) } if(sess->flags & SESS_DISCONNECT) { - val = 0; - if(ioctl(sess->fd, ISCSISTOP, &val)) { - perror("ISCSISTOP"); - } sess->flags &= ~SESS_FULLFEATURE; return T9; } else { + val = 0; + if(ioctl(sess->fd, ISCSISTOP, &val)) { + perror("ISCSISTOP"); + } sess->flags |= SESS_INITIALLOGIN1; } return T8; @@ -490,7 +504,7 @@ handledDiscoveryResp(isess_t *sess, pdu_t *pp) debug_called(3); len = pp->ds_len; - ptr = pp->ds; + ptr = pp->ds_addr; while(len > 0) { if(*ptr != 0) printf("%s\n", ptr); @@ -579,8 +593,13 @@ doLogin(isess_t *sess) static int handleLogoutResp(isess_t *sess, pdu_t *pp) { - if(sess->flags & SESS_DISCONNECT) + if(sess->flags & SESS_DISCONNECT) { + int val = 0; + if(ioctl(sess->fd, ISCSISTOP, &val)) { + perror("ISCSISTOP"); + } return 0; + } return T13; } @@ -610,7 +629,7 @@ typedef enum { S1, S2, /*S3,*/ S4, S5, S6, S7, S8 } state_t; -#if 0 +/** S1: FREE S2: XPT_WAIT S4: IN_LOGIN @@ -652,7 +671,7 @@ typedef enum { | +-----\ /--->\ / T14 | | ------- --+----+------+T17 +---------------------------+ -#endif +*/ int fsm(isc_opt_t *op) diff --git a/sbin/iscontrol/iscontrol.8 b/sbin/iscontrol/iscontrol.8 index 71595db23ab7..d2e8bdddd3d0 100644 --- a/sbin/iscontrol/iscontrol.8 +++ b/sbin/iscontrol/iscontrol.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2007-2008 Daniel Braniss +.\" Copyright (c) 2007-2010 Daniel Braniss .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -32,11 +32,12 @@ .Nd login/negotiator/control for an iSCSI initiator session .Sh SYNOPSIS .Nm -.Op Fl vd +.Op Fl dv .Oo -.Op Fl c Ar file +.Fl c Ar file .Op Fl n Ar nickname .Oc +.Op Fl p Ar pidfile .Op Fl t Ar target .Op Ar variable Ns = Ns Ar value .Sh DESCRIPTION @@ -57,26 +58,29 @@ It will terminate/logout the session when a SIGHUP signal is received. The flags are as follows: .Bl -tag -width variable=value -.It Fl v -verbose mode. -.It Fl d -do a -.Em discovery session -and exit. .It Fl c Ar file a file containing configuration .Em key-options , see -.Xr iscsi.conf 5 +.Xr iscsi.conf 5 . +.It Fl d +do a +.Em discovery session +and exit. .It Fl n Ar nickname if .Sy -c file is specified, then search for the block named .Em nickname in that file, see -.Xr iscsi.conf 5 +.Xr iscsi.conf 5 . +.It Fl p Ar pidfile +will write the process ID of the session to the specified +.Em pidfile .It Fl t Ar target -is the target's IP address or name +the target's IP address or name. +.It Fl v +verbose mode. .It Ar variable Ns = Ns Ar value see .Xr iscsi.conf 5 @@ -86,13 +90,13 @@ possible values. .Sh EXAMPLES .Dl iscontrol -dt myiscsitarget .Pp -will start a +will start a .Em discovery session with the target and print to stdout the list of available targetnames/targetadresses. Note: this listing does not necessarily mean availability, since depending on the target configuration, a discovery session might -not need login/access permission, but a +not need login/access permission, but a .Em full session certainly does. .sp diff --git a/sbin/iscontrol/iscontrol.c b/sbin/iscontrol/iscontrol.c index 8cfa5fa469c0..c7bda0e13fc1 100644 --- a/sbin/iscontrol/iscontrol.c +++ b/sbin/iscontrol/iscontrol.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,15 +53,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include "iscsi.h" +#include #include "iscontrol.h" -#define USAGE "[-v] [-d] [-c config] [-n name] [-t target] " -#define OPTIONS "vdc:t:n:" - -#ifndef DEBUG -//int vflag; -#endif +#define USAGE "[-v] [-d] [-c config] [-n name] [-t target] [-p pidfile]" +#define OPTIONS "vdc:t:n:p:" token_t AuthMethods[] = { {"None", NONE}, @@ -70,14 +66,14 @@ token_t AuthMethods[] = { {"SPKM2", SPKM2}, {"SRP", SRP}, {"CHAP", CHAP}, - {0} + {0, 0} }; token_t DigestMethods[] = { {"None", 0}, {"CRC32", 1}, {"CRC32C", 1}, - {0} + {0, 0} }; u_char isid[6 + 6]; @@ -128,7 +124,7 @@ int main(int cc, char **vv) { int ch, disco; - char *pname, *p, *q, *ta, *kw; + char *pname, *pidfile, *p, *q, *ta, *kw; isc_opt_t *op; FILE *fd; @@ -141,6 +137,7 @@ main(int cc, char **vv) kw = ta = 0; disco = 0; + pidfile = NULL; while((ch = getopt(cc, vv, OPTIONS)) != -1) { switch(ch) { @@ -163,6 +160,9 @@ main(int cc, char **vv) case 'n': kw = optarg; break; + case 'p': + pidfile = optarg; + break; default: badu: fprintf(stderr, "Usage: %s %s\n", pname, USAGE); @@ -225,7 +225,7 @@ main(int cc, char **vv) op->sessionType = "Discovery"; op->targetName = 0; } - + op->pidfile = pidfile; fsm(op); exit(0); diff --git a/sbin/iscontrol/iscontrol.h b/sbin/iscontrol/iscontrol.h index 5ab296d0a5c9..6aa5612e2321 100644 --- a/sbin/iscontrol/iscontrol.h +++ b/sbin/iscontrol/iscontrol.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -154,7 +154,7 @@ void parseArgs(int nargs, char **args, isc_opt_t *op); void parseConfig(FILE *fd, char *key, isc_opt_t *op); char *chapDigest(char *ap, char id, char *cp, char *chapSecret); -char *genChapChallenge(char *encoding, int len); +char *genChapChallenge(char *encoding, uint len); int str2bin(char *str, char **rsp); char *bin2str(char *fmt, unsigned char *md, int blen); diff --git a/sbin/iscontrol/iscsi.conf.5 b/sbin/iscontrol/iscsi.conf.5 index 299fa16ddb21..84f0f01b6b72 100644 --- a/sbin/iscontrol/iscsi.conf.5 +++ b/sbin/iscontrol/iscsi.conf.5 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2007-2008 Daniel Braniss +.\" Copyright (c) 2007-2010 Daniel Braniss .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -68,6 +68,7 @@ Only CRC32C is implemented. Default is none. .It Cm DataDigest same as for HeaderDigest, but on the data part of the iSCSI PDU. +(not yet tested) .It Cm MaxConnections is the number of simultaneous connections per session, currently only 1. diff --git a/sbin/iscontrol/login.c b/sbin/iscontrol/login.c index ec17f211573a..e2a9e5f5edff 100644 --- a/sbin/iscontrol/login.c +++ b/sbin/iscontrol/login.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "iscsi.h" +#include #include "iscontrol.h" static char *status_class1[] = { @@ -107,7 +107,7 @@ getkeyval(char *key, pdu_t *pp) debug_called(3); len = pp->ds_len; - ptr = (char *)pp->ds; + ptr = (char *)pp->ds_addr; klen = strlen(key); while(len > klen) { if(strncmp(key, ptr, klen) == 0) @@ -163,7 +163,7 @@ processParams(isess_t *sess, pdu_t *pp) debug_called(3); len = pp->ds_len; - ptr = (char *)pp->ds; + ptr = (char *)pp->ds_addr; while(len > 0) { if(vflag > 1) printf("got: len=%d %s\n", len, ptr); @@ -233,7 +233,7 @@ handleLoginResp(isess_t *sess, pdu_t *pp) st_class = status >> 8; if(status) { - int st_detail = status & 0xff; + uint st_detail = status & 0xff; switch(st_class) { case 1: // Redirect diff --git a/sbin/iscontrol/misc.c b/sbin/iscontrol/misc.c index 9634a1bb023c..1c7a1ad9821a 100644 --- a/sbin/iscontrol/misc.c +++ b/sbin/iscontrol/misc.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include "iscontrol.h" + static inline char c2b(unsigned char c) { diff --git a/sbin/iscontrol/pdu.c b/sbin/iscontrol/pdu.c index 444c1f11ab21..c4d3a2a2556b 100644 --- a/sbin/iscontrol/pdu.c +++ b/sbin/iscontrol/pdu.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005-2008 Daniel Braniss + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include "iscsi.h" +#include #include "iscontrol.h" static void pukeText(char *it, pdu_t *pp); @@ -85,7 +85,7 @@ sendPDU(isess_t *sess, pdu_t *pp, handler_t *hdlr) int res; pp->ahs_size = 8 * 1024; - if((pp->ahs = malloc(pp->ahs_size)) == NULL) { + if((pp->ahs_addr = malloc(pp->ahs_size)) == NULL) { fprintf(stderr, "out of mem!"); return -1; } @@ -126,16 +126,16 @@ addText(pdu_t *pp, char *fmt, ...) if((pp->ds_len + len) > pp->ds_size) { u_char *np; - np = realloc(pp->ds, pp->ds_size + len + FUDGE); + np = realloc(pp->ds_addr, pp->ds_size + len + FUDGE); if(np == NULL) { free(str); //XXX: out of memory! return -1; } - pp->ds = np; + pp->ds_addr = np; pp->ds_size += len + FUDGE; } - memcpy(pp->ds + pp->ds_len, str, len); + memcpy(pp->ds_addr + pp->ds_len, str, len); pp->ds_len += len; free(str); return len; @@ -145,12 +145,12 @@ void freePDU(pdu_t *pp) { if(pp->ahs_size) - free(pp->ahs); + free(pp->ahs_addr); if(pp->ds_size) - free(pp->ds); + free(pp->ds_addr); bzero(&pp->ipdu, sizeof(union ipdu_u)); - pp->ahs = NULL; - pp->ds = NULL; + pp->ahs_addr = NULL; + pp->ds_addr = NULL; pp->ahs_size = 0; pp->ds_size = pp->ds_len = 0; } @@ -163,7 +163,7 @@ pukeText(char *it, pdu_t *pp) size_t len, n; len = pp->ds_len; - ptr = (char *)pp->ds; + ptr = (char *)pp->ds_addr; cmd = pp->ipdu.bhs.opcode; printf("%s: cmd=0x%x len=%d\n", it, cmd, (int)len); diff --git a/sbin/iscontrol/pdu.h b/sbin/iscontrol/pdu.h deleted file mode 100644 index 0154f9e60171..000000000000 --- a/sbin/iscontrol/pdu.h +++ /dev/null @@ -1,134 +0,0 @@ -/*- - * Copyright (c) 2005 Daniel Braniss - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ -/* - | $Id: pdu.h,v 2.1 2006/11/12 08:06:51 danny Exp $ - */ - -/* - | keep in BIG endian order (network byte order). - */ - -typedef struct login_req { - char cmd; // 0x03 - - u_char NSG:2; - u_char CSG:2; - u_char _:2; - u_char C:1; - u_char T:1; - - char v_max; - char v_min; - - int len; // remapped via standard bhs - char isid[6]; - short tsih; - int itt; // Initiator Task Tag; - - int CID:16; - int rsv:16; - - int cmdSN; - int expStatSN; - int unused[4]; -} login_req_t; - -typedef struct login_rsp { - char cmd; // 0x23 - u_char NSG:2; - u_char CSG:2; - u_char _1:2; - u_char C:1; - u_char T:1; - - char v_max; - char v_act; - - int len; // remapped via standard bhs - char isid[6]; - short tsih; - int itt; // Initiator Task Tag; - int _2; - rsp_sn_t sn; - int status:16; - int _3:16; - int _4[2]; -} login_rsp_t; - -typedef struct text_req { - char cmd; // 0x04 - - u_char _1:6; - u_char C:1; // Continuation - u_char F:1; // Final - char _2[2]; - - int len; - int itt; // Initiator Task Tag - int LUN[2]; - int ttt; // Target Transfer Tag - int cmdSN; - int expStatSN; - int unused[4]; -} text_req_t; - -/* - | Responses - */ -typedef struct logout_req { - char cmd; // 0x06 - char reason; // 0 - close session - // 1 - close connection - // 2 - remove the connection for recovery - char _2[2]; - - int len; - int _r[2]; - int itt; // Initiator Task Tag; - - u_int CID:16; - u_int rsv:16; - - int cmdSN; - int expStatSN; - int unused[4]; -} logout_req_t; - -typedef struct logout_rsp { - char cmd; // 0x26 - char cbits; - char _1[2]; - int len; - int _2[2]; - int itt; - int _3; - rsp_sn_t sn; - short time2wait; - short time2retain; - int _4; -} logout_rsp_t; diff --git a/sys/dev/iscsi/initiator/isc_cam.c b/sys/dev/iscsi/initiator/isc_cam.c index 0d8782351c86..706ea4fbabd4 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 + * Copyright (c) 2005-2010 Daniel Braniss * 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 __FBSDID("$FreeBSD$"); @@ -43,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -53,146 +56,34 @@ __FBSDID("$FreeBSD$"); #include #include -// XXX: untested/incomplete -void -ic_freeze(isc_session_t *sp) -{ - 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); - } -#endif - sp->flags |= ISC_FROZEN; -} - -// XXX: untested/incomplete -void -ic_release(isc_session_t *sp) -{ - 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); - } -#endif - sp->flags &= ~ISC_FROZEN; -} - -void -ic_lost_target(isc_session_t *sp, int target) -{ - struct isc_softc *isp = sp->isc; - - debug_called(8); - sdebug(2, "target=%d", target); - if(sp->cam_path != NULL) { - mtx_lock(&isp->cam_mtx); - xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); - xpt_free_path(sp->cam_path); - mtx_unlock(&isp->cam_mtx); - sp->cam_path = 0; // XXX - } -} - static void -_scan_callback(struct cam_periph *periph, union ccb *ccb) -{ - isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0; - - debug_called(8); - - free(ccb, M_TEMP); - - if(sp->flags & ISC_FFPWAIT) { - sp->flags &= ~ISC_FFPWAIT; - wakeup(sp); - } -} - -static void -_scan_target(isc_session_t *sp, int target) -{ - union ccb *ccb; - - debug_called(8); - sdebug(2, "target=%d", target); - - if((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) { - xdebug("scan failed (can't allocate CCB)"); - return; - } - 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; - - 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) { - xdebug("can't create cam path"); - CAM_UNLOCK(isp); - return ENODEV; // XXX - } - CAM_UNLOCK(isp); - - _scan_target(sp, sp->sid); - - while(sp->flags & ISC_FFPWAIT) - tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should - // be configurable - if(sp->target_nluns > 0) { - sp->flags |= ISC_FFPHASE; - return 0; - } - - return ENODEV; -} - -static void -_inq(struct cam_sim *sim, union ccb *ccb, int maxluns) +_inq(struct cam_sim *sim, union ccb *ccb) { struct ccb_pathinq *cpi = &ccb->cpi; + isc_session_t *sp = cam_sim_softc(sim); - debug_called(4); + debug_called(8); + 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 = ISCSI_MAX_TARGETS - 1; + cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1; cpi->initiator_id = ISCSI_MAX_TARGETS; - cpi->max_lun = maxluns; + cpi->max_lun = sp->opt.maxluns - 1; cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; + 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; - cpi->ccb_h.status = CAM_REQ_CMP; +#endif } static __inline int @@ -203,77 +94,111 @@ _scsi_encap(struct cam_sim *sim, union ccb *ccb) #if __FreeBSD_version < 700000 ret = scsi_encap(sim, ccb); #else - struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim); + isc_session_t *sp = cam_sim_softc(sim); - mtx_unlock(&isp->cam_mtx); + mtx_unlock(&sp->cam_mtx); ret = scsi_encap(sim, ccb); - mtx_lock(&isp->cam_mtx); + mtx_lock(&sp->cam_mtx); #endif return ret; } +void +ic_lost_target(isc_session_t *sp, int target) +{ + debug_called(8); + sdebug(2, "lost target=%d", target); + + if(sp->cam_path != NULL) { + mtx_lock(&sp->cam_mtx); + xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); + xpt_free_path(sp->cam_path); + mtx_unlock(&sp->cam_mtx); + sp->cam_path = 0; // XXX + } +} + +static void +scan_callback(struct cam_periph *periph, union ccb *ccb) +{ + isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0; + + debug_called(8); + + free(ccb, M_TEMP); + + if(sp->flags & ISC_SCANWAIT) { + sp->flags &= ~ISC_SCANWAIT; + wakeup(sp); + } +} + +static int +ic_scan(isc_session_t *sp) +{ + union ccb *ccb; + + debug_called(8); + 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 ENOMEM; // XXX + } + + sp->flags &= ~ISC_CAMDEVS; + sp->flags |= ISC_SCANWAIT; + + 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(sp); + free(ccb, M_TEMP); + return ENODEV; // XXX + } + 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); + + 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_CAMDEVS; + return 0; + } + + return ENODEV; +} + 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 - */ + if(sp == NULL) { + xdebug("sp == NULL! cannot happen"); + return; + } 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; - } - } - - 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 :-) + 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*/); - 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*/); - - 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_UNLOCK(isp); - - isp->cam_sim = sim; - isp->cam_path = path; - - 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); + cam_sim_free(sim, /*free_devq*/TRUE); + CAM_UNLOCK(sp); #if __FreeBSD_version >= 700000 - mtx_destroy(&isp->cam_mtx); + mtx_destroy(&sp->cam_mtx); #endif - return ENXIO; + return ENXIO; + } + sp->cam_sim = sim; + CAM_UNLOCK(sp); + + sdebug(1, "cam subsystem initialized"); + + ic_scan(sp); + + return 0; } diff --git a/sys/dev/iscsi/initiator/isc_sm.c b/sys/dev/iscsi/initiator/isc_sm.c index ec9d34695af1..25a091978af1 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 + * Copyright (c) 2005-2010 Daniel Braniss * 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 @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -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 ef32e63efe47..329f830b6694 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 + * Copyright (c) 2005-2010 Daniel Braniss * 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 __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; + mh->m_len = sizeof(union ipdu_u); - if(sp->hdrDigest) - pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0); + 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(sp->hdrDigest) - len += 4; - if(bhs->DSLength) { - n = bhs->DSLength; -#if BYTE_ORDER == LITTLE_ENDIAN - pp->ds_len = ((n & 0x00ff0000) >> 16) - | (n & 0x0000ff00) - | ((n & 0x000000ff) << 16); -#else - pp->ds_len = n; -#endif - len += pp->ds_len; - while(len & 03) - len++; - if(sp->dataDigest) - 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(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(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); - } - } + 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; } } - error = soreceive(so, NULL, uio, mp, NULL, &flags); + 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) { + len = bhs->DSLength; +#if BYTE_ORDER == LITTLE_ENDIAN + len = ((len & 0x00ff0000) >> 16) + | (len & 0x0000ff00) + | ((len & 0x000000ff) << 16); +#endif + 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(ISOK2DIG(sp->dataDigest, pp)) + len += 4; + uio->uio_resid = len; + 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 b59516df8d81..7a8138b93720 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 + * Copyright (c) 2005-2010 Daniel Braniss * 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 @@ -58,20 +58,22 @@ __FBSDID("$FreeBSD$"); #include #include +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 2296989ad0e2..b44c4f76efcc 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 + * Copyright (c) 2005-2010 Daniel Braniss * 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 @@ -56,15 +55,17 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +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); @@ -588,34 +578,58 @@ i_recv(struct cdev *dev, caddr_t arg, struct thread *td) return error; } +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; } - TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link); - sc->nsess++; - mtx_unlock(&sc->mtx); + sx_unlock(&sc->unit_sx); + + mtx_lock(&sc->isc_mtx); + TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link); + 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 2eace6839a40..31421138ea15 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 + * Copyright (c) 2005-2010 Daniel Braniss * 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 #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; - - ahs_t *ahs; - u_int ahs_len; - u_int ahs_size; // the allocated size u_int hdr_dig; // header digest - u_char *ds; + ahs_t *ahs_addr; + u_int ahs_len; + u_int ahs_size; // the allocated size + + 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 9ef92d57c18e..03d9293e7e3c 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 + * Copyright (c) 2005-2010 Daniel Braniss * 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 @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -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 128a745c5677..a6eae21ee03b 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 + * Copyright (c) 2005-2010 Daniel Braniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,9 +25,18 @@ * * $FreeBSD$ */ + /* - | $Id: iscsivar.h,v 1.30 2007/04/22 10:12:11 danny Exp danny $ + | $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 +/* + | 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_HOLD BIT(14) -#define ISC_HOLDED BIT(15) +#define ISC_MEMWAIT BIT(11) +#define ISC_SIGNALED BIT(12) + +#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,16 +158,18 @@ 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 */ @@ -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 cdev *dev; - eventhandler_tag eh; - char isid[6]; // Initiator Session ID (48 bits) - struct mtx mtx; - - int nsess; + struct mtx isc_mtx; TAILQ_HEAD(,isc_session) isc_sess; - isc_session_t *sessions[MAX_SESSIONS]; + int nsess; + struct cdev *dev; + char isid[6]; // Initiator Session ID (48 bits) + struct unrhdr *unit; + struct sx unit_sx; + + 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); @@ -564,6 +567,27 @@ i_search_hld(isc_session_t *sp, int itt, int keep) return pq; } +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) {