Index: iscsi_globals.h
===================================================================
RCS file: /cvsroot/src/sys/dev/iscsi/iscsi_globals.h,v
retrieving revision 1.5
diff -u -r1.5 iscsi_globals.h
--- iscsi_globals.h 12 Aug 2012 13:26:18 -0000 1.5
+++ iscsi_globals.h 11 Sep 2012 19:22:21 -0000
@@ -84,7 +84,7 @@
effectively says "don't bother testing these values", and is used right
now only in iscsi_send.c.
*/
-#define ISCSI_TROTTLING_ENABLED 1
+#define ISCSI_THROTTLING_ENABLED 1
#define ISCSI_SERVER_TRUSTED 1
/*
@@ -131,14 +131,15 @@
/* CCB Flags */
-#define CCBF_COMPLETE 0x01 /* received status */
-#define CCBF_RESENT 0x02 /* ccb was resent */
-#define CCBF_SENDTARGET 0x04 /* SendTargets text request, not negotiation */
-#define CCBF_WAITING 0x08 /* CCB is waiting for MaxCmdSN, wake it up */
-#define CCBF_GOT_RSP 0x10 /* Got at least one response to this request */
-#define CCBF_REASSIGN 0x20 /* Command can be reassigned */
-#define CCBF_OTHERCONN 0x40 /* a logout for a different connection */
-
+#define CCBF_COMPLETE 0x0001 /* received status */
+#define CCBF_RESENT 0x0002 /* ccb was resent */
+#define CCBF_SENDTARGET 0x0004 /* SendTargets text request, not negotiation */
+#define CCBF_WAITING 0x0008 /* CCB is waiting for MaxCmdSN, wake it up */
+#define CCBF_GOT_RSP 0x0010 /* Got at least one response to this request */
+#define CCBF_REASSIGN 0x0020 /* Command can be reassigned */
+#define CCBF_OTHERCONN 0x0040 /* a logout for a different connection */
+#define CCBF_WAITQUEUE 0x0080 /* CCB is on waiting queue */
+#define CCBF_THROTTLING 0x0100 /* CCB is on throttling queue */
/* --------------------------- Global Types ------------------------------- */
@@ -602,9 +603,6 @@
/* Critical section macros */
-#define CS_BEGIN { int s = splbio ();
-#define CS_END splx (s); }
-
/* misc stuff */
#define min(a, b) ((a) < (b)) ? (a) : (b)
#define max(a, b) ((a) < (b)) ? (b) : (a)
@@ -801,12 +799,12 @@
void create_ccbs(session_t *);
ccb_t *get_ccb(connection_t *, bool);
void free_ccb(ccb_t *);
-void wake_ccb(ccb_t *);
-void complete_ccb(ccb_t *);
+void suspend_ccb(ccb_t *, bool);
+void throttle_ccb(ccb_t *, bool);
+void wake_ccb(ccb_t *, uint32_t);
void create_pdus(connection_t *);
-pdu_t *get_pdu(connection_t *);
-pdu_t *get_pdu_c(connection_t *, bool);
+pdu_t *get_pdu(connection_t *, bool);
void free_pdu(pdu_t *);
void init_sernum(sernum_buffer_t *);
Index: iscsi_ioctl.c
===================================================================
RCS file: /cvsroot/src/sys/dev/iscsi/iscsi_ioctl.c,v
retrieving revision 1.5
diff -u -r1.5 iscsi_ioctl.c
--- iscsi_ioctl.c 12 Aug 2012 13:26:18 -0000 1.5
+++ iscsi_ioctl.c 11 Sep 2012 19:22:21 -0000
@@ -90,6 +90,7 @@
{
event_handler_t *handler;
int was_empty;
+ int s;
handler = malloc(sizeof(event_handler_t), M_DEVBUF, M_WAITOK | M_ZERO);
if (handler == NULL) {
@@ -101,7 +102,7 @@
TAILQ_INIT(&handler->events);
/* create a unique ID */
- CS_BEGIN;
+ s = splbio();
do {
++handler_id;
} while (!handler_id || find_handler(handler_id) != NULL);
@@ -114,7 +115,7 @@
if (was_empty) {
wakeup(&iscsi_cleanup_list);
}
- CS_END;
+ splx(s);
par->status = ISCSI_STATUS_SUCCESS;
DEB(5, ("Register Event OK, ID %d\n", par->event_id));
@@ -134,6 +135,7 @@
{
event_handler_t *handler;
event_t *evt;
+ int s;
handler = find_handler(par->event_id);
if (handler == NULL) {
@@ -141,9 +143,11 @@
par->status = ISCSI_STATUS_INVALID_EVENT_ID;
return;
}
- CS_BEGIN;
+
+ s = splbio();
TAILQ_REMOVE(&event_handlers, handler, link);
- CS_END;
+ splx(s);
+
if (handler->waiter != NULL) {
handler->waiter->status = ISCSI_STATUS_EVENT_DEREGISTERED;
wakeup(handler->waiter);
@@ -238,10 +242,12 @@
{
event_handler_t *curr;
event_t *evt;
+ int s;
DEB(9, ("Add_event kind %d, sid %d, cid %d, reason %d\n",
kind, sid, cid, reason));
+ s = splbio();
TAILQ_FOREACH(curr, &event_handlers, link) {
evt = malloc(sizeof(*evt), M_TEMP, M_WAITOK);
if (evt == NULL) {
@@ -251,14 +257,14 @@
evt->session_id = sid;
evt->connection_id = cid;
evt->reason = reason;
- CS_BEGIN;
+
TAILQ_INSERT_TAIL(&curr->events, evt, link);
if (curr->waiter != NULL) {
wakeup(curr->waiter);
curr->waiter = NULL;
}
- CS_END;
}
+ splx(s);
}
@@ -273,6 +279,8 @@
* list has changed at all. If not, the event is deregistered.
* Note that this will not detect dead handlers if no events are pending,
* but we don't care as long as events don't accumulate in the list.
+ *
+ * this function must be called at splbio
*/
STATIC void
@@ -367,11 +375,14 @@
find_session(uint32_t id)
{
session_t *curr;
+ int s;
+ s = splbio();
TAILQ_FOREACH(curr, &iscsi_sessions, sessions)
if (curr->id == id) {
break;
}
+ splx(s);
return curr;
}
@@ -389,11 +400,14 @@
find_connection(session_t *session, uint32_t id)
{
connection_t *curr;
+ int s;
+ s = splbio();
TAILQ_FOREACH(curr, &session->conn_list, connections)
if (curr->id == id) {
break;
}
+ splx(s);
return curr;
}
@@ -413,6 +427,7 @@
kill_connection(connection_t *conn, uint32_t status, int logout, bool recover)
{
session_t *sess = conn->session;
+ int s;
DEBC(conn, 1, ("Kill_connection: terminating=%d, status=%d, logout=%d, "
"state=%d\n",
@@ -427,13 +442,15 @@
}
if (!recover || conn->destroy) {
- CS_BEGIN;
+
+ s = splbio();
if (conn->in_session) {
conn->in_session = FALSE;
TAILQ_REMOVE(&sess->conn_list, conn, connections);
sess->mru_connection = TAILQ_FIRST(&sess->conn_list);
}
- CS_END;
+ splx(s);
+
if (!conn->destroy) {
DEBC(conn, 1, ("Kill_connection setting destroy flag\n"));
conn->destroy = TRUE;
@@ -512,6 +529,7 @@
{
connection_t *curr;
ccb_t *ccb;
+ int s;
DEB(1, ("ISCSI: kill_session %d, status %d, logout %d, recover %d\n",
session->id, status, logout, recover));
@@ -543,15 +561,16 @@
}
/* remove from session list */
+ s = splbio();
TAILQ_REMOVE(&iscsi_sessions, session, sessions);
+ splx(s);
session->sessions.tqe_next = NULL;
session->sessions.tqe_prev = NULL;
/* complete any throttled CCBs */
while ((ccb = TAILQ_FIRST(&session->ccbs_throttled)) != NULL) {
- ccb->status = ISCSI_STATUS_LOGOUT;
- TAILQ_REMOVE(&session->ccbs_throttled, ccb, chain);
- complete_ccb(ccb);
+ throttle_ccb(ccb, FALSE);
+ wake_ccb(ccb, ISCSI_STATUS_LOGOUT);
}
/*
@@ -595,7 +614,7 @@
PTHREADOBJ p)
{
connection_t *connection;
- int rc;
+ int rc, s;
DEB(1, ("Create Connection for Session %d\n", session->id));
@@ -709,15 +728,14 @@
return -1;
}
- CS_BEGIN;
+ s = splbio();
connection->state = ST_FULL_FEATURE;
-
TAILQ_INSERT_TAIL(&session->conn_list, connection, connections);
connection->in_session = TRUE;
session->total_connections++;
session->active_connections++;
session->mru_connection = connection;
- CS_END;
+ splx(s);
DEBC(connection, 5, ("Connection created successfully!\n"));
return 0;
@@ -742,7 +760,7 @@
recreate_connection(iscsi_login_parameters_t *par, session_t *session,
connection_t *connection, PTHREADOBJ p)
{
- int rc;
+ int rc, s;
ccb_t *ccb;
ccb_list_t old_waiting;
@@ -777,10 +795,9 @@
session->active_connections++;
TAILQ_INIT(&old_waiting);
- while ((ccb = TAILQ_FIRST(&connection->ccbs_waiting)) != NULL) {
- TAILQ_REMOVE(&connection->ccbs_waiting, ccb, chain);
- TAILQ_INSERT_TAIL(&old_waiting, ccb, chain);
- }
+ s = splbio();
+ TAILQ_CONCAT(&old_waiting, &connection->ccbs_waiting, chain);
+ splx(s);
init_sernum(&connection->StatSN_buf);
wakeup(connection);
@@ -789,8 +806,7 @@
DEBOUT(("Login failed (rc %d)\n", rc));
while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
TAILQ_REMOVE(&old_waiting, ccb, chain);
- ccb->status = rc;
- complete_ccb(ccb);
+ wake_ccb(ccb, rc);
}
/* Don't attempt to recover, there seems to be something amiss */
kill_connection(connection, rc, NO_LOGOUT, FALSE);
@@ -800,14 +816,15 @@
DEBC(connection, 9, ("Re-Login successful\n"));
par->status = ISCSI_STATUS_SUCCESS;
- CS_BEGIN;
+
+ s = splbio();
connection->state = ST_FULL_FEATURE;
session->mru_connection = connection;
- CS_END;
+ splx(s);
while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
TAILQ_REMOVE(&old_waiting, ccb, chain);
- TAILQ_INSERT_TAIL(&connection->ccbs_waiting, ccb, chain);
+ suspend_ccb(ccb, TRUE);
rc = send_task_management(connection, ccb, NULL, TASK_REASSIGN);
/* if we get an error on reassign, restart the original request */
@@ -926,7 +943,7 @@
login(iscsi_login_parameters_t *par, PTHREADOBJ p)
{
session_t *session;
- int rc;
+ int rc, s;
DEB(99, ("ISCSI: login\n"));
@@ -967,9 +984,9 @@
return;
}
- CS_BEGIN;
+ s = splbio();
TAILQ_INSERT_HEAD(&iscsi_sessions, session, sessions);
- CS_END;
+ splx(s);
/* Session established, map LUNs? */
if (par->login_type == ISCSI_LOGINTYPE_MAP) {
Index: iscsi_main.c
===================================================================
RCS file: /cvsroot/src/sys/dev/iscsi/iscsi_main.c,v
retrieving revision 1.6
diff -u -r1.6 iscsi_main.c
--- iscsi_main.c 12 Aug 2012 13:26:18 -0000 1.6
+++ iscsi_main.c 11 Sep 2012 19:22:21 -0000
@@ -361,6 +361,7 @@
struct scsipi_xfer *xs;
session_t *session;
int flags;
+ struct scsipi_xfer_mode *xm;
session = (session_t *) adapt; /* adapter is first field in session */
@@ -400,6 +401,9 @@
case ADAPTER_REQ_SET_XFER_MODE:
DEB(5, ("ISCSI: scsipi_request SET_XFER_MODE\n"));
+ xm = (struct scsipi_xfer_mode *)arg;
+ xm->xm_mode |= PERIPH_CAP_TQING;
+ scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
return;
default:
@@ -478,8 +482,6 @@
scsipi_done(xs);
DEB(99, ("scsipi_done returned\n"));
}
-
- free_ccb(ccb);
}
/* Kernel Module support */
Index: iscsi_rcv.c
===================================================================
RCS file: /cvsroot/src/sys/dev/iscsi/iscsi_rcv.c,v
retrieving revision 1.3
diff -u -r1.3 iscsi_rcv.c
--- iscsi_rcv.c 24 Jun 2012 17:01:35 -0000 1.3
+++ iscsi_rcv.c 11 Sep 2012 19:22:22 -0000
@@ -278,7 +278,9 @@
nlen = req_ccb->text_len + pdu->temp_data_len;
/* Note: allocate extra 2 bytes for text terminator */
if ((newp = malloc(nlen + 2, M_TEMP, M_WAITOK)) == NULL) {
+ DEBOUT(("Collect Text Data: Out of Memory, ccb = %p\n", req_ccb));
req_ccb->status = ISCSI_STATUS_NO_RESOURCES;
+ /* XXX where is CCB freed? */
return 1;
}
memcpy(newp, req_ccb->text_data, req_ccb->text_len);
@@ -374,8 +376,7 @@
uint32_t sn = ntohl(nw_sn);
ccb_t *ccb, *nxt;
- for (ccb = TAILQ_FIRST(&conn->ccbs_waiting); ccb != NULL; ccb = nxt) {
- nxt = TAILQ_NEXT(ccb, chain);
+ TAILQ_FOREACH_SAFE(ccb, &conn->ccbs_waiting, chain, nxt) {
DEBC(conn, 10,
("CheckCmdSN - CmdSN=%d, ExpCmdSn=%d, waiting=%p, flags=%x\n",
ccb->CmdSN, sn, ccb->pdu_waiting, ccb->flags));
@@ -429,10 +430,7 @@
DEBC(conn, 1, ("Login problem - Class = %x, Detail = %x\n",
pdu->pdu.p.login_rsp.StatusClass,
pdu->pdu.p.login_rsp.StatusDetail));
-
- req_ccb->status = ISCSI_STATUS_LOGIN_FAILED;
- /* XXX */
- wake_ccb(req_ccb);
+ wake_ccb(req_ccb, ISCSI_STATUS_LOGIN_FAILED);
return 0;
}
@@ -511,6 +509,7 @@
{
bool otherconn;
uint8_t response;
+ uint32_t status;
otherconn = (req_ccb != NULL) ? (req_ccb->flags & CCBF_OTHERCONN) != 0 : 1;
response = pdu->pdu.OpcodeSpecific [0];
@@ -526,16 +525,16 @@
switch (response) {
case 0:
- req_ccb->status = ISCSI_STATUS_SUCCESS;
+ status = ISCSI_STATUS_SUCCESS;
break;
case 1:
- req_ccb->status = ISCSI_STATUS_LOGOUT_CID_NOT_FOUND;
+ status = ISCSI_STATUS_LOGOUT_CID_NOT_FOUND;
break;
case 2:
- req_ccb->status = ISCSI_STATUS_LOGOUT_RECOVERY_NS;
+ status = ISCSI_STATUS_LOGOUT_RECOVERY_NS;
break;
default:
- req_ccb->status = ISCSI_STATUS_LOGOUT_ERROR;
+ status = ISCSI_STATUS_LOGOUT_ERROR;
break;
}
@@ -546,7 +545,7 @@
refconn->Time2Retain = ntohs(pdu->pdu.p.logout_rsp.Time2Retain);
}
- wake_ccb(req_ccb);
+ wake_ccb(req_ccb, status);
if (!otherconn && conn->state == ST_LOGOUT_SENT) {
conn->terminating = ISCSI_STATUS_LOGOUT;
@@ -641,14 +640,13 @@
/* successful transfer, reset recover count */
conn->recover = 0;
- if (done) {
- wake_ccb(req_ccb);
- }
- if (check_StatSN(conn, pdu->pdu.p.data_in.StatSN, done)) {
+ if (done)
+ wake_ccb(req_ccb, ISCSI_STATUS_SUCCESS);
+ if (check_StatSN(conn, pdu->pdu.p.data_in.StatSN, done))
return -1;
- }
+
} else if (done && (req_ccb->flags & CCBF_COMPLETE)) {
- wake_ccb(req_ccb);
+ wake_ccb(req_ccb, ISCSI_STATUS_SUCCESS);
}
/* else wait for command response */
@@ -699,6 +697,7 @@
{
int len, rc;
bool done;
+ uint32_t status;
/* Read any provided data */
if (pdu->temp_data_len && req_ccb != NULL && req_ccb->sense_len_req) {
@@ -726,23 +725,23 @@
conn->recover = 0; /* successful transfer, reset recover count */
if (pdu->pdu.OpcodeSpecific[0]) { /* Response */
- req_ccb->status = ISCSI_STATUS_TARGET_FAILURE;
+ status = ISCSI_STATUS_TARGET_FAILURE;
} else {
switch (pdu->pdu.OpcodeSpecific[1]) { /* Status */
case 0x00:
- /* success */
+ status = ISCSI_STATUS_SUCCESS;
break;
case 0x02:
- req_ccb->status = ISCSI_STATUS_CHECK_CONDITION;
+ status = ISCSI_STATUS_CHECK_CONDITION;
break;
case 0x08:
- req_ccb->status = ISCSI_STATUS_TARGET_BUSY;
+ status = ISCSI_STATUS_TARGET_BUSY;
break;
default:
- req_ccb->status = ISCSI_STATUS_TARGET_ERROR;
+ status = ISCSI_STATUS_TARGET_ERROR;
break;
}
}
@@ -750,7 +749,7 @@
if (pdu->pdu.Flags & (FLAG_OVERFLOW | FLAG_UNDERFLOW))
req_ccb->residual = ntohl(pdu->pdu.p.response.ResidualCount);
- done = req_ccb->status || sn_empty(&req_ccb->DataSN_buf);
+ done = status || sn_empty(&req_ccb->DataSN_buf);
DEBC(conn, 10, ("Rx Command Response rsp = %x, status = %x\n",
pdu->pdu.OpcodeSpecific[0], pdu->pdu.OpcodeSpecific[1]));
@@ -758,7 +757,7 @@
rc = check_StatSN(conn, pdu->pdu.p.response.StatSN, done);
if (done)
- wake_ccb(req_ccb);
+ wake_ccb(req_ccb, status);
return rc;
}
@@ -836,6 +835,7 @@
{
pdu_header_t *hpdu;
ccb_t *req_ccb;
+ uint32_t status;
DEBOUT(("Received Reject PDU, reason = %x, data_len = %d\n",
pdu->pdu.OpcodeSpecific[0], pdu->temp_data_len));
@@ -864,23 +864,23 @@
case REJECT_SNACK:
case REJECT_PROTOCOL_ERROR:
- req_ccb->status = ISCSI_STATUS_PROTOCOL_ERROR;
+ status = ISCSI_STATUS_PROTOCOL_ERROR;
break;
case REJECT_CMD_NOT_SUPPORTED:
- req_ccb->status = ISCSI_STATUS_CMD_NOT_SUPPORTED;
+ status = ISCSI_STATUS_CMD_NOT_SUPPORTED;
break;
case REJECT_INVALID_PDU_FIELD:
- req_ccb->status = ISCSI_STATUS_PDU_ERROR;
+ status = ISCSI_STATUS_PDU_ERROR;
break;
default:
- req_ccb->status = ISCSI_STATUS_GENERAL_ERROR;
+ status = ISCSI_STATUS_GENERAL_ERROR;
break;
}
- wake_ccb(req_ccb);
+ wake_ccb(req_ccb, status);
handle_connection_error(conn, ISCSI_STATUS_PROTOCOL_ERROR,
LOGOUT_CONNECTION);
}
@@ -901,6 +901,7 @@
STATIC int
receive_task_management_pdu(connection_t *conn, pdu_t *pdu, ccb_t *req_ccb)
{
+ uint32_t status;
DEBC(conn, 2, ("Received Task Management PDU, response %d, req_ccb %p\n",
pdu->pdu.OpcodeSpecific[0], req_ccb));
@@ -908,34 +909,34 @@
if (req_ccb != NULL) {
switch (pdu->pdu.OpcodeSpecific[0]) { /* Response */
case 0:
- req_ccb->status = ISCSI_STATUS_SUCCESS;
+ status = ISCSI_STATUS_SUCCESS;
break;
case 1:
- req_ccb->status = ISCSI_STATUS_TASK_NOT_FOUND;
+ status = ISCSI_STATUS_TASK_NOT_FOUND;
break;
case 2:
- req_ccb->status = ISCSI_STATUS_LUN_NOT_FOUND;
+ status = ISCSI_STATUS_LUN_NOT_FOUND;
break;
case 3:
- req_ccb->status = ISCSI_STATUS_TASK_ALLEGIANT;
+ status = ISCSI_STATUS_TASK_ALLEGIANT;
break;
case 4:
- req_ccb->status = ISCSI_STATUS_CANT_REASSIGN;
+ status = ISCSI_STATUS_CANT_REASSIGN;
break;
case 5:
- req_ccb->status = ISCSI_STATUS_FUNCTION_UNSUPPORTED;
+ status = ISCSI_STATUS_FUNCTION_UNSUPPORTED;
break;
case 6:
- req_ccb->status = ISCSI_STATUS_FUNCTION_NOT_AUTHORIZED;
+ status = ISCSI_STATUS_FUNCTION_NOT_AUTHORIZED;
break;
case 255:
- req_ccb->status = ISCSI_STATUS_FUNCTION_REJECTED;
+ status = ISCSI_STATUS_FUNCTION_REJECTED;
break;
default:
- req_ccb->status = ISCSI_STATUS_UNKNOWN_REASON;
+ status = ISCSI_STATUS_UNKNOWN_REASON;
break;
}
- wake_ccb(req_ccb);
+ wake_ccb(req_ccb, status);
}
check_StatSN(conn, pdu->pdu.p.task_rsp.StatSN, TRUE);
@@ -982,7 +983,7 @@
/* and advance StatSN */
check_CmdSN(conn, pdu->pdu.p.nop_in.ExpCmdSN);
- wake_ccb(req_ccb);
+ wake_ccb(req_ccb, ISCSI_STATUS_SUCCESS);
check_StatSN(conn, pdu->pdu.p.nop_in.StatSN, TRUE);
}
@@ -1007,7 +1008,7 @@
{
ccb_t *req_ccb;
ccb_list_t waiting;
- int rc;
+ int rc, s;
uint32_t MaxCmdSN, digest;
session_t *sess = conn->session;
@@ -1131,22 +1132,16 @@
*/
if (MaxCmdSN != sess->MaxCmdSN) {
sess->MaxCmdSN = MaxCmdSN;
-#if 0
-/* XXX - agc */
- if (TAILQ_FIRST(&sess->ccbs_throttled) == NULL ||
- !sn_a_lt_b(sess->CmdSN, MaxCmdSN))
- return 0;
-#else
if (TAILQ_FIRST(&sess->ccbs_throttled) == NULL)
return 0;
-#endif
DEBC(conn, 1, ("Unthrottling - MaxCmdSN = %d\n", MaxCmdSN));
- CS_BEGIN;
TAILQ_INIT(&waiting);
+ s = splbio();
TAILQ_CONCAT(&waiting, &sess->ccbs_throttled, chain);
- CS_END;
+ splx(s);
+
while ((req_ccb = TAILQ_FIRST(&waiting)) != NULL) {
TAILQ_REMOVE(&waiting, req_ccb, chain);
DEBC(conn, 1, ("Unthrottling - ccb = %p, disp = %d\n",
@@ -1181,7 +1176,7 @@
do {
while (!conn->terminating) {
- pdu = get_pdu(conn);
+ pdu = get_pdu(conn, TRUE);
pdu->uio.uio_iov = pdu->io_vec;
UIO_SETUP_SYSSPACE(&pdu->uio);
pdu->uio.uio_iovcnt = 1;
Index: iscsi_send.c
===================================================================
RCS file: /cvsroot/src/sys/dev/iscsi/iscsi_send.c,v
retrieving revision 1.7
diff -u -r1.7 iscsi_send.c
--- iscsi_send.c 9 Sep 2012 06:06:29 -0000 1.7
+++ iscsi_send.c 11 Sep 2012 19:22:22 -0000
@@ -172,7 +172,7 @@
TAILQ_FOREACH(ccb, &oldconn->ccbs_waiting, chain) {
/* Copy PDU contents (PDUs are bound to connection) */
- if ((pdu = get_pdu(conn)) == NULL) {
+ if ((pdu = get_pdu(conn, TRUE)) == NULL) {
break;
}
opdu = ccb->pdu_waiting;
@@ -214,15 +214,14 @@
DEBC(conn, 1, ("Error while copying PDUs in reassign_tasks!\n"));
/* give up recovering, the other connection is screwed up as well... */
while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) {
- ccb->status = oldconn->terminating;
- wake_ccb(ccb);
+ wake_ccb(ccb, oldconn->terminating);
}
return;
}
while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) {
TAILQ_REMOVE(&oldconn->ccbs_waiting, ccb, chain);
- TAILQ_INSERT_TAIL(&conn->ccbs_waiting, ccb, chain);
+ suspend_ccb(ccb, TRUE);
if (!no_tm) {
rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN);
@@ -353,13 +352,11 @@
sounlock((struct socket *) fp->f_data);
/* wake up any non-reassignable waiting CCBs */
- for (ccb = TAILQ_FIRST(&conn->ccbs_waiting); ccb != NULL; ccb = nccb) {
- nccb = TAILQ_NEXT(ccb, chain);
+ TAILQ_FOREACH_SAFE(ccb, &conn->ccbs_waiting, chain, nccb) {
if (!(ccb->flags & CCBF_REASSIGN) || ccb->pdu_waiting == NULL) {
DEBC(conn, 9, ("Terminating CCB %p (t=%p)\n",
ccb,&ccb->timeout));
- ccb->status = conn->terminating;
- wake_ccb(ccb);
+ wake_ccb(ccb, conn->terminating);
} else {
callout_stop(&ccb->timeout);
ccb->num_timeouts = 0;
@@ -377,7 +374,7 @@
}
}
- /* If there's another connection available, transfer pending tasks */
+ /* If there's another connection available, transfer pending tasks */
if (sess->active_connections &&
TAILQ_FIRST(&conn->ccbs_waiting) != NULL) {
reassign_tasks (conn);
@@ -399,8 +396,7 @@
/* wake up any waiting CCBs */
while ((ccb = TAILQ_FIRST(&conn->ccbs_waiting)) != NULL) {
- ccb->status = conn->terminating;
- wake_ccb(ccb);
+ wake_ccb(ccb, conn->terminating);
/* NOTE: wake_ccb will remove the CCB from the queue */
}
@@ -441,6 +437,7 @@
{
connection_t *conn = pdu->connection;
ccb_disp_t prev_cdisp = 0;
+ int s;
if (ccb != NULL) {
prev_cdisp = ccb->disp;
@@ -455,7 +452,7 @@
DEBC(conn, 10, ("Send_pdu: ccb=%p, pcd=%d, cdsp=%d, pdu=%p, pdsp=%d\n",
ccb, prev_cdisp, cdisp, pdu, pdisp));
- CS_BEGIN;
+ s = splbio();
if (pdisp == PDUDISP_WAIT) {
ccb->pdu_waiting = pdu;
@@ -479,12 +476,12 @@
SET_CCB_TIMEOUT(conn, ccb, COMMAND_TIMEOUT);
if (prev_cdisp <= CCBDISP_NOWAIT)
- TAILQ_INSERT_TAIL(&conn->ccbs_waiting, ccb, chain);
+ suspend_ccb(ccb, TRUE);
if (cdisp == CCBDISP_WAIT)
tsleep(ccb, PWAIT, "sendpdu", 0);
}
- CS_END;
+ splx(s);
}
@@ -671,11 +668,11 @@
set_negotiated_parameters(tx_ccb);
DEBC(conn, 5, ("Login Successful!\n"));
- wake_ccb(tx_ccb);
+ wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
return;
}
- tx_pdu = get_pdu(conn);
+ tx_pdu = get_pdu(conn, TRUE);
if (tx_pdu == NULL)
return;
@@ -699,8 +696,7 @@
}
if (rc > 0) {
- tx_ccb->status = rc;
- wake_ccb(tx_ccb);
+ wake_ccb(tx_ccb, rc);
free_pdu(tx_pdu);
} else {
init_login_pdu(conn, tx_pdu, next);
@@ -754,7 +750,7 @@
{
pdu_t *tx_pdu;
- tx_pdu = get_pdu(conn);
+ tx_pdu = get_pdu(conn, TRUE);
if (tx_pdu == NULL)
return;
@@ -786,7 +782,7 @@
ccb = get_ccb(conn, TRUE);
if (ccb == NULL)
return;
- pdu = get_pdu(conn);
+ pdu = get_pdu(conn, TRUE);
if (pdu == NULL) {
free_ccb(ccb);
return;
@@ -830,10 +826,10 @@
tx_ccb->text_data = rx_pdu->temp_data;
tx_ccb->text_len = rx_pdu->temp_data_len;
rx_pdu->temp_data = NULL;
- wake_ccb(tx_ccb);
+ wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
} else {
if (!(rx_pdu->pdu.Flags & FLAG_FINAL))
- tx_pdu = get_pdu(conn);
+ tx_pdu = get_pdu(conn, TRUE);
else
tx_pdu = NULL;
@@ -850,7 +846,7 @@
send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE);
} else {
set_negotiated_parameters(tx_ccb);
- wake_ccb(tx_ccb);
+ wake_ccb(tx_ccb, ISCSI_STATUS_SUCCESS);
}
}
}
@@ -886,7 +882,7 @@
ccb = get_ccb(conn, TRUE);
if (ccb == NULL)
return conn->terminating;
- pdu = get_pdu(conn);
+ pdu = get_pdu(conn, TRUE);
if (pdu == NULL) {
free_ccb(ccb);
return conn->terminating;
@@ -939,7 +935,7 @@
if (rx_pdu != NULL) {
ccb = NULL;
- ppdu = get_pdu(conn);
+ ppdu = get_pdu(conn, TRUE);
if (ppdu == NULL)
return 1;
} else {
@@ -948,7 +944,7 @@
DEBOUT(("Can't get CCB in send_nop_out\n"));
return 1;
}
- ppdu = get_pdu_c(conn, FALSE);
+ ppdu = get_pdu(conn, FALSE);
if (ppdu == NULL) {
free_ccb(ccb);
DEBOUT(("Can't get PDU in send_nop_out\n"));
@@ -1001,7 +997,7 @@
PDEBC(conn, 1, ("SNACK Missing type = %d, BegRun %d RunLength %d\n",
type, BegRun, RunLength));
- ppdu = get_pdu(conn);
+ ppdu = get_pdu(conn, TRUE);
if (ppdu == NULL)
return;
pdu = &ppdu->pdu;
@@ -1041,7 +1037,7 @@
PDEBC(conn, 1, ("Send SNACK type = %d\n", type));
- ppdu = get_pdu(conn);
+ ppdu = get_pdu(conn, TRUE);
if (ppdu == NULL)
return;
pdu = &ppdu->pdu;
@@ -1108,7 +1104,7 @@
/* only if terminating (which couldn't possibly happen here, but...) */
if (ccb == NULL)
return conn->terminating;
- pdu = get_pdu(conn);
+ pdu = get_pdu(conn, TRUE);
if (pdu == NULL) {
free_ccb(ccb);
return conn->terminating;
@@ -1154,7 +1150,7 @@
/* can only happen if terminating... */
if (ccb == NULL)
return conn->terminating;
- ppdu = get_pdu(conn);
+ ppdu = get_pdu(conn, TRUE);
if (ppdu == NULL) {
free_ccb(ccb);
return conn->terminating;
@@ -1221,7 +1217,7 @@
/* can only happen if terminating... */
if (ccb == NULL)
return conn->terminating;
- ppdu = get_pdu(conn);
+ ppdu = get_pdu(conn, TRUE);
if (ppdu == NULL) {
free_ccb(ccb);
return conn->terminating;
@@ -1290,7 +1286,7 @@
while (totlen) {
len = min(totlen, conn->max_transfer);
- tx_pdu = get_pdu_c(conn, waitok);
+ tx_pdu = get_pdu(conn, waitok);
if (tx_pdu == NULL) {
DEBOUT(("No PDU in send_data_out\n"));
@@ -1351,52 +1347,41 @@
PERF_BEGIN(ccb, !waitok);
- if (!waitok) {
- s = splbio();
- if (/*CONSTCOND*/ISCSI_TROTTLING_ENABLED &&
- /*CONSTCOND*/ISCSI_SERVER_TRUSTED &&
- !sn_a_le_b(sess->CmdSN, sess->MaxCmdSN)) {
- ccb->disp = disp;
- TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain);
- splx(s);
- PDEBOUT(("Throttling S - CmdSN = %d, MaxCmdSN = %d\n",
- sess->CmdSN, sess->MaxCmdSN));
- return;
- }
- splx(s);
- ppdu = get_pdu_c(conn, FALSE);
- if (ppdu == NULL) {
- ccb->status = ISCSI_STATUS_NO_RESOURCES;
- iscsi_done(ccb);
- return;
- }
- } else {
- s = splbio();
- while (/*CONSTCOND*/ISCSI_TROTTLING_ENABLED &&
- /*CONSTCOND*/ISCSI_SERVER_TRUSTED &&
- !sn_a_le_b(sess->CmdSN, sess->MaxCmdSN)) {
- ccb->disp = disp;
+ s = splbio();
+ if (/*CONSTCOND*/ISCSI_THROTTLING_ENABLED &&
+ /*CONSTCOND*/ISCSI_SERVER_TRUSTED &&
+ !sn_a_le_b(sess->CmdSN, sess->MaxCmdSN)) {
+
+ ccb->disp = disp;
+ if (waitok)
ccb->flags |= CCBF_WAITING;
- TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain);
- PDEBOUT(("Throttling W - CmdSN = %d, MaxCmdSN = %d\n",
- sess->CmdSN, sess->MaxCmdSN));
+ throttle_ccb(ccb, TRUE);
+
+ PDEBOUT(("Throttling S - CmdSN = %d, MaxCmdSN = %d\n",
+ sess->CmdSN, sess->MaxCmdSN));
+ if (waitok)
tsleep(ccb, PWAIT, "waitMaxCmd", 0);
- splbio();
- }
+
splx(s);
- ppdu = get_pdu(conn);
+ return;
}
+ splx(s);
+ ppdu = get_pdu(conn, FALSE);
+ if (ppdu == NULL) {
+ wake_ccb(ccb, ISCSI_STATUS_NO_RESOURCES);
+ return;
+ }
+
+ totlen = len = ccb->data_len;
pdu = &ppdu->pdu;
pdu->LUN = htonq(ccb->lun);
memcpy(pdu->p.command.SCSI_CDB, ccb->cmd, ccb->cmdlen);
- totlen = len = ccb->data_len;
pdu->Opcode = IOP_SCSI_Command;
if (immed)
pdu->Opcode |= OP_IMMEDIATE;
pdu->p.command.ExpectedDataTransferLength = htonl(totlen);
-
if (totlen) {
if (ccb->data_in) {
pdu->Flags = FLAG_READ;
@@ -1436,7 +1421,6 @@
PERF_PDUSET(ppdu, ccb, PERF_BEGIN_PDUWRITECMD);
setup_tx_uio(ppdu, len, ccb->data_ptr, ccb->data_in);
-
send_pdu(ccb, ppdu, (totlen) ? CCBDISP_DEFER : disp, PDUDISP_WAIT);
if (totlen)
@@ -1634,9 +1618,8 @@
ccb->total_tries > MAX_CCB_TRIES ||
ccb->disp <= CCBDISP_FREE ||
!ccb->session->ErrorRecoveryLevel) {
- ccb->status = ISCSI_STATUS_TIMEOUT;
- complete_ccb(ccb);
+ wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, RECOVER_CONNECTION);
} else {
if (ccb->data_in && ccb->xfer_len < ccb->data_len) {
Index: iscsi_test.c
===================================================================
RCS file: /cvsroot/src/sys/dev/iscsi/iscsi_test.c,v
retrieving revision 1.2
diff -u -r1.2 iscsi_test.c
--- iscsi_test.c 29 Nov 2011 03:50:31 -0000 1.2
+++ iscsi_test.c 11 Sep 2012 19:22:22 -0000
@@ -294,7 +294,7 @@
{
mod_desc_t *mod;
uint32_t mpoff, off;
- int i, rc = 0;
+ int i, rc = 0, s;
tp->pdu_count[kind][rxtx]++;
tp->pdu_count[ANY_PDU][rxtx]++;
@@ -363,9 +363,10 @@
if (!off || (mpoff != 0 && mpoff < off)) {
/* This might happen in some cases. Just discard the modification. */
- CS_BEGIN;
+ s = splbio();
TAILQ_REMOVE(&tp->mods, mod, link);
- CS_END;
+ splx(s);
+
update_options(tp, mod);
if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) {
@@ -413,8 +414,7 @@
if (ccb != NULL &&
(ccb->disp == CCBDISP_WAIT || ccb->disp == CCBDISP_SCSIPI)) {
/* simulate timeout */
- ccb->status = ISCSI_STATUS_TIMEOUT;
- wake_ccb(ccb);
+ wake_ccb(ccb, ISCSI_STATUS_TIMEOUT);
}
}
@@ -436,14 +436,13 @@
}
}
- CS_BEGIN;
+ s = splbio();
TAILQ_REMOVE(&tp->mods, mod, link);
-
update_options(tp, mod);
-
/* we've modified a PDU - copy current count into last count */
memcpy(tp->pdu_last, tp->pdu_count, sizeof(tp->pdu_last));
- CS_END;
+ splx(s);
+
if (mod->pars.options & ISCSITEST_OPT_WAIT_FOR_COMPLETION) {
wakeup(mod);
}
@@ -941,6 +940,7 @@
test_cancel(iscsi_test_cancel_parameters_t *par)
{
test_pars_t *tp;
+ int s;
if ((tp = find_test_id(par->test_id)) == NULL) {
par->status = ISCSI_STATUS_INVALID_ID;
@@ -948,11 +948,12 @@
}
DEB(1, ("Test Cancel, id %d\n", par->test_id));
- CS_BEGIN;
+ s = splbio();
if (tp->connection)
tp->connection->test_pars = NULL;
TAILQ_REMOVE(&test_list, tp, link);
- CS_END;
+ splx(s);
+
free_negs(tp);
free_mods(tp, ISCSI_STATUS_TEST_CANCELED);
free(tp, M_TEMP);
@@ -980,6 +981,7 @@
void *pdu_ptr = par->pdu_ptr;
struct uio *uio;
uint32_t i, pad, dsl, size;
+ int s;
if ((tp = find_test_id(par->test_id)) == NULL) {
par->status = ISCSI_STATUS_INVALID_ID;
@@ -994,7 +996,7 @@
par->status = ISCSI_STATUS_TEST_INACTIVE;
return;
}
- if ((pdu = get_pdu(conn)) == NULL) {
+ if ((pdu = get_pdu(conn, TRUE)) == NULL) {
par->status = ISCSI_STATUS_TEST_CONNECTION_CLOSED;
return;
}
@@ -1068,8 +1070,8 @@
pdu->disp = PDUDISP_SIGNAL;
pdu->flags = PDUF_BUSY | PDUF_NOUPDATE;
- CS_BEGIN;
- /* Enqueue for sending */
+ s = splbio();
+ /* Enqueue for sending */
if (pdu->pdu.Opcode & OP_IMMEDIATE)
TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain);
else
@@ -1077,7 +1079,8 @@
wakeup(&conn->pdus_to_send);
tsleep(pdu, PINOD, "test_send_pdu", 0);
- CS_END;
+ splx(s);
+
unmap_databuf(p, pdu_ptr, psize);
par->status = ISCSI_STATUS_SUCCESS;
if (par->options & ISCSITEST_KILL_CONNECTION)
Index: iscsi_utils.c
===================================================================
RCS file: /cvsroot/src/sys/dev/iscsi/iscsi_utils.c,v
retrieving revision 1.4
diff -u -r1.4 iscsi_utils.c
--- iscsi_utils.c 25 Jun 2012 20:34:26 -0000 1.4
+++ iscsi_utils.c 11 Sep 2012 19:22:22 -0000
@@ -219,14 +219,15 @@
{
ccb_t *ccb;
session_t *sess = conn->session;
+ int s;
do {
- CS_BEGIN;
+ s = splbio();
ccb = TAILQ_FIRST(&sess->ccb_pool);
- if (ccb != NULL) {
+ if (ccb != NULL)
TAILQ_REMOVE(&sess->ccb_pool, ccb, chain);
- }
- CS_END;
+ s = splx(s);
+
DEB(100, ("get_ccb: ccb = %p, waitok = %d\n", ccb, waitok));
if (ccb == NULL) {
if (!waitok || conn->terminating) {
@@ -262,6 +263,9 @@
{
session_t *sess = ccb->session;
pdu_t *pdu;
+ int s;
+
+ KASSERT((ccb->flags & (CCBF_THROTTLING|CCBF_WAITQUEUE)) == 0);
ccb->connection->usecount--;
ccb->connection = NULL;
@@ -281,9 +285,10 @@
free_pdu(pdu);
}
- CS_BEGIN;
+ s = splbio();
TAILQ_INSERT_TAIL(&sess->ccb_pool, ccb, chain);
- CS_END;
+ splx(s);
+
wakeup(&sess->ccb_pool);
}
@@ -319,132 +324,128 @@
}
}
-
/*
- * wake_ccb:
- * Wake up (or dispose of) a CCB. Depending on the CCB's disposition,
- * either wake up the requesting thread, signal SCSIPI that we're done,
- * or just free the CCB for CCBDISP_FREE.
- *
- * Parameter: The CCB to handle.
+ * suspend_ccb:
+ * Put CCB on wait queue
*/
-
void
-wake_ccb(ccb_t *ccb)
+suspend_ccb(ccb_t *ccb, bool yes)
{
- ccb_disp_t disp;
connection_t *conn;
int s;
-#ifdef ISCSI_DEBUG
- static ccb_t *lastccb = NULL;
- static int lastdisp = -1;
-#endif
-
- /* Just in case */
- if (ccb == NULL)
- return;
conn = ccb->connection;
-
-#ifdef ISCSI_DEBUG
- if (ccb != lastccb || ccb->disp != lastdisp) {
- DEBC(conn, 9, ("Wake CCB, ccb = %p, disp = %d\n",
- ccb, (ccb) ? ccb->disp : 0));
- lastccb = ccb;
- lastdisp = (ccb) ? ccb->disp : 0;
- }
-#endif
-
- callout_stop(&ccb->timeout);
-
s = splbio();
- disp = ccb->disp;
- if (disp <= CCBDISP_NOWAIT ||
- (disp == CCBDISP_DEFER && conn->state <= ST_WINDING_DOWN)) {
- splx(s);
- return;
+ if (yes) {
+ KASSERT((ccb->flags & (CCBF_THROTTLING|CCBF_WAITQUEUE)) == 0);
+ TAILQ_INSERT_TAIL(&conn->ccbs_waiting, ccb, chain);
+ ccb->flags |= CCBF_WAITQUEUE;
+ } else if (ccb->flags & CCBF_WAITQUEUE) {
+ KASSERT((ccb->flags & CCBF_THROTTLING) == 0);
+ TAILQ_REMOVE(&conn->ccbs_waiting, ccb, chain);
+ ccb->flags &= ~CCBF_WAITQUEUE;
}
-
- TAILQ_REMOVE(&conn->ccbs_waiting, ccb, chain);
-
- /* change the disposition so nobody tries this again */
- ccb->disp = CCBDISP_BUSY;
splx(s);
+}
- PERF_END(ccb);
-
- switch (disp) {
- case CCBDISP_WAIT:
- wakeup(ccb);
- break;
-
- case CCBDISP_SCSIPI:
- iscsi_done(ccb);
- break;
-
- case CCBDISP_DEFER:
- break;
+/*
+ * throttle_ccb:
+ * Put CCB on throttling queue
+ */
+void
+throttle_ccb(ccb_t *ccb, bool yes)
+{
+ session_t *sess;
+ int s;
- default:
- free_ccb(ccb);
- break;
+ sess = ccb->session;
+ s = splbio();
+ if (yes) {
+ KASSERT((ccb->flags & (CCBF_THROTTLING|CCBF_WAITQUEUE)) == 0);
+ TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain);
+ ccb->flags |= CCBF_THROTTLING;
+ } else if (ccb->flags & CCBF_THROTTLING) {
+ KASSERT((ccb->flags & CCBF_WAITQUEUE) == 0);
+ TAILQ_REMOVE(&sess->ccbs_throttled, ccb, chain);
+ ccb->flags &= ~CCBF_THROTTLING;
}
+ splx(s);
}
/*
- * complete_ccb:
- * Same as wake_ccb, but the CCB is not assumed to be in the waiting list.
+ * wake_ccb:
+ * Wake up (or dispose of) a CCB. Depending on the CCB's disposition,
+ * either wake up the requesting thread, signal SCSIPI that we're done,
+ * or just free the CCB for CCBDISP_FREE.
*
- * Parameter: The CCB to handle.
+ * Parameter: The CCB to handle and the new status of the CCB
*/
void
-complete_ccb(ccb_t *ccb)
+wake_ccb(ccb_t *ccb, uint32_t status)
{
ccb_disp_t disp;
+ connection_t *conn;
int s;
- /* Just in case */
- if (ccb == NULL)
- return;
+ conn = ccb->connection;
+
+#ifdef ISCSI_DEBUG
+ DEBC(conn, 9, ("CCB done, ccb = %p, disp = %d\n",
+ ccb, ccb->disp));
+#endif
callout_stop(&ccb->timeout);
s = splbio();
disp = ccb->disp;
- if (disp <= CCBDISP_NOWAIT || disp == CCBDISP_DEFER) {
+ if (disp <= CCBDISP_NOWAIT ||
+ (disp == CCBDISP_DEFER && conn->state <= ST_WINDING_DOWN)) {
splx(s);
return;
}
+
+ suspend_ccb(ccb, FALSE);
+ throttle_ccb(ccb, FALSE);
+
/* change the disposition so nobody tries this again */
ccb->disp = CCBDISP_BUSY;
+ ccb->status = status;
splx(s);
PERF_END(ccb);
switch (disp) {
+ case CCBDISP_FREE:
+ free_ccb(ccb);
+ break;
+
case CCBDISP_WAIT:
wakeup(ccb);
break;
case CCBDISP_SCSIPI:
iscsi_done(ccb);
+ free_ccb(ccb);
+ break;
+
+ case CCBDISP_DEFER:
break;
default:
+ DEBC(conn, 1, ("CCB done, ccb = %p, invalid disposition %d", ccb, disp));
free_ccb(ccb);
break;
}
}
-
/*****************************************************************************
* PDU management functions
*****************************************************************************/
/*
- * get_pdu_c:
+ * get_pdu:
* Get a PDU for the SCSI operation.
*
* Parameter:
@@ -455,17 +456,18 @@
*/
pdu_t *
-get_pdu_c(connection_t *conn, bool waitok)
+get_pdu(connection_t *conn, bool waitok)
{
pdu_t *pdu;
+ int s;
do {
- CS_BEGIN;
+ s = splbio();
pdu = TAILQ_FIRST(&conn->pdu_pool);
- if (pdu != NULL) {
+ if (pdu != NULL)
TAILQ_REMOVE(&conn->pdu_pool, pdu, chain);
- }
- CS_END;
+ splx(s);
+
DEB(100, ("get_pdu_c: pdu = %p, waitok = %d\n", pdu, waitok));
if (pdu == NULL) {
if (!waitok || conn->terminating)
@@ -483,46 +485,6 @@
}
/*
- * get_pdu:
- * Get a PDU for the SCSI operation, waits if none is available.
- * Same as get_pdu_c, but with wait always OK.
- * Duplicated code because this is the more common case.
- *
- * Parameter: The connection this PDU should be associated with.
- *
- * Returns: The PDU.
- */
-
-pdu_t *
-get_pdu(connection_t *conn)
-{
- pdu_t *pdu;
-
- do {
- CS_BEGIN;
- pdu = TAILQ_FIRST(&conn->pdu_pool);
- if (pdu != NULL) {
- TAILQ_REMOVE(&conn->pdu_pool, pdu, chain);
- }
- CS_END;
- DEB(100, ("get_pdu: pdu = %p\n", pdu));
- if (pdu == NULL) {
- if (conn->terminating)
- return NULL;
-
- PDEBOUT(("Waiting for PDU!\n"));
- tsleep(&conn->pdu_pool, PWAIT, "get_pdu", 0);
- }
- } while (pdu == NULL);
-
- memset(pdu, 0, sizeof(pdu_t));
- pdu->connection = conn;
- pdu->disp = PDUDISP_FREE;
-
- return pdu;
-}
-
-/*
* free_pdu:
* Put a PDU back onto the free list.
*
@@ -534,6 +496,7 @@
{
connection_t *conn = pdu->connection;
pdu_disp_t pdisp;
+ int s;
if (PDUDISP_UNUSED == (pdisp = pdu->disp))
return;
@@ -551,9 +514,10 @@
if (pdu->temp_data)
free(pdu->temp_data, M_TEMP);
- CS_BEGIN;
+ s = splbio();
TAILQ_INSERT_TAIL(&conn->pdu_pool, pdu, chain);
- CS_END;
+ splx(s);
+
wakeup(&conn->pdu_pool);
}