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.
This commit is contained in:
parent
d7fc161785
commit
d1c48dff5a
|
@ -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;
|
||||
|
|
|
@ -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_t *par, bool wait)
|
|||
}
|
||||
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 */
|
||||
fp->f_count++;
|
||||
|
||||
/*simple_unlock (&fp->f_slock); */
|
||||
/* Add the reference */
|
||||
mutex_enter(&fp->f_lock);
|
||||
fp->f_count++;
|
||||
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_t *par, session_t *session,
|
|||
"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_t *par, session_t *session,
|
|||
*/
|
||||
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_t *par, session_t *session,
|
|||
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_parameters_t *par, session_t *session,
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *conn)
|
|||
ccb_t *ccb;
|
||||
|
||||
ccb = get_ccb(conn, TRUE);
|
||||
pdu = get_pdu(conn);
|
||||
if (ccb == NULL || pdu == NULL)
|
||||
if (ccb == NULL)
|
||||
return;
|
||||
pdu = get_pdu(conn);
|
||||
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, uint8_t *key)
|
|||
: ISCSI_STATUS_CONNECTION_FAILED;
|
||||
|
||||
ccb = get_ccb(conn, TRUE);
|
||||
pdu = get_pdu(conn);
|
||||
/* can only happen if terminating... */
|
||||
if (ccb == NULL || pdu == NULL)
|
||||
if (ccb == NULL)
|
||||
return conn->terminating;
|
||||
pdu = get_pdu(conn);
|
||||
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, connection_t *refconn, int reason,
|
|||
|
||||
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, ccb_t *ref_ccb, struct scsipi_xfer *xs,
|
|||
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, bool waitok, bool immed)
|
|||
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 scsipi_xfer *xs)
|
|||
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 scsipi_xfer *xs)
|
|||
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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue