iscsi: Remove icl_soft-only fields from struct icl_conn.
Create a struct icl_soft_conn which extends struct icl_conn and move fields only used by icl_soft from struct icl_conn to struct icl_soft_conn. Reviewed by: mav Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D31414
This commit is contained in:
parent
383dbdb2eb
commit
87322a9075
@ -569,10 +569,6 @@ icl_cxgbei_new_conn(const char *name, struct mtx *lock)
|
|||||||
ic = &icc->ic;
|
ic = &icc->ic;
|
||||||
ic->ic_lock = lock;
|
ic->ic_lock = lock;
|
||||||
|
|
||||||
/* XXXNP: review. Most of these icl_conn fields aren't really used */
|
|
||||||
STAILQ_INIT(&ic->ic_to_send);
|
|
||||||
cv_init(&ic->ic_send_cv, "icl_cxgbei_tx");
|
|
||||||
cv_init(&ic->ic_receive_cv, "icl_cxgbei_rx");
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
refcount_init(&ic->ic_outstanding_pdus, 0);
|
refcount_init(&ic->ic_outstanding_pdus, 0);
|
||||||
#endif
|
#endif
|
||||||
@ -594,9 +590,6 @@ icl_cxgbei_conn_free(struct icl_conn *ic)
|
|||||||
|
|
||||||
CTR2(KTR_CXGBE, "%s: icc %p", __func__, icc);
|
CTR2(KTR_CXGBE, "%s: icc %p", __func__, icc);
|
||||||
|
|
||||||
cv_destroy(&ic->ic_send_cv);
|
|
||||||
cv_destroy(&ic->ic_receive_cv);
|
|
||||||
|
|
||||||
mtx_destroy(&icc->cmp_lock);
|
mtx_destroy(&icc->cmp_lock);
|
||||||
hashdestroy(icc->cmp_table, M_CXGBEI, icc->cmp_hash_mask);
|
hashdestroy(icc->cmp_table, M_CXGBEI, icc->cmp_hash_mask);
|
||||||
kobj_delete((struct kobj *)icc, M_CXGBE);
|
kobj_delete((struct kobj *)icc, M_CXGBE);
|
||||||
@ -864,10 +857,6 @@ icl_cxgbei_conn_close(struct icl_conn *ic)
|
|||||||
}
|
}
|
||||||
ic->ic_disconnecting = true;
|
ic->ic_disconnecting = true;
|
||||||
|
|
||||||
/* These are unused in this driver right now. */
|
|
||||||
MPASS(STAILQ_EMPTY(&ic->ic_to_send));
|
|
||||||
MPASS(ic->ic_receive_pdu == NULL);
|
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
KASSERT(ic->ic_outstanding_pdus == 0,
|
KASSERT(ic->ic_outstanding_pdus == 0,
|
||||||
("destroying session with %d outstanding PDUs",
|
("destroying session with %d outstanding PDUs",
|
||||||
|
@ -82,13 +82,6 @@ struct icl_pdu {
|
|||||||
void *ip_prv1;
|
void *ip_prv1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ICL_CONN_STATE_INVALID 0
|
|
||||||
#define ICL_CONN_STATE_BHS 1
|
|
||||||
#define ICL_CONN_STATE_AHS 2
|
|
||||||
#define ICL_CONN_STATE_HEADER_DIGEST 3
|
|
||||||
#define ICL_CONN_STATE_DATA 4
|
|
||||||
#define ICL_CONN_STATE_DATA_DIGEST 5
|
|
||||||
|
|
||||||
#define ICL_NOCOPY (1 << 30)
|
#define ICL_NOCOPY (1 << 30)
|
||||||
|
|
||||||
struct icl_conn {
|
struct icl_conn {
|
||||||
@ -98,20 +91,11 @@ struct icl_conn {
|
|||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
volatile u_int ic_outstanding_pdus;
|
volatile u_int ic_outstanding_pdus;
|
||||||
#endif
|
#endif
|
||||||
STAILQ_HEAD(, icl_pdu) ic_to_send;
|
|
||||||
bool ic_check_send_space;
|
|
||||||
size_t ic_receive_len;
|
|
||||||
int ic_receive_state;
|
|
||||||
struct icl_pdu *ic_receive_pdu;
|
|
||||||
struct cv ic_send_cv;
|
|
||||||
struct cv ic_receive_cv;
|
|
||||||
bool ic_header_crc32c;
|
|
||||||
bool ic_data_crc32c;
|
|
||||||
bool ic_send_running;
|
|
||||||
bool ic_receive_running;
|
|
||||||
uint32_t ic_max_recv_data_segment_length;
|
uint32_t ic_max_recv_data_segment_length;
|
||||||
uint32_t ic_max_send_data_segment_length;
|
uint32_t ic_max_send_data_segment_length;
|
||||||
size_t ic_maxtags;
|
size_t ic_maxtags;
|
||||||
|
bool ic_header_crc32c;
|
||||||
|
bool ic_data_crc32c;
|
||||||
bool ic_disconnecting;
|
bool ic_disconnecting;
|
||||||
bool ic_iser;
|
bool ic_iser;
|
||||||
bool ic_unmapped;
|
bool ic_unmapped;
|
||||||
|
@ -63,6 +63,27 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <dev/iscsi/iscsi_proto.h>
|
#include <dev/iscsi/iscsi_proto.h>
|
||||||
#include <icl_conn_if.h>
|
#include <icl_conn_if.h>
|
||||||
|
|
||||||
|
#define ICL_CONN_STATE_BHS 1
|
||||||
|
#define ICL_CONN_STATE_AHS 2
|
||||||
|
#define ICL_CONN_STATE_HEADER_DIGEST 3
|
||||||
|
#define ICL_CONN_STATE_DATA 4
|
||||||
|
#define ICL_CONN_STATE_DATA_DIGEST 5
|
||||||
|
|
||||||
|
struct icl_soft_conn {
|
||||||
|
struct icl_conn ic;
|
||||||
|
|
||||||
|
/* soft specific stuff goes here. */
|
||||||
|
STAILQ_HEAD(, icl_pdu) to_send;
|
||||||
|
struct cv send_cv;
|
||||||
|
struct cv receive_cv;
|
||||||
|
struct icl_pdu *receive_pdu;
|
||||||
|
size_t receive_len;
|
||||||
|
int receive_state;
|
||||||
|
bool receive_running;
|
||||||
|
bool check_send_space;
|
||||||
|
bool send_running;
|
||||||
|
};
|
||||||
|
|
||||||
struct icl_soft_pdu {
|
struct icl_soft_pdu {
|
||||||
struct icl_pdu ip;
|
struct icl_pdu ip;
|
||||||
|
|
||||||
@ -150,7 +171,7 @@ static kobj_method_t icl_soft_methods[] = {
|
|||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_CLASS(icl_soft, icl_soft_methods, sizeof(struct icl_conn));
|
DEFINE_CLASS(icl_soft, icl_soft_methods, sizeof(struct icl_soft_conn));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
icl_conn_fail(struct icl_conn *ic)
|
icl_conn_fail(struct icl_conn *ic)
|
||||||
@ -441,14 +462,14 @@ static int
|
|||||||
icl_pdu_receive_data_segment(struct icl_pdu *request, struct mbuf **r,
|
icl_pdu_receive_data_segment(struct icl_pdu *request, struct mbuf **r,
|
||||||
size_t *rs, bool *more_neededp)
|
size_t *rs, bool *more_neededp)
|
||||||
{
|
{
|
||||||
struct icl_conn *ic;
|
struct icl_soft_conn *isc;
|
||||||
size_t len, padding = 0;
|
size_t len, padding = 0;
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
|
|
||||||
ic = request->ip_conn;
|
isc = (struct icl_soft_conn *)request->ip_conn;
|
||||||
|
|
||||||
*more_neededp = false;
|
*more_neededp = false;
|
||||||
ic->ic_receive_len = 0;
|
isc->receive_len = 0;
|
||||||
|
|
||||||
len = icl_pdu_data_segment_length(request);
|
len = icl_pdu_data_segment_length(request);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
@ -497,8 +518,7 @@ icl_pdu_receive_data_segment(struct icl_pdu *request, struct mbuf **r,
|
|||||||
ICL_DEBUG("len 0");
|
ICL_DEBUG("len 0");
|
||||||
|
|
||||||
if (*more_neededp)
|
if (*more_neededp)
|
||||||
ic->ic_receive_len =
|
isc->receive_len = icl_pdu_data_segment_receive_len(request);
|
||||||
icl_pdu_data_segment_receive_len(request);
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -537,16 +557,17 @@ icl_pdu_check_data_digest(struct icl_pdu *request, struct mbuf **r, size_t *rs)
|
|||||||
* "part" of PDU at a time; call it repeatedly until it returns non-NULL.
|
* "part" of PDU at a time; call it repeatedly until it returns non-NULL.
|
||||||
*/
|
*/
|
||||||
static struct icl_pdu *
|
static struct icl_pdu *
|
||||||
icl_conn_receive_pdu(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
icl_conn_receive_pdu(struct icl_soft_conn *isc, struct mbuf **r, size_t *rs)
|
||||||
{
|
{
|
||||||
|
struct icl_conn *ic = &isc->ic;
|
||||||
struct icl_pdu *request;
|
struct icl_pdu *request;
|
||||||
size_t len;
|
size_t len;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
bool more_needed;
|
bool more_needed;
|
||||||
|
|
||||||
if (ic->ic_receive_state == ICL_CONN_STATE_BHS) {
|
if (isc->receive_state == ICL_CONN_STATE_BHS) {
|
||||||
KASSERT(ic->ic_receive_pdu == NULL,
|
KASSERT(isc->receive_pdu == NULL,
|
||||||
("ic->ic_receive_pdu != NULL"));
|
("isc->receive_pdu != NULL"));
|
||||||
request = icl_soft_conn_new_pdu(ic, M_NOWAIT);
|
request = icl_soft_conn_new_pdu(ic, M_NOWAIT);
|
||||||
if (request == NULL) {
|
if (request == NULL) {
|
||||||
ICL_DEBUG("failed to allocate PDU; "
|
ICL_DEBUG("failed to allocate PDU; "
|
||||||
@ -554,14 +575,14 @@ icl_conn_receive_pdu(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
icl_conn_fail(ic);
|
icl_conn_fail(ic);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
ic->ic_receive_pdu = request;
|
isc->receive_pdu = request;
|
||||||
} else {
|
} else {
|
||||||
KASSERT(ic->ic_receive_pdu != NULL,
|
KASSERT(isc->receive_pdu != NULL,
|
||||||
("ic->ic_receive_pdu == NULL"));
|
("isc->receive_pdu == NULL"));
|
||||||
request = ic->ic_receive_pdu;
|
request = isc->receive_pdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ic->ic_receive_state) {
|
switch (isc->receive_state) {
|
||||||
case ICL_CONN_STATE_BHS:
|
case ICL_CONN_STATE_BHS:
|
||||||
//ICL_DEBUG("receiving BHS");
|
//ICL_DEBUG("receiving BHS");
|
||||||
icl_soft_receive_buf(r, rs, request->ip_bhs,
|
icl_soft_receive_buf(r, rs, request->ip_bhs,
|
||||||
@ -581,18 +602,18 @@ icl_conn_receive_pdu(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ic->ic_receive_state = ICL_CONN_STATE_AHS;
|
isc->receive_state = ICL_CONN_STATE_AHS;
|
||||||
ic->ic_receive_len = icl_pdu_ahs_length(request);
|
isc->receive_len = icl_pdu_ahs_length(request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICL_CONN_STATE_AHS:
|
case ICL_CONN_STATE_AHS:
|
||||||
//ICL_DEBUG("receiving AHS");
|
//ICL_DEBUG("receiving AHS");
|
||||||
icl_pdu_receive_ahs(request, r, rs);
|
icl_pdu_receive_ahs(request, r, rs);
|
||||||
ic->ic_receive_state = ICL_CONN_STATE_HEADER_DIGEST;
|
isc->receive_state = ICL_CONN_STATE_HEADER_DIGEST;
|
||||||
if (ic->ic_header_crc32c == false)
|
if (ic->ic_header_crc32c == false)
|
||||||
ic->ic_receive_len = 0;
|
isc->receive_len = 0;
|
||||||
else
|
else
|
||||||
ic->ic_receive_len = ISCSI_HEADER_DIGEST_SIZE;
|
isc->receive_len = ISCSI_HEADER_DIGEST_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICL_CONN_STATE_HEADER_DIGEST:
|
case ICL_CONN_STATE_HEADER_DIGEST:
|
||||||
@ -604,9 +625,8 @@ icl_conn_receive_pdu(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ic->ic_receive_state = ICL_CONN_STATE_DATA;
|
isc->receive_state = ICL_CONN_STATE_DATA;
|
||||||
ic->ic_receive_len =
|
isc->receive_len = icl_pdu_data_segment_receive_len(request);
|
||||||
icl_pdu_data_segment_receive_len(request);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICL_CONN_STATE_DATA:
|
case ICL_CONN_STATE_DATA:
|
||||||
@ -622,11 +642,11 @@ icl_conn_receive_pdu(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
if (more_needed)
|
if (more_needed)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ic->ic_receive_state = ICL_CONN_STATE_DATA_DIGEST;
|
isc->receive_state = ICL_CONN_STATE_DATA_DIGEST;
|
||||||
if (request->ip_data_len == 0 || ic->ic_data_crc32c == false)
|
if (request->ip_data_len == 0 || ic->ic_data_crc32c == false)
|
||||||
ic->ic_receive_len = 0;
|
isc->receive_len = 0;
|
||||||
else
|
else
|
||||||
ic->ic_receive_len = ISCSI_DATA_DIGEST_SIZE;
|
isc->receive_len = ISCSI_DATA_DIGEST_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ICL_CONN_STATE_DATA_DIGEST:
|
case ICL_CONN_STATE_DATA_DIGEST:
|
||||||
@ -642,18 +662,18 @@ icl_conn_receive_pdu(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
* We've received complete PDU; reset the receive state machine
|
* We've received complete PDU; reset the receive state machine
|
||||||
* and return the PDU.
|
* and return the PDU.
|
||||||
*/
|
*/
|
||||||
ic->ic_receive_state = ICL_CONN_STATE_BHS;
|
isc->receive_state = ICL_CONN_STATE_BHS;
|
||||||
ic->ic_receive_len = sizeof(struct iscsi_bhs);
|
isc->receive_len = sizeof(struct iscsi_bhs);
|
||||||
ic->ic_receive_pdu = NULL;
|
isc->receive_pdu = NULL;
|
||||||
return (request);
|
return (request);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("invalid ic_receive_state %d\n", ic->ic_receive_state);
|
panic("invalid receive_state %d\n", isc->receive_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
/*
|
/*
|
||||||
* Don't free the PDU; it's pointed to by ic->ic_receive_pdu
|
* Don't free the PDU; it's pointed to by isc->receive_pdu
|
||||||
* and will get freed in icl_soft_conn_close().
|
* and will get freed in icl_soft_conn_close().
|
||||||
*/
|
*/
|
||||||
icl_conn_fail(ic);
|
icl_conn_fail(ic);
|
||||||
@ -663,8 +683,9 @@ icl_conn_receive_pdu(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
icl_conn_receive_pdus(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
icl_conn_receive_pdus(struct icl_soft_conn *isc, struct mbuf **r, size_t *rs)
|
||||||
{
|
{
|
||||||
|
struct icl_conn *ic = &isc->ic;
|
||||||
struct icl_pdu *response;
|
struct icl_pdu *response;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -675,15 +696,15 @@ icl_conn_receive_pdus(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
* Loop until we have a complete PDU or there is not enough
|
* Loop until we have a complete PDU or there is not enough
|
||||||
* data in the socket buffer.
|
* data in the socket buffer.
|
||||||
*/
|
*/
|
||||||
if (*rs < ic->ic_receive_len) {
|
if (*rs < isc->receive_len) {
|
||||||
#if 0
|
#if 0
|
||||||
ICL_DEBUG("not enough data; have %zd, need %zd",
|
ICL_DEBUG("not enough data; have %zd, need %zd",
|
||||||
*rs, ic->ic_receive_len);
|
*rs, isc->receive_len);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
response = icl_conn_receive_pdu(ic, r, rs);
|
response = icl_conn_receive_pdu(isc, r, rs);
|
||||||
if (response == NULL)
|
if (response == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -703,14 +724,14 @@ icl_conn_receive_pdus(struct icl_conn *ic, struct mbuf **r, size_t *rs)
|
|||||||
static void
|
static void
|
||||||
icl_receive_thread(void *arg)
|
icl_receive_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct icl_conn *ic;
|
struct icl_soft_conn *isc = arg;
|
||||||
|
struct icl_conn *ic = &isc->ic;
|
||||||
size_t available, read = 0;
|
size_t available, read = 0;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
struct mbuf *m, *r = NULL;
|
struct mbuf *m, *r = NULL;
|
||||||
struct uio uio;
|
struct uio uio;
|
||||||
int error, flags;
|
int error, flags;
|
||||||
|
|
||||||
ic = arg;
|
|
||||||
so = ic->ic_socket;
|
so = ic->ic_socket;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -727,9 +748,9 @@ icl_receive_thread(void *arg)
|
|||||||
* is enough data received to read the PDU.
|
* is enough data received to read the PDU.
|
||||||
*/
|
*/
|
||||||
available = sbavail(&so->so_rcv);
|
available = sbavail(&so->so_rcv);
|
||||||
if (read + available < ic->ic_receive_len) {
|
if (read + available < isc->receive_len) {
|
||||||
so->so_rcv.sb_lowat = ic->ic_receive_len - read;
|
so->so_rcv.sb_lowat = isc->receive_len - read;
|
||||||
cv_wait(&ic->ic_receive_cv, SOCKBUF_MTX(&so->so_rcv));
|
cv_wait(&isc->receive_cv, SOCKBUF_MTX(&so->so_rcv));
|
||||||
so->so_rcv.sb_lowat = so->so_rcv.sb_hiwat + 1;
|
so->so_rcv.sb_lowat = so->so_rcv.sb_hiwat + 1;
|
||||||
available = sbavail(&so->so_rcv);
|
available = sbavail(&so->so_rcv);
|
||||||
}
|
}
|
||||||
@ -764,15 +785,15 @@ icl_receive_thread(void *arg)
|
|||||||
r = m;
|
r = m;
|
||||||
read += available;
|
read += available;
|
||||||
|
|
||||||
icl_conn_receive_pdus(ic, &r, &read);
|
icl_conn_receive_pdus(isc, &r, &read);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
m_freem(r);
|
m_freem(r);
|
||||||
|
|
||||||
ICL_CONN_LOCK(ic);
|
ICL_CONN_LOCK(ic);
|
||||||
ic->ic_receive_running = false;
|
isc->receive_running = false;
|
||||||
cv_signal(&ic->ic_send_cv);
|
cv_signal(&isc->send_cv);
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
kthread_exit();
|
kthread_exit();
|
||||||
}
|
}
|
||||||
@ -780,13 +801,13 @@ icl_receive_thread(void *arg)
|
|||||||
static int
|
static int
|
||||||
icl_soupcall_receive(struct socket *so, void *arg, int waitflag)
|
icl_soupcall_receive(struct socket *so, void *arg, int waitflag)
|
||||||
{
|
{
|
||||||
struct icl_conn *ic;
|
struct icl_soft_conn *isc;
|
||||||
|
|
||||||
if (!soreadable(so))
|
if (!soreadable(so))
|
||||||
return (SU_OK);
|
return (SU_OK);
|
||||||
|
|
||||||
ic = arg;
|
isc = arg;
|
||||||
cv_signal(&ic->ic_receive_cv);
|
cv_signal(&isc->receive_cv);
|
||||||
return (SU_OK);
|
return (SU_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,8 +867,9 @@ icl_pdu_finalize(struct icl_pdu *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
icl_conn_send_pdus(struct icl_conn *ic, struct icl_pdu_stailq *queue)
|
icl_conn_send_pdus(struct icl_soft_conn *isc, struct icl_pdu_stailq *queue)
|
||||||
{
|
{
|
||||||
|
struct icl_conn *ic = &isc->ic;
|
||||||
struct icl_pdu *request, *request2;
|
struct icl_pdu *request, *request2;
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
@ -866,7 +888,7 @@ icl_conn_send_pdus(struct icl_conn *ic, struct icl_pdu_stailq *queue)
|
|||||||
* of error.
|
* of error.
|
||||||
*/
|
*/
|
||||||
available = sbspace(&so->so_snd);
|
available = sbspace(&so->so_snd);
|
||||||
ic->ic_check_send_space = false;
|
isc->check_send_space = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notify the socket upcall that we don't need wakeups
|
* Notify the socket upcall that we don't need wakeups
|
||||||
@ -961,10 +983,12 @@ icl_conn_send_pdus(struct icl_conn *ic, struct icl_pdu_stailq *queue)
|
|||||||
static void
|
static void
|
||||||
icl_send_thread(void *arg)
|
icl_send_thread(void *arg)
|
||||||
{
|
{
|
||||||
|
struct icl_soft_conn *isc;
|
||||||
struct icl_conn *ic;
|
struct icl_conn *ic;
|
||||||
struct icl_pdu_stailq queue;
|
struct icl_pdu_stailq queue;
|
||||||
|
|
||||||
ic = arg;
|
isc = arg;
|
||||||
|
ic = &isc->ic;
|
||||||
|
|
||||||
STAILQ_INIT(&queue);
|
STAILQ_INIT(&queue);
|
||||||
|
|
||||||
@ -976,18 +1000,18 @@ icl_send_thread(void *arg)
|
|||||||
* This way the icl_conn_send_pdus() can go through
|
* This way the icl_conn_send_pdus() can go through
|
||||||
* all the queued PDUs without holding any locks.
|
* all the queued PDUs without holding any locks.
|
||||||
*/
|
*/
|
||||||
if (STAILQ_EMPTY(&queue) || ic->ic_check_send_space)
|
if (STAILQ_EMPTY(&queue) || isc->check_send_space)
|
||||||
STAILQ_CONCAT(&queue, &ic->ic_to_send);
|
STAILQ_CONCAT(&queue, &isc->to_send);
|
||||||
|
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
icl_conn_send_pdus(ic, &queue);
|
icl_conn_send_pdus(isc, &queue);
|
||||||
ICL_CONN_LOCK(ic);
|
ICL_CONN_LOCK(ic);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The icl_soupcall_send() was called since the last
|
* The icl_soupcall_send() was called since the last
|
||||||
* call to sbspace(); go around;
|
* call to sbspace(); go around;
|
||||||
*/
|
*/
|
||||||
if (ic->ic_check_send_space)
|
if (isc->check_send_space)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -995,7 +1019,7 @@ icl_send_thread(void *arg)
|
|||||||
* in the main one; go around.
|
* in the main one; go around.
|
||||||
*/
|
*/
|
||||||
if (STAILQ_EMPTY(&queue) &&
|
if (STAILQ_EMPTY(&queue) &&
|
||||||
!STAILQ_EMPTY(&ic->ic_to_send))
|
!STAILQ_EMPTY(&isc->to_send))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1011,17 +1035,17 @@ icl_send_thread(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cv_wait(&ic->ic_send_cv, ic->ic_lock);
|
cv_wait(&isc->send_cv, ic->ic_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We're exiting; move PDUs back to the main queue, so they can
|
* We're exiting; move PDUs back to the main queue, so they can
|
||||||
* get freed properly. At this point ordering doesn't matter.
|
* get freed properly. At this point ordering doesn't matter.
|
||||||
*/
|
*/
|
||||||
STAILQ_CONCAT(&ic->ic_to_send, &queue);
|
STAILQ_CONCAT(&isc->to_send, &queue);
|
||||||
|
|
||||||
ic->ic_send_running = false;
|
isc->send_running = false;
|
||||||
cv_signal(&ic->ic_send_cv);
|
cv_signal(&isc->send_cv);
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
kthread_exit();
|
kthread_exit();
|
||||||
}
|
}
|
||||||
@ -1029,18 +1053,20 @@ icl_send_thread(void *arg)
|
|||||||
static int
|
static int
|
||||||
icl_soupcall_send(struct socket *so, void *arg, int waitflag)
|
icl_soupcall_send(struct socket *so, void *arg, int waitflag)
|
||||||
{
|
{
|
||||||
|
struct icl_soft_conn *isc;
|
||||||
struct icl_conn *ic;
|
struct icl_conn *ic;
|
||||||
|
|
||||||
if (!sowriteable(so))
|
if (!sowriteable(so))
|
||||||
return (SU_OK);
|
return (SU_OK);
|
||||||
|
|
||||||
ic = arg;
|
isc = arg;
|
||||||
|
ic = &isc->ic;
|
||||||
|
|
||||||
ICL_CONN_LOCK(ic);
|
ICL_CONN_LOCK(ic);
|
||||||
ic->ic_check_send_space = true;
|
isc->check_send_space = true;
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
|
|
||||||
cv_signal(&ic->ic_send_cv);
|
cv_signal(&isc->send_cv);
|
||||||
|
|
||||||
return (SU_OK);
|
return (SU_OK);
|
||||||
}
|
}
|
||||||
@ -1112,6 +1138,7 @@ static void
|
|||||||
icl_soft_conn_pdu_queue_cb(struct icl_conn *ic, struct icl_pdu *ip,
|
icl_soft_conn_pdu_queue_cb(struct icl_conn *ic, struct icl_pdu *ip,
|
||||||
icl_pdu_cb cb)
|
icl_pdu_cb cb)
|
||||||
{
|
{
|
||||||
|
struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
|
||||||
struct icl_soft_pdu *isp = (struct icl_soft_pdu *)ip;
|
struct icl_soft_pdu *isp = (struct icl_soft_pdu *)ip;
|
||||||
|
|
||||||
ICL_CONN_LOCK_ASSERT(ic);
|
ICL_CONN_LOCK_ASSERT(ic);
|
||||||
@ -1124,8 +1151,8 @@ icl_soft_conn_pdu_queue_cb(struct icl_conn *ic, struct icl_pdu *ip,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!STAILQ_EMPTY(&ic->ic_to_send)) {
|
if (!STAILQ_EMPTY(&isc->to_send)) {
|
||||||
STAILQ_INSERT_TAIL(&ic->ic_to_send, ip, ip_next);
|
STAILQ_INSERT_TAIL(&isc->to_send, ip, ip_next);
|
||||||
/*
|
/*
|
||||||
* If the queue is not empty, someone else had already
|
* If the queue is not empty, someone else had already
|
||||||
* signaled the send thread; no need to do that again,
|
* signaled the send thread; no need to do that again,
|
||||||
@ -1134,23 +1161,27 @@ icl_soft_conn_pdu_queue_cb(struct icl_conn *ic, struct icl_pdu *ip,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
STAILQ_INSERT_TAIL(&ic->ic_to_send, ip, ip_next);
|
STAILQ_INSERT_TAIL(&isc->to_send, ip, ip_next);
|
||||||
cv_signal(&ic->ic_send_cv);
|
cv_signal(&isc->send_cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct icl_conn *
|
static struct icl_conn *
|
||||||
icl_soft_new_conn(const char *name, struct mtx *lock)
|
icl_soft_new_conn(const char *name, struct mtx *lock)
|
||||||
{
|
{
|
||||||
|
struct icl_soft_conn *isc;
|
||||||
struct icl_conn *ic;
|
struct icl_conn *ic;
|
||||||
|
|
||||||
refcount_acquire(&icl_ncons);
|
refcount_acquire(&icl_ncons);
|
||||||
|
|
||||||
ic = (struct icl_conn *)kobj_create(&icl_soft_class, M_ICL_SOFT, M_WAITOK | M_ZERO);
|
isc = (struct icl_soft_conn *)kobj_create(&icl_soft_class, M_ICL_SOFT,
|
||||||
|
M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
STAILQ_INIT(&ic->ic_to_send);
|
STAILQ_INIT(&isc->to_send);
|
||||||
|
cv_init(&isc->send_cv, "icl_tx");
|
||||||
|
cv_init(&isc->receive_cv, "icl_rx");
|
||||||
|
|
||||||
|
ic = &isc->ic;
|
||||||
ic->ic_lock = lock;
|
ic->ic_lock = lock;
|
||||||
cv_init(&ic->ic_send_cv, "icl_tx");
|
|
||||||
cv_init(&ic->ic_receive_cv, "icl_rx");
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
refcount_init(&ic->ic_outstanding_pdus, 0);
|
refcount_init(&ic->ic_outstanding_pdus, 0);
|
||||||
#endif
|
#endif
|
||||||
@ -1164,21 +1195,23 @@ icl_soft_new_conn(const char *name, struct mtx *lock)
|
|||||||
void
|
void
|
||||||
icl_soft_conn_free(struct icl_conn *ic)
|
icl_soft_conn_free(struct icl_conn *ic)
|
||||||
{
|
{
|
||||||
|
struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
KASSERT(ic->ic_outstanding_pdus == 0,
|
KASSERT(ic->ic_outstanding_pdus == 0,
|
||||||
("destroying session with %d outstanding PDUs",
|
("destroying session with %d outstanding PDUs",
|
||||||
ic->ic_outstanding_pdus));
|
ic->ic_outstanding_pdus));
|
||||||
#endif
|
#endif
|
||||||
cv_destroy(&ic->ic_send_cv);
|
cv_destroy(&isc->send_cv);
|
||||||
cv_destroy(&ic->ic_receive_cv);
|
cv_destroy(&isc->receive_cv);
|
||||||
kobj_delete((struct kobj *)ic, M_ICL_SOFT);
|
kobj_delete((struct kobj *)isc, M_ICL_SOFT);
|
||||||
refcount_release(&icl_ncons);
|
refcount_release(&icl_ncons);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
icl_conn_start(struct icl_conn *ic)
|
icl_conn_start(struct icl_conn *ic)
|
||||||
{
|
{
|
||||||
|
struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
|
||||||
size_t minspace;
|
size_t minspace;
|
||||||
struct sockopt opt;
|
struct sockopt opt;
|
||||||
int error, one = 1;
|
int error, one = 1;
|
||||||
@ -1193,8 +1226,8 @@ icl_conn_start(struct icl_conn *ic)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ic->ic_receive_state = ICL_CONN_STATE_BHS;
|
isc->receive_state = ICL_CONN_STATE_BHS;
|
||||||
ic->ic_receive_len = sizeof(struct iscsi_bhs);
|
isc->receive_len = sizeof(struct iscsi_bhs);
|
||||||
ic->ic_disconnecting = false;
|
ic->ic_disconnecting = false;
|
||||||
|
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
@ -1251,25 +1284,25 @@ icl_conn_start(struct icl_conn *ic)
|
|||||||
* and free space to send outgoing ones.
|
* and free space to send outgoing ones.
|
||||||
*/
|
*/
|
||||||
SOCKBUF_LOCK(&ic->ic_socket->so_snd);
|
SOCKBUF_LOCK(&ic->ic_socket->so_snd);
|
||||||
soupcall_set(ic->ic_socket, SO_SND, icl_soupcall_send, ic);
|
soupcall_set(ic->ic_socket, SO_SND, icl_soupcall_send, isc);
|
||||||
SOCKBUF_UNLOCK(&ic->ic_socket->so_snd);
|
SOCKBUF_UNLOCK(&ic->ic_socket->so_snd);
|
||||||
SOCKBUF_LOCK(&ic->ic_socket->so_rcv);
|
SOCKBUF_LOCK(&ic->ic_socket->so_rcv);
|
||||||
soupcall_set(ic->ic_socket, SO_RCV, icl_soupcall_receive, ic);
|
soupcall_set(ic->ic_socket, SO_RCV, icl_soupcall_receive, isc);
|
||||||
SOCKBUF_UNLOCK(&ic->ic_socket->so_rcv);
|
SOCKBUF_UNLOCK(&ic->ic_socket->so_rcv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start threads.
|
* Start threads.
|
||||||
*/
|
*/
|
||||||
ICL_CONN_LOCK(ic);
|
ICL_CONN_LOCK(ic);
|
||||||
ic->ic_send_running = ic->ic_receive_running = true;
|
isc->send_running = isc->receive_running = true;
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
error = kthread_add(icl_send_thread, ic, NULL, NULL, 0, 0, "%stx",
|
error = kthread_add(icl_send_thread, ic, NULL, NULL, 0, 0, "%stx",
|
||||||
ic->ic_name);
|
ic->ic_name);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
ICL_WARN("kthread_add(9) failed with error %d", error);
|
ICL_WARN("kthread_add(9) failed with error %d", error);
|
||||||
ICL_CONN_LOCK(ic);
|
ICL_CONN_LOCK(ic);
|
||||||
ic->ic_send_running = ic->ic_receive_running = false;
|
isc->send_running = isc->receive_running = false;
|
||||||
cv_signal(&ic->ic_send_cv);
|
cv_signal(&isc->send_cv);
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
icl_soft_conn_close(ic);
|
icl_soft_conn_close(ic);
|
||||||
return (error);
|
return (error);
|
||||||
@ -1279,8 +1312,8 @@ icl_conn_start(struct icl_conn *ic)
|
|||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
ICL_WARN("kthread_add(9) failed with error %d", error);
|
ICL_WARN("kthread_add(9) failed with error %d", error);
|
||||||
ICL_CONN_LOCK(ic);
|
ICL_CONN_LOCK(ic);
|
||||||
ic->ic_receive_running = false;
|
isc->receive_running = false;
|
||||||
cv_signal(&ic->ic_send_cv);
|
cv_signal(&isc->send_cv);
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
icl_soft_conn_close(ic);
|
icl_soft_conn_close(ic);
|
||||||
return (error);
|
return (error);
|
||||||
@ -1355,6 +1388,7 @@ icl_soft_conn_handoff(struct icl_conn *ic, int fd)
|
|||||||
void
|
void
|
||||||
icl_soft_conn_close(struct icl_conn *ic)
|
icl_soft_conn_close(struct icl_conn *ic)
|
||||||
{
|
{
|
||||||
|
struct icl_soft_conn *isc = (struct icl_soft_conn *)ic;
|
||||||
struct icl_pdu *pdu;
|
struct icl_pdu *pdu;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
@ -1371,10 +1405,10 @@ icl_soft_conn_close(struct icl_conn *ic)
|
|||||||
if (so)
|
if (so)
|
||||||
SOCKBUF_UNLOCK(&so->so_rcv);
|
SOCKBUF_UNLOCK(&so->so_rcv);
|
||||||
}
|
}
|
||||||
while (ic->ic_receive_running || ic->ic_send_running) {
|
while (isc->receive_running || isc->send_running) {
|
||||||
cv_signal(&ic->ic_receive_cv);
|
cv_signal(&isc->receive_cv);
|
||||||
cv_signal(&ic->ic_send_cv);
|
cv_signal(&isc->send_cv);
|
||||||
cv_wait(&ic->ic_send_cv, ic->ic_lock);
|
cv_wait(&isc->send_cv, ic->ic_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some other thread could close the connection same time. */
|
/* Some other thread could close the connection same time. */
|
||||||
@ -1400,22 +1434,22 @@ icl_soft_conn_close(struct icl_conn *ic)
|
|||||||
soclose(so);
|
soclose(so);
|
||||||
ICL_CONN_LOCK(ic);
|
ICL_CONN_LOCK(ic);
|
||||||
|
|
||||||
if (ic->ic_receive_pdu != NULL) {
|
if (isc->receive_pdu != NULL) {
|
||||||
//ICL_DEBUG("freeing partially received PDU");
|
//ICL_DEBUG("freeing partially received PDU");
|
||||||
icl_soft_conn_pdu_free(ic, ic->ic_receive_pdu);
|
icl_soft_conn_pdu_free(ic, isc->receive_pdu);
|
||||||
ic->ic_receive_pdu = NULL;
|
isc->receive_pdu = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove any outstanding PDUs from the send queue.
|
* Remove any outstanding PDUs from the send queue.
|
||||||
*/
|
*/
|
||||||
while (!STAILQ_EMPTY(&ic->ic_to_send)) {
|
while (!STAILQ_EMPTY(&isc->to_send)) {
|
||||||
pdu = STAILQ_FIRST(&ic->ic_to_send);
|
pdu = STAILQ_FIRST(&isc->to_send);
|
||||||
STAILQ_REMOVE_HEAD(&ic->ic_to_send, ip_next);
|
STAILQ_REMOVE_HEAD(&isc->to_send, ip_next);
|
||||||
icl_soft_pdu_done(pdu, ENOTCONN);
|
icl_soft_pdu_done(pdu, ENOTCONN);
|
||||||
}
|
}
|
||||||
|
|
||||||
KASSERT(STAILQ_EMPTY(&ic->ic_to_send),
|
KASSERT(STAILQ_EMPTY(&isc->to_send),
|
||||||
("destroying session with non-empty send queue"));
|
("destroying session with non-empty send queue"));
|
||||||
ICL_CONN_UNLOCK(ic);
|
ICL_CONN_UNLOCK(ic);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user