#include "target_core_pr.h"
#include "target_core_ua.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/target.h>
+
static struct workqueue_struct *target_completion_wq;
static struct kmem_cache *se_sess_cache;
struct kmem_cache *se_ua_cache;
spin_unlock_irqrestore(&dev->execute_task_lock, flags);
}
-static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists)
+static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists,
+ bool write_pending)
{
unsigned long flags;
spin_lock_irqsave(&cmd->t_state_lock, flags);
+ if (write_pending)
+ cmd->t_state = TRANSPORT_WRITE_PENDING;
+
/*
* Determine if IOCTL context caller in requesting the stopping of this
* command for LUN shutdown purposes.
static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
{
- return transport_cmd_check_stop(cmd, true);
+ return transport_cmd_check_stop(cmd, true, false);
}
static void transport_lun_remove_cmd(struct se_cmd *cmd)
if (!lun)
return;
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
- cmd->transport_state &= ~CMD_T_DEV_ACTIVE;
- target_remove_from_state_list(cmd);
- }
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
spin_lock_irqsave(&lun->lun_cmd_lock, flags);
if (!list_empty(&cmd->se_lun_node))
list_del_init(&cmd->se_lun_node);
target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
{
struct se_device *dev = cmd->se_dev;
- unsigned long flags;
sense_reason_t ret;
/*
*/
memcpy(cmd->t_task_cdb, cdb, scsi_command_size(cdb));
+ trace_target_sequencer_start(cmd);
+
/*
* Check for an existing UNIT ATTENTION condition
*/
if (ret)
return ret;
- spin_lock_irqsave(&cmd->t_state_lock, flags);
cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
spin_lock(&cmd->se_lun->lun_sep_lock);
if (cmd->se_lun->lun_sep)
cmd->orig_fe_lun, 0x2C,
ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
- ret = cmd->se_tfo->queue_status(cmd);
+ trace_target_cmd_complete(cmd);
+ ret = cmd->se_tfo-> queue_status(cmd);
if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
goto check_stop;
{
sense_reason_t 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 = cmd->execute_cmd(cmd);
if (ret) {
}
cmd->t_state = TRANSPORT_PROCESSING;
- cmd->transport_state |= CMD_T_ACTIVE;
+ cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
spin_unlock_irq(&cmd->t_state_lock);
- if (!target_handle_task_attr(cmd))
- __target_execute_cmd(cmd);
+ if (target_handle_task_attr(cmd)) {
+ spin_lock_irq(&cmd->t_state_lock);
+ cmd->transport_state &= ~CMD_T_BUSY|CMD_T_SENT;
+ spin_unlock_irq(&cmd->t_state_lock);
+ return;
+ }
+
+ __target_execute_cmd(cmd);
}
EXPORT_SYMBOL(target_execute_cmd);
transport_complete_task_attr(cmd);
if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
+ trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_status(cmd);
if (ret)
goto out;
switch (cmd->data_direction) {
case DMA_FROM_DEVICE:
+ trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_data_in(cmd);
break;
case DMA_TO_DEVICE:
}
/* Fall through for DMA_TO_DEVICE */
case DMA_NONE:
+ trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_status(cmd);
break;
default:
}
spin_unlock(&cmd->se_lun->lun_sep_lock);
+ trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_data_in(cmd);
if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
}
/* Fall through for DMA_TO_DEVICE */
case DMA_NONE:
+ trace_target_cmd_complete(cmd);
ret = cmd->se_tfo->queue_status(cmd);
if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
* If this cmd has been setup with target_get_sess_cmd(), drop
* the kref and call ->release_cmd() in kref callback.
*/
- if (cmd->check_release != 0)
- return target_put_sess_cmd(cmd->se_sess, cmd);
-
- cmd->se_tfo->release_cmd(cmd);
- return 1;
+ return target_put_sess_cmd(cmd->se_sess, cmd);
}
/**
*/
static int transport_put_cmd(struct se_cmd *cmd)
{
- unsigned long flags;
-
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- if (atomic_read(&cmd->t_fe_count) &&
- !atomic_dec_and_test(&cmd->t_fe_count)) {
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- return 0;
- }
-
- if (cmd->transport_state & CMD_T_DEV_ACTIVE) {
- cmd->transport_state &= ~CMD_T_DEV_ACTIVE;
- target_remove_from_state_list(cmd);
- }
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
transport_free_pages(cmd);
return transport_release_cmd(cmd);
}
if (ret < 0)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
-
- atomic_inc(&cmd->t_fe_count);
-
/*
* If this command is not a write we can execute it right here,
* for write buffers we need to notify the fabric driver first
target_execute_cmd(cmd);
return 0;
}
-
- spin_lock_irq(&cmd->t_state_lock);
- cmd->t_state = TRANSPORT_WRITE_PENDING;
- spin_unlock_irq(&cmd->t_state_lock);
-
- transport_cmd_check_stop(cmd, false);
+ transport_cmd_check_stop(cmd, false, true);
ret = cmd->se_tfo->write_pending(cmd);
if (ret == -EAGAIN || ret == -ENOMEM)
goto out;
}
list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
- se_cmd->check_release = 1;
-
out:
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
return ret;
pr_debug("ConfigFS ITT[0x%08x] - CMD_T_STOP, skipping\n",
cmd->se_tfo->get_task_tag(cmd));
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- transport_cmd_check_stop(cmd, false);
+ transport_cmd_check_stop(cmd, false, false);
return -EPERM;
}
cmd->transport_state |= CMD_T_LUN_FE_STOP;
spin_unlock_irqrestore(&cmd->t_state_lock,
cmd_flags);
- transport_cmd_check_stop(cmd, false);
+ transport_cmd_check_stop(cmd, false, false);
complete(&cmd->transport_lun_fe_stop_comp);
spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags);
continue;
cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER;
after_reason:
+ trace_target_cmd_complete(cmd);
return cmd->se_tfo->queue_status(cmd);
}
EXPORT_SYMBOL(transport_send_check_condition_and_sense);
cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd));
cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS;
+ trace_target_cmd_complete(cmd);
cmd->se_tfo->queue_status(cmd);
return 1;
" ITT: 0x%08x\n", cmd->t_task_cdb[0],
cmd->se_tfo->get_task_tag(cmd));
+ trace_target_cmd_complete(cmd);
cmd->se_tfo->queue_status(cmd);
}