mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger:
"The highlights this round include:
- enable dual mode (initiator + target) qla2xxx operation. (Quinn +
Himanshu)
- add a framework for qla2xxx async fabric discovery. (Quinn +
Himanshu)
- enable iscsi PDU DDP completion offload in cxgbit/T6 NICs. (Varun)
- fix target-core handling of aborted failed commands. (Bart)
- fix a long standing target-core issue NULL pointer dereference with
active I/O LUN shutdown. (Rob Millner + Bryant + nab)"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (44 commits)
target: Add counters for ABORT_TASK success + failure
iscsi-target: Fix early login failure statistics misses
target: Fix NULL dereference during LUN lookup + active I/O shutdown
target: Delete tmr from list before processing
target: Fix handling of aborted failed commands
uapi: fix linux/target_core_user.h userspace compilation errors
target: export protocol identifier
qla2xxx: Fix a warning reported by the "smatch" static checker
target/iscsi: Fix unsolicited data seq_end_offset calculation
target/cxgbit: add T6 iSCSI DDP completion feature
target/cxgbit: Enable DDP for T6 only if data sequence and pdu are in order
target/cxgbit: Use T6 specific macros to get ETH/IP hdr len
target/cxgbit: use cxgb4_tp_smt_idx() to get smt idx
target/iscsi: split iscsit_check_dataout_hdr()
target: Remove command flag CMD_T_DEV_ACTIVE
target: Remove command flag CMD_T_BUSY
target: Move session check from target_put_sess_cmd() into target_release_cmd_kref()
target: Inline transport_cmd_check_stop()
target: Remove an overly chatty debug message
target: Stop execution if CMD_T_STOP has been set
...
This commit is contained in:
commit
821fd6f6cb
43 changed files with 4790 additions and 2858 deletions
|
|
@ -872,7 +872,8 @@ cxgbit_offload_init(struct cxgbit_sock *csk, int iptype, __u8 *peer_ip,
|
|||
goto out;
|
||||
csk->mtu = ndev->mtu;
|
||||
csk->tx_chan = cxgb4_port_chan(ndev);
|
||||
csk->smac_idx = (cxgb4_port_viid(ndev) & 0x7F) << 1;
|
||||
csk->smac_idx = cxgb4_tp_smt_idx(cdev->lldi.adapter_type,
|
||||
cxgb4_port_viid(ndev));
|
||||
step = cdev->lldi.ntxq /
|
||||
cdev->lldi.nchan;
|
||||
csk->txq_idx = cxgb4_port_idx(ndev) * step;
|
||||
|
|
@ -907,7 +908,8 @@ cxgbit_offload_init(struct cxgbit_sock *csk, int iptype, __u8 *peer_ip,
|
|||
port_id = cxgb4_port_idx(ndev);
|
||||
csk->mtu = dst_mtu(dst);
|
||||
csk->tx_chan = cxgb4_port_chan(ndev);
|
||||
csk->smac_idx = (cxgb4_port_viid(ndev) & 0x7F) << 1;
|
||||
csk->smac_idx = cxgb4_tp_smt_idx(cdev->lldi.adapter_type,
|
||||
cxgb4_port_viid(ndev));
|
||||
step = cdev->lldi.ntxq /
|
||||
cdev->lldi.nports;
|
||||
csk->txq_idx = (port_id * step) +
|
||||
|
|
@ -1066,6 +1068,7 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
|||
struct sk_buff *skb;
|
||||
const struct tcphdr *tcph;
|
||||
struct cpl_t5_pass_accept_rpl *rpl5;
|
||||
struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
|
||||
unsigned int len = roundup(sizeof(*rpl5), 16);
|
||||
unsigned int mtu_idx;
|
||||
u64 opt0;
|
||||
|
|
@ -1111,6 +1114,9 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
|||
opt2 = RX_CHANNEL_V(0) |
|
||||
RSS_QUEUE_VALID_F | RSS_QUEUE_V(csk->rss_qid);
|
||||
|
||||
if (!is_t5(lldi->adapter_type))
|
||||
opt2 |= RX_FC_DISABLE_F;
|
||||
|
||||
if (req->tcpopt.tstamp)
|
||||
opt2 |= TSTAMPS_EN_F;
|
||||
if (req->tcpopt.sack)
|
||||
|
|
@ -1119,8 +1125,13 @@ cxgbit_pass_accept_rpl(struct cxgbit_sock *csk, struct cpl_pass_accept_req *req)
|
|||
opt2 |= WND_SCALE_EN_F;
|
||||
|
||||
hlen = ntohl(req->hdr_len);
|
||||
tcph = (const void *)(req + 1) + ETH_HDR_LEN_G(hlen) +
|
||||
IP_HDR_LEN_G(hlen);
|
||||
|
||||
if (is_t5(lldi->adapter_type))
|
||||
tcph = (struct tcphdr *)((u8 *)(req + 1) +
|
||||
ETH_HDR_LEN_G(hlen) + IP_HDR_LEN_G(hlen));
|
||||
else
|
||||
tcph = (struct tcphdr *)((u8 *)(req + 1) +
|
||||
T6_ETH_HDR_LEN_G(hlen) + T6_IP_HDR_LEN_G(hlen));
|
||||
|
||||
if (tcph->ece && tcph->cwr)
|
||||
opt2 |= CCTRL_ECN_V(1);
|
||||
|
|
@ -1726,7 +1737,7 @@ static bool cxgbit_credit_err(const struct cxgbit_sock *csk)
|
|||
}
|
||||
|
||||
while (skb) {
|
||||
credit += skb->csum;
|
||||
credit += (__force u32)skb->csum;
|
||||
skb = cxgbit_skcb_tx_wr_next(skb);
|
||||
}
|
||||
|
||||
|
|
@ -1753,6 +1764,7 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
|
|||
|
||||
while (credits) {
|
||||
struct sk_buff *p = cxgbit_sock_peek_wr(csk);
|
||||
const u32 csum = (__force u32)p->csum;
|
||||
|
||||
if (unlikely(!p)) {
|
||||
pr_err("csk 0x%p,%u, cr %u,%u+%u, empty.\n",
|
||||
|
|
@ -1761,17 +1773,17 @@ static void cxgbit_fw4_ack(struct cxgbit_sock *csk, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
|
||||
if (unlikely(credits < p->csum)) {
|
||||
if (unlikely(credits < csum)) {
|
||||
pr_warn("csk 0x%p,%u, cr %u,%u+%u, < %u.\n",
|
||||
csk, csk->tid,
|
||||
credits, csk->wr_cred, csk->wr_una_cred,
|
||||
p->csum);
|
||||
p->csum -= credits;
|
||||
csum);
|
||||
p->csum = (__force __wsum)(csum - credits);
|
||||
break;
|
||||
}
|
||||
|
||||
cxgbit_sock_dequeue_wr(csk);
|
||||
credits -= p->csum;
|
||||
credits -= csum;
|
||||
kfree_skb(p);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,9 @@ enum cxgbit_pducb_flags {
|
|||
PDUCBF_RX_DATA = (1 << 1), /* received pdu payload */
|
||||
PDUCBF_RX_STATUS = (1 << 2), /* received ddp status */
|
||||
PDUCBF_RX_DATA_DDPD = (1 << 3), /* pdu payload ddp'd */
|
||||
PDUCBF_RX_HCRC_ERR = (1 << 4), /* header digest error */
|
||||
PDUCBF_RX_DCRC_ERR = (1 << 5), /* data digest error */
|
||||
PDUCBF_RX_DDP_CMP = (1 << 4), /* ddp completion */
|
||||
PDUCBF_RX_HCRC_ERR = (1 << 5), /* header digest error */
|
||||
PDUCBF_RX_DCRC_ERR = (1 << 6), /* data digest error */
|
||||
};
|
||||
|
||||
struct cxgbit_lro_pdu_cb {
|
||||
|
|
|
|||
|
|
@ -165,29 +165,24 @@ static int cxgbit_uld_state_change(void *handle, enum cxgb4_state state)
|
|||
}
|
||||
|
||||
static void
|
||||
cxgbit_proc_ddp_status(unsigned int tid, struct cpl_rx_data_ddp *cpl,
|
||||
struct cxgbit_lro_pdu_cb *pdu_cb)
|
||||
cxgbit_process_ddpvld(struct cxgbit_sock *csk, struct cxgbit_lro_pdu_cb *pdu_cb,
|
||||
u32 ddpvld)
|
||||
{
|
||||
unsigned int status = ntohl(cpl->ddpvld);
|
||||
|
||||
pdu_cb->flags |= PDUCBF_RX_STATUS;
|
||||
pdu_cb->ddigest = ntohl(cpl->ulp_crc);
|
||||
pdu_cb->pdulen = ntohs(cpl->len);
|
||||
|
||||
if (status & (1 << CPL_RX_ISCSI_DDP_STATUS_HCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, hcrc bad.\n", tid, status);
|
||||
if (ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_HCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, hcrc bad.\n", csk->tid, ddpvld);
|
||||
pdu_cb->flags |= PDUCBF_RX_HCRC_ERR;
|
||||
}
|
||||
|
||||
if (status & (1 << CPL_RX_ISCSI_DDP_STATUS_DCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, dcrc bad.\n", tid, status);
|
||||
if (ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_DCRC_SHIFT)) {
|
||||
pr_info("tid 0x%x, status 0x%x, dcrc bad.\n", csk->tid, ddpvld);
|
||||
pdu_cb->flags |= PDUCBF_RX_DCRC_ERR;
|
||||
}
|
||||
|
||||
if (status & (1 << CPL_RX_ISCSI_DDP_STATUS_PAD_SHIFT))
|
||||
pr_info("tid 0x%x, status 0x%x, pad bad.\n", tid, status);
|
||||
if (ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_PAD_SHIFT))
|
||||
pr_info("tid 0x%x, status 0x%x, pad bad.\n", csk->tid, ddpvld);
|
||||
|
||||
if ((status & (1 << CPL_RX_ISCSI_DDP_STATUS_DDP_SHIFT)) &&
|
||||
if ((ddpvld & (1 << CPL_RX_ISCSI_DDP_STATUS_DDP_SHIFT)) &&
|
||||
(!(pdu_cb->flags & PDUCBF_RX_DATA))) {
|
||||
pdu_cb->flags |= PDUCBF_RX_DATA_DDPD;
|
||||
}
|
||||
|
|
@ -201,13 +196,17 @@ cxgbit_lro_add_packet_rsp(struct sk_buff *skb, u8 op, const __be64 *rsp)
|
|||
lro_cb->pdu_idx);
|
||||
struct cpl_rx_iscsi_ddp *cpl = (struct cpl_rx_iscsi_ddp *)(rsp + 1);
|
||||
|
||||
cxgbit_proc_ddp_status(lro_cb->csk->tid, cpl, pdu_cb);
|
||||
cxgbit_process_ddpvld(lro_cb->csk, pdu_cb, be32_to_cpu(cpl->ddpvld));
|
||||
|
||||
pdu_cb->flags |= PDUCBF_RX_STATUS;
|
||||
pdu_cb->ddigest = ntohl(cpl->ulp_crc);
|
||||
pdu_cb->pdulen = ntohs(cpl->len);
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_HDR)
|
||||
pdu_cb->complete = true;
|
||||
|
||||
lro_cb->complete = true;
|
||||
lro_cb->pdu_totallen += pdu_cb->pdulen;
|
||||
lro_cb->complete = true;
|
||||
lro_cb->pdu_idx++;
|
||||
}
|
||||
|
||||
|
|
@ -257,7 +256,7 @@ cxgbit_lro_add_packet_gl(struct sk_buff *skb, u8 op, const struct pkt_gl *gl)
|
|||
cxgbit_skcb_flags(skb) = 0;
|
||||
|
||||
lro_cb->complete = false;
|
||||
} else {
|
||||
} else if (op == CPL_ISCSI_DATA) {
|
||||
struct cpl_iscsi_data *cpl = (struct cpl_iscsi_data *)gl->va;
|
||||
|
||||
offset = sizeof(struct cpl_iscsi_data);
|
||||
|
|
@ -267,6 +266,36 @@ cxgbit_lro_add_packet_gl(struct sk_buff *skb, u8 op, const struct pkt_gl *gl)
|
|||
pdu_cb->doffset = lro_cb->offset;
|
||||
pdu_cb->nr_dfrags = gl->nfrags;
|
||||
pdu_cb->dfrag_idx = skb_shinfo(skb)->nr_frags;
|
||||
lro_cb->complete = false;
|
||||
} else {
|
||||
struct cpl_rx_iscsi_cmp *cpl;
|
||||
|
||||
cpl = (struct cpl_rx_iscsi_cmp *)gl->va;
|
||||
offset = sizeof(struct cpl_rx_iscsi_cmp);
|
||||
pdu_cb->flags |= (PDUCBF_RX_HDR | PDUCBF_RX_STATUS);
|
||||
len = be16_to_cpu(cpl->len);
|
||||
pdu_cb->hdr = gl->va + offset;
|
||||
pdu_cb->hlen = len;
|
||||
pdu_cb->hfrag_idx = skb_shinfo(skb)->nr_frags;
|
||||
pdu_cb->ddigest = be32_to_cpu(cpl->ulp_crc);
|
||||
pdu_cb->pdulen = ntohs(cpl->len);
|
||||
|
||||
if (unlikely(gl->nfrags > 1))
|
||||
cxgbit_skcb_flags(skb) = 0;
|
||||
|
||||
cxgbit_process_ddpvld(lro_cb->csk, pdu_cb,
|
||||
be32_to_cpu(cpl->ddpvld));
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DATA_DDPD) {
|
||||
pdu_cb->flags |= PDUCBF_RX_DDP_CMP;
|
||||
pdu_cb->complete = true;
|
||||
} else if (pdu_cb->flags & PDUCBF_RX_DATA) {
|
||||
pdu_cb->complete = true;
|
||||
}
|
||||
|
||||
lro_cb->pdu_totallen += pdu_cb->hlen + pdu_cb->dlen;
|
||||
lro_cb->complete = true;
|
||||
lro_cb->pdu_idx++;
|
||||
}
|
||||
|
||||
cxgbit_copy_frags(skb, gl, offset);
|
||||
|
|
@ -413,6 +442,7 @@ cxgbit_uld_lro_rx_handler(void *hndl, const __be64 *rsp,
|
|||
switch (op) {
|
||||
case CPL_ISCSI_HDR:
|
||||
case CPL_ISCSI_DATA:
|
||||
case CPL_RX_ISCSI_CMP:
|
||||
case CPL_RX_ISCSI_DDP:
|
||||
case CPL_FW4_ACK:
|
||||
lro_flush = false;
|
||||
|
|
@ -454,12 +484,13 @@ cxgbit_uld_lro_rx_handler(void *hndl, const __be64 *rsp,
|
|||
if (unlikely(op != *(u8 *)gl->va)) {
|
||||
pr_info("? FL 0x%p,RSS%#llx,FL %#llx,len %u.\n",
|
||||
gl->va, be64_to_cpu(*rsp),
|
||||
be64_to_cpu(*(u64 *)gl->va),
|
||||
get_unaligned_be64(gl->va),
|
||||
gl->tot_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (op == CPL_ISCSI_HDR || op == CPL_ISCSI_DATA) {
|
||||
if ((op == CPL_ISCSI_HDR) || (op == CPL_ISCSI_DATA) ||
|
||||
(op == CPL_RX_ISCSI_CMP)) {
|
||||
if (!cxgbit_lro_receive(csk, op, rsp, gl, lro_mgr,
|
||||
napi))
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -162,12 +162,14 @@ cxgbit_tx_data_wr(struct cxgbit_sock *csk, struct sk_buff *skb, u32 dlen,
|
|||
u32 len, u32 credits, u32 compl)
|
||||
{
|
||||
struct fw_ofld_tx_data_wr *req;
|
||||
const struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
|
||||
u32 submode = cxgbit_skcb_submode(skb);
|
||||
u32 wr_ulp_mode = 0;
|
||||
u32 hdr_size = sizeof(*req);
|
||||
u32 opcode = FW_OFLD_TX_DATA_WR;
|
||||
u32 immlen = 0;
|
||||
u32 force = TX_FORCE_V(!submode);
|
||||
u32 force = is_t5(lldi->adapter_type) ? TX_FORCE_V(!submode) :
|
||||
T6_TX_FORCE_F;
|
||||
|
||||
if (cxgbit_skcb_flags(skb) & SKCBF_TX_ISO) {
|
||||
opcode = FW_ISCSI_TX_DATA_WR;
|
||||
|
|
@ -243,7 +245,7 @@ void cxgbit_push_tx_frames(struct cxgbit_sock *csk)
|
|||
}
|
||||
__skb_unlink(skb, &csk->txq);
|
||||
set_wr_txq(skb, CPL_PRIORITY_DATA, csk->txq_idx);
|
||||
skb->csum = credits_needed + flowclen16;
|
||||
skb->csum = (__force __wsum)(credits_needed + flowclen16);
|
||||
csk->wr_cred -= credits_needed;
|
||||
csk->wr_una_cred += credits_needed;
|
||||
|
||||
|
|
@ -651,26 +653,6 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
|
|||
u32 max_npdu, max_iso_npdu;
|
||||
|
||||
if (conn->login->leading_connection) {
|
||||
param = iscsi_find_param_from_key(DATASEQUENCEINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATASEQUENCEINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 0;
|
||||
|
||||
param = iscsi_find_param_from_key(DATAPDUINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATAPDUINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 0;
|
||||
|
||||
param = iscsi_find_param_from_key(MAXBURSTLENGTH,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
|
|
@ -681,11 +663,6 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
|
|||
if (kstrtou32(param->value, 0, &mbl) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
if (!conn->sess->sess_ops->DataSequenceInOrder)
|
||||
return 0;
|
||||
if (!conn->sess->sess_ops->DataPDUInOrder)
|
||||
return 0;
|
||||
|
||||
mbl = conn->sess->sess_ops->MaxBurstLength;
|
||||
}
|
||||
|
||||
|
|
@ -704,6 +681,53 @@ static int cxgbit_set_iso_npdu(struct cxgbit_sock *csk)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cxgbit_seq_pdu_inorder()
|
||||
* @csk: pointer to cxgbit socket structure
|
||||
*
|
||||
* This function checks whether data sequence and data
|
||||
* pdu are in order.
|
||||
*
|
||||
* Return: returns -1 on error, 0 if data sequence and
|
||||
* data pdu are in order, 1 if data sequence or data pdu
|
||||
* is not in order.
|
||||
*/
|
||||
static int cxgbit_seq_pdu_inorder(struct cxgbit_sock *csk)
|
||||
{
|
||||
struct iscsi_conn *conn = csk->conn;
|
||||
struct iscsi_param *param;
|
||||
|
||||
if (conn->login->leading_connection) {
|
||||
param = iscsi_find_param_from_key(DATASEQUENCEINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATASEQUENCEINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 1;
|
||||
|
||||
param = iscsi_find_param_from_key(DATAPDUINORDER,
|
||||
conn->param_list);
|
||||
if (!param) {
|
||||
pr_err("param not found key %s\n", DATAPDUINORDER);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(param->value, YES))
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
if (!conn->sess->sess_ops->DataSequenceInOrder)
|
||||
return 1;
|
||||
if (!conn->sess->sess_ops->DataPDUInOrder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxgbit_set_params(struct iscsi_conn *conn)
|
||||
{
|
||||
struct cxgbit_sock *csk = conn->context;
|
||||
|
|
@ -730,11 +754,24 @@ static int cxgbit_set_params(struct iscsi_conn *conn)
|
|||
}
|
||||
|
||||
if (!erl) {
|
||||
int ret;
|
||||
|
||||
ret = cxgbit_seq_pdu_inorder(csk);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
} else if (ret > 0) {
|
||||
if (is_t5(cdev->lldi.adapter_type))
|
||||
goto enable_ddp;
|
||||
else
|
||||
goto enable_digest;
|
||||
}
|
||||
|
||||
if (test_bit(CDEV_ISO_ENABLE, &cdev->flags)) {
|
||||
if (cxgbit_set_iso_npdu(csk))
|
||||
return -1;
|
||||
}
|
||||
|
||||
enable_ddp:
|
||||
if (test_bit(CDEV_DDP_ENABLE, &cdev->flags)) {
|
||||
if (cxgbit_setup_conn_pgidx(csk,
|
||||
ppm->tformat.pgsz_idx_dflt))
|
||||
|
|
@ -743,6 +780,7 @@ static int cxgbit_set_params(struct iscsi_conn *conn)
|
|||
}
|
||||
}
|
||||
|
||||
enable_digest:
|
||||
if (cxgbit_set_digest(csk))
|
||||
return -1;
|
||||
|
||||
|
|
@ -983,11 +1021,36 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
|
|||
int rc, sg_nents, sg_off;
|
||||
bool dcrc_err = false;
|
||||
|
||||
rc = iscsit_check_dataout_hdr(conn, (unsigned char *)hdr, &cmd);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
else if (!cmd)
|
||||
return 0;
|
||||
if (pdu_cb->flags & PDUCBF_RX_DDP_CMP) {
|
||||
u32 offset = be32_to_cpu(hdr->offset);
|
||||
u32 ddp_data_len;
|
||||
u32 payload_length = ntoh24(hdr->dlength);
|
||||
bool success = false;
|
||||
|
||||
cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, 0);
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
ddp_data_len = offset - cmd->write_data_done;
|
||||
atomic_long_add(ddp_data_len, &conn->sess->rx_data_octets);
|
||||
|
||||
cmd->write_data_done = offset;
|
||||
cmd->next_burst_len = ddp_data_len;
|
||||
cmd->data_sn = be32_to_cpu(hdr->datasn);
|
||||
|
||||
rc = __iscsit_check_dataout_hdr(conn, (unsigned char *)hdr,
|
||||
cmd, payload_length, &success);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
else if (!success)
|
||||
return 0;
|
||||
} else {
|
||||
rc = iscsit_check_dataout_hdr(conn, (unsigned char *)hdr, &cmd);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
else if (!cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DCRC_ERR) {
|
||||
pr_err("ITT: 0x%08x, Offset: %u, Length: %u,"
|
||||
|
|
@ -1351,6 +1414,9 @@ static void cxgbit_lro_hskb_reset(struct cxgbit_sock *csk)
|
|||
for (i = 0; i < ssi->nr_frags; i++)
|
||||
put_page(skb_frag_page(&ssi->frags[i]));
|
||||
ssi->nr_frags = 0;
|
||||
skb->data_len = 0;
|
||||
skb->truesize -= skb->len;
|
||||
skb->len = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1364,39 +1430,42 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx)
|
|||
unsigned int len = 0;
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_HDR) {
|
||||
hpdu_cb->flags = pdu_cb->flags;
|
||||
u8 hfrag_idx = hssi->nr_frags;
|
||||
|
||||
hpdu_cb->flags |= pdu_cb->flags;
|
||||
hpdu_cb->seq = pdu_cb->seq;
|
||||
hpdu_cb->hdr = pdu_cb->hdr;
|
||||
hpdu_cb->hlen = pdu_cb->hlen;
|
||||
|
||||
memcpy(&hssi->frags[0], &ssi->frags[pdu_cb->hfrag_idx],
|
||||
memcpy(&hssi->frags[hfrag_idx], &ssi->frags[pdu_cb->hfrag_idx],
|
||||
sizeof(skb_frag_t));
|
||||
|
||||
get_page(skb_frag_page(&hssi->frags[0]));
|
||||
hssi->nr_frags = 1;
|
||||
hpdu_cb->frags = 1;
|
||||
hpdu_cb->hfrag_idx = 0;
|
||||
get_page(skb_frag_page(&hssi->frags[hfrag_idx]));
|
||||
hssi->nr_frags++;
|
||||
hpdu_cb->frags++;
|
||||
hpdu_cb->hfrag_idx = hfrag_idx;
|
||||
|
||||
len = hssi->frags[0].size;
|
||||
hskb->len = len;
|
||||
hskb->data_len = len;
|
||||
hskb->truesize = len;
|
||||
len = hssi->frags[hfrag_idx].size;
|
||||
hskb->len += len;
|
||||
hskb->data_len += len;
|
||||
hskb->truesize += len;
|
||||
}
|
||||
|
||||
if (pdu_cb->flags & PDUCBF_RX_DATA) {
|
||||
u8 hfrag_idx = 1, i;
|
||||
u8 dfrag_idx = hssi->nr_frags, i;
|
||||
|
||||
hpdu_cb->flags |= pdu_cb->flags;
|
||||
hpdu_cb->dfrag_idx = dfrag_idx;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < pdu_cb->nr_dfrags; hfrag_idx++, i++) {
|
||||
memcpy(&hssi->frags[hfrag_idx],
|
||||
for (i = 0; i < pdu_cb->nr_dfrags; dfrag_idx++, i++) {
|
||||
memcpy(&hssi->frags[dfrag_idx],
|
||||
&ssi->frags[pdu_cb->dfrag_idx + i],
|
||||
sizeof(skb_frag_t));
|
||||
|
||||
get_page(skb_frag_page(&hssi->frags[hfrag_idx]));
|
||||
get_page(skb_frag_page(&hssi->frags[dfrag_idx]));
|
||||
|
||||
len += hssi->frags[hfrag_idx].size;
|
||||
len += hssi->frags[dfrag_idx].size;
|
||||
|
||||
hssi->nr_frags++;
|
||||
hpdu_cb->frags++;
|
||||
|
|
@ -1405,7 +1474,6 @@ cxgbit_lro_skb_merge(struct cxgbit_sock *csk, struct sk_buff *skb, u8 pdu_idx)
|
|||
hpdu_cb->dlen = pdu_cb->dlen;
|
||||
hpdu_cb->doffset = hpdu_cb->hlen;
|
||||
hpdu_cb->nr_dfrags = pdu_cb->nr_dfrags;
|
||||
hpdu_cb->dfrag_idx = 1;
|
||||
hskb->len += len;
|
||||
hskb->data_len += len;
|
||||
hskb->truesize += len;
|
||||
|
|
@ -1490,10 +1558,15 @@ static int cxgbit_rx_lro_skb(struct cxgbit_sock *csk, struct sk_buff *skb)
|
|||
|
||||
static int cxgbit_rx_skb(struct cxgbit_sock *csk, struct sk_buff *skb)
|
||||
{
|
||||
struct cxgb4_lld_info *lldi = &csk->com.cdev->lldi;
|
||||
int ret = -1;
|
||||
|
||||
if (likely(cxgbit_skcb_flags(skb) & SKCBF_RX_LRO))
|
||||
ret = cxgbit_rx_lro_skb(csk, skb);
|
||||
if (likely(cxgbit_skcb_flags(skb) & SKCBF_RX_LRO)) {
|
||||
if (is_t5(lldi->adapter_type))
|
||||
ret = cxgbit_rx_lro_skb(csk, skb);
|
||||
else
|
||||
ret = cxgbit_process_lro_skb(csk, skb);
|
||||
}
|
||||
|
||||
__kfree_skb(skb);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -1431,36 +1431,17 @@ static void iscsit_do_crypto_hash_buf(
|
|||
}
|
||||
|
||||
int
|
||||
iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
||||
struct iscsi_cmd **out_cmd)
|
||||
__iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
|
||||
struct iscsi_cmd *cmd, u32 payload_length,
|
||||
bool *success)
|
||||
{
|
||||
struct iscsi_data *hdr = (struct iscsi_data *)buf;
|
||||
struct iscsi_cmd *cmd = NULL;
|
||||
struct iscsi_data *hdr = buf;
|
||||
struct se_cmd *se_cmd;
|
||||
u32 payload_length = ntoh24(hdr->dlength);
|
||||
int rc;
|
||||
|
||||
if (!payload_length) {
|
||||
pr_warn("DataOUT payload is ZERO, ignoring.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* iSCSI write */
|
||||
atomic_long_add(payload_length, &conn->sess->rx_data_octets);
|
||||
|
||||
if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
|
||||
pr_err("DataSegmentLength: %u is greater than"
|
||||
" MaxXmitDataSegmentLength: %u\n", payload_length,
|
||||
conn->conn_ops->MaxXmitDataSegmentLength);
|
||||
return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
|
||||
buf);
|
||||
}
|
||||
|
||||
cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt,
|
||||
payload_length);
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
|
||||
" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
|
||||
hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
|
||||
|
|
@ -1545,7 +1526,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
|||
}
|
||||
}
|
||||
/*
|
||||
* Preform DataSN, DataSequenceInOrder, DataPDUInOrder, and
|
||||
* Perform DataSN, DataSequenceInOrder, DataPDUInOrder, and
|
||||
* within-command recovery checks before receiving the payload.
|
||||
*/
|
||||
rc = iscsit_check_pre_dataout(cmd, buf);
|
||||
|
|
@ -1553,10 +1534,44 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
|
|||
return 0;
|
||||
else if (rc == DATAOUT_CANNOT_RECOVER)
|
||||
return -1;
|
||||
|
||||
*out_cmd = cmd;
|
||||
*success = true;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__iscsit_check_dataout_hdr);
|
||||
|
||||
int
|
||||
iscsit_check_dataout_hdr(struct iscsi_conn *conn, void *buf,
|
||||
struct iscsi_cmd **out_cmd)
|
||||
{
|
||||
struct iscsi_data *hdr = buf;
|
||||
struct iscsi_cmd *cmd;
|
||||
u32 payload_length = ntoh24(hdr->dlength);
|
||||
int rc;
|
||||
bool success = false;
|
||||
|
||||
if (!payload_length) {
|
||||
pr_warn_ratelimited("DataOUT payload is ZERO, ignoring.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
|
||||
pr_err_ratelimited("DataSegmentLength: %u is greater than"
|
||||
" MaxXmitDataSegmentLength: %u\n", payload_length,
|
||||
conn->conn_ops->MaxXmitDataSegmentLength);
|
||||
return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf);
|
||||
}
|
||||
|
||||
cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, payload_length);
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
rc = __iscsit_check_dataout_hdr(conn, buf, cmd, payload_length, &success);
|
||||
|
||||
if (success)
|
||||
*out_cmd = cmd;
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_check_dataout_hdr);
|
||||
|
||||
static int
|
||||
|
|
@ -1920,6 +1935,28 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static enum tcm_tmreq_table iscsit_convert_tmf(u8 iscsi_tmf)
|
||||
{
|
||||
switch (iscsi_tmf) {
|
||||
case ISCSI_TM_FUNC_ABORT_TASK:
|
||||
return TMR_ABORT_TASK;
|
||||
case ISCSI_TM_FUNC_ABORT_TASK_SET:
|
||||
return TMR_ABORT_TASK_SET;
|
||||
case ISCSI_TM_FUNC_CLEAR_ACA:
|
||||
return TMR_CLEAR_ACA;
|
||||
case ISCSI_TM_FUNC_CLEAR_TASK_SET:
|
||||
return TMR_CLEAR_TASK_SET;
|
||||
case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
|
||||
return TMR_LUN_RESET;
|
||||
case ISCSI_TM_FUNC_TARGET_WARM_RESET:
|
||||
return TMR_TARGET_WARM_RESET;
|
||||
case ISCSI_TM_FUNC_TARGET_COLD_RESET:
|
||||
return TMR_TARGET_COLD_RESET;
|
||||
default:
|
||||
return TMR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
unsigned char *buf)
|
||||
|
|
@ -1929,7 +1966,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
struct iscsi_tm *hdr;
|
||||
int out_of_order_cmdsn = 0, ret;
|
||||
bool sess_ref = false;
|
||||
u8 function;
|
||||
u8 function, tcm_function = TMR_UNKNOWN;
|
||||
|
||||
hdr = (struct iscsi_tm *) buf;
|
||||
hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
|
||||
|
|
@ -1975,54 +2012,27 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
|||
* LIO-Target $FABRIC_MOD
|
||||
*/
|
||||
if (function != ISCSI_TM_FUNC_TASK_REASSIGN) {
|
||||
|
||||
u8 tcm_function;
|
||||
int ret;
|
||||
|
||||
transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
|
||||
conn->sess->se_sess, 0, DMA_NONE,
|
||||
TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
|
||||
|
||||
target_get_sess_cmd(&cmd->se_cmd, true);
|
||||
sess_ref = true;
|
||||
|
||||
switch (function) {
|
||||
case ISCSI_TM_FUNC_ABORT_TASK:
|
||||
tcm_function = TMR_ABORT_TASK;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_ABORT_TASK_SET:
|
||||
tcm_function = TMR_ABORT_TASK_SET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_CLEAR_ACA:
|
||||
tcm_function = TMR_CLEAR_ACA;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_CLEAR_TASK_SET:
|
||||
tcm_function = TMR_CLEAR_TASK_SET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
|
||||
tcm_function = TMR_LUN_RESET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_TARGET_WARM_RESET:
|
||||
tcm_function = TMR_TARGET_WARM_RESET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_TARGET_COLD_RESET:
|
||||
tcm_function = TMR_TARGET_COLD_RESET;
|
||||
break;
|
||||
default:
|
||||
tcm_function = iscsit_convert_tmf(function);
|
||||
if (tcm_function == TMR_UNKNOWN) {
|
||||
pr_err("Unknown iSCSI TMR Function:"
|
||||
" 0x%02x\n", function);
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
|
||||
}
|
||||
|
||||
ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req,
|
||||
tcm_function, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
}
|
||||
ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
return iscsit_add_reject_cmd(cmd,
|
||||
ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
|
||||
|
||||
cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
|
||||
}
|
||||
cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;
|
||||
|
||||
cmd->iscsi_opcode = ISCSI_OP_SCSI_TMFUNC;
|
||||
cmd->i_state = ISTATE_SEND_TASKMGTRSP;
|
||||
|
|
@ -4136,7 +4146,7 @@ int iscsit_close_connection(
|
|||
/*
|
||||
* During Connection recovery drop unacknowledged out of order
|
||||
* commands for this connection, and prepare the other commands
|
||||
* for realligence.
|
||||
* for reallegiance.
|
||||
*
|
||||
* During normal operation clear the out of order commands (but
|
||||
* do not free the struct iscsi_ooo_cmdsn's) and release all
|
||||
|
|
@ -4144,7 +4154,7 @@ int iscsit_close_connection(
|
|||
*/
|
||||
if (atomic_read(&conn->connection_recovery)) {
|
||||
iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(conn);
|
||||
iscsit_prepare_cmds_for_realligance(conn);
|
||||
iscsit_prepare_cmds_for_reallegiance(conn);
|
||||
} else {
|
||||
iscsit_clear_ooo_cmdsns_for_conn(conn);
|
||||
iscsit_release_commands_from_conn(conn);
|
||||
|
|
|
|||
|
|
@ -44,10 +44,8 @@ void iscsit_set_dataout_sequence_values(
|
|||
*/
|
||||
if (cmd->unsolicited_data) {
|
||||
cmd->seq_start_offset = cmd->write_data_done;
|
||||
cmd->seq_end_offset = (cmd->write_data_done +
|
||||
((cmd->se_cmd.data_length >
|
||||
conn->sess->sess_ops->FirstBurstLength) ?
|
||||
conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length));
|
||||
cmd->seq_end_offset = min(cmd->se_cmd.data_length,
|
||||
conn->sess->sess_ops->FirstBurstLength);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
||||
int iscsit_prepare_cmds_for_reallegiance(struct iscsi_conn *conn)
|
||||
{
|
||||
u32 cmd_count = 0;
|
||||
struct iscsi_cmd *cmd, *cmd_tmp;
|
||||
|
|
@ -347,7 +347,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
|||
|
||||
if ((cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD) &&
|
||||
(cmd->iscsi_opcode != ISCSI_OP_NOOP_OUT)) {
|
||||
pr_debug("Not performing realligence on"
|
||||
pr_debug("Not performing reallegiance on"
|
||||
" Opcode: 0x%02x, ITT: 0x%08x, CmdSN: 0x%08x,"
|
||||
" CID: %hu\n", cmd->iscsi_opcode,
|
||||
cmd->init_task_tag, cmd->cmd_sn, conn->cid);
|
||||
|
|
@ -382,7 +382,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
|||
cmd_count++;
|
||||
pr_debug("Preparing Opcode: 0x%02x, ITT: 0x%08x,"
|
||||
" CmdSN: 0x%08x, StatSN: 0x%08x, CID: %hu for"
|
||||
" realligence.\n", cmd->iscsi_opcode,
|
||||
" reallegiance.\n", cmd->iscsi_opcode,
|
||||
cmd->init_task_tag, cmd->cmd_sn, cmd->stat_sn,
|
||||
conn->cid);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ extern int iscsit_remove_cmd_from_connection_recovery(struct iscsi_cmd *,
|
|||
struct iscsi_session *);
|
||||
extern void iscsit_discard_cr_cmds_by_expstatsn(struct iscsi_conn_recovery *, u32);
|
||||
extern int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *);
|
||||
extern int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *);
|
||||
extern int iscsit_prepare_cmds_for_reallegiance(struct iscsi_conn *);
|
||||
extern int iscsit_connection_recovery_transport_reset(struct iscsi_conn *);
|
||||
|
||||
#endif /*** ISCSI_TARGET_ERL2_H ***/
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
|
|||
return 0;
|
||||
|
||||
pr_debug("%s iSCSI Session SID %u is still active for %s,"
|
||||
" preforming session reinstatement.\n", (sessiontype) ?
|
||||
" performing session reinstatement.\n", (sessiontype) ?
|
||||
"Discovery" : "Normal", sess->sid,
|
||||
sess->sess_ops->InitiatorName);
|
||||
|
||||
|
|
|
|||
|
|
@ -1249,16 +1249,16 @@ int iscsi_target_start_negotiation(
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (conn->sock) {
|
||||
struct sock *sk = conn->sock->sk;
|
||||
if (conn->sock) {
|
||||
struct sock *sk = conn->sock->sk;
|
||||
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
set_bit(LOGIN_FLAGS_READY, &conn->login_flags);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
write_lock_bh(&sk->sk_callback_lock);
|
||||
set_bit(LOGIN_FLAGS_READY, &conn->login_flags);
|
||||
write_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
|
||||
ret = iscsi_target_do_login(conn, login);
|
||||
if (ret < 0) {
|
||||
ret = iscsi_target_do_login(conn, login);
|
||||
if (ret < 0) {
|
||||
cancel_delayed_work_sync(&conn->login_work);
|
||||
cancel_delayed_work_sync(&conn->login_cleanup_work);
|
||||
iscsi_target_restore_sock_callbacks(conn);
|
||||
|
|
|
|||
|
|
@ -440,14 +440,14 @@ static int iscsit_task_reassign_complete(
|
|||
break;
|
||||
default:
|
||||
pr_err("Illegal iSCSI Opcode 0x%02x during"
|
||||
" command realligence\n", cmd->iscsi_opcode);
|
||||
" command reallegiance\n", cmd->iscsi_opcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
pr_debug("Completed connection realligence for Opcode: 0x%02x,"
|
||||
pr_debug("Completed connection reallegiance for Opcode: 0x%02x,"
|
||||
" ITT: 0x%08x to CID: %hu.\n", cmd->iscsi_opcode,
|
||||
cmd->init_task_tag, conn->cid);
|
||||
|
||||
|
|
|
|||
|
|
@ -417,6 +417,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
|
|||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_find_cmd_from_itt_or_dump);
|
||||
|
||||
struct iscsi_cmd *iscsit_find_cmd_from_ttt(
|
||||
struct iscsi_conn *conn,
|
||||
|
|
@ -1377,33 +1378,6 @@ int tx_data(
|
|||
return iscsit_do_tx_data(conn, &c);
|
||||
}
|
||||
|
||||
static bool sockaddr_equal(struct sockaddr_storage *x, struct sockaddr_storage *y)
|
||||
{
|
||||
switch (x->ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *sinx = (struct sockaddr_in *)x;
|
||||
struct sockaddr_in *siny = (struct sockaddr_in *)y;
|
||||
if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
|
||||
return false;
|
||||
if (sinx->sin_port != siny->sin_port)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
|
||||
struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
|
||||
if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
|
||||
return false;
|
||||
if (sinx->sin6_port != siny->sin6_port)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void iscsit_collect_login_stats(
|
||||
struct iscsi_conn *conn,
|
||||
u8 status_class,
|
||||
|
|
@ -1420,13 +1394,6 @@ void iscsit_collect_login_stats(
|
|||
ls = &tiqn->login_stats;
|
||||
|
||||
spin_lock(&ls->lock);
|
||||
if (sockaddr_equal(&conn->login_sockaddr, &ls->last_intr_fail_sockaddr) &&
|
||||
((get_jiffies_64() - ls->last_fail_time) < 10)) {
|
||||
/* We already have the failure info for this login */
|
||||
spin_unlock(&ls->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status_class == ISCSI_STATUS_CLS_SUCCESS)
|
||||
ls->accepts++;
|
||||
else if (status_class == ISCSI_STATUS_CLS_REDIRECT) {
|
||||
|
|
@ -1471,10 +1438,10 @@ struct iscsi_tiqn *iscsit_snmp_get_tiqn(struct iscsi_conn *conn)
|
|||
{
|
||||
struct iscsi_portal_group *tpg;
|
||||
|
||||
if (!conn || !conn->sess)
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
||||
tpg = conn->sess->tpg;
|
||||
tpg = conn->tpg;
|
||||
if (!tpg)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -78,12 +78,16 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
|
|||
&deve->read_bytes);
|
||||
|
||||
se_lun = rcu_dereference(deve->se_lun);
|
||||
|
||||
if (!percpu_ref_tryget_live(&se_lun->lun_ref)) {
|
||||
se_lun = NULL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
se_cmd->se_lun = rcu_dereference(deve->se_lun);
|
||||
se_cmd->pr_res_key = deve->pr_res_key;
|
||||
se_cmd->orig_fe_lun = unpacked_lun;
|
||||
se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
|
||||
|
||||
percpu_ref_get(&se_lun->lun_ref);
|
||||
se_cmd->lun_ref_active = true;
|
||||
|
||||
if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
|
||||
|
|
@ -97,6 +101,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
|
|||
goto ref_dev;
|
||||
}
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!se_lun) {
|
||||
|
|
@ -163,7 +168,6 @@ int transport_lookup_tmr_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
|
|||
rcu_read_lock();
|
||||
deve = target_nacl_find_deve(nacl, unpacked_lun);
|
||||
if (deve) {
|
||||
se_tmr->tmr_lun = rcu_dereference(deve->se_lun);
|
||||
se_cmd->se_lun = rcu_dereference(deve->se_lun);
|
||||
se_lun = rcu_dereference(deve->se_lun);
|
||||
se_cmd->pr_res_key = deve->pr_res_key;
|
||||
|
|
@ -816,6 +820,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
|||
xcopy_lun = &dev->xcopy_lun;
|
||||
rcu_assign_pointer(xcopy_lun->lun_se_dev, dev);
|
||||
init_completion(&xcopy_lun->lun_ref_comp);
|
||||
init_completion(&xcopy_lun->lun_shutdown_comp);
|
||||
INIT_LIST_HEAD(&xcopy_lun->lun_deve_list);
|
||||
INIT_LIST_HEAD(&xcopy_lun->lun_dev_link);
|
||||
mutex_init(&xcopy_lun->lun_tg_pt_md_mutex);
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
|
|||
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->t_state = TRANSPORT_PROCESSING;
|
||||
cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
|
||||
cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
|
||||
__target_execute_cmd(cmd, false);
|
||||
|
|
|
|||
|
|
@ -158,12 +158,28 @@ static ssize_t target_stat_tgt_resets_show(struct config_item *item,
|
|||
atomic_long_read(&to_stat_tgt_dev(item)->num_resets));
|
||||
}
|
||||
|
||||
static ssize_t target_stat_tgt_aborts_complete_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
return snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&to_stat_tgt_dev(item)->aborts_complete));
|
||||
}
|
||||
|
||||
static ssize_t target_stat_tgt_aborts_no_task_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
return snprintf(page, PAGE_SIZE, "%lu\n",
|
||||
atomic_long_read(&to_stat_tgt_dev(item)->aborts_no_task));
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, inst);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, indx);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, num_lus);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, status);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, non_access_lus);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, resets);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, aborts_complete);
|
||||
CONFIGFS_ATTR_RO(target_stat_tgt_, aborts_no_task);
|
||||
|
||||
static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
|
||||
&target_stat_tgt_attr_inst,
|
||||
|
|
@ -172,6 +188,8 @@ static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
|
|||
&target_stat_tgt_attr_status,
|
||||
&target_stat_tgt_attr_non_access_lus,
|
||||
&target_stat_tgt_attr_resets,
|
||||
&target_stat_tgt_attr_aborts_complete,
|
||||
&target_stat_tgt_attr_aborts_no_task,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -795,16 +813,34 @@ static ssize_t target_stat_transport_dev_name_show(struct config_item *item,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t target_stat_transport_proto_id_show(struct config_item *item,
|
||||
char *page)
|
||||
{
|
||||
struct se_lun *lun = to_transport_stat(item);
|
||||
struct se_device *dev;
|
||||
struct se_portal_group *tpg = lun->lun_tpg;
|
||||
ssize_t ret = -ENODEV;
|
||||
|
||||
rcu_read_lock();
|
||||
dev = rcu_dereference(lun->lun_se_dev);
|
||||
if (dev)
|
||||
ret = snprintf(page, PAGE_SIZE, "%u\n", tpg->proto_id);
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, inst);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, device);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, indx);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, dev_name);
|
||||
CONFIGFS_ATTR_RO(target_stat_transport_, proto_id);
|
||||
|
||||
static struct configfs_attribute *target_stat_scsi_transport_attrs[] = {
|
||||
&target_stat_transport_attr_inst,
|
||||
&target_stat_transport_attr_device,
|
||||
&target_stat_transport_attr_indx,
|
||||
&target_stat_transport_attr_dev_name,
|
||||
&target_stat_transport_attr_proto_id,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -175,10 +175,9 @@ void core_tmr_abort_task(
|
|||
printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
|
||||
se_cmd->se_tfo->get_fabric_name(), ref_tag);
|
||||
|
||||
if (!__target_check_io_state(se_cmd, se_sess, 0)) {
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
if (!__target_check_io_state(se_cmd, se_sess, 0))
|
||||
continue;
|
||||
|
||||
list_del_init(&se_cmd->se_cmd_list);
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
|
|
@ -191,14 +190,15 @@ void core_tmr_abort_task(
|
|||
printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
|
||||
" ref_tag: %llu\n", ref_tag);
|
||||
tmr->response = TMR_FUNCTION_COMPLETE;
|
||||
atomic_long_inc(&dev->aborts_complete);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
out:
|
||||
printk("ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST for ref_tag: %lld\n",
|
||||
tmr->ref_task_tag);
|
||||
tmr->response = TMR_TASK_DOES_NOT_EXIST;
|
||||
atomic_long_inc(&dev->aborts_no_task);
|
||||
}
|
||||
|
||||
static void core_tmr_drain_tmr_list(
|
||||
|
|
@ -217,13 +217,8 @@ static void core_tmr_drain_tmr_list(
|
|||
* LUN_RESET tmr..
|
||||
*/
|
||||
spin_lock_irqsave(&dev->se_tmr_lock, flags);
|
||||
list_del_init(&tmr->tmr_list);
|
||||
list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) {
|
||||
/*
|
||||
* Allow the received TMR to return with FUNCTION_COMPLETE.
|
||||
*/
|
||||
if (tmr_p == tmr)
|
||||
continue;
|
||||
|
||||
cmd = tmr_p->task_cmd;
|
||||
if (!cmd) {
|
||||
pr_err("Unable to locate struct se_cmd for TMR\n");
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ static void core_tpg_lun_ref_release(struct percpu_ref *ref)
|
|||
{
|
||||
struct se_lun *lun = container_of(ref, struct se_lun, lun_ref);
|
||||
|
||||
complete(&lun->lun_ref_comp);
|
||||
complete(&lun->lun_shutdown_comp);
|
||||
}
|
||||
|
||||
/* Does not change se_wwn->priv. */
|
||||
|
|
@ -572,6 +572,7 @@ struct se_lun *core_tpg_alloc_lun(
|
|||
lun->lun_link_magic = SE_LUN_LINK_MAGIC;
|
||||
atomic_set(&lun->lun_acl_count, 0);
|
||||
init_completion(&lun->lun_ref_comp);
|
||||
init_completion(&lun->lun_shutdown_comp);
|
||||
INIT_LIST_HEAD(&lun->lun_deve_list);
|
||||
INIT_LIST_HEAD(&lun->lun_dev_link);
|
||||
atomic_set(&lun->lun_tg_pt_secondary_offline, 0);
|
||||
|
|
|
|||
|
|
@ -593,9 +593,6 @@ static void target_remove_from_state_list(struct se_cmd *cmd)
|
|||
if (!dev)
|
||||
return;
|
||||
|
||||
if (cmd->transport_state & CMD_T_BUSY)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev->execute_task_lock, flags);
|
||||
if (cmd->state_active) {
|
||||
list_del(&cmd->state_list);
|
||||
|
|
@ -604,24 +601,18 @@ static void target_remove_from_state_list(struct se_cmd *cmd)
|
|||
spin_unlock_irqrestore(&dev->execute_task_lock, flags);
|
||||
}
|
||||
|
||||
static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
|
||||
bool write_pending)
|
||||
static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (remove_from_lists) {
|
||||
target_remove_from_state_list(cmd);
|
||||
target_remove_from_state_list(cmd);
|
||||
|
||||
/*
|
||||
* Clear struct se_cmd->se_lun before the handoff to FE.
|
||||
*/
|
||||
cmd->se_lun = NULL;
|
||||
}
|
||||
/*
|
||||
* Clear struct se_cmd->se_lun before the handoff to FE.
|
||||
*/
|
||||
cmd->se_lun = NULL;
|
||||
|
||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||
if (write_pending)
|
||||
cmd->t_state = TRANSPORT_WRITE_PENDING;
|
||||
|
||||
/*
|
||||
* Determine if frontend context caller is requesting the stopping of
|
||||
* this command for frontend exceptions.
|
||||
|
|
@ -635,31 +626,18 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
|
|||
complete_all(&cmd->t_transport_stop_comp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmd->transport_state &= ~CMD_T_ACTIVE;
|
||||
if (remove_from_lists) {
|
||||
/*
|
||||
* Some fabric modules like tcm_loop can release
|
||||
* their internally allocated I/O reference now and
|
||||
* struct se_cmd now.
|
||||
*
|
||||
* Fabric modules are expected to return '1' here if the
|
||||
* se_cmd being passed is released at this point,
|
||||
* or zero if not being released.
|
||||
*/
|
||||
if (cmd->se_tfo->check_stop_free != NULL) {
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
return cmd->se_tfo->check_stop_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
|
||||
{
|
||||
return transport_cmd_check_stop(cmd, true, false);
|
||||
/*
|
||||
* Some fabric modules like tcm_loop can release their internally
|
||||
* allocated I/O reference and struct se_cmd now.
|
||||
*
|
||||
* Fabric modules are expected to return '1' here if the se_cmd being
|
||||
* passed is released at this point, or zero if not being released.
|
||||
*/
|
||||
return cmd->se_tfo->check_stop_free ? cmd->se_tfo->check_stop_free(cmd)
|
||||
: 0;
|
||||
}
|
||||
|
||||
static void transport_lun_remove_cmd(struct se_cmd *cmd)
|
||||
|
|
@ -733,7 +711,6 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
|
|||
|
||||
|
||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||
cmd->transport_state &= ~CMD_T_BUSY;
|
||||
|
||||
if (dev && dev->transport->transport_complete) {
|
||||
dev->transport->transport_complete(cmd,
|
||||
|
|
@ -1246,7 +1223,6 @@ void transport_init_se_cmd(
|
|||
init_completion(&cmd->cmd_wait_comp);
|
||||
spin_lock_init(&cmd->t_state_lock);
|
||||
kref_init(&cmd->cmd_kref);
|
||||
cmd->transport_state = CMD_T_DEV_ACTIVE;
|
||||
|
||||
cmd->se_tfo = tfo;
|
||||
cmd->se_sess = se_sess;
|
||||
|
|
@ -1671,6 +1647,9 @@ void transport_generic_request_failure(struct se_cmd *cmd,
|
|||
{
|
||||
int ret = 0, post_ret = 0;
|
||||
|
||||
if (transport_check_aborted_status(cmd, 1))
|
||||
return;
|
||||
|
||||
pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08llx"
|
||||
" CDB: 0x%02x\n", cmd, cmd->tag, cmd->t_task_cdb[0]);
|
||||
pr_debug("-----[ i_state: %d t_state: %d sense_reason: %d\n",
|
||||
|
|
@ -1801,7 +1780,7 @@ void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
|
|||
return;
|
||||
err:
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
|
||||
cmd->transport_state &= ~CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
|
||||
transport_generic_request_failure(cmd, ret);
|
||||
|
|
@ -1829,7 +1808,7 @@ static int target_write_prot_action(struct se_cmd *cmd)
|
|||
sectors, 0, cmd->t_prot_sg, 0);
|
||||
if (unlikely(cmd->pi_err)) {
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
|
||||
cmd->transport_state &= ~CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
transport_generic_request_failure(cmd, cmd->pi_err);
|
||||
return -1;
|
||||
|
|
@ -1918,7 +1897,7 @@ void target_execute_cmd(struct se_cmd *cmd)
|
|||
}
|
||||
|
||||
cmd->t_state = TRANSPORT_PROCESSING;
|
||||
cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
|
||||
cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
|
||||
if (target_write_prot_action(cmd))
|
||||
|
|
@ -1926,7 +1905,7 @@ void target_execute_cmd(struct se_cmd *cmd)
|
|||
|
||||
if (target_handle_task_attr(cmd)) {
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
cmd->transport_state &= ~(CMD_T_BUSY | CMD_T_SENT);
|
||||
cmd->transport_state &= ~CMD_T_SENT;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1979,8 +1958,6 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
|
|||
if (cmd->sam_task_attr == TCM_SIMPLE_TAG) {
|
||||
atomic_dec_mb(&dev->simple_cmds);
|
||||
dev->dev_cur_ordered_id++;
|
||||
pr_debug("Incremented dev->dev_cur_ordered_id: %u for SIMPLE\n",
|
||||
dev->dev_cur_ordered_id);
|
||||
} else if (cmd->sam_task_attr == TCM_HEAD_TAG) {
|
||||
dev->dev_cur_ordered_id++;
|
||||
pr_debug("Incremented dev_cur_ordered_id: %u for HEAD_OF_QUEUE\n",
|
||||
|
|
@ -2387,6 +2364,7 @@ EXPORT_SYMBOL(target_alloc_sgl);
|
|||
sense_reason_t
|
||||
transport_generic_new_cmd(struct se_cmd *cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
|
||||
|
||||
|
|
@ -2452,7 +2430,24 @@ transport_generic_new_cmd(struct se_cmd *cmd)
|
|||
target_execute_cmd(cmd);
|
||||
return 0;
|
||||
}
|
||||
transport_cmd_check_stop(cmd, false, true);
|
||||
|
||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||
cmd->t_state = TRANSPORT_WRITE_PENDING;
|
||||
/*
|
||||
* Determine if frontend context caller is requesting the stopping of
|
||||
* this command for frontend exceptions.
|
||||
*/
|
||||
if (cmd->transport_state & CMD_T_STOP) {
|
||||
pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08llx\n",
|
||||
__func__, __LINE__, cmd->tag);
|
||||
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
|
||||
complete_all(&cmd->t_transport_stop_comp);
|
||||
return 0;
|
||||
}
|
||||
cmd->transport_state &= ~CMD_T_ACTIVE;
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
|
||||
ret = cmd->se_tfo->write_pending(cmd);
|
||||
if (ret == -EAGAIN || ret == -ENOMEM)
|
||||
|
|
@ -2595,39 +2590,38 @@ static void target_release_cmd_kref(struct kref *kref)
|
|||
unsigned long flags;
|
||||
bool fabric_stop;
|
||||
|
||||
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
|
||||
if (se_sess) {
|
||||
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
spin_lock(&se_cmd->t_state_lock);
|
||||
fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
|
||||
(se_cmd->transport_state & CMD_T_ABORTED);
|
||||
spin_unlock(&se_cmd->t_state_lock);
|
||||
spin_lock(&se_cmd->t_state_lock);
|
||||
fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
|
||||
(se_cmd->transport_state & CMD_T_ABORTED);
|
||||
spin_unlock(&se_cmd->t_state_lock);
|
||||
|
||||
if (se_cmd->cmd_wait_set || fabric_stop) {
|
||||
if (se_cmd->cmd_wait_set || fabric_stop) {
|
||||
list_del_init(&se_cmd->se_cmd_list);
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
target_free_cmd_mem(se_cmd);
|
||||
complete(&se_cmd->cmd_wait_comp);
|
||||
return;
|
||||
}
|
||||
list_del_init(&se_cmd->se_cmd_list);
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
target_free_cmd_mem(se_cmd);
|
||||
complete(&se_cmd->cmd_wait_comp);
|
||||
return;
|
||||
}
|
||||
list_del_init(&se_cmd->se_cmd_list);
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
|
||||
target_free_cmd_mem(se_cmd);
|
||||
se_cmd->se_tfo->release_cmd(se_cmd);
|
||||
}
|
||||
|
||||
/* target_put_sess_cmd - Check for active I/O shutdown via kref_put
|
||||
* @se_cmd: command descriptor to drop
|
||||
/**
|
||||
* target_put_sess_cmd - decrease the command reference count
|
||||
* @se_cmd: command to drop a reference from
|
||||
*
|
||||
* Returns 1 if and only if this target_put_sess_cmd() call caused the
|
||||
* refcount to drop to zero. Returns zero otherwise.
|
||||
*/
|
||||
int target_put_sess_cmd(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct se_session *se_sess = se_cmd->se_sess;
|
||||
|
||||
if (!se_sess) {
|
||||
target_free_cmd_mem(se_cmd);
|
||||
se_cmd->se_tfo->release_cmd(se_cmd);
|
||||
return 1;
|
||||
}
|
||||
return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
|
||||
}
|
||||
EXPORT_SYMBOL(target_put_sess_cmd);
|
||||
|
|
@ -2706,10 +2700,39 @@ void target_wait_for_sess_cmds(struct se_session *se_sess)
|
|||
}
|
||||
EXPORT_SYMBOL(target_wait_for_sess_cmds);
|
||||
|
||||
static void target_lun_confirm(struct percpu_ref *ref)
|
||||
{
|
||||
struct se_lun *lun = container_of(ref, struct se_lun, lun_ref);
|
||||
|
||||
complete(&lun->lun_ref_comp);
|
||||
}
|
||||
|
||||
void transport_clear_lun_ref(struct se_lun *lun)
|
||||
{
|
||||
percpu_ref_kill(&lun->lun_ref);
|
||||
/*
|
||||
* Mark the percpu-ref as DEAD, switch to atomic_t mode, drop
|
||||
* the initial reference and schedule confirm kill to be
|
||||
* executed after one full RCU grace period has completed.
|
||||
*/
|
||||
percpu_ref_kill_and_confirm(&lun->lun_ref, target_lun_confirm);
|
||||
/*
|
||||
* The first completion waits for percpu_ref_switch_to_atomic_rcu()
|
||||
* to call target_lun_confirm after lun->lun_ref has been marked
|
||||
* as __PERCPU_REF_DEAD on all CPUs, and switches to atomic_t
|
||||
* mode so that percpu_ref_tryget_live() lookup of lun->lun_ref
|
||||
* fails for all new incoming I/O.
|
||||
*/
|
||||
wait_for_completion(&lun->lun_ref_comp);
|
||||
/*
|
||||
* The second completion waits for percpu_ref_put_many() to
|
||||
* invoke ->release() after lun->lun_ref has switched to
|
||||
* atomic_t mode, and lun->lun_ref.count has reached zero.
|
||||
*
|
||||
* At this point all target-core lun->lun_ref references have
|
||||
* been dropped via transport_lun_remove_cmd(), and it's safe
|
||||
* to proceed with the remaining LUN shutdown.
|
||||
*/
|
||||
wait_for_completion(&lun->lun_shutdown_comp);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -2765,11 +2788,8 @@ __transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop,
|
|||
}
|
||||
|
||||
/**
|
||||
* transport_wait_for_tasks - wait for completion to occur
|
||||
* @cmd: command to wait
|
||||
*
|
||||
* Called from frontend fabric context to wait for storage engine
|
||||
* to pause and/or release frontend generated struct se_cmd.
|
||||
* transport_wait_for_tasks - set CMD_T_STOP and wait for t_transport_stop_comp
|
||||
* @cmd: command to wait on
|
||||
*/
|
||||
bool transport_wait_for_tasks(struct se_cmd *cmd)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -83,14 +83,12 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
|
|||
static void ft_free_cmd(struct ft_cmd *cmd)
|
||||
{
|
||||
struct fc_frame *fp;
|
||||
struct fc_lport *lport;
|
||||
struct ft_sess *sess;
|
||||
|
||||
if (!cmd)
|
||||
return;
|
||||
sess = cmd->sess;
|
||||
fp = cmd->req_frame;
|
||||
lport = fr_dev(fp);
|
||||
if (fr_seq(fp))
|
||||
fc_seq_release(fr_seq(fp));
|
||||
fc_frame_free(fp);
|
||||
|
|
|
|||
Loading…
Reference in a new issue