From owner-freebsd-scsi@FreeBSD.ORG Wed Jul 28 08:41:14 2010 Return-Path: Delivered-To: freebsd-scsi@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 95ED31065674 for ; Wed, 28 Jul 2010 08:41:14 +0000 (UTC) (envelope-from des@des.no) Received: from smtp.des.no (smtp.des.no [194.63.250.102]) by mx1.freebsd.org (Postfix) with ESMTP id E095E8FC08 for ; Wed, 28 Jul 2010 08:41:13 +0000 (UTC) Received: from ds4.des.no (des.no [84.49.246.2]) by smtp.des.no (Postfix) with ESMTP id B40821FFC33; Wed, 28 Jul 2010 08:41:11 +0000 (UTC) Received: by ds4.des.no (Postfix, from userid 1001) id 8445A84525; Wed, 28 Jul 2010 10:41:11 +0200 (CEST) From: =?utf-8?Q?Dag-Erling_Sm=C3=B8rgrav?= To: Daniel Braniss References: <86k4ogoyy7.fsf@ds4.des.no> <86fwz4oxqw.fsf@ds4.des.no> <86bp9soxlj.fsf@ds4.des.no> Date: Wed, 28 Jul 2010 10:41:11 +0200 In-Reply-To: <86bp9soxlj.fsf@ds4.des.no> ("Dag-Erling =?utf-8?Q?Sm=C3=B8rg?= =?utf-8?Q?rav=22's?= message of "Wed, 28 Jul 2010 09:48:56 +0200") Message-ID: <86y6cwngm0.fsf@ds4.des.no> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (berkeley-unix) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Cc: freebsd-scsi@freebsd.org Subject: Re: iscsi_initiator patches X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Jul 2010 08:41:14 -0000 --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable New new patch with WARNS=3D3 fixes. DES --=20 Dag-Erling Sm=C3=B8rgrav - des@des.no --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=iscsi-des.diff Index: sbin/iscontrol/iscsi.conf.5 =================================================================== --- sbin/iscontrol/iscsi.conf.5 (revision 210555) +++ sbin/iscontrol/iscsi.conf.5 (working copy) @@ -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 @@ 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. Index: sbin/iscontrol/iscontrol.8 =================================================================== --- sbin/iscontrol/iscontrol.8 (revision 210555) +++ sbin/iscontrol/iscontrol.8 (working copy) @@ -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 @@ 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 @@ .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 Index: sbin/iscontrol/iscontrol.h =================================================================== --- sbin/iscontrol/iscontrol.h (revision 210555) +++ sbin/iscontrol/iscontrol.h (working copy) @@ -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 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); Index: sbin/iscontrol/config.c =================================================================== --- sbin/iscontrol/config.c (revision 210555) +++ sbin/iscontrol/config.c (working copy) @@ -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 @@ #include #include -#include "iscsi.h" +#include #include "iscontrol.h" /* @@ -94,6 +94,11 @@ #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 @@ _E(U_LO, S_SW, sessionType), - {0} + _E(0, 0, end) }; #define _OPT_INT(w) strtol((char *)w, NULL, 0) @@ -154,7 +159,7 @@ 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 @@ 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 @@ } - 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 @@ 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; Index: sbin/iscontrol/fsm.c =================================================================== --- sbin/iscontrol/fsm.c (revision 210555) +++ sbin/iscontrol/fsm.c (working copy) @@ -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 @@ #include #include -#include "iscsi.h" +#include #include "iscontrol.h" typedef enum { @@ -99,26 +99,26 @@ #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 @@ 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 @@ } sess->flags |= SESS_CONNECTED; return T1; - } + } fprintf(stderr, "errno=%d\n", sv_errno); perror("connect"); @@ -289,7 +289,7 @@ // 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 @@ } } -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } if(sess->flags & SESS_DISCONNECT) { + sess->flags &= ~SESS_FULLFEATURE; + return T9; + } + else { val = 0; if(ioctl(sess->fd, ISCSISTOP, &val)) { perror("ISCSISTOP"); } - sess->flags &= ~SESS_FULLFEATURE; - return T9; - } - else { sess->flags |= SESS_INITIALLOGIN1; } return T8; @@ -490,7 +504,7 @@ 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 @@ 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; } Index: sbin/iscontrol/login.c =================================================================== --- sbin/iscontrol/login.c (revision 210555) +++ sbin/iscontrol/login.c (working copy) @@ -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 @@ #include #include -#include "iscsi.h" +#include #include "iscontrol.h" static char *status_class1[] = { @@ -107,7 +107,7 @@ 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 @@ 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 @@ st_class = status >> 8; if(status) { - int st_detail = status & 0xff; + uint st_detail = status & 0xff; switch(st_class) { case 1: // Redirect Index: sbin/iscontrol/pdu.c =================================================================== --- sbin/iscontrol/pdu.c (revision 210555) +++ sbin/iscontrol/pdu.c (working copy) @@ -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,10 +43,10 @@ #include #include -#include "iscsi.h" +#include #include "iscontrol.h" -static void pukeText(char *it, pdu_t *pp); +static void pukeText(char *it, pdu_t *pp); int xmitpdu(isess_t *sess, pdu_t *pp) @@ -85,7 +85,7 @@ 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 @@ 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 @@ 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 @@ 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); Index: sbin/iscontrol/misc.c =================================================================== --- sbin/iscontrol/misc.c (revision 210555) +++ sbin/iscontrol/misc.c (working copy) @@ -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 @@ #include #include +#include +#include "iscontrol.h" + static inline char c2b(unsigned char c) { Index: sbin/iscontrol/Makefile =================================================================== --- sbin/iscontrol/Makefile (revision 210555) +++ sbin/iscontrol/Makefile (working copy) @@ -4,9 +4,10 @@ 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 Index: sbin/iscontrol/auth_subr.c =================================================================== --- sbin/iscontrol/auth_subr.c (revision 210555) +++ sbin/iscontrol/auth_subr.c (working copy) @@ -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 @@ #include #include -#include "iscsi.h" +#include #include "iscontrol.h" static int @@ -152,7 +152,7 @@ } char * -genChapChallenge(char *encoding, int len) +genChapChallenge(char *encoding, uint len) { int fd; unsigned char tmp[1024]; Index: sbin/iscontrol/iscontrol.c =================================================================== --- sbin/iscontrol/iscontrol.c (revision 210555) +++ sbin/iscontrol/iscontrol.c (working copy) @@ -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,16 +53,12 @@ #include #include -#include "iscsi.h" +#include #include "iscontrol.h" -#define USAGE "[-v] [-d] [-c config] [-n name] [-t target] " -#define OPTIONS "vdc:t:n:" +#define USAGE "[-v] [-d] [-c config] [-n name] [-t target] [-p pidfile]" +#define OPTIONS "vdc:t:n:p:" -#ifndef DEBUG -//int vflag; -#endif - token_t AuthMethods[] = { {"None", NONE}, {"KRB5", KRB5}, @@ -70,14 +66,14 @@ {"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 @@ 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 @@ kw = ta = 0; disco = 0; + pidfile = NULL; while((ch = getopt(cc, vv, OPTIONS)) != -1) { switch(ch) { @@ -163,6 +160,9 @@ case 'n': kw = optarg; break; + case 'p': + pidfile = optarg; + break; default: badu: fprintf(stderr, "Usage: %s %s\n", pname, USAGE); @@ -225,7 +225,7 @@ op->sessionType = "Discovery"; op->targetName = 0; } - + op->pidfile = pidfile; fsm(op); exit(0); Index: sbin/iscontrol/pdu.h =================================================================== --- sbin/iscontrol/pdu.h (revision 210555) +++ sbin/iscontrol/pdu.h (working copy) @@ -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; Index: sys/dev/iscsi/initiator/isc_cam.c =================================================================== --- sys/dev/iscsi/initiator/isc_cam.c (revision 210555) +++ sys/dev/iscsi/initiator/isc_cam.c (working copy) @@ -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 @@ #include #include #include +#include #include #include @@ -53,52 +56,72 @@ #include #include -// XXX: untested/incomplete -void -ic_freeze(isc_session_t *sp) +static void +_inq(struct cam_sim *sim, union ccb *ccb) { + struct ccb_pathinq *cpi = &ccb->cpi; + isc_session_t *sp = cam_sim_softc(sim); + debug_called(8); -#if 0 - sdebug(2, "freezing path=%p", sp->cam_path == NULL? 0: sp->cam_path); - if((sp->cam_path != NULL) && !(sp->flags & ISC_FROZEN)) { - xpt_freeze_devq(sp->cam_path, 1); - } + debug(3, "sid=%d target=%d lun=%d", sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun); + + cpi->version_num = 1; /* XXX??? */ + cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32; + cpi->target_sprt = 0; + cpi->hba_misc = 0; + cpi->hba_eng_cnt = 0; + cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1; + cpi->initiator_id = ISCSI_MAX_TARGETS; + cpi->max_lun = sp->opt.maxluns - 1; + cpi->bus_id = cam_sim_bus(sim); + cpi->base_transfer_speed = 3300; // 40000; // XXX: + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); + cpi->unit_number = cam_sim_unit(sim); + cpi->transport = XPORT_ISCSI; + cpi->transport_version = 0; + cpi->ccb_h.status = CAM_REQ_CMP; +#if defined(KNOB_VALID_ADDRESS) + cpi->transport = XPORT_ISCSI; + cpi->transport_version = 0; #endif - sp->flags |= ISC_FROZEN; } -// XXX: untested/incomplete -void -ic_release(isc_session_t *sp) +static __inline int +_scsi_encap(struct cam_sim *sim, union ccb *ccb) { - debug_called(8); -#if 0 - sdebug(2, "release path=%p", sp->cam_path == NULL? 0: sp->cam_path); - if((sp->cam_path != NULL) && (sp->flags & ISC_FROZEN)) { - xpt_release_devq(sp->cam_path, 1, TRUE); - } + int ret; + +#if __FreeBSD_version < 700000 + ret = scsi_encap(sim, ccb); +#else + isc_session_t *sp = cam_sim_softc(sim); + + mtx_unlock(&sp->cam_mtx); + ret = scsi_encap(sim, ccb); + mtx_lock(&sp->cam_mtx); #endif - sp->flags &= ~ISC_FROZEN; + return ret; } void ic_lost_target(isc_session_t *sp, int target) { - struct isc_softc *isp = sp->isc; - debug_called(8); - sdebug(2, "target=%d", target); + sdebug(2, "lost target=%d", target); + if(sp->cam_path != NULL) { - mtx_lock(&isp->cam_mtx); + mtx_lock(&sp->cam_mtx); xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); xpt_free_path(sp->cam_path); - mtx_unlock(&isp->cam_mtx); + mtx_unlock(&sp->cam_mtx); sp->cam_path = 0; // XXX } } static void -_scan_callback(struct cam_periph *periph, union ccb *ccb) +scan_callback(struct cam_periph *periph, union ccb *ccb) { isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0; @@ -106,63 +129,52 @@ free(ccb, M_TEMP); - if(sp->flags & ISC_FFPWAIT) { - sp->flags &= ~ISC_FFPWAIT; + if(sp->flags & ISC_SCANWAIT) { + sp->flags &= ~ISC_SCANWAIT; wakeup(sp); } } -static void -_scan_target(isc_session_t *sp, int target) +static int +ic_scan(isc_session_t *sp) { - union ccb *ccb; + union ccb *ccb; debug_called(8); - sdebug(2, "target=%d", target); + sdebug(2, "scanning sid=%d", sp->sid); if((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) { xdebug("scan failed (can't allocate CCB)"); - return; + return ENOMEM; // XXX } - CAM_LOCK(sp->isc); + + 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->ccb_h.cbfcnp = scan_callback; ccb->crcn.flags = CAM_FLAG_NONE; ccb->ccb_h.spriv_ptr0 = sp; xpt_action(ccb); - CAM_UNLOCK(sp->isc); -} + CAM_UNLOCK(sp); -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) + while(sp->flags & ISC_SCANWAIT) tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should // be configurable + sdebug(2, "# of luns=%d", sp->target_nluns); + if(sp->target_nluns > 0) { - sp->flags |= ISC_FFPHASE; + sp->flags |= ISC_CAMDEVS; return 0; } @@ -170,110 +182,25 @@ } static void -_inq(struct cam_sim *sim, union ccb *ccb, int maxluns) -{ - struct ccb_pathinq *cpi = &ccb->cpi; - - debug_called(4); - - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32; - cpi->target_sprt = 0; - cpi->hba_misc = 0; - cpi->hba_eng_cnt = 0; - cpi->max_target = ISCSI_MAX_TARGETS - 1; - cpi->initiator_id = ISCSI_MAX_TARGETS; - cpi->max_lun = maxluns; - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; - strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN); - strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->transport = XPORT_ISCSI; - cpi->transport_version = 0; - cpi->ccb_h.status = CAM_REQ_CMP; -} - -static __inline int -_scsi_encap(struct cam_sim *sim, union ccb *ccb) -{ - int ret; - -#if __FreeBSD_version < 700000 - ret = scsi_encap(sim, ccb); -#else - struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim); - - mtx_unlock(&isp->cam_mtx); - ret = scsi_encap(sim, ccb); - mtx_lock(&isp->cam_mtx); -#endif - return ret; -} - -static void ic_action(struct cam_sim *sim, union ccb *ccb) { + isc_session_t *sp = cam_sim_softc(sim); struct ccb_hdr *ccb_h = &ccb->ccb_h; - struct isc_softc *isp = (struct isc_softc *)cam_sim_softc(sim); - isc_session_t *sp; debug_called(8); - if((ccb_h->target_id != CAM_TARGET_WILDCARD) && (ccb_h->target_id < MAX_SESSIONS)) - sp = isp->sessions[ccb_h->target_id]; - else - sp = NULL; - ccb_h->spriv_ptr0 = sp; - - debug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d", + sdebug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d", ccb_h->func_code, ccb->ccb_h.flags, ccb->ccb_h.status, ccb->ccb_h.target_id, ccb->ccb_h.target_lun, ccb->ccb_h.retry_count, ccb_h->timeout); - /* - | first quick check - */ + 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 +237,35 @@ 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 +275,7 @@ break; } #if __FreeBSD_version < 700000 - XPT_DONE(isp, ccb); + XPT_DONE(sp, ccb); #else xpt_done(ccb); #endif @@ -337,102 +285,102 @@ 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_sim_free(sim, /*free_devq*/TRUE); + CAM_UNLOCK(sp); +#if __FreeBSD_version >= 700000 + mtx_destroy(&sp->cam_mtx); +#endif + return ENXIO; } + sp->cam_sim = sim; + CAM_UNLOCK(sp); - CAM_UNLOCK(isp); + sdebug(1, "cam subsystem initialized"); - isp->cam_sim = sim; - isp->cam_path = path; + ic_scan(sp); - debug(2, "cam subsystem initialized"); // XXX: add dev ... - debug(4, "sim=%p path=%p", sim, path); return 0; - - bad: - cam_sim_free(sim, /*free_devq*/TRUE); - CAM_UNLOCK(isp); -#if __FreeBSD_version >= 700000 - mtx_destroy(&isp->cam_mtx); -#endif - return ENXIO; } Index: sys/dev/iscsi/initiator/iscsi.h =================================================================== --- sys/dev/iscsi/initiator/iscsi.h (revision 210555) +++ sys/dev/iscsi/initiator/iscsi.h (working copy) @@ -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 @@ #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 { union ipdu_u ipdu; + u_int hdr_dig; // header digest - ahs_t *ahs; + ahs_t *ahs_addr; u_int ahs_len; u_int ahs_size; // the allocated size - u_int hdr_dig; // header digest - u_char *ds; + u_char *ds_addr; u_int ds_len; u_int ds_size; // the allocated size u_int ds_dig; // data digest @@ -474,6 +470,7 @@ u_char tgtChapID; char *tgtChapDigest; char *iqn; + char *pidfile; } isc_opt_t; /* @@ -498,7 +495,6 @@ 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) Index: sys/dev/iscsi/initiator/isc_soc.c =================================================================== --- sys/dev/iscsi/initiator/isc_soc.c (revision 210555) +++ sys/dev/iscsi/initiator/isc_soc.c (working copy) @@ -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 @@ #endif #ifdef USE_MBUF - static int ou_refcnt = 0; - /* | function for freeing external storage for mbuf */ @@ -79,7 +75,7 @@ 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 @@ 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; - } + 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); + MH_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(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; - } 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 @@ 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 @@ | 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 @@ if(error == 0) { sp->stats.nsent++; getbintime(&sp->stats.t_sent); - } return error; @@ -322,159 +336,197 @@ 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(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) { + uio->uio_rw = UIO_READ; + uio->uio_segflg = UIO_SYSSPACE; + uio->uio_resid = len; + uio->uio_td = sp->td; // why ... + error = soreceive(sp->soc, NULL, uio, NULL, NULL, &flags); + //if(error == EAGAIN) + // XXX: this needs work! it hangs iscontrol + if(error || uio->uio_resid) { + debug(2, +#if __FreeBSD_version > 800000 + "len=%d error=%d uio->uio_resid=%zd", +#else + "len=%d error=%d uio->uio_resid=%d", +#endif + len, error, uio->uio_resid); + goto out; + } + if(ISOK2DIG(sp->hdrDigest, pp)) { + bhs_t *bhs; + u_int digest; + + bhs = (bhs_t *)&pp->ipdu; + digest = sp->hdrDigest(bhs, sizeof(bhs_t), 0); + if(pp->ahs_len) + digest = sp->hdrDigest(pp->ahs_addr, pp->ahs_len, digest); + if(pp->hdr_dig != digest) { + debug(2, "bad header digest: received=%x calculated=%x", pp->hdr_dig, digest); + // XXX: now what? + error = EIO; + goto out; + } + } + if(pp->ahs_len) { + debug(2, "ahs len=%x type=%x spec=%x", + pp->ahs_addr->len, pp->ahs_addr->type, pp->ahs_addr->spec); + // XXX: till I figure out what to do with this + free(pp->ahs_addr, M_TEMP); + } + pq->len += len; // XXX: who needs this? + bzero(uio, sizeof(struct uio)); + len = 0; + } + if(bhs->DSLength) { - n = bhs->DSLength; + len = bhs->DSLength; #if BYTE_ORDER == LITTLE_ENDIAN - pp->ds_len = ((n & 0x00ff0000) >> 16) - | (n & 0x0000ff00) - | ((n & 0x000000ff) << 16); -#else - pp->ds_len = n; + len = ((len & 0x00ff0000) >> 16) + | (len & 0x0000ff00) + | ((len & 0x000000ff) << 16); #endif - len += pp->ds_len; + pp->ds_len = len; + if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) { + xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d", + len, sp->opt.maxRecvDataSegmentLength); + log(LOG_ERR, + "so_recv: impossible PDU length(%d) from iSCSI %s/%s\n", + len, sp->opt.targetAddress, sp->opt.targetName); + /* + | XXX: this will really screwup the stream. + | should clear up the buffer till a valid header + | is found, or just close connection ... + | should read the RFC. + */ + error = E2BIG; + goto out; + } while(len & 03) len++; - if(sp->dataDigest) + if(ISOK2DIG(sp->dataDigest, pp)) len += 4; - } - - if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) { -#if 0 - xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d", - len, sp->opt.maxRecvDataSegmentLength); - // deep trouble here, probably all we can do is - // force a disconnect, XXX: check RFC ... - log(LOG_ERR, - "so_recv: impossible PDU length(%ld) from iSCSI %s/%s\n", - len, sp->opt.targetAddress, sp->opt.targetName); -#endif - /* - | XXX: this will really screwup the stream. - | should clear up the buffer till a valid header - | is found, or just close connection ... - | should read the RFC. - */ - error = E2BIG; - goto out; - } - if(len) { - int flags = MSG_WAITALL; - struct mbuf **mp; - - mp = &pq->mp; - uio->uio_resid = len; - uio->uio_td = curthread; // why ... - if(sp->douio) { - // it's more efficient to use mbufs -- why? - if(bhs->opcode == ISCSI_READ_DATA) { - pduq_t *opq; - - opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1); - if(opq != NULL) { - union ccb *ccb = opq->ccb; - struct ccb_scsiio *csio = &ccb->csio; - pdu_t *opp = &opq->pdu; - scsi_req_t *cmd = &opp->ipdu.scsi_req; - data_in_t *rcmd = &pq->pdu.ipdu.data_in; - bhs_t *bhp = &opp->ipdu.bhs; - int r; - - if(bhp->opcode == ISCSI_SCSI_CMD - && cmd->R - && (ntohl(cmd->edtlen) >= pq->pdu.ds_len)) { - struct iovec *iov = pq->iov; - iov->iov_base = csio->data_ptr + ntohl(rcmd->bo); - iov->iov_len = pq->pdu.ds_len; - - uio->uio_rw = UIO_READ; - uio->uio_segflg = UIO_SYSSPACE; - uio->uio_iov = iov; - uio->uio_iovcnt = 1; - if(len > pq->pdu.ds_len) { - pq->iov[1].iov_base = &r; - pq->iov[1].iov_len = len - pq->pdu.ds_len; - uio->uio_iovcnt++; - } - mp = NULL; - - sdebug(4, "uio_resid=0x%zx itt=0x%x bp=%p bo=%x len=%x/%x", - uio->uio_resid, - ntohl(pq->pdu.ipdu.bhs.itt), - csio->data_ptr, ntohl(rcmd->bo), ntohl(cmd->edtlen), pq->pdu.ds_len); - } - } - } - } - error = soreceive(so, NULL, uio, mp, NULL, &flags); + uio->uio_td = sp->td; // why ... + pq->len += len; // XXX: do we need this? + error = soreceive(sp->soc, NULL, uio, &pq->mp, NULL, &flags); //if(error == EAGAIN) // XXX: this needs work! it hangs iscontrol if(error || uio->uio_resid) goto out; + if(ISOK2DIG(sp->dataDigest, pp)) { + struct mbuf *m; + u_int digest, ds_len, cnt; + + // get the received digest + m_copydata(pq->mp, + len - sizeof(pp->ds_dig), + sizeof(pp->ds_dig), + (caddr_t)&pp->ds_dig); + // calculate all mbufs + digest = 0; + ds_len = len - sizeof(pp->ds_dig); + for(m = pq->mp; m != NULL; m = m->m_next) { + cnt = MIN(ds_len, m->m_len); + digest = sp->dataDigest(mtod(m, char *), cnt, digest); + ds_len -= cnt; + if(ds_len == 0) + break; + } + if(digest != pp->ds_dig) { + sdebug(1, "bad data digest: received=%x calculated=%x", pp->ds_dig, digest); + error = EIO; // XXX: find a better error + goto out; + } + KASSERT(ds_len == 0, ("ds_len not zero")); + } } - pq->len += len; sdebug(6, "len=%d] opcode=0x%x ahs_len=0x%x ds_len=0x%x", pq->len, bhs->opcode, pp->ahs_len, pp->ds_len); max = ntohl(bhs->MaxCmdSN); exp = ntohl(bhs->ExpStSN); - if(max < exp - 1 && max > exp - _MAXINCR) { sdebug(2, "bad cmd window size"); error = EIO; // XXX: for now; goto out; // error } - if(SNA_GT(max, sn->maxCmd)) sn->maxCmd = max; - if(SNA_GT(exp, sn->expCmd)) sn->expCmd = exp; + /* + | remove from the holding queue packets + | that have been acked and don't need + | further processing. + */ + i_acked_hld(sp, NULL); sp->cws = sn->maxCmd - sn->expCmd + 1; @@ -482,6 +534,10 @@ 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 @@ */ 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 @@ | 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 @@ 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 @@ 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 @@ 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 @@ } mtx_unlock(&sp->io_mtx); - if(sp->fp != NULL) fdrop(sp->fp, sp->td); fputsock(sp->soc); @@ -637,6 +692,10 @@ 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); } Index: sys/dev/iscsi/initiator/iscsi_subr.c =================================================================== --- sys/dev/iscsi/initiator/iscsi_subr.c (revision 210555) +++ sys/dev/iscsi/initiator/iscsi_subr.c (working copy) @@ -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 @@ #include #include #include +#include #include #include @@ -122,7 +123,7 @@ 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 @@ | 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ */ 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 @@ return 1; invalid: ccb->ccb_h.status = CAM_REQ_INVALID; - pdu_free(isp, pq); + pdu_free(sp->isc, pq); + return 0; } @@ -573,16 +559,16 @@ 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", ntohl(cmd->edtlen), pq->pdu.ds_len); @@ -592,7 +578,7 @@ /* | 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; Index: sys/dev/iscsi/initiator/iscsivar.h =================================================================== --- sys/dev/iscsi/initiator/iscsivar.h (revision 210555) +++ sys/dev/iscsi/initiator/iscsivar.h (working copy) @@ -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 @@ #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,16 +82,16 @@ #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 @@ 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 @@ digest_t *dataDigest; // the digest alg. if any int sid; // Session ID - int targetid; -// int cid; // Connection ID -// int tsih; // target session identifier handle sn_t sn; // sequence number stuff; int cws; // current window size int target_nluns; // this and target_lun are // hopefully temporal till I // figure out a better way. - lun_id_t target_lun[ISCSI_MAX_LUNS]; + int target_lun[ISCSI_MAX_LUNS/(sizeof(int)*8) + 1]; struct mtx rsp_mtx; struct mtx rsv_mtx; @@ -150,17 +158,19 @@ queue_t wsnd; queue_t hld; - /* - | negotiable values - */ - isc_opt_t opt; + isc_opt_t opt; // negotiable values struct i_stats stats; - struct cam_path *cam_path; bhs_t bhs; struct uio uio; struct iovec iov; /* + | cam stuff + */ + struct cam_sim *cam_sim; + struct cam_path *cam_path; + struct mtx cam_mtx; + /* | sysctl stuff */ struct sysctl_ctx_list clist; @@ -180,34 +190,30 @@ struct iovec iov[5]; // XXX: careful ... struct mbuf *mp; struct bintime ts; - queue_t *pduq; + queue_t *pduq; } pduq_t; - +/* + */ struct isc_softc { - //int state; + struct mtx isc_mtx; + TAILQ_HEAD(,isc_session) isc_sess; + int nsess; struct cdev *dev; - eventhandler_tag eh; char isid[6]; // Initiator Session ID (48 bits) - struct mtx mtx; + struct unrhdr *unit; + struct sx unit_sx; - int nsess; - TAILQ_HEAD(,isc_session) isc_sess; - isc_session_t *sessions[MAX_SESSIONS]; + struct mtx pdu_mtx; + uma_zone_t pdu_zone; // pool of free pdu's + TAILQ_HEAD(,pduq) freepdu; - struct mtx pdu_mtx; #ifdef ISCSI_INITIATOR_DEBUG - int npdu_alloc, npdu_max; // for instrumentation + int npdu_alloc, npdu_max; // for instrumentation #endif -#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; +#ifdef DO_EVENTHANDLER + eventhandler_tag eh; +#endif /* - | cam stuff - */ - struct cam_sim *cam_sim; - struct cam_path *cam_path; - struct mtx cam_mtx; - /* | sysctl stuff */ struct sysctl_ctx_list clist; @@ -231,14 +237,14 @@ 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_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 @@ #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 @@ #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 @@ m_freem(pq->mp); #ifdef NO_USE_MBUF if(pq->buf != NULL) - free(pq->buf, M_ISCSI); + free(pq->buf, M_ISCSIBUF); #endif mtx_lock(&isc->pdu_mtx); TAILQ_INSERT_TAIL(&isc->freepdu, pq, pq_link); @@ -565,6 +568,27 @@ } static __inline void +i_acked_hld(isc_session_t *sp, pdu_t *op) +{ + pduq_t *pq, *tmp; + u_int exp = sp->sn.expCmd; + + pq = NULL; + mtx_lock(&sp->hld_mtx); + TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) { + if((op && op->ipdu.bhs.itt == pq->pdu.ipdu.bhs.itt) + || (pq->ccb == NULL + && (pq->pdu.ipdu.bhs.opcode != ISCSI_WRITE_DATA) + && SNA_GT(exp, ntohl(pq->pdu.ipdu.bhs.ExpStSN)))) { + sp->stats.nhld--; + TAILQ_REMOVE(&sp->hld, pq, pq_link); + pdu_free(sp->isc, pq); + } + } + mtx_unlock(&sp->hld_mtx); +} + +static __inline void i_mbufcopy(struct mbuf *mp, caddr_t dp, int len) { struct mbuf *m; Index: sys/dev/iscsi/initiator/isc_subr.c =================================================================== --- sys/dev/iscsi/initiator/isc_subr.c (revision 210555) +++ sys/dev/iscsi/initiator/isc_subr.c (working copy) @@ -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,29 +58,121 @@ #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; } +/*****************************************************************/ +/* */ +/* CRC LOOKUP TABLE */ +/* ================ */ +/* The following CRC lookup table was generated automagically */ +/* by the Rocksoft^tm Model CRC Algorithm Table Generation */ +/* Program V1.0 using the following model parameters: */ +/* */ +/* Width : 4 bytes. */ +/* Poly : 0x1EDC6F41L */ +/* Reverse : TRUE. */ +/* */ +/* For more information on the Rocksoft^tm Model CRC Algorithm, */ +/* see the document titled "A Painless Guide to CRC Error */ +/* Detection Algorithms" by Ross Williams */ +/* (ross@guest.adelaide.edu.au.). This document is likely to be */ +/* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */ +/* */ +/*****************************************************************/ + +static uint32_t crc32Table[256] = { + 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, + 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, + 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, + 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, + 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, + 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, + 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, + 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, + 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, + 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, + 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, + 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, + 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, + 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL, + 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, + 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, + 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, + 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, + 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, + 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, + 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, + 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, + 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L, + 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, + 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, + 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, + 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, + 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, + 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, + 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, + 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, + 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, + 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, + 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, + 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, + 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, + 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, + 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, + 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, + 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, + 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, + 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, + 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, + 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, + 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, + 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, + 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, + 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, + 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, + 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, + 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, + 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, + 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, + 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, + 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, + 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, + 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, + 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, + 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L, + 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, + 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, + 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, + 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, + 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L +}; + static uint32_t i_crc32c(const void *buf, size_t size, uint32_t crc) { + const uint8_t *p = buf; + crc = crc ^ 0xffffffff; - crc = calculate_crc32c(crc, buf, size); + while (size--) + crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8); crc = crc ^ 0xffffffff; return crc; } @@ -98,50 +190,51 @@ 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 +244,18 @@ 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; } } Index: sys/dev/iscsi/initiator/iscsi.c =================================================================== --- sys/dev/iscsi/initiator/iscsi.c (revision 210555) +++ sys/dev/iscsi/initiator/iscsi.c (working copy) @@ -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 @@ #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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ } mtx_unlock(&sp->rsp_mtx); - sdebug(4, "cnt=%d", cnt); + sdebug(6, "cnt=%d", cnt); if(pq == NULL) { error = ENOTCONN; @@ -536,19 +534,15 @@ 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 @@ if(pp->ahs_len) { need = pp->ahs_len; - if(sp->hdrDigest) - need += 4; n = MIN(up->ahs_size, need); - error = copyout(bp, (caddr_t)up->ahs, n); + error = copyout(bp, (caddr_t)up->ahs_addr, n); up->ahs_len = n; bp += need; } if(!error && pp->ds_len) { need = pp->ds_len; - if(sp->hdrDigest) - need += 4; if((have = up->ds_size) == 0) { have = up->ahs_size - n; - up->ds = (caddr_t)up->ahs + n; + up->ds_addr = (caddr_t)up->ahs_addr + n; } n = MIN(have, need); - error = copyout(bp, (caddr_t)up->ds, n); + error = copyout(bp, (caddr_t)up->ds_addr, n); up->ds_len = n; } if(mustfree) - free(bp, M_ISCSI); + free(bp, M_TMP); } sdebug(6, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len); @@ -589,33 +579,57 @@ } static int +i_fullfeature(struct cdev *dev, int flag) +{ + isc_session_t *sp = dev->si_drv2; + int error; + + sdebug(2, "flag=%d", flag); + + error = 0; + switch(flag) { + case 0: // stop + sp->flags &= ~ISC_FFPHASE; + break; + case 1: // start + sp->flags |= ISC_FFPHASE; + error = ic_init(sp); + break; + case 2: // restart + sp->flags |= ISC_FFPHASE; + ism_restart(sp); + break; + } + return error; +} + +static int i_create_session(struct cdev *dev, int *ndev) { - struct isc_softc *sc = (struct isc_softc *)dev->si_drv1; + struct isc_softc *sc = dev->si_drv1; isc_session_t *sp; int error, n; debug_called(8); - sp = (isc_session_t *)malloc(sizeof *sp, M_ISCSI, M_WAITOK | M_ZERO); + + sp = malloc(sizeof(isc_session_t), M_ISCSI, M_WAITOK | M_ZERO); if(sp == NULL) return ENOMEM; - mtx_lock(&sc->mtx); - /* - | search for the lowest unused sid - */ - for(n = 0; n < MAX_SESSIONS; n++) - if(sc->sessions[n] == NULL) - break; - if(n == MAX_SESSIONS) { - mtx_unlock(&sc->mtx); + + sx_xlock(&sc->unit_sx); + if((n = alloc_unr(sc->unit)) < 0) { + sx_unlock(&sc->unit_sx); free(sp, M_ISCSI); + xdebug("too many sessions!"); return EPERM; } + sx_unlock(&sc->unit_sx); + + mtx_lock(&sc->isc_mtx); TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link); - sc->nsess++; - mtx_unlock(&sc->mtx); + isc->nsess++; + mtx_unlock(&sc->isc_mtx); - sc->sessions[n] = sp; sp->dev = make_dev(&iscsi_cdevsw, n, UID_ROOT, GID_WHEEL, 0600, "iscsi%d", n); *ndev = sp->sid = n; sp->isc = sc; @@ -624,10 +638,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); + 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"); -#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 - #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 @@ 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 @@ 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 @@ static void iscsi_stop(void) { - struct isc_softc *sc = &isc; isc_session_t *sp, *sp_tmp; debug_called(8); @@ -813,24 +811,26 @@ | 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 @@ 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; Index: sys/dev/iscsi/initiator/isc_sm.c =================================================================== --- sys/dev/iscsi/initiator/isc_sm.c (revision 210555) +++ sys/dev/iscsi/initiator/isc_sm.c (working copy) @@ -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 @@ #include #include #include +#include #include #include @@ -131,8 +132,10 @@ 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 @@ 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 @@ n = 4 - (len & 03); len += n; } - if(sp->dataDigest) + if(ISOK2DIG(sp->dataDigest, pp)) len += 4; } @@ -321,7 +324,7 @@ 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 @@ /* | called when a fullPhase is restarted */ -static void +void ism_restart(isc_session_t *sp) { int lastcmd; @@ -348,32 +351,9 @@ } mtx_unlock(&sp->io_mtx); - sdebug(2, "restarted lastcmd=0x%x", lastcmd); + sdebug(2, "restarted sn.cmd=0x%x lastcmd=0x%x", sp->sn.cmd, 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; -} - void ism_recv(isc_session_t *sp, pduq_t *pq) { @@ -384,26 +364,6 @@ 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 @@ break; } } - + /* | go through the out queues looking for work | if either nothing to do, or window is closed @@ -465,11 +425,10 @@ { 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 @@ sn->cmd++; case ISCSI_WRITE_DATA: - bhs->ExpStSN = htonl(sn->stat); + bhs->ExpStSN = htonl(sn->stat + 1); break; default: @@ -523,19 +482,21 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ 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 @@ 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 @@ 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 } --=-=-=--