Commit 66a523db authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target fixes from Nicholas Bellinger:
 "This series addresses a number of outstanding issues wrt to active I/O
  shutdown using iser-target.  This includes:

   - Fix a long standing tpg_state bug where a tpg could be referenced
     during explicit shutdown (v3.1+ stable)
   - Use list_del_init for iscsi_cmd->i_conn_node so list_empty checks
     work as expected (v3.10+ stable)
   - Fix a isert_conn->state related hung task bug + ensure outstanding
     I/O completes during session shutdown.  (v3.10+ stable)
   - Fix isert_conn->post_send_buf_count accounting for RDMA READ/WRITEs
     (v3.10+ stable)
   - Ignore FRWR completions during active I/O shutdown (v3.12+ stable)
   - Fix command leakage for interrupt coalescing during active I/O
     shutdown (v3.13+ stable)

  Also included is another DIF emulation fix from Sagi specific to
  v3.14-rc code"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  Target/sbc: Fix sbc_copy_prot for offset scatters
  iser-target: Fix command leak for tx_desc->comp_llnode_batch
  iser-target: Ignore completions for FRWRs in isert_cq_tx_work
  iser-target: Fix post_send_buf_count for RDMA READ/WRITE
  iscsi/iser-target: Fix isert_conn->state hung shutdown issues
  iscsi/iser-target: Use list_del_init for ->i_conn_node
  iscsi-target: Fix iscsit_get_tpg_from_np tpg_state bug
parents 4c7b7040 16c0ae02
This diff is collapsed.
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define ISERT_RDMA_LISTEN_BACKLOG 10 #define ISERT_RDMA_LISTEN_BACKLOG 10
#define ISCSI_ISER_SG_TABLESIZE 256 #define ISCSI_ISER_SG_TABLESIZE 256
#define ISER_FASTREG_LI_WRID 0xffffffffffffffffULL
enum isert_desc_type { enum isert_desc_type {
ISCSI_TX_CONTROL, ISCSI_TX_CONTROL,
...@@ -45,6 +46,7 @@ struct iser_tx_desc { ...@@ -45,6 +46,7 @@ struct iser_tx_desc {
struct isert_cmd *isert_cmd; struct isert_cmd *isert_cmd;
struct llist_node *comp_llnode_batch; struct llist_node *comp_llnode_batch;
struct llist_node comp_llnode; struct llist_node comp_llnode;
bool llnode_active;
struct ib_send_wr send_wr; struct ib_send_wr send_wr;
} __packed; } __packed;
...@@ -116,8 +118,8 @@ struct isert_conn { ...@@ -116,8 +118,8 @@ struct isert_conn {
struct isert_device *conn_device; struct isert_device *conn_device;
struct work_struct conn_logout_work; struct work_struct conn_logout_work;
struct mutex conn_mutex; struct mutex conn_mutex;
wait_queue_head_t conn_wait; struct completion conn_wait;
wait_queue_head_t conn_wait_comp_err; struct completion conn_wait_comp_err;
struct kref conn_kref; struct kref conn_kref;
struct list_head conn_fr_pool; struct list_head conn_fr_pool;
int conn_fr_pool_size; int conn_fr_pool_size;
...@@ -126,7 +128,6 @@ struct isert_conn { ...@@ -126,7 +128,6 @@ struct isert_conn {
#define ISERT_COMP_BATCH_COUNT 8 #define ISERT_COMP_BATCH_COUNT 8
int conn_comp_batch; int conn_comp_batch;
struct llist_head conn_comp_llist; struct llist_head conn_comp_llist;
struct mutex conn_comp_mutex;
}; };
#define ISERT_MAX_CQ 64 #define ISERT_MAX_CQ 64
......
...@@ -785,7 +785,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn) ...@@ -785,7 +785,7 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) { list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
iscsit_free_cmd(cmd, false); iscsit_free_cmd(cmd, false);
} }
} }
...@@ -3708,7 +3708,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state ...@@ -3708,7 +3708,7 @@ iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state
break; break;
case ISTATE_REMOVE: case ISTATE_REMOVE:
spin_lock_bh(&conn->cmd_lock); spin_lock_bh(&conn->cmd_lock);
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd, false); iscsit_free_cmd(cmd, false);
...@@ -4151,7 +4151,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) ...@@ -4151,7 +4151,7 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
spin_lock_bh(&conn->cmd_lock); spin_lock_bh(&conn->cmd_lock);
list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) { list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
iscsit_increment_maxcmdsn(cmd, sess); iscsit_increment_maxcmdsn(cmd, sess);
...@@ -4196,6 +4196,10 @@ int iscsit_close_connection( ...@@ -4196,6 +4196,10 @@ int iscsit_close_connection(
iscsit_stop_timers_for_cmds(conn); iscsit_stop_timers_for_cmds(conn);
iscsit_stop_nopin_response_timer(conn); iscsit_stop_nopin_response_timer(conn);
iscsit_stop_nopin_timer(conn); iscsit_stop_nopin_timer(conn);
if (conn->conn_transport->iscsit_wait_conn)
conn->conn_transport->iscsit_wait_conn(conn);
iscsit_free_queue_reqs_for_conn(conn); iscsit_free_queue_reqs_for_conn(conn);
/* /*
......
...@@ -138,7 +138,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess) ...@@ -138,7 +138,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
list_for_each_entry_safe(cmd, cmd_tmp, list_for_each_entry_safe(cmd, cmd_tmp,
&cr->conn_recovery_cmd_list, i_conn_node) { &cr->conn_recovery_cmd_list, i_conn_node) {
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
cmd->conn = NULL; cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock); spin_unlock(&cr->conn_recovery_cmd_lock);
iscsit_free_cmd(cmd, true); iscsit_free_cmd(cmd, true);
...@@ -160,7 +160,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess) ...@@ -160,7 +160,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
list_for_each_entry_safe(cmd, cmd_tmp, list_for_each_entry_safe(cmd, cmd_tmp,
&cr->conn_recovery_cmd_list, i_conn_node) { &cr->conn_recovery_cmd_list, i_conn_node) {
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
cmd->conn = NULL; cmd->conn = NULL;
spin_unlock(&cr->conn_recovery_cmd_lock); spin_unlock(&cr->conn_recovery_cmd_lock);
iscsit_free_cmd(cmd, true); iscsit_free_cmd(cmd, true);
...@@ -216,7 +216,7 @@ int iscsit_remove_cmd_from_connection_recovery( ...@@ -216,7 +216,7 @@ int iscsit_remove_cmd_from_connection_recovery(
} }
cr = cmd->cr; cr = cmd->cr;
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
return --cr->cmd_count; return --cr->cmd_count;
} }
...@@ -297,7 +297,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn) ...@@ -297,7 +297,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
if (!(cmd->cmd_flags & ICF_OOO_CMDSN)) if (!(cmd->cmd_flags & ICF_OOO_CMDSN))
continue; continue;
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd, true); iscsit_free_cmd(cmd, true);
...@@ -335,7 +335,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) ...@@ -335,7 +335,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
/* /*
* Only perform connection recovery on ISCSI_OP_SCSI_CMD or * Only perform connection recovery on ISCSI_OP_SCSI_CMD or
* ISCSI_OP_NOOP_OUT opcodes. For all other opcodes call * ISCSI_OP_NOOP_OUT opcodes. For all other opcodes call
* list_del(&cmd->i_conn_node); to release the command to the * list_del_init(&cmd->i_conn_node); to release the command to the
* session pool and remove it from the connection's list. * session pool and remove it from the connection's list.
* *
* Also stop the DataOUT timer, which will be restarted after * Also stop the DataOUT timer, which will be restarted after
...@@ -351,7 +351,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) ...@@ -351,7 +351,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
" CID: %hu\n", cmd->iscsi_opcode, " CID: %hu\n", cmd->iscsi_opcode,
cmd->init_task_tag, cmd->cmd_sn, conn->cid); cmd->init_task_tag, cmd->cmd_sn, conn->cid);
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd, true); iscsit_free_cmd(cmd, true);
spin_lock_bh(&conn->cmd_lock); spin_lock_bh(&conn->cmd_lock);
...@@ -371,7 +371,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) ...@@ -371,7 +371,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
*/ */
if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) {
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
iscsit_free_cmd(cmd, true); iscsit_free_cmd(cmd, true);
spin_lock_bh(&conn->cmd_lock); spin_lock_bh(&conn->cmd_lock);
...@@ -393,7 +393,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) ...@@ -393,7 +393,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
cmd->sess = conn->sess; cmd->sess = conn->sess;
list_del(&cmd->i_conn_node); list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
iscsit_free_all_datain_reqs(cmd); iscsit_free_all_datain_reqs(cmd);
......
...@@ -137,7 +137,7 @@ struct iscsi_portal_group *iscsit_get_tpg_from_np( ...@@ -137,7 +137,7 @@ struct iscsi_portal_group *iscsit_get_tpg_from_np(
list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) { list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
spin_lock(&tpg->tpg_state_lock); spin_lock(&tpg->tpg_state_lock);
if (tpg->tpg_state == TPG_STATE_FREE) { if (tpg->tpg_state != TPG_STATE_ACTIVE) {
spin_unlock(&tpg->tpg_state_lock); spin_unlock(&tpg->tpg_state_lock);
continue; continue;
} }
......
...@@ -1079,25 +1079,31 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read, ...@@ -1079,25 +1079,31 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
left = sectors * dev->prot_length; left = sectors * dev->prot_length;
for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) { for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {
unsigned int psg_len, copied = 0;
len = min(psg->length, left);
if (offset >= sg->length) {
sg = sg_next(sg);
offset = 0;
}
paddr = kmap_atomic(sg_page(psg)) + psg->offset; paddr = kmap_atomic(sg_page(psg)) + psg->offset;
addr = kmap_atomic(sg_page(sg)) + sg->offset + offset; psg_len = min(left, psg->length);
while (psg_len) {
if (read) len = min(psg_len, sg->length - offset);
memcpy(paddr, addr, len); addr = kmap_atomic(sg_page(sg)) + sg->offset + offset;
else
memcpy(addr, paddr, len); if (read)
memcpy(paddr + copied, addr, len);
left -= len; else
offset += len; memcpy(addr, paddr + copied, len);
left -= len;
offset += len;
copied += len;
psg_len -= len;
if (offset >= sg->length) {
sg = sg_next(sg);
offset = 0;
}
kunmap_atomic(addr);
}
kunmap_atomic(paddr); kunmap_atomic(paddr);
kunmap_atomic(addr);
} }
} }
......
...@@ -12,6 +12,7 @@ struct iscsit_transport { ...@@ -12,6 +12,7 @@ struct iscsit_transport {
int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *); int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *);
int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *); int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *);
void (*iscsit_free_np)(struct iscsi_np *); void (*iscsit_free_np)(struct iscsi_np *);
void (*iscsit_wait_conn)(struct iscsi_conn *);
void (*iscsit_free_conn)(struct iscsi_conn *); void (*iscsit_free_conn)(struct iscsi_conn *);
int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *); int (*iscsit_get_login_rx)(struct iscsi_conn *, struct iscsi_login *);
int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32); int (*iscsit_put_login_tx)(struct iscsi_conn *, struct iscsi_login *, u32);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment