Module Name:    src
Committed By:   mlelstv
Date:           Sat Jun  9 06:19:58 UTC 2012

Modified Files:
        src/sys/dev/iscsi: iscsi_globals.h iscsi_ioctl.c iscsi_main.c
            iscsi_send.c iscsi_text.c iscsi_utils.c

Log Message:
Close file descriptor passed into the kernel on success.
Fix locking of file handle. More cleanup on error paths.
Keep track of CCBs, so they cannot be used after a session ends.
Handle CCB timeouts even when the connection is terminated.
Compute firstdata, firstimmed correctly.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/iscsi/iscsi_globals.h \
    src/sys/dev/iscsi/iscsi_text.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/iscsi/iscsi_ioctl.c \
    src/sys/dev/iscsi/iscsi_send.c
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/iscsi/iscsi_main.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/iscsi/iscsi_utils.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/iscsi/iscsi_globals.h
diff -u src/sys/dev/iscsi/iscsi_globals.h:1.3 src/sys/dev/iscsi/iscsi_globals.h:1.4
--- src/sys/dev/iscsi/iscsi_globals.h:1.3	Sat Jun  2 16:52:11 2012
+++ src/sys/dev/iscsi/iscsi_globals.h	Sat Jun  9 06:19:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: iscsi_globals.h,v 1.3 2012/06/02 16:52:11 mlelstv Exp $	*/
+/*	$NetBSD: iscsi_globals.h,v 1.4 2012/06/09 06:19:58 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
@@ -387,6 +387,7 @@ struct connection_s {
 					/* if closing down: status */
 	int				recover; /* recovery count */
 		/* (reset on first successful data transfer) */
+	int				usecount; /* number of active CCBs */
 
 	bool				destroy; /* conn will be destroyed */
 	bool				in_session;
Index: src/sys/dev/iscsi/iscsi_text.c
diff -u src/sys/dev/iscsi/iscsi_text.c:1.3 src/sys/dev/iscsi/iscsi_text.c:1.4
--- src/sys/dev/iscsi/iscsi_text.c:1.3	Sat Dec 17 20:05:39 2011
+++ src/sys/dev/iscsi/iscsi_text.c	Sat Jun  9 06:19:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: iscsi_text.c,v 1.3 2011/12/17 20:05:39 tls Exp $	*/
+/*	$NetBSD: iscsi_text.c,v 1.4 2012/06/09 06:19:58 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
@@ -1773,11 +1773,12 @@ set_negotiated_parameters(ccb_t *ccb)
 		state->FirstBurstLength, state->InitialR2T,
 		state->ImmediateData));
 
-	conn->max_transfer = min(sess->MaxBurstLength,
-					conn->MaxRecvDataSegmentLength);
+	conn->max_transfer = min(sess->MaxBurstLength, conn->MaxRecvDataSegmentLength);
 
 	conn->max_firstimmed = (!sess->ImmediateData) ? 0 :
 				min(sess->FirstBurstLength, conn->max_transfer);
 
-	conn->max_firstdata = (sess->InitialR2T) ? 0 : sess->FirstBurstLength;
+	conn->max_firstdata = (sess->InitialR2T || sess->FirstBurstLength < conn->max_firstimmed) ? 0 :
+				min(sess->FirstBurstLength - conn->max_firstimmed, conn->max_transfer);
+
 }

Index: src/sys/dev/iscsi/iscsi_ioctl.c
diff -u src/sys/dev/iscsi/iscsi_ioctl.c:1.2 src/sys/dev/iscsi/iscsi_ioctl.c:1.3
--- src/sys/dev/iscsi/iscsi_ioctl.c:1.2	Fri Jan 27 19:48:39 2012
+++ src/sys/dev/iscsi/iscsi_ioctl.c	Sat Jun  9 06:19:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: iscsi_ioctl.c,v 1.2 2012/01/27 19:48:39 para Exp $	*/
+/*	$NetBSD: iscsi_ioctl.c,v 1.3 2012/06/09 06:19:58 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
@@ -207,7 +207,8 @@ check_event(iscsi_wait_event_parameters_
 			}
 			handler->waiter = par;
 			splx(s);
-			tsleep(par, PRIBIO, "iscsievtwait", 0);
+			if (tsleep(par, PRIBIO | PCATCH, "iscsievtwait", 0))
+				return;
 		}
 	} while (evt == NULL);
 
@@ -324,15 +325,34 @@ get_socket(int fdes, struct file **fpp)
 	if (fp->f_type != DTYPE_SOCKET) {
 		return ENOTSOCK;
 	}
+
 	/* Add the reference */
+	mutex_enter(&fp->f_lock);
 	fp->f_count++;
-
-	/*simple_unlock (&fp->f_slock); */
+	mutex_exit(&fp->f_lock);
 
 	*fpp = fp;
 	return 0;
 }
 
+/*
+ * release_socket:
+ *    Release the file pointer from the socket handle passed into login.
+ *
+ *    Parameter:
+ *          fp       IN: The pointer to the resulting file pointer
+ *
+ */
+
+STATIC void
+release_socket(struct file *fp)
+{
+	/* Add the reference */
+	mutex_enter(&fp->f_lock);
+	fp->f_count--;
+	mutex_exit(&fp->f_lock);
+}
+
 
 /*
  * find_session:
@@ -635,6 +655,7 @@ create_connection(iscsi_login_parameters
 				"ConnRcv")) != 0) {
 		DEBOUT(("Can't create rcv thread (rc %d)\n", rc));
 
+		release_socket(connection->sock);
 		free(connection, M_DEVBUF);
 		par->status = ISCSI_STATUS_NO_RESOURCES;
 		return rc;
@@ -653,18 +674,15 @@ create_connection(iscsi_login_parameters
 		 */
 		DEBC(connection, 1,
 			("Closing Socket %p\n", connection->sock));
-#if __NetBSD_Version__ > 500000000
 		mutex_enter(&connection->sock->f_lock);
 		connection->sock->f_count += 1;
 		mutex_exit(&connection->sock->f_lock);
-#else
-		FILE_USE(connection->sock);
-#endif
 		closef(connection->sock);
 
 		/* give receive thread time to exit */
 		tsleep(connection, PWAIT, "settle", 20);
 
+		release_socket(connection->sock);
 		free(connection, M_DEVBUF);
 		par->status = ISCSI_STATUS_NO_RESOURCES;
 		return rc;
@@ -698,6 +716,9 @@ create_connection(iscsi_login_parameters
 	session->mru_connection = connection;
 	CS_END;
 
+	/* close the file descriptor */
+	fd_close(par->socket);
+
 	DEBC(connection, 5, ("Connection created successfully!\n"));
 	return 0;
 }
@@ -809,6 +830,10 @@ recreate_connection(iscsi_login_paramete
 
 	DEBC(connection, 5, ("Connection ReCreated successfully - status %d\n",
 						 par->status));
+
+	/* close the file descriptor */
+	fd_close(par->socket);
+
 	return 0;
 }
 
@@ -1463,9 +1488,8 @@ iscsi_cleanup_thread(void *par)
 			while (conn->sendproc || conn->rcvproc)
 				tsleep(conn, PWAIT, "termwait", 20);
 
-			/* just in case any CCB is still being processed */
-			/* that references this connection */
-			tsleep(conn, PWAIT, "finalwait", 20);
+			while (conn->usecount > 0)
+				tsleep(conn, PWAIT, "finalwait", 20);
 
 			free(conn, M_DEVBUF);
 
Index: src/sys/dev/iscsi/iscsi_send.c
diff -u src/sys/dev/iscsi/iscsi_send.c:1.2 src/sys/dev/iscsi/iscsi_send.c:1.3
--- src/sys/dev/iscsi/iscsi_send.c:1.2	Tue Jun  5 16:36:07 2012
+++ src/sys/dev/iscsi/iscsi_send.c	Sat Jun  9 06:19:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: iscsi_send.c,v 1.2 2012/06/05 16:36:07 mhitch Exp $	*/
+/*	$NetBSD: iscsi_send.c,v 1.3 2012/06/09 06:19:58 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
@@ -199,6 +199,8 @@ reassign_tasks(connection_t *oldconn)
 		ccb->pdu_waiting = pdu;
 		ccb->connection = conn;
 		ccb->num_timeouts = 0;
+		oldconn->usecount--;
+		conn->usecount++;
 
 		DEBC(conn, 1, ("CCB %p: Copied PDU %p to %p\n",
 					   ccb, opdu, pdu));
@@ -341,25 +343,15 @@ iscsi_send_thread(void *par)
 
 		fp = conn->sock;
 
-		DEBC(conn, 9, ("Closing Socket %p\n", conn->sock));
 		/*
 		 * We must close the socket here to force the receive
 		 * thread to wake up
 		 */
+		DEBC(conn, 9, ("Closing Socket %p\n", conn->sock));
 		solock((struct socket *) fp->f_data);
 		soshutdown((struct socket *) fp->f_data, SHUT_RDWR);
 		sounlock((struct socket *) fp->f_data);
-
-#if __NetBSD_Version__ > 500000000
-		mutex_enter(&fp->f_lock);
-		fp->f_count += 1;
-		mutex_exit(&fp->f_lock);
 		closef(fp);
-#else
-		simple_lock(&fp->f_slock);
-		FILE_USE(fp);
-		closef(fp, NULL);
-#endif
 
 		/* wake up any non-reassignable waiting CCBs */
 		for (ccb = TAILQ_FIRST(&conn->ccbs_waiting); ccb != NULL; ccb = nccb) {
@@ -791,9 +783,13 @@ start_text_negotiation(connection_t *con
 	ccb_t *ccb;
 
 	ccb = get_ccb(conn, TRUE);
+	if (ccb == NULL)
+		return;
 	pdu = get_pdu(conn);
-	if (ccb == NULL || pdu == NULL)
+	if (pdu == NULL) {
+		free_ccb(ccb);
 		return;
+	}
 
 	if (init_text_parameters(conn, ccb)) {
 		free_ccb(ccb);
@@ -887,10 +883,13 @@ send_send_targets(session_t *session, ui
 			: ISCSI_STATUS_CONNECTION_FAILED;
 
 	ccb = get_ccb(conn, TRUE);
+	if (ccb == NULL)
+		return conn->terminating;
 	pdu = get_pdu(conn);
-	/* can only happen if terminating... */
-	if (ccb == NULL || pdu == NULL)
+	if (pdu == NULL) {
+		free_ccb(ccb);
 		return conn->terminating;
+	}
 
 	ccb->flags |= CCBF_SENDTARGET;
 
@@ -1105,12 +1104,15 @@ send_login(connection_t *conn)
 
 	DEBC(conn, 9, ("Send_login\n"));
 	ccb = get_ccb(conn, TRUE);
-	pdu = get_pdu(conn);
-
 	/* only if terminating (which couldn't possibly happen here, but...) */
-	if (ccb == NULL || pdu == NULL) {
+	if (ccb == NULL)
+		return conn->terminating;
+	pdu = get_pdu(conn);
+	if (pdu == NULL) {
+		free_ccb(ccb);
 		return conn->terminating;
 	}
+
 	if ((rc = assemble_login_parameters(conn, ccb, pdu)) >= 0) {
 		init_login_pdu(conn, pdu, !rc);
 		setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE);
@@ -1148,10 +1150,14 @@ send_logout(connection_t *conn, connecti
 
 	DEBC(conn, 5, ("Send_logout\n"));
 	ccb = get_ccb(conn, TRUE);
-	ppdu = get_pdu(conn);
 	/* can only happen if terminating... */
-	if (ccb == NULL || ppdu == NULL)
+	if (ccb == NULL)
 		return conn->terminating;
+	ppdu = get_pdu(conn);
+	if (ppdu == NULL) {
+		free_ccb(ccb);
+		return conn->terminating;
+	}
 
 	pdu = &ppdu->pdu;
 	pdu->Opcode = IOP_Logout_Request | OP_IMMEDIATE;
@@ -1211,10 +1217,14 @@ send_task_management(connection_t *conn,
 		return ISCSI_STATUS_CANT_REASSIGN;
 
 	ccb = get_ccb(conn, xs == NULL);
-	ppdu = get_pdu(conn);
 	/* can only happen if terminating... */
-	if (ccb == NULL || ppdu == NULL)
+	if (ccb == NULL)
 		return conn->terminating;
+	ppdu = get_pdu(conn);
+	if (ppdu == NULL) {
+		free_ccb(ccb);
+		return conn->terminating;
+	}
 
 	ccb->xs = xs;
 
@@ -1392,12 +1402,11 @@ send_command(ccb_t *ccb, ccb_disp_t disp
 			totlen = 0;
 		} else {
 			pdu->Flags = FLAG_WRITE;
+			/* immediate data we can send */
 			len = min(totlen, conn->max_firstimmed);
-			/* this means InitialR2T=Yes or FirstBurstLength=0 */
-			if (!len)	
-				totlen = 0;
-			else
-				totlen -= len;
+
+			/* can we send more unsolicited data ? */
+			totlen = conn->max_firstdata ? totlen - len : 0;
 		}
 	}
 
@@ -1459,7 +1468,7 @@ send_run_xfer(session_t *session, struct
 	conn = assign_connection(session, waitok);
 
 	if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) {
-		xs->error = XS_REQUEUE;
+		xs->error = XS_SELTIMEOUT;
 		DEBC(conn, 10, ("run_xfer on dead connection\n"));
 		scsipi_done(xs);
 		return;
@@ -1500,6 +1509,7 @@ send_run_xfer(session_t *session, struct
 	ccb->lun += 0x1000000000000LL;
 	ccb->cmd[1] += 0x10;
 #endif
+	ccb->disp = CCBDISP_SCSIPI;
 	send_command(ccb, CCBDISP_SCSIPI, waitok, FALSE);
 }
 
@@ -1615,23 +1625,19 @@ ccb_timeout(void *par)
 {
 	ccb_t *ccb = (ccb_t *) par;
 	connection_t *conn = ccb->connection;
-
 	PDEBC(conn, 1, ("CCB Timeout, ccb=%x, num_timeouts=%d\n",
 			 (int) ccb, ccb->num_timeouts));
 
-	/* ignore CCB timeouts outside full feature phase */
-	if (conn->state != ST_FULL_FEATURE)
-		return;
-
 	ccb->total_tries++;
 
 	if (++ccb->num_timeouts > MAX_CCB_TIMEOUTS ||
 		ccb->total_tries > MAX_CCB_TRIES ||
 		ccb->disp <= CCBDISP_FREE ||
 		!ccb->session->ErrorRecoveryLevel) {
-		handle_connection_error(conn, ISCSI_STATUS_TIMEOUT,
-					(ccb->total_tries <= MAX_CCB_TRIES) ? RECOVER_CONNECTION
-														: LOGOUT_CONNECTION);
+		ccb->status = ISCSI_STATUS_TIMEOUT;
+		complete_ccb(ccb);
+
+		handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION);
 	} else {
 		if (ccb->data_in && ccb->xfer_len < ccb->data_len) {
 			/* request resend of all missing data */

Index: src/sys/dev/iscsi/iscsi_main.c
diff -u src/sys/dev/iscsi/iscsi_main.c:1.4 src/sys/dev/iscsi/iscsi_main.c:1.5
--- src/sys/dev/iscsi/iscsi_main.c:1.4	Sat Jun  2 16:52:11 2012
+++ src/sys/dev/iscsi/iscsi_main.c	Sat Jun  9 06:19:58 2012
@@ -449,7 +449,6 @@ iscsi_done(ccb_t *ccb)
 
 		case ISCSI_STATUS_CHECK_CONDITION:
 			xs->error = XS_SENSE;
-			xs->error = XS_SENSE;
 #ifdef ISCSI_DEBUG
 			{
 				uint8_t *s = (uint8_t *) (&xs->sense);

Index: src/sys/dev/iscsi/iscsi_utils.c
diff -u src/sys/dev/iscsi/iscsi_utils.c:1.1 src/sys/dev/iscsi/iscsi_utils.c:1.2
--- src/sys/dev/iscsi/iscsi_utils.c:1.1	Sun Oct 23 21:15:02 2011
+++ src/sys/dev/iscsi/iscsi_utils.c	Sat Jun  9 06:19:58 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: iscsi_utils.c,v 1.1 2011/10/23 21:15:02 agc Exp $	*/
+/*	$NetBSD: iscsi_utils.c,v 1.2 2012/06/09 06:19:58 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 2004,2005,2006,2008 The NetBSD Foundation, Inc.
@@ -244,6 +244,7 @@ get_ccb(connection_t *conn, bool waitok)
 	ccb->ITT = (ccb->ITT & 0xffffff) | (++sess->itt_id << 24);
 	ccb->disp = CCBDISP_NOWAIT;
 	ccb->connection = conn;
+	conn->usecount++;
 
 	return ccb;
 }
@@ -261,6 +262,9 @@ free_ccb(ccb_t *ccb)
 	session_t *sess = ccb->session;
 	pdu_t *pdu;
 
+	ccb->connection->usecount--;
+	ccb->connection = NULL;
+
 	ccb->disp = CCBDISP_UNUSED;
 
 	/* free temporary data */

Reply via email to