Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Jul 2010 09:48:56 +0200
From:      =?utf-8?Q?Dag-Erling_Sm=C3=B8rgrav?= <des@des.no>
To:        Daniel Braniss <danny@cs.huji.ac.il>
Cc:        freebsd-scsi@freebsd.org
Subject:   Re: iscsi_initiator patches
Message-ID:  <86bp9soxlj.fsf@ds4.des.no>
In-Reply-To: <86fwz4oxqw.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:45:43 %2B0200")
References:  <E1OdipG-0008ZN-SQ@kabab.cs.huji.ac.il> <86k4ogoyy7.fsf@ds4.des.no> <86fwz4oxqw.fsf@ds4.des.no>

next in thread | previous in thread | raw e-mail | index | archive | help
--=-=-=
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

Dag-Erling Sm=C3=B8rgrav <des@des.no> writes:
> Your patch does not apply cleanly to head, nor stable/8.

Here's one that does, but I have no way of testing it.  Note that it
includes some additional mdoc cleanup.

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 <danny@cs.huji.ac.il>
+.\" Copyright (c) 2007-2010 Daniel Braniss <danny@cs.huji.ac.il>
 .\" 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 <danny@cs.huji.ac.il>
+.\" Copyright (c) 2007-2010 Daniel Braniss <danny@cs.huji.ac.il>
 .\" 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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2009 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
 #include <ctype.h>
 #include <camlib.h>
 
-#include "iscsi.h"
+#include <dev/iscsi/initiator/iscsi.h>
 #include "iscontrol.h"
 
 /*
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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -56,7 +56,7 @@
 #include <stdarg.h>
 #include <camlib.h>
 
-#include "iscsi.h"
+#include <dev/iscsi/initiator/iscsi.h>
 #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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "iscsi.h"
+#include <dev/iscsi/initiator/iscsi.h>
 #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);
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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,10 +43,9 @@
 #include <stdarg.h>
 #include <camlib.h>
 
-#include "iscsi.h"
 #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 +84,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 +125,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 +144,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 +162,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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
Index: sbin/iscontrol/Makefile
===================================================================
--- sbin/iscontrol/Makefile	(revision 210555)
+++ sbin/iscontrol/Makefile	(working copy)
@@ -1,12 +1,13 @@
 # $FreeBSD$
 
-SRCS= iscontrol.c pdu.c fsm.c config.c login.c auth_subr.c misc.c
-PROG= iscontrol
-DPADD= ${LIBCAM} ${LIBMD}
-LDADD= -lcam -lmd
+SRCS=	iscontrol.c pdu.c fsm.c config.c login.c auth_subr.c misc.c
+PROG=	iscontrol
+DPADD=	${LIBCAM} ${LIBMD}
+LDADD=	-lcam -lmd
+S=	${.CURDIR}/../../sys
 
 WARNS?=	2
-CFLAGS += -I${.CURDIR}/../../sys/dev/iscsi/initiator
+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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@
 #include <md5.h>
 #include <sha.h>
 
-#include "iscsi.h"
+#include <dev/iscsi/initiator/iscsi.h>
 #include "iscontrol.h"
 
 static int
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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -53,16 +53,12 @@
 #include <time.h>
 #include <camlib.h>
 
-#include "iscsi.h"
+#include <dev/iscsi/initiator/iscsi.h>
 #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},
@@ -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 <danny@cs.huji.ac.il>
- * 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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,9 @@
  * SUCH DAMAGE.
  *
  */
-
+/*
+ | $Id: isc_cam.c 998 2009-12-20 10:32:45Z danny $
+ */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -43,6 +45,7 @@
 #include <sys/mbuf.h>
 #include <sys/uio.h>
 #include <sys/sysctl.h>
+#include <sys/sx.h>
 
 #include <cam/cam.h>
 #include <cam/cam_ccb.h>
@@ -53,52 +56,72 @@
 #include <dev/iscsi/initiator/iscsi.h>
 #include <dev/iscsi/initiator/iscsivar.h>
 
-// XXX: untested/incomplete
-void
-ic_freeze(isc_session_t *sp)
+static void
+_inq(struct cam_sim *sim, union ccb *ccb)
 {
+     struct ccb_pathinq *cpi = &ccb->cpi;
+     isc_session_t *sp = cam_sim_softc(sim);
+
      debug_called(8);
-#if 0
-     sdebug(2, "freezing path=%p", sp->cam_path == NULL? 0: sp->cam_path);
-     if((sp->cam_path != NULL) && !(sp->flags & ISC_FROZEN)) {
-	  xpt_freeze_devq(sp->cam_path, 1);
-     }
+     debug(3, "sid=%d target=%d lun=%d", sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
+
+     cpi->version_num = 1; /* XXX??? */
+     cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32;
+     cpi->target_sprt = 0;
+     cpi->hba_misc = 0;
+     cpi->hba_eng_cnt = 0;
+     cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1;
+     cpi->initiator_id = ISCSI_MAX_TARGETS;
+     cpi->max_lun = sp->opt.maxluns - 1;
+     cpi->bus_id = cam_sim_bus(sim);
+     cpi->base_transfer_speed = 3300; // 40000; // XXX:
+     strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+     strncpy(cpi->hba_vid, "iSCSI", HBA_IDLEN);
+     strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+     cpi->unit_number = cam_sim_unit(sim);
+     cpi->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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
  * $FreeBSD$
  */
 /*
- | $Id: iscsi.h,v 1.17 2006/12/01 09:10:17 danny Exp danny $
+ | $Id: iscsi.h 743 2009-08-08 10:54:53Z danny $
  */
 #define	TRUE	1
 #define FALSE	0
@@ -37,11 +37,7 @@
 #include <cam/cam.h>
 
 #define ISCSIDEV	"iscsi"
-
-#define ISCSI_MAX_TARGETS	4 //64
-
-#define ISCSI_MAX_LUNS		4
-
+#define ISCSI_MAX_TARGETS	64
 /*
  | iSCSI commands
  */
@@ -422,13 +418,13 @@
  */
 typedef struct {
      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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,10 +25,8 @@
  *
  */
 /*
- | iSCSI
- | $Id: isc_soc.c,v 1.26 2007/05/19 06:09:01 danny Exp danny $
+ | $Id: isc_soc.c 998 2009-12-20 10:32:45Z danny $
  */
-
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -66,9 +64,7 @@
 #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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
  *
  */
 /*
- | $Id: iscsi_subr.c,v 1.17 2006/11/26 14:50:43 danny Exp danny $
+ | $Id: iscsi_subr.c 743 2009-08-08 10:54:53Z danny $
  */
 
 #include <sys/cdefs.h>
@@ -43,6 +43,7 @@
 #include <sys/mutex.h>
 #include <sys/uio.h>
 #include <sys/sysctl.h>
+#include <sys/sx.h>
 
 #include <cam/cam.h>
 #include <cam/cam_ccb.h>
@@ -122,7 +123,7 @@
 		    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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,9 +25,18 @@
  *
  * $FreeBSD$
  */
+
 /*
- | $Id: iscsivar.h,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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
  */
 /*
  | iSCSI
- | $Id: isc_subr.c,v 1.20 2006/12/01 09:10:17 danny Exp danny $
+ | $Id: isc_subr.c 560 2009-05-07 07:37:49Z danny $
  */
 
 #include <sys/cdefs.h>
@@ -58,29 +58,121 @@
 #include <dev/iscsi/initiator/iscsi.h>
 #include <dev/iscsi/initiator/iscsivar.h>
 
+MALLOC_DEFINE(M_ISC, "iSC", "iSCSI driver options");
+
 static char *
 i_strdupin(char *s, size_t maxlen)
 {
      size_t	len;
      char	*p, *q;
 
-     p = malloc(maxlen, M_ISCSI, M_WAITOK);
+     p = malloc(maxlen, M_ISC, M_WAITOK);
      if(copyinstr(s, p, maxlen, &len)) {
-	  free(p, M_ISCSI);
+	  free(p, M_ISC);
 	  return NULL;
      }
-     q = malloc(len, M_ISCSI, M_WAITOK);
+     q = malloc(len, M_ISC, M_WAITOK);
      bcopy(p, q, len);
-     free(p, M_ISCSI);
+     free(p, M_ISC);
 
      return q;
 }
 
+/*****************************************************************/
+/*                                                               */
+/* 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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,8 +25,7 @@
  *
  */
 /*
- | iSCSI
- | $Id: iscsi.c,v 1.35 2007/04/22 08:58:29 danny Exp danny $
+ | $Id: iscsi.c 752 2009-08-20 11:23:28Z danny $
  */
 
 #include <sys/cdefs.h>
@@ -56,15 +55,17 @@
 #include <sys/mbuf.h>
 #include <sys/syslog.h>
 #include <vm/uma.h>
+#include <sys/sx.h>
 
 #include <dev/iscsi/initiator/iscsi.h>
 #include <dev/iscsi/initiator/iscsivar.h>
+static char *iscsi_driver_version = "2.2.4.2";
 
-static char *iscsi_driver_version = "2.1.0";
+static struct isc_softc *isc;
 
-static struct isc_softc isc;
-
 MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI driver");
+MALLOC_DEFINE(M_ISCSIBUF, "iSCbuf", "iSCSI buffers");
+MALLOC_DEFINE(M_TMP, "iSCtmp", "iSCSI tmp");
 
 #ifdef ISCSI_INITIATOR_DEBUG
 int iscsi_debug = ISCSI_INITIATOR_DEBUG;
@@ -74,6 +75,12 @@
 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 <danny@cs.huji.ac.il>
+ * Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
  */
 /*
  | iSCSI - Session Manager
- | $Id: isc_sm.c,v 1.30 2007/04/22 09:53:09 danny Exp danny $
+ | $Id: isc_sm.c 743 2009-08-08 10:54:53Z danny $
  */
 
 #include <sys/cdefs.h>
@@ -54,6 +54,7 @@
 #include <sys/syslog.h>
 #include <sys/mbuf.h>
 #include <sys/bus.h>
+#include <sys/sx.h>
 
 #include <cam/cam.h>
 #include <cam/cam_ccb.h>
@@ -131,8 +132,10 @@
      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
 }

--=-=-=--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86bp9soxlj.fsf>