svn commit: r185289 - in head: sbin/iscontrol sys/dev/iscsi/initiator

Scott Long scottl at FreeBSD.org
Mon Nov 24 23:17:12 PST 2008


Author: scottl
Date: Tue Nov 25 07:17:11 2008
New Revision: 185289
URL: http://svn.freebsd.org/changeset/base/185289

Log:
  Big update to the iSCSI initiator code.  Highlights include IPv6 support,
  many bugs fixes, many more performance improvements.
  
  Submitted by:	Danny Braniss
  
  M    sbin/iscontrol/iscsi.conf.5
  M    sbin/iscontrol/iscontrol.8
  M    sbin/iscontrol/iscontrol.h
  M    sbin/iscontrol/config.c
  M    sbin/iscontrol/fsm.c
  M    sbin/iscontrol/login.c
  M    sbin/iscontrol/pdu.c
  M    sbin/iscontrol/misc.c
  M    sbin/iscontrol/auth_subr.c
  M    sbin/iscontrol/iscontrol.c
  M    sys/dev/iscsi/initiator/isc_cam.c
  M    sys/dev/iscsi/initiator/iscsi.h
  M    sys/dev/iscsi/initiator/isc_soc.c
  M    sys/dev/iscsi/initiator/iscsi_subr.c
  M    sys/dev/iscsi/initiator/iscsivar.h
  M    sys/dev/iscsi/initiator/isc_subr.c
  M    sys/dev/iscsi/initiator/iscsi.c
  M    sys/dev/iscsi/initiator/isc_sm.c

Modified:
  head/sbin/iscontrol/auth_subr.c
  head/sbin/iscontrol/config.c
  head/sbin/iscontrol/fsm.c
  head/sbin/iscontrol/iscontrol.8
  head/sbin/iscontrol/iscontrol.c
  head/sbin/iscontrol/iscontrol.h
  head/sbin/iscontrol/iscsi.conf.5
  head/sbin/iscontrol/login.c
  head/sbin/iscontrol/misc.c
  head/sbin/iscontrol/pdu.c
  head/sys/dev/iscsi/initiator/isc_cam.c
  head/sys/dev/iscsi/initiator/isc_sm.c
  head/sys/dev/iscsi/initiator/isc_soc.c
  head/sys/dev/iscsi/initiator/isc_subr.c
  head/sys/dev/iscsi/initiator/iscsi.c
  head/sys/dev/iscsi/initiator/iscsi.h
  head/sys/dev/iscsi/initiator/iscsi_subr.c
  head/sys/dev/iscsi/initiator/iscsivar.h

Modified: head/sbin/iscontrol/auth_subr.c
==============================================================================
--- head/sbin/iscontrol/auth_subr.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/auth_subr.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005-2007 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
 
 #include "iscsi.h"
 #include "iscontrol.h"
-#include "pdu.h"
 
 static int
 chapMD5(char id, char *cp, char *chapSecret, unsigned char *digest)

Modified: head/sbin/iscontrol/config.c
==============================================================================
--- head/sbin/iscontrol/config.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/config.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
  /*-
- * Copyright (c) 2005-2007 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without

Modified: head/sbin/iscontrol/fsm.c
==============================================================================
--- head/sbin/iscontrol/fsm.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/fsm.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005-2007 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$");
 
 #include "iscsi.h"
 #include "iscontrol.h"
-#include "pdu.h"
 
 typedef enum {
      T1 = 1,
@@ -66,38 +65,40 @@ typedef enum {
      T10, T11, T12, T13, T14, T15, T16, T18
 } trans_t;
 
+/*
+ | now supports IPV6
+ | thanks to:
+ |	Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
+ |	ume at mahoroba.org  ume@{,jp.}FreeBSD.org
+ |	http://www.imasy.org/~ume/
+ */
 static trans_t
 tcpConnect(isess_t *sess)
 {
      isc_opt_t *op = sess->op;
-     int	val, sv_errno;
-     struct     addrinfo *res, hints;
-     struct	sockaddr_in sn;
-     struct	in_addr ipn;
-     time_t	sec;
+     int	val, sv_errno, soc;
+     struct     addrinfo *res, *res0, hints;
+     char	pbuf[10];
 
      debug_called(3);
      if(sess->flags & (SESS_RECONNECT|SESS_REDIRECT)) {
 	  syslog(LOG_INFO, "%s", (sess->flags & SESS_RECONNECT)
 		 ? "Reconnect": "Redirected");
 	  
-	  debug(3, "%s", (sess->flags & SESS_RECONNECT) ? "Reconnect": "Redirected");
+	  debug(1, "%s", (sess->flags & SESS_RECONNECT) ? "Reconnect": "Redirected");
 	  shutdown(sess->soc, SHUT_RDWR);
 	  //close(sess->soc);
-	  sleep(5); // XXX: actually should be ?
 	  sess->soc = -1;
 
 	  sess->flags &= ~SESS_CONNECTED;
 	  if(sess->flags & SESS_REDIRECT) {
-	       if(sess->redirect_cnt++ > MAXREDIRECTS) {
-		    syslog(LOG_WARNING, "too many redirects > %d", MAXREDIRECTS);
-		    return 0;
-	       }
+	       sess->redirect_cnt++;
 	       sess->flags |= SESS_RECONNECT;
-	  }
-	  if((sess->flags & SESS_RECONNECT) == 0)
-	       return 0;
-
+	  } else
+	       sleep(2); // XXX: actually should be ?
+#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;
@@ -117,41 +118,46 @@ tcpConnect(isess_t *sess)
 		    return 0;
 	       }
 	  }
-	  sess->reconnect_cnt++;
-	  // sess->flags &= ~(SESS_RECONNECT|SESS_REDIRECT);
      }
-
-     if((sess->soc = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-	  fprintf(stderr, "tcpConnect: socket: %m");
-	  return 0;
+#endif
+	  sess->reconnect_cnt++;
      }
 
+     snprintf(pbuf, sizeof(pbuf), "%d", op->port);
      memset(&hints, 0, sizeof(hints));
-     hints.ai_family	= PF_INET;
+     hints.ai_family	= PF_UNSPEC;
      hints.ai_socktype	= SOCK_STREAM;
-
-     debug(3, "targetAddress=%s port=%d", op->targetAddress, op->port);
-     if(inet_aton(op->targetAddress, &ipn))
-	  hints.ai_flags |= AI_NUMERICHOST;
-     if((val = getaddrinfo(op->targetAddress, NULL, &hints, &res)) != 0) {
+     debug(1, "targetAddress=%s port=%d", op->targetAddress, op->port);
+     if((val = getaddrinfo(op->targetAddress, pbuf, &hints, &res0)) != 0) {
           fprintf(stderr, "getaddrinfo(%s): %s\n", op->targetAddress, gai_strerror(val));
           return 0;
      }
-     memcpy(&sn, res->ai_addr, sizeof(struct sockaddr_in));
-     sn.sin_port = htons(op->port);
-     freeaddrinfo(res);
+     sess->flags &= ~SESS_CONNECTED;
+     sv_errno = 0;
+     soc = -1;
+     for(res = res0; res; res = res->ai_next) {
+	  soc = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+	  if (soc == -1)
+	       continue;
 
      // from Patrick.Guelat at imp.ch:
      // iscontrol can be called without waiting for the socket entry to time out
      val = 1;
-     if(setsockopt(sess->soc, SOL_SOCKET, SO_REUSEADDR, &val, (socklen_t)sizeof(val)) < 0) {
+	  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));
      }
 
-     sess->flags &= ~SESS_CONNECTED;
+	  if(connect(soc, res->ai_addr, res->ai_addrlen) == 0)
+	       break;
+	  sv_errno = errno;
+	  close(soc);
+	  soc = -1;
+     }
+     freeaddrinfo(res0);
+     if(soc != -1) {
+	  sess->soc = soc;
 
-     if(connect(sess->soc, (struct sockaddr *)&sn, sizeof(struct sockaddr_in)) != -1) {
 #if 0
 	  struct	timeval timeout;
 
@@ -190,21 +196,29 @@ tcpConnect(isess_t *sess)
 	  }
 	  sess->flags |= SESS_CONNECTED;
 	  return T1;
-
      } 
-     sv_errno = errno;
+
      fprintf(stderr, "errno=%d\n", sv_errno);
      perror("connect");
      switch(sv_errno) {
      case ECONNREFUSED:
      case ENETUNREACH:
      case ETIMEDOUT:
+	  if((sess->flags & SESS_REDIRECT) == 0) {
+	       if(strcmp(op->targetAddress, sess->target.address) != 0) {
+		    syslog(LOG_INFO, "reconnecting to original target address");
+		    free(op->targetAddress);
+		    op->targetAddress           = sess->target.address;
+		    op->port                    = sess->target.port;
+		    op->targetPortalGroupTag    = sess->target.pgt;
+		    return T1;
+	       }
+	  }
 	  sleep(5); // for now ...
 	  return T1;
      default:
 	  return 0; // terminal error
      }
-
 }
 
 int
@@ -416,7 +430,6 @@ supervise(isess_t *sess)
 
      }
      else {
-	  
 	  if(ioctl(sess->fd, ISCSIRESTART)) {
 	       perror("ISCSIRESTART");
 	       return -1;
@@ -554,7 +567,10 @@ doLogin(isess_t *sess)
 	  return T7;
 
      case 2: // initiator terminal error
+	  return 0;
      case 3: // target terminal error -- could retry ...
+	  sleep(5);
+	  return T7; // lets try
      default:
 	  return 0;
      }
@@ -654,6 +670,9 @@ fsm(isc_opt_t *op)
      sess->op = op;
      sess->fd = -1;
      sess->soc = -1;
+     sess->target.address = strdup(op->targetAddress);
+     sess->target.port = op->port;
+     sess->target.pgt = op->targetPortalGroupTag;
 
      sess->flags = SESS_INITIALLOGIN | SESS_INITIALLOGIN1;
 

Modified: head/sbin/iscontrol/iscontrol.8
==============================================================================
--- head/sbin/iscontrol/iscontrol.8	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/iscontrol.8	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2007 Daniel Braniss <danny at cs.huji.ac.il>
+.\" Copyright (c) 2007-2008 Daniel Braniss <danny at cs.huji.ac.il>
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without

Modified: head/sbin/iscontrol/iscontrol.c
==============================================================================
--- head/sbin/iscontrol/iscontrol.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/iscontrol.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
 
 #include "iscsi.h"
 #include "iscontrol.h"
-//#include "pdu.h"
 
 #define USAGE "[-v] [-d] [-c config] [-n name] [-t target] "
 #define OPTIONS	"vdc:t:n:"
@@ -129,7 +128,7 @@ int
 main(int cc, char **vv)
 {
      int	ch, disco;
-     char	*pname, *p, *ta, *kw;
+     char	*pname, *p, *q, *ta, *kw;
      isc_opt_t	*op;
      FILE	*fd;
 
@@ -191,12 +190,18 @@ main(int cc, char **vv)
 	  fprintf(stderr, "No target!\n");
 	  goto badu;
      }
-     if((p = strchr(op->targetAddress, ':')) != NULL) {
+     q = op->targetAddress;
+     if(*q == '[' && (q = strchr(q, ']')) != NULL) {
+	  *q++ = '\0';
+	  op->targetAddress++;
+     } else
+	  q = op->targetAddress;
+     if((p = strchr(q, ':')) != NULL) {
 	  *p++ = 0;
 	  op->port = atoi(p);
 	  p = strchr(p, ',');
      }
-     if(p || ((p = strchr(op->targetAddress, ',')) != NULL)) {
+     if(p || ((p = strchr(q, ',')) != NULL)) {
 	  *p++ = 0;
 	  op->targetPortalGroupTag = atoi(p);
      }

Modified: head/sbin/iscontrol/iscontrol.h
==============================================================================
--- head/sbin/iscontrol/iscontrol.h	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/iscontrol.h	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,12 @@ int vflag;
 
 typedef int auth_t(void *sess);
 
+typedef struct {
+     char      *address;
+     int       port;
+     int       pgt;
+} target_t;
+
 typedef struct isess {
      int	flags;
 #define SESS_CONNECTED		BIT(0)
@@ -61,6 +67,7 @@ typedef struct isess {
 
 
      isc_opt_t	*op;		// operational values
+     target_t  target;         // the Original target address
      int	fd;		// the session fd
      int	soc;		// the socket
      iscsi_cam_t	cam;

Modified: head/sbin/iscontrol/iscsi.conf.5
==============================================================================
--- head/sbin/iscontrol/iscsi.conf.5	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/iscsi.conf.5	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2007 Daniel Braniss <danny at cs.huji.ac.il>
+.\" Copyright (c) 2007-2008 Daniel Braniss <danny at cs.huji.ac.il>
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without

Modified: head/sbin/iscontrol/login.c
==============================================================================
--- head/sbin/iscontrol/login.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/login.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
 
 #include "iscsi.h"
 #include "iscontrol.h"
-#include "pdu.h"
 
 static char *status_class1[] = {
      "Initiator error",
@@ -173,16 +172,18 @@ processParams(isess_t *sess, pdu_t *pp)
 	       klen = eq - ptr;
 	  if(klen > 0) {
 	       if(strncmp(ptr, "TargetAddress", klen) == 0) {
-		    char	*p, *q;
+		    char	*p, *q, *ta = NULL;
 
 		    // TargetAddress=domainname[:port][,portal-group-tag]
 		    // XXX: if(op->targetAddress) free(op->targetAddress);
 		    q = op->targetAddress = strdup(eq+1);
 		    if(*q == '[') {
 			 // bracketed IPv6
-			 if((q = strchr(q, ']')) != NULL)
-			      q++;
-			 else
+			 if((q = strchr(q, ']')) != NULL) {
+			      *q++ = '\0';
+			      ta = op->targetAddress;
+			      op->targetAddress = strdup(ta+1);
+			 } else
 			      q = op->targetAddress;
 		    }
 		    if((p = strchr(q, ',')) != NULL) {
@@ -193,6 +194,8 @@ processParams(isess_t *sess, pdu_t *pp)
 			 *p++ = 0;
 			 op->port = atoi(p);
 		    }
+		    if(ta)
+			 free(ta);
 	       } else if(strncmp(ptr, "MaxRecvDataSegmentLength", klen) == 0) {
 		    // danny's RFC
 		    op->maxXmitDataSegmentLength = strtol(eq+1, (char **)NULL, 0);

Modified: head/sbin/iscontrol/misc.c
==============================================================================
--- head/sbin/iscontrol/misc.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/misc.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without

Modified: head/sbin/iscontrol/pdu.c
==============================================================================
--- head/sbin/iscontrol/pdu.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sbin/iscontrol/pdu.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
 
 #include "iscsi.h"
 #include "iscontrol.h"
-#include "pdu.h"
 
 int
 xmitpdu(isess_t *sess, pdu_t *pp)

Modified: head/sys/dev/iscsi/initiator/isc_cam.c
==============================================================================
--- head/sys/dev/iscsi/initiator/isc_cam.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sys/dev/iscsi/initiator/isc_cam.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005-2007 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -193,6 +193,23 @@ _inq(struct cam_sim *sim, union ccb *ccb
      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)
 {
@@ -281,17 +298,8 @@ ic_action(struct cam_sim *sim, union ccb
 	       ccb_h->status = CAM_LUN_INVALID;
 	       break;
 	  }
-#if __FreeBSD_version < 700000
-	  if(scsi_encap(sim, ccb) != 0)
+	  if(_scsi_encap(sim, ccb) != 0)
 	       return;
-#else
-	  mtx_unlock(&isp->cam_mtx);
-	  if(scsi_encap(sim, ccb) != 0) {
-	       mtx_lock(&isp->cam_mtx);
-	       return;
-	  }
-	  mtx_lock(&isp->cam_mtx);
-#endif
 	  break;
      }
  
@@ -396,7 +404,11 @@ ic_init(struct isc_softc *isp)
 	  return ENXIO;
      }
      CAM_LOCK(isp);
-     if(xpt_bus_register(sim, NULL, 0/*bus_number*/) != CAM_SUCCESS)
+     if(xpt_bus_register(sim,
+#if __FreeBSD_version >= 700000
+			 NULL,
+#endif
+			 0/*bus_number*/) != CAM_SUCCESS)
 	  goto bad;
 
      if(xpt_create_path(&path, xpt_periph, cam_sim_path(sim),

Modified: head/sys/dev/iscsi/initiator/isc_sm.c
==============================================================================
--- head/sys/dev/iscsi/initiator/isc_sm.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sys/dev/iscsi/initiator/isc_sm.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005-2007 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -174,7 +174,7 @@ _nop_out(isc_session_t *sp)
 	  /*
 	   | only send a nop if window is closed.
 	   */
-	  if((pq = pdu_alloc(sp->isc, 0)) == NULL)
+	  if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL)
 	       // I guess we ran out of resources
 	       return;
 	  nop_out = &pq->pdu.ipdu.nop_out;
@@ -224,7 +224,6 @@ _nop_in(isc_session_t *sp, pduq_t *pq)
 	       nop_out = &pp->ipdu.nop_out;
 	       nop_out->sn.maxcmd = 0;
 	       memset(nop_out->mbz, 0, sizeof(nop_out->mbz));
-
 	       (void)isc_qout(sp, pq); //XXX: should check return?
 	       return;
 	  }
@@ -318,27 +317,24 @@ isc_qout(isc_session_t *sp, pduq_t *pq)
 	  i_nqueue_csnd(sp, pq);
 
      sdebug(5, "enqued: pq=%p", pq);
-#ifdef ISC_OWAITING
-     if(sp->flags & ISC_OWAITING) {
-	  mtx_lock(&sp->io_mtx);	// XXX
-	  wakeup(&sp->flags);
-	  mtx_unlock(&sp->io_mtx);	// XXX
-     }
-#else
+
+     mtx_lock(&sp->io_mtx);
+     sp->flags |= ISC_OQNOTEMPTY;
+     if(sp->flags & ISC_OWAITING)
      wakeup(&sp->flags);
-#endif
+     mtx_unlock(&sp->io_mtx);
+
      return error;
 }
 /*
  | called when a fullPhase is restarted
  */
-static int
+static void
 ism_restart(isc_session_t *sp)
 {
      int lastcmd;
 
      sdebug(2, "restart ...");
-     sp->flags |= ISC_SM_HOLD;
      lastcmd = iscsi_requeue(sp);
 #if 0
      if(lastcmd != sp->sn.cmd) {
@@ -346,8 +342,13 @@ ism_restart(isc_session_t *sp)
 	  sp->sn.cmd = lastcmd;
      }
 #endif
-     sp->flags &= ~ISC_SM_HOLD;
-     return 0;
+     mtx_lock(&sp->io_mtx);
+     if(sp->flags & ISC_OWAITING) {
+	  wakeup(&sp->flags);
+     }
+     mtx_unlock(&sp->io_mtx);
+
+     sdebug(2, "restarted lastcmd=0x%x", lastcmd);
 }
 
 int
@@ -367,7 +368,7 @@ ism_fullfeature(struct cdev *dev, int fl
 	  error = ic_fullfeature(dev);
 	  break;
      case 2: // restart
-	  error = ism_restart(sp);
+	  ism_restart(sp);
 	  break;
      }
      return error;
@@ -454,32 +455,40 @@ ism_recv(isc_session_t *sp, pduq_t *pq)
      }
 }
 
+/*
+ | go through the out queues looking for work
+ | if either nothing to do, or window is closed
+ | return.
+ */
 static int
 proc_out(isc_session_t *sp)
 {
      sn_t	*sn = &sp->sn;
      pduq_t	*pq;
-     int	error, ndone = 0;
+     int	error, ndone;
      int	which;
 
      debug_called(8);
+     error = ndone = 0;
 
-     while(1) {
+     while(sp->flags & ISC_LINK_UP) {
 	  pdu_t *pp;
 	  bhs_t	*bhs;
-
 	  /*
 	   | check if there is outstanding work in:
-	   | 1- the Inmediate queue
+	   | 1- the Immediate queue
 	   | 2- the R2T queue
 	   | 3- the cmd queue, only if the command window allows it.
 	   */
 	  which = BIT(0) | BIT(1);
-	  if(SNA_GT(sn->cmd, sn->maxCmd) == 0)
+	  if(SNA_GT(sn->cmd, sn->maxCmd) == 0) // if(sn->maxCmd - sn->smc + 1) > 0
 	       which |= BIT(2);
 
+	  sdebug(4, "which=%d sn->maxCmd=%d sn->cmd=%d", which, sn->maxCmd, sn->cmd);
+
 	  if((pq = i_dqueue_snd(sp, which)) == NULL)
 	       break;
+	  sdebug(4, "pq=%p", pq);
 
 	  pp = &pq->pdu;
 	  bhs = &pp->ipdu.bhs;
@@ -510,38 +519,45 @@ proc_out(isc_session_t *sp)
 	       // XXX: and now?
 	  }
 
-	  sdebug(5, "opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)",
+	  sdebug(4, "opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)",
 		bhs->opcode,
 		sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt);
 
 	  if(pq->ccb)
 	       i_nqueue_hld(sp, pq);
 
-	  if((error = isc_sendPDU(sp, pq)) == 0)
+	  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(error == EPIPE) {
-		    // XXX: better do some error recovery ...
+	       if(pq->ccb)
+		    i_remove_hld(sp, pq);
+	       switch(error) {
+	       case EPIPE:
+		    sp->flags &= ~ISC_LINK_UP;
+
+	       case EAGAIN:
+		    xdebug("requed");
+		    i_rqueue_pdu(sp, pq);
 		    break;
-	       }
-#if 0
+
+	       default:
 	       if(pq->ccb) {
-		    i_remove_hld(sp, pq);
-		    pq->ccb->ccb_h.status |= CAM_UNREC_HBA_ERROR; // some better error?
-		    XPT_DONE(pq->ccb);
+			 xdebug("back to cam");
+			 pq->ccb->ccb_h.status |= CAM_REQUEUE_REQ; // some better error?
+			 XPT_DONE(sp->isc, pq->ccb);
+			 pdu_free(sp->isc, pq);
 	       }
-	       else {
-		    // XXX: now what?
-		    // how do we pass back an error?
+		    else
+			 xdebug("we lost it!");
 	       }
-#endif
 	  }
-	  if(pq->ccb == NULL || error)
-	       pdu_free(sp->isc, pq);
      }
-     return ndone;
+     return error;
 }
 
 /*
@@ -551,42 +567,46 @@ static void
 ism_proc(void *vp)
 {
      isc_session_t 	*sp = (isc_session_t *)vp;
-     int		odone;
+     int		error;
 
      debug_called(8);
-     sdebug(3, "started");
 
      sp->flags |= ISC_SM_RUNNING;
+     sdebug(3, "started sp->flags=%x", sp->flags);
      do {
-	  if(sp->flags & ISC_SM_HOLD)
-	       odone = 0;
-	  else
-	       odone = proc_out(sp);
-	  sdebug(7, "odone=%d", odone);
-	  if(odone == 0) {
+	  if((sp->flags & ISC_HOLD) == 0) {
+	       error = proc_out(sp);
+	       if(error) {
+		    sdebug(3, "error=%d", error);
+	       }
+	  }
 	       mtx_lock(&sp->io_mtx);
-#ifdef ISC_OWAITING
+	  if((sp->flags & ISC_LINK_UP) == 0) {
+	       wakeup(&sp->soc);
+	  }
+
+	  if(!(sp->flags & ISC_OQNOTEMPTY)) {
 	       sp->flags |= ISC_OWAITING;
-#endif
-	       if((msleep(&sp->flags, &sp->io_mtx, PRIBIO, "isc_proc", hz*30) == EWOULDBLOCK)
-		  && (sp->flags & ISC_CON_RUNNING))
+	       if(msleep(&sp->flags, &sp->io_mtx, PRIBIO, "isc_proc", hz*30) == EWOULDBLOCK) {
+		    if(sp->flags & ISC_CON_RUNNING)
 		    _nop_out(sp);
-#ifdef ISC_OWAITING
+	       }
 	       sp->flags &= ~ISC_OWAITING;
-#endif
-	       mtx_unlock(&sp->io_mtx);
 	  }
+	  sp->flags &= ~ISC_OQNOTEMPTY;
+	  mtx_unlock(&sp->io_mtx);
      } while(sp->flags & ISC_SM_RUN);
 
      sp->flags &= ~ISC_SM_RUNNING;
+     sdebug(3, "dropped ISC_SM_RUNNING");
 
 #if __FreeBSD_version >= 700000
      destroy_dev(sp->dev);
 #endif
+     wakeup(sp);
 
-     sdebug(3, "terminated");
+     debug(3, "terminated sp=%p sp->sid=%d", sp, sp->sid);
 
-     wakeup(sp);
      kproc_exit(0);
 }
 
@@ -695,6 +715,13 @@ isc_add_sysctls(isc_session_t *sp)
 		     CTLFLAG_RD,
 		     (void *)sp, 0,
 		     isc_dump_stats, "A", "statistics");
+
+     SYSCTL_ADD_INT(&sp->clist,
+		     SYSCTL_CHILDREN(sp->oid),
+		     OID_AUTO,
+		     "douio",
+		     CTLFLAG_RW,
+		     &sp->douio, 0, "enable uio on read");
 }
 
 void
@@ -782,5 +809,6 @@ ism_start(isc_session_t *sp)
 
      sp->flags |= ISC_SM_RUN;
 
+     debug(4, "starting ism_proc: sp->sid=%d", sp->sid);
      return kproc_create(ism_proc, sp, &sp->stp, 0, 0, "ism_%d", sp->sid);
 }

Modified: head/sys/dev/iscsi/initiator/isc_soc.c
==============================================================================
--- head/sys/dev/iscsi/initiator/isc_soc.c	Tue Nov 25 05:17:39 2008	(r185288)
+++ head/sys/dev/iscsi/initiator/isc_soc.c	Tue Nov 25 07:17:11 2008	(r185289)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005-2007 Daniel Braniss <danny at cs.huji.ac.il>
+ * Copyright (c) 2005-2008 Daniel Braniss <danny at cs.huji.ac.il>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,157 +55,179 @@ __FBSDID("$FreeBSD$");
 #include <sys/mbuf.h>
 #include <sys/user.h>
 
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+
 #include <dev/iscsi/initiator/iscsi.h>
 #include <dev/iscsi/initiator/iscsivar.h>
 
-#ifndef USE_MBUF
+#ifndef NO_USE_MBUF
 #define USE_MBUF
 #endif
 
 #ifdef USE_MBUF
+
+static int ou_refcnt = 0;
+
 /*
- |  a dummy function for freeing external storage for mbuf
+ | function for freeing external storage for mbuf
  */
 static void
-nil_fn(void *a, void *b)
+ext_free(void *a, void *b)
 {
+     pduq_t *pq = b;
+
+     if(pq->buf != NULL) {
+	  debug(3, "ou_refcnt=%d a=%p b=%p", ou_refcnt, a, pq->buf);
+	  free(pq->buf, M_ISCSI);
+	  pq->buf = NULL;
+     }
 }
-static int nil_refcnt = 0;
-#endif /* USE_MBUF */
 
 int
 isc_sendPDU(isc_session_t *sp, pduq_t *pq)
 {
+     struct mbuf *mh, **mp;
      pdu_t		*pp = &pq->pdu;
      int		len, error;
-#ifdef USE_MBUF
-     struct mbuf        *mh, **mp;
-#else
-     struct uio		*uio = &pq->uio;
-     struct iovec	*iv;
-#endif /* USE_MBUF */
 
      debug_called(8);
-
-#ifndef USE_MBUF
-     bzero(uio, sizeof(struct uio));
-     uio->uio_rw	= UIO_WRITE;
-     uio->uio_segflg	= UIO_SYSSPACE;
-     uio->uio_td	= sp->td;
-     uio->uio_iov 	= iv = pq->iov;
-
-     iv->iov_base	= &pp->ipdu;
-     iv->iov_len	= sizeof(union ipdu_u);
-     uio->uio_resid	= pq->len;
-     iv++;
-#else /* USE_MBUF */
-     /*  mbuf for the iSCSI header */
-     MGETHDR(mh, M_WAIT, MT_DATA);
+     /* 
+      | 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;
-#endif /* USE_MBUF */
 
      if(sp->hdrDigest)
 	  pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
      if(pp->ahs_len) {
-#ifndef USE_MBUF
-	  iv->iov_base	= pp->ahs;
-	  iv->iov_len	= pp->ahs_len;
-	  iv++;
-#else /* USE_MBUF */
-          /* Add any AHS to the iSCSI hdr mbuf */
-          /* XXX Assert: (mh->m_pkthdr.len + pp->ahs_len) < MHLEN */
+          /* 
+	   | 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;
-#endif /* USE_MBUF */
+
 	  if(sp->hdrDigest)
 	       pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig);
      }
      if(sp->hdrDigest) {
 	  debug(2, "hdr_dig=%x", pq->pdu.hdr_dig);
-#ifndef USE_MBUF
-	  iv->iov_base	= &pp->hdr_dig;
-	  iv->iov_len	= sizeof(int);
-	  iv++;
-#else /* USE_MBUF */
-          /* Add header digest to the iSCSI hdr mbuf */ 
-          /* XXX Assert: (mh->m_pkthdr.len + 4) < MHLEN */
+          /* 
+	   | 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);
-#endif /* USE_MBUF */
      }
-#ifdef USE_MBUF
      mp = &mh->m_next;
-#endif /* USE_MBUF */
      if(pq->pdu.ds) {
-#ifndef USE_MBUF
-	  iv->iov_base	= pp->ds;
-	  iv->iov_len	= pp->ds_len;
-	  while(iv->iov_len & 03) // the specs say it must be int alligned
-	       iv->iov_len++;
-	  iv++;
-#else /* USE_MBUF */
           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) {
+          while(len > 0) {
                 int       l;
           
-                MGET(md, M_WAIT, MT_DATA);
-		md->m_ext.ref_cnt = &nil_refcnt;
+	       MGET(md, M_TRYWAIT, MT_DATA);
+	       md->m_ext.ref_cnt = &ou_refcnt;
                 l = min(MCLBYTES, len);
-                MEXTADD(md, pp->ds + off, l, nil_fn,
-                        pp->ds + off, NULL, 0, EXT_EXTREF);
+	       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;
           } 
-#endif /* USE_MBUF */
      }
      if(sp->dataDigest) {
-#ifdef USE_MBUF
           struct mbuf   *me;
 
-#endif /* USE_MBUF */
 	  pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0);
-#ifndef USE_MBUF
-	  iv->iov_base	= &pp->ds_dig;
-	  iv->iov_len	= sizeof(int);
-	  iv++;
-#else /* USE_MBUF */
-          MGET(me, M_WAIT, MT_DATA);
+
+          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;
-#endif /* USE_MBUF */
      }
+     if((error = sosend(sp->soc, NULL, NULL, mh, 0, 0, sp->td)) != 0) {
+	  sdebug(3, "error=%d", error);
+	  return error;
+     }
+     sp->stats.nsent++;
+     getbintime(&sp->stats.t_sent);
+     return 0;
+}
+#else /* NO_USE_MBUF */
+int
+isc_sendPDU(isc_session_t *sp, pduq_t *pq)
+{
+     struct uio *uio = &pq->uio;
+     struct iovec *iv;
+     pdu_t	*pp = &pq->pdu;
+     int	len, error;
+
+     debug_called(8);
+
+     bzero(uio, sizeof(struct uio));
+     uio->uio_rw = UIO_WRITE;
+     uio->uio_segflg = UIO_SYSSPACE;
+     uio->uio_td = sp->td;
+     uio->uio_iov = iv = pq->iov;
+
+     iv->iov_base = &pp->ipdu;
+     iv->iov_len = sizeof(union ipdu_u);
+     uio->uio_resid = pq->len;
+     iv++;
+     if(sp->hdrDigest)
+	  pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0);
+     if(pp->ahs_len) {
+	  iv->iov_base = pp->ahs;
+	  iv->iov_len = pp->ahs_len;
+	  iv++;
 
-#ifndef USE_MBUF
+	  if(sp->hdrDigest)
+	       pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig);
+     }
+     if(sp->hdrDigest) {
+	  debug(2, "hdr_dig=%x", pq->pdu.hdr_dig);
+	  iv->iov_base = &pp->hdr_dig;
+	  iv->iov_len = sizeof(int);
+	  iv++;
+     }
+     if(pq->pdu.ds) {
+	  iv->iov_base = pp->ds;
+	  iv->iov_len = pp->ds_len;
+	  while(iv->iov_len & 03) // the specs say it must be int alligned
+	       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",
 	    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",
 	    sp, sp->soc, uio, sp->td);
-
      do {
 	  len = uio->uio_resid;
 	  error = sosend(sp->soc, NULL, uio, 0, 0, 0, sp->td);
@@ -243,20 +265,12 @@ isc_sendPDU(isc_session_t *sp, pduq_t *p

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list