Correctly handle the case where an inp has already been dropped by the time
the TOE driver reports that an active open failed. toe_connect_failed is supposed to handle this but it should be provided the inpcb instead of the tcpcb which may no longer be around.
This commit is contained in:
parent
988a1851d7
commit
06fd9875aa
@ -880,10 +880,10 @@ act_open_rpl_status_to_errno(int status)
|
||||
case CPL_ERR_CONN_TIMEDOUT:
|
||||
return (ETIMEDOUT);
|
||||
case CPL_ERR_TCAM_FULL:
|
||||
return (ENOMEM);
|
||||
return (EAGAIN);
|
||||
case CPL_ERR_CONN_EXIST:
|
||||
log(LOG_ERR, "ACTIVE_OPEN_RPL: 4-tuple in use\n");
|
||||
return (EADDRINUSE);
|
||||
return (EAGAIN);
|
||||
default:
|
||||
return (EIO);
|
||||
}
|
||||
@ -912,8 +912,7 @@ do_act_open_rpl(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
|
||||
unsigned int atid = G_TID(ntohl(rpl->atid));
|
||||
struct toepcb *toep = lookup_atid(&td->tid_maps, atid);
|
||||
struct inpcb *inp = toep->tp_inp;
|
||||
struct tcpcb *tp = intotcpcb(inp);
|
||||
int s = rpl->status;
|
||||
int s = rpl->status, rc;
|
||||
|
||||
CTR3(KTR_CXGB, "%s: atid %u, status %u ", __func__, atid, s);
|
||||
|
||||
@ -923,17 +922,14 @@ do_act_open_rpl(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
|
||||
if (act_open_has_tid(s))
|
||||
queue_tid_release(tod, GET_TID(rpl));
|
||||
|
||||
if (s == CPL_ERR_TCAM_FULL || s == CPL_ERR_CONN_EXIST) {
|
||||
INP_WLOCK(inp);
|
||||
toe_connect_failed(tod, tp, EAGAIN);
|
||||
toepcb_release(toep); /* unlocks inp */
|
||||
} else {
|
||||
rc = act_open_rpl_status_to_errno(s);
|
||||
if (rc != EAGAIN)
|
||||
INP_INFO_WLOCK(&V_tcbinfo);
|
||||
INP_WLOCK(inp);
|
||||
toe_connect_failed(tod, tp, act_open_rpl_status_to_errno(s));
|
||||
toepcb_release(toep); /* unlocks inp */
|
||||
INP_WLOCK(inp);
|
||||
toe_connect_failed(tod, inp, rc);
|
||||
toepcb_release(toep); /* unlocks inp */
|
||||
if (rc != EAGAIN)
|
||||
INP_INFO_WUNLOCK(&V_tcbinfo);
|
||||
}
|
||||
|
||||
m_freem(m);
|
||||
return (0);
|
||||
|
@ -167,10 +167,10 @@ act_open_rpl_status_to_errno(int status)
|
||||
case CPL_ERR_CONN_TIMEDOUT:
|
||||
return (ETIMEDOUT);
|
||||
case CPL_ERR_TCAM_FULL:
|
||||
return (ENOMEM);
|
||||
return (EAGAIN);
|
||||
case CPL_ERR_CONN_EXIST:
|
||||
log(LOG_ERR, "ACTIVE_OPEN_RPL: 4-tuple in use\n");
|
||||
return (EADDRINUSE);
|
||||
return (EAGAIN);
|
||||
default:
|
||||
return (EIO);
|
||||
}
|
||||
@ -186,8 +186,8 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
|
||||
unsigned int status = G_AOPEN_STATUS(be32toh(cpl->atid_status));
|
||||
struct toepcb *toep = lookup_atid(sc, atid);
|
||||
struct inpcb *inp = toep->inp;
|
||||
struct tcpcb *tp = intotcpcb(inp);
|
||||
struct toedev *tod = &toep->td->tod;
|
||||
int rc;
|
||||
|
||||
KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
|
||||
KASSERT(toep->tid == atid, ("%s: toep tid/atid mismatch", __func__));
|
||||
@ -204,17 +204,14 @@ do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss,
|
||||
if (status && act_open_has_tid(status))
|
||||
release_tid(sc, GET_TID(cpl), toep->ctrlq);
|
||||
|
||||
if (status == CPL_ERR_TCAM_FULL) {
|
||||
INP_WLOCK(inp);
|
||||
toe_connect_failed(tod, tp, EAGAIN);
|
||||
final_cpl_received(toep); /* unlocks inp */
|
||||
} else {
|
||||
rc = act_open_rpl_status_to_errno(status);
|
||||
if (rc != EAGAIN)
|
||||
INP_INFO_WLOCK(&V_tcbinfo);
|
||||
INP_WLOCK(inp);
|
||||
toe_connect_failed(tod, tp, act_open_rpl_status_to_errno(status));
|
||||
final_cpl_received(toep); /* unlocks inp */
|
||||
INP_WLOCK(inp);
|
||||
toe_connect_failed(tod, inp, rc);
|
||||
final_cpl_received(toep); /* unlocks inp */
|
||||
if (rc != EAGAIN)
|
||||
INP_INFO_WUNLOCK(&V_tcbinfo);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -478,15 +478,17 @@ toe_l2_resolve(struct toedev *tod, struct ifnet *ifp, struct sockaddr *sa,
|
||||
}
|
||||
|
||||
void
|
||||
toe_connect_failed(struct toedev *tod, struct tcpcb *tp, int err)
|
||||
toe_connect_failed(struct toedev *tod, struct inpcb *inp, int err)
|
||||
{
|
||||
struct inpcb *inp = tp->t_inpcb;
|
||||
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
KASSERT(tp->t_flags & TF_TOE,
|
||||
("%s: tp %p not offloaded.", __func__, tp));
|
||||
|
||||
if (!(inp->inp_flags & INP_DROPPED)) {
|
||||
struct tcpcb *tp = intotcpcb(inp);
|
||||
|
||||
KASSERT(tp->t_flags & TF_TOE,
|
||||
("%s: tp %p not offloaded.", __func__, tp));
|
||||
|
||||
if (err == EAGAIN) {
|
||||
|
||||
/*
|
||||
|
@ -119,7 +119,7 @@ int unregister_toedev(struct toedev *);
|
||||
int toe_l2_resolve(struct toedev *, struct ifnet *, struct sockaddr *,
|
||||
uint8_t *, uint16_t *);
|
||||
|
||||
void toe_connect_failed(struct toedev *, struct tcpcb *, int);
|
||||
void toe_connect_failed(struct toedev *, struct inpcb *, int);
|
||||
|
||||
void toe_syncache_add(struct in_conninfo *, struct tcpopt *, struct tcphdr *,
|
||||
struct inpcb *, void *, void *);
|
||||
|
Loading…
Reference in New Issue
Block a user