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 most notable item is IBM virtual SCSI target driver, that was
  originally ported to target-core back in 2010 by Tomo-san, and has
  been brought forward to v4.x code by Bryant Ly, Michael Cyr and co
  over the last months.

  Also included are two ORDERED task related bug-fixes Bryant + Michael
  found along the way using ibmvscsis with AIX guests, plus a few
  miscellaneous target-core + iscsi-target bug-fixes with associated
  stable tags"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  target: fix spelling mistake: "limitiation" -> "limitation"
  target: Fix residual overflow handling in target_complete_cmd_with_length
  tcm_fc: set and unset FCP_SPPF_TARG_FCN
  iscsi-target: Fix panic when adding second TCP connection to iSCSI session
  ibmvscsis: Initial commit of IBM VSCSI Tgt Driver
  target: Fix ordered task CHECK_CONDITION early exception handling
  target: Fix ordered task target_setup_cmd_from_cdb exception hang
  target: Fix max_unmap_lba_count calc overflow
  target: Fix race between iscsi-target connection shutdown + ABORT_TASK
  target: Fix missing complete during ABORT_TASK + CMD_T_FABRIC_STOP
This commit is contained in:
Linus Torvalds
2016-08-04 20:04:37 -04:00
23 changed files with 5113 additions and 70 deletions

View File

@@ -492,7 +492,8 @@ void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD);
spin_lock_bh(&conn->cmd_lock);
if (!list_empty(&cmd->i_conn_node))
if (!list_empty(&cmd->i_conn_node) &&
!(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
@@ -4034,6 +4035,7 @@ int iscsi_target_rx_thread(void *arg)
static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
{
LIST_HEAD(tmp_list);
struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
struct iscsi_session *sess = conn->sess;
/*
@@ -4042,18 +4044,26 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
* has been reset -> returned sleeping pre-handler state.
*/
spin_lock_bh(&conn->cmd_lock);
list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
list_splice_init(&conn->conn_cmd_list, &tmp_list);
list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
list_for_each_entry(cmd, &tmp_list, i_conn_node) {
struct se_cmd *se_cmd = &cmd->se_cmd;
iscsit_increment_maxcmdsn(cmd, sess);
iscsit_free_cmd(cmd, true);
spin_lock_bh(&conn->cmd_lock);
if (se_cmd->se_tfo != NULL) {
spin_lock(&se_cmd->t_state_lock);
se_cmd->transport_state |= CMD_T_FABRIC_STOP;
spin_unlock(&se_cmd->t_state_lock);
}
}
spin_unlock_bh(&conn->cmd_lock);
list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
list_del_init(&cmd->i_conn_node);
iscsit_increment_maxcmdsn(cmd, sess);
iscsit_free_cmd(cmd, true);
}
}
static void iscsit_stop_timers_for_cmds(

View File

@@ -1371,8 +1371,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
}
login->zero_tsih = zero_tsih;
conn->sess->se_sess->sup_prot_ops =
conn->conn_transport->iscsit_get_sup_prot_ops(conn);
if (conn->sess)
conn->sess->se_sess->sup_prot_ops =
conn->conn_transport->iscsit_get_sup_prot_ops(conn);
tpg = conn->tpg;
if (!tpg) {

View File

@@ -821,13 +821,15 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
* in ATA and we need to set TPE=1
*/
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
struct request_queue *q, int block_size)
struct request_queue *q)
{
int block_size = queue_logical_block_size(q);
if (!blk_queue_discard(q))
return false;
attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) /
block_size;
attrib->max_unmap_lba_count =
q->limits.max_discard_sectors >> (ilog2(block_size) - 9);
/*
* Currently hardcoded to 1 in Linux/SCSI code..
*/

View File

@@ -161,8 +161,7 @@ static int fd_configure_device(struct se_device *dev)
dev_size, div_u64(dev_size, fd_dev->fd_block_size),
fd_dev->fd_block_size);
if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
fd_dev->fd_block_size))
if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
pr_debug("IFILE: BLOCK Discard support available,"
" disabled by default\n");
/*
@@ -523,7 +522,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
*/
if (cmd->data_length > FD_MAX_BYTES) {
pr_err("FILEIO: Not able to process I/O of %u bytes due to"
"FD_MAX_BYTES: %u iovec count limitiation\n",
"FD_MAX_BYTES: %u iovec count limitation\n",
cmd->data_length, FD_MAX_BYTES);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}

View File

@@ -121,8 +121,7 @@ static int iblock_configure_device(struct se_device *dev)
dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
dev->dev_attrib.hw_queue_depth = q->nr_requests;
if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
dev->dev_attrib.hw_block_size))
if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
pr_debug("IBLOCK: BLOCK Discard support available,"
" disabled by default\n");

View File

@@ -146,6 +146,7 @@ sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
void target_qf_do_work(struct work_struct *work);
bool target_check_wce(struct se_device *dev);
bool target_check_fua(struct se_device *dev);
void __target_execute_cmd(struct se_cmd *, bool);
/* target_core_stat.c */
void target_stat_setup_dev_default_groups(struct se_device *);

View File

@@ -602,7 +602,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
spin_unlock_irq(&cmd->t_state_lock);
__target_execute_cmd(cmd);
__target_execute_cmd(cmd, false);
kfree(buf);
return ret;

View File

@@ -754,7 +754,15 @@ EXPORT_SYMBOL(target_complete_cmd);
void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
{
if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
if (scsi_status != SAM_STAT_GOOD) {
return;
}
/*
* Calculate new residual count based upon length of SCSI data
* transferred.
*/
if (length < cmd->data_length) {
if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
cmd->residual_count += cmd->data_length - length;
} else {
@@ -763,6 +771,12 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len
}
cmd->data_length = length;
} else if (length > cmd->data_length) {
cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
cmd->residual_count = length - cmd->data_length;
} else {
cmd->se_cmd_flags &= ~(SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT);
cmd->residual_count = 0;
}
target_complete_cmd(cmd, scsi_status);
@@ -1303,23 +1317,6 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
trace_target_sequencer_start(cmd);
/*
* Check for an existing UNIT ATTENTION condition
*/
ret = target_scsi3_ua_check(cmd);
if (ret)
return ret;
ret = target_alua_state_check(cmd);
if (ret)
return ret;
ret = target_check_reservation(cmd);
if (ret) {
cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
return ret;
}
ret = dev->transport->parse_cdb(cmd);
if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
@@ -1761,20 +1758,45 @@ queue_full:
}
EXPORT_SYMBOL(transport_generic_request_failure);
void __target_execute_cmd(struct se_cmd *cmd)
void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
{
sense_reason_t ret;
if (cmd->execute_cmd) {
ret = cmd->execute_cmd(cmd);
if (ret) {
spin_lock_irq(&cmd->t_state_lock);
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
spin_unlock_irq(&cmd->t_state_lock);
if (!cmd->execute_cmd) {
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
goto err;
}
if (do_checks) {
/*
* Check for an existing UNIT ATTENTION condition after
* target_handle_task_attr() has done SAM task attr
* checking, and possibly have already defered execution
* out to target_restart_delayed_cmds() context.
*/
ret = target_scsi3_ua_check(cmd);
if (ret)
goto err;
transport_generic_request_failure(cmd, ret);
ret = target_alua_state_check(cmd);
if (ret)
goto err;
ret = target_check_reservation(cmd);
if (ret) {
cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
goto err;
}
}
ret = cmd->execute_cmd(cmd);
if (!ret)
return;
err:
spin_lock_irq(&cmd->t_state_lock);
cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
spin_unlock_irq(&cmd->t_state_lock);
transport_generic_request_failure(cmd, ret);
}
static int target_write_prot_action(struct se_cmd *cmd)
@@ -1819,6 +1841,8 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return false;
cmd->se_cmd_flags |= SCF_TASK_ATTR_SET;
/*
* Check for the existence of HEAD_OF_QUEUE, and if true return 1
* to allow the passed struct se_cmd list of tasks to the front of the list.
@@ -1899,7 +1923,7 @@ void target_execute_cmd(struct se_cmd *cmd)
return;
}
__target_execute_cmd(cmd);
__target_execute_cmd(cmd, true);
}
EXPORT_SYMBOL(target_execute_cmd);
@@ -1923,7 +1947,7 @@ static void target_restart_delayed_cmds(struct se_device *dev)
list_del(&cmd->se_delayed_node);
spin_unlock(&dev->delayed_cmd_lock);
__target_execute_cmd(cmd);
__target_execute_cmd(cmd, true);
if (cmd->sam_task_attr == TCM_ORDERED_TAG)
break;
@@ -1941,6 +1965,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return;
if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET))
goto restart;
if (cmd->sam_task_attr == TCM_SIMPLE_TAG) {
atomic_dec_mb(&dev->simple_cmds);
dev->dev_cur_ordered_id++;
@@ -1957,7 +1984,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n",
dev->dev_cur_ordered_id);
}
restart:
target_restart_delayed_cmds(dev);
}
@@ -2557,15 +2584,10 @@ static void target_release_cmd_kref(struct kref *kref)
bool fabric_stop;
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
if (list_empty(&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);
return;
}
spin_lock(&se_cmd->t_state_lock);
fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP);
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) {

View File

@@ -91,6 +91,7 @@ static void ft_tport_delete(struct ft_tport *tport)
ft_sess_delete_all(tport);
lport = tport->lport;
lport->service_params &= ~FCP_SPPF_TARG_FCN;
BUG_ON(tport != lport->prov[FC_TYPE_FCP]);
RCU_INIT_POINTER(lport->prov[FC_TYPE_FCP], NULL);
@@ -110,6 +111,7 @@ void ft_lport_add(struct fc_lport *lport, void *arg)
{
mutex_lock(&ft_lport_lock);
ft_tport_get(lport);
lport->service_params |= FCP_SPPF_TARG_FCN;
mutex_unlock(&ft_lport_lock);
}