#include <linux/kthread.h>
#include <linux/in.h>
#include <linux/cdrom.h>
+#include <linux/module.h>
#include <asm/unaligned.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <target/target_core_configfs.h>
#include "target_core_alua.h"
+#include "target_core_cdb.h"
#include "target_core_hba.h"
#include "target_core_pr.h"
#include "target_core_ua.h"
static void transport_put_cmd(struct se_cmd *cmd);
static void transport_remove_cmd_from_queue(struct se_cmd *cmd);
static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
-static void transport_generic_request_failure(struct se_cmd *, int, int);
+static void transport_generic_request_failure(struct se_cmd *);
static void target_complete_ok_work(struct work_struct *work);
int init_se_kmem_caches(void)
task->task_scsi_status = GOOD;
} else {
task->task_scsi_status = SAM_STAT_CHECK_CONDITION;
- task->task_error_status = PYX_TRANSPORT_ILLEGAL_REQUEST;
- task->task_se_cmd->transport_error_status =
- PYX_TRANSPORT_ILLEGAL_REQUEST;
+ task->task_se_cmd->scsi_sense_reason =
+ TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
}
transport_complete_task(task, good);
{
struct se_cmd *cmd = container_of(work, struct se_cmd, work);
- transport_generic_request_failure(cmd, 1, 1);
+ transport_generic_request_failure(cmd);
}
/* transport_complete_task():
if (cmd->t_tasks_failed) {
if (!task->task_error_status) {
task->task_error_status =
- PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
- cmd->transport_error_status =
- PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ cmd->scsi_sense_reason =
+ TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
+
INIT_WORK(&cmd->work, target_complete_failure_work);
} else {
atomic_set(&cmd->t_transport_complete, 1);
pr_err("Received SCSI CDB with command_size: %d that"
" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
scsi_command_size(cdb), SCSI_MAX_VARLEN_CDB_SIZE);
+ cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
return -EINVAL;
}
/*
" %u > sizeof(cmd->__t_task_cdb): %lu ops\n",
scsi_command_size(cdb),
(unsigned long)sizeof(cmd->__t_task_cdb));
+ cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ cmd->scsi_sense_reason =
+ TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -ENOMEM;
}
} else
* and call transport_generic_request_failure() if necessary..
*/
ret = transport_generic_new_cmd(cmd);
- if (ret < 0) {
- cmd->transport_error_status = ret;
- transport_generic_request_failure(cmd, 0,
- (cmd->data_direction != DMA_TO_DEVICE));
- }
+ if (ret < 0)
+ transport_generic_request_failure(cmd);
+
return 0;
}
EXPORT_SYMBOL(transport_handle_cdb_direct);
/*
* Handle SAM-esque emulation for generic transport request failures.
*/
-static void transport_generic_request_failure(
- struct se_cmd *cmd,
- int complete,
- int sc)
+static void transport_generic_request_failure(struct se_cmd *cmd)
{
int ret = 0;
pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08x"
" CDB: 0x%02x\n", cmd, cmd->se_tfo->get_task_tag(cmd),
cmd->t_task_cdb[0]);
- pr_debug("-----[ i_state: %d t_state: %d transport_error_status: %d\n",
+ pr_debug("-----[ i_state: %d t_state: %d scsi_sense_reason: %d\n",
cmd->se_tfo->get_cmd_state(cmd),
- cmd->t_state,
- cmd->transport_error_status);
+ cmd->t_state, cmd->scsi_sense_reason);
pr_debug("-----[ t_tasks: %d t_task_cdbs_left: %d"
" t_task_cdbs_sent: %d t_task_cdbs_ex_left: %d --"
" t_transport_active: %d t_transport_stop: %d"
if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
transport_complete_task_attr(cmd);
- if (complete) {
- cmd->transport_error_status = PYX_TRANSPORT_LU_COMM_FAILURE;
- }
-
- switch (cmd->transport_error_status) {
- case PYX_TRANSPORT_UNKNOWN_SAM_OPCODE:
- cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
- break;
- case PYX_TRANSPORT_REQ_TOO_MANY_SECTORS:
- cmd->scsi_sense_reason = TCM_SECTOR_COUNT_TOO_MANY;
- break;
- case PYX_TRANSPORT_INVALID_CDB_FIELD:
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
- break;
- case PYX_TRANSPORT_INVALID_PARAMETER_LIST:
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
- break;
- case PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES:
- if (!sc)
- transport_new_cmd_failure(cmd);
- /*
- * Currently for PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES,
- * we force this session to fall back to session
- * recovery.
- */
- cmd->se_tfo->fall_back_to_erl0(cmd->se_sess);
- cmd->se_tfo->stop_session(cmd->se_sess, 0, 0);
-
- goto check_stop;
- case PYX_TRANSPORT_LU_COMM_FAILURE:
- case PYX_TRANSPORT_ILLEGAL_REQUEST:
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- break;
- case PYX_TRANSPORT_UNKNOWN_MODE_PAGE:
- cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE;
- break;
- case PYX_TRANSPORT_WRITE_PROTECTED:
- cmd->scsi_sense_reason = TCM_WRITE_PROTECTED;
+ switch (cmd->scsi_sense_reason) {
+ case TCM_NON_EXISTENT_LUN:
+ case TCM_UNSUPPORTED_SCSI_OPCODE:
+ case TCM_INVALID_CDB_FIELD:
+ case TCM_INVALID_PARAMETER_LIST:
+ case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
+ case TCM_UNKNOWN_MODE_PAGE:
+ case TCM_WRITE_PROTECTED:
+ case TCM_CHECK_CONDITION_ABORT_CMD:
+ case TCM_CHECK_CONDITION_UNIT_ATTENTION:
+ case TCM_CHECK_CONDITION_NOT_READY:
break;
- case PYX_TRANSPORT_RESERVATION_CONFLICT:
+ case TCM_RESERVATION_CONFLICT:
/*
* No SENSE Data payload for this case, set SCSI Status
* and queue the response to $FABRIC_MOD.
if (ret == -EAGAIN || ret == -ENOMEM)
goto queue_full;
goto check_stop;
- case PYX_TRANSPORT_USE_SENSE_REASON:
- /*
- * struct se_cmd->scsi_sense_reason already set
- */
- break;
default:
pr_err("Unknown transport error for CDB 0x%02x: %d\n",
- cmd->t_task_cdb[0],
- cmd->transport_error_status);
+ cmd->t_task_cdb[0], cmd->scsi_sense_reason);
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
break;
}
* transport_send_check_condition_and_sense() after handling
* possible unsoliticied write data payloads.
*/
- if (!sc && !cmd->se_tfo->new_cmd_map)
- transport_new_cmd_failure(cmd);
- else {
- ret = transport_send_check_condition_and_sense(cmd,
- cmd->scsi_sense_reason, 0);
- if (ret == -EAGAIN || ret == -ENOMEM)
- goto queue_full;
- }
+ ret = transport_send_check_condition_and_sense(cmd,
+ cmd->scsi_sense_reason, 0);
+ if (ret == -EAGAIN || ret == -ENOMEM)
+ goto queue_full;
check_stop:
transport_lun_remove_cmd(cmd);
int add_tasks;
if (se_dev_check_online(cmd->se_orig_obj_ptr) != 0) {
- cmd->transport_error_status = PYX_TRANSPORT_LU_COMM_FAILURE;
- transport_generic_request_failure(cmd, 0, 1);
+ cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ transport_generic_request_failure(cmd);
return 0;
}
atomic_set(&cmd->t_transport_sent, 1);
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- /*
- * The struct se_cmd->transport_emulate_cdb() function pointer is used
- * to grab REPORT_LUNS and other CDBs we want to handle before they hit the
- * struct se_subsystem_api->do_task() caller below.
- */
- if (cmd->transport_emulate_cdb) {
- error = cmd->transport_emulate_cdb(cmd);
- if (error != 0) {
- cmd->transport_error_status = error;
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- task->task_flags &= ~TF_ACTIVE;
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- atomic_set(&cmd->t_transport_sent, 0);
- transport_stop_tasks_for_cmd(cmd);
- atomic_inc(&dev->depth_left);
- transport_generic_request_failure(cmd, 0, 1);
- goto check_depth;
- }
- /*
- * Handle the successful completion for transport_emulate_cdb()
- * for synchronous operation, following SCF_EMULATE_CDB_ASYNC
- * Otherwise the caller is expected to complete the task with
- * proper status.
- */
- if (!(cmd->se_cmd_flags & SCF_EMULATE_CDB_ASYNC)) {
- cmd->scsi_status = SAM_STAT_GOOD;
- task->task_scsi_status = GOOD;
- transport_complete_task(task, 1);
- }
- } else {
- /*
- * Currently for all virtual TCM plugins including IBLOCK, FILEIO and
- * RAMDISK we use the internal transport_emulate_control_cdb() logic
- * with struct se_subsystem_api callers for the primary SPC-3 TYPE_DISK
- * LUN emulation code.
- *
- * For TCM/pSCSI and all other SCF_SCSI_DATA_SG_IO_CDB I/O tasks we
- * call ->do_task() directly and let the underlying TCM subsystem plugin
- * code handle the CDB emulation.
- */
- if ((dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) &&
- (!(task->task_se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
- error = transport_emulate_control_cdb(task);
- else
- error = dev->transport->do_task(task);
- if (error != 0) {
- cmd->transport_error_status = error;
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- task->task_flags &= ~TF_ACTIVE;
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- atomic_set(&cmd->t_transport_sent, 0);
- transport_stop_tasks_for_cmd(cmd);
- atomic_inc(&dev->depth_left);
- transport_generic_request_failure(cmd, 0, 1);
- }
+ if (cmd->execute_task)
+ error = cmd->execute_task(task);
+ else
+ error = dev->transport->do_task(task);
+ if (error != 0) {
+ spin_lock_irqsave(&cmd->t_state_lock, flags);
+ task->task_flags &= ~TF_ACTIVE;
+ spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+ atomic_set(&cmd->t_transport_sent, 0);
+ transport_stop_tasks_for_cmd(cmd);
+ atomic_inc(&dev->depth_left);
+ transport_generic_request_failure(cmd);
}
goto check_depth;
return 0;
}
-void transport_new_cmd_failure(struct se_cmd *se_cmd)
-{
- unsigned long flags;
- /*
- * Any unsolicited data will get dumped for failed command inside of
- * the fabric plugin
- */
- spin_lock_irqsave(&se_cmd->t_state_lock, flags);
- se_cmd->se_cmd_flags |= SCF_SE_CMD_FAILED;
- se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
- spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
-}
-
static inline u32 transport_get_sectors_6(
unsigned char *cdb,
struct se_cmd *cmd,
return -1;
}
-static int
-transport_handle_reservation_conflict(struct se_cmd *cmd)
-{
- cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
- cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
- cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
- /*
- * For UA Interlock Code 11b, a RESERVATION CONFLICT will
- * establish a UNIT ATTENTION with PREVIOUS RESERVATION
- * CONFLICT STATUS.
- *
- * See spc4r17, section 7.4.6 Control Mode Page, Table 349
- */
- if (cmd->se_sess &&
- cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2)
- core_scsi3_ua_allocate(cmd->se_sess->se_node_acl,
- cmd->orig_fe_lun, 0x2C,
- ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS);
- return -EINVAL;
-}
-
static inline long long transport_dev_end_lba(struct se_device *dev)
{
return dev->transport->get_blocks(dev) + 1;
*/
if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type) != 0) {
if (su_dev->t10_pr.pr_ops.t10_seq_non_holder(
- cmd, cdb, pr_reg_type) != 0)
- return transport_handle_reservation_conflict(cmd);
+ cmd, cdb, pr_reg_type) != 0) {
+ cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+ cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
+ cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
+ return -EBUSY;
+ }
/*
* This means the CDB is allowed for the SCSI Initiator port
* when said port is *NOT* holding the legacy SPC-2 or
*/
}
+ /*
+ * If we operate in passthrough mode we skip most CDB emulation and
+ * instead hand the commands down to the physical SCSI device.
+ */
+ passthrough =
+ (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV);
+
switch (cdb[0]) {
case READ_6:
sectors = transport_get_sectors_6(cdb, cmd, §or_ret);
cmd->t_task_lba = transport_lba_32(cdb);
cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
- if (dev->transport->transport_type ==
- TRANSPORT_PLUGIN_PHBA_PDEV)
+ /*
+ * Do now allow BIDI commands for passthrough mode.
+ */
+ if (passthrough)
goto out_unsupported_cdb;
+
/*
* Setup BIDI XOR callback to be run after I/O completion.
*/
break;
case VARIABLE_LENGTH_CMD:
service_action = get_unaligned_be16(&cdb[8]);
- /*
- * Determine if this is TCM/PSCSI device and we should disable
- * internal emulation for this CDB.
- */
- passthrough = (dev->transport->transport_type ==
- TRANSPORT_PLUGIN_PHBA_PDEV);
-
switch (service_action) {
case XDWRITEREAD_32:
sectors = transport_get_sectors_32(cdb, cmd, §or_ret);
cmd->t_task_lba = transport_lba_64_ext(cdb);
cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
+ /*
+ * Do now allow BIDI commands for passthrough mode.
+ */
if (passthrough)
goto out_unsupported_cdb;
+
/*
* Setup BIDI XOR callback to be run during after I/O
* completion.
if (target_check_write_same_discard(&cdb[10], dev) < 0)
goto out_invalid_cdb_field;
-
+ if (!passthrough)
+ cmd->execute_task = target_emulate_write_same;
break;
default:
pr_err("VARIABLE_LENGTH_CMD service action"
/*
* Check for emulated MI_REPORT_TARGET_PGS.
*/
- if (cdb[1] == MI_REPORT_TARGET_PGS) {
- cmd->transport_emulate_cdb =
- (su_dev->t10_alua.alua_type ==
- SPC3_ALUA_EMULATED) ?
- core_emulate_report_target_port_groups :
- NULL;
+ if (cdb[1] == MI_REPORT_TARGET_PGS &&
+ su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+ cmd->execute_task =
+ target_emulate_report_target_port_groups;
}
size = (cdb[6] << 24) | (cdb[7] << 16) |
(cdb[8] << 8) | cdb[9];
case MODE_SENSE:
size = cdb[4];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_modesense;
break;
case MODE_SENSE_10:
+ size = (cdb[7] << 8) + cdb[8];
+ cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_modesense;
+ break;
case GPCMD_READ_BUFFER_CAPACITY:
case GPCMD_SEND_OPC:
case LOG_SELECT:
break;
case PERSISTENT_RESERVE_IN:
if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
- cmd->transport_emulate_cdb = target_scsi3_emulate_pr_in;
+ cmd->execute_task = target_scsi3_emulate_pr_in;
size = (cdb[7] << 8) + cdb[8];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
break;
case PERSISTENT_RESERVE_OUT:
if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
- cmd->transport_emulate_cdb = target_scsi3_emulate_pr_out;
+ cmd->execute_task = target_scsi3_emulate_pr_out;
size = (cdb[7] << 8) + cdb[8];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
break;
*
* Check for emulated MO_SET_TARGET_PGS.
*/
- if (cdb[1] == MO_SET_TARGET_PGS) {
- cmd->transport_emulate_cdb =
- (su_dev->t10_alua.alua_type ==
- SPC3_ALUA_EMULATED) ?
- core_emulate_set_target_port_groups :
- NULL;
+ if (cdb[1] == MO_SET_TARGET_PGS &&
+ su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+ cmd->execute_task =
+ target_emulate_set_target_port_groups;
}
size = (cdb[6] << 24) | (cdb[7] << 16) |
if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
cmd->sam_task_attr = MSG_HEAD_TAG;
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_inquiry;
break;
case READ_BUFFER:
size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
case READ_CAPACITY:
size = READ_CAP_LEN;
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_readcapacity;
break;
case READ_MEDIA_SERIAL_NUMBER:
case SECURITY_PROTOCOL_IN:
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
break;
case SERVICE_ACTION_IN:
+ switch (cmd->t_task_cdb[1] & 0x1f) {
+ case SAI_READ_CAPACITY_16:
+ if (!passthrough)
+ cmd->execute_task =
+ target_emulate_readcapacity_16;
+ break;
+ default:
+ if (passthrough)
+ break;
+
+ pr_err("Unsupported SA: 0x%02x\n",
+ cmd->t_task_cdb[1] & 0x1f);
+ goto out_unsupported_cdb;
+ }
+ /*FALLTHROUGH*/
case ACCESS_CONTROL_IN:
case ACCESS_CONTROL_OUT:
case EXTENDED_COPY:
case REQUEST_SENSE:
size = cdb[4];
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_request_sense;
break;
case READ_ELEMENT_STATUS:
size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
* is running in SPC_PASSTHROUGH, and wants reservations
* emulation disabled.
*/
- if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) {
- cmd->transport_emulate_cdb =
- target_scsi2_reservation_reserve;
- }
+ if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
+ cmd->execute_task = target_scsi2_reservation_reserve;
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
break;
case RELEASE:
else
size = cmd->data_length;
- if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) {
- cmd->transport_emulate_cdb =
- target_scsi2_reservation_release;
- }
+ if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
+ cmd->execute_task = target_scsi2_reservation_release;
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
break;
case SYNCHRONIZE_CACHE:
size = transport_get_size(sectors, cdb, cmd);
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
- /*
- * For TCM/pSCSI passthrough, skip cmd->transport_emulate_cdb()
- */
- if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
+ if (passthrough)
break;
- /*
- * Set SCF_EMULATE_CDB_ASYNC to ensure asynchronous operation
- * for SYNCHRONIZE_CACHE* Immed=1 case in __transport_execute_tasks()
- */
- cmd->se_cmd_flags |= SCF_EMULATE_CDB_ASYNC;
+
/*
* Check to ensure that LBA + Range does not exceed past end of
* device for IBLOCK and FILEIO ->do_sync_cache() backend calls
if (transport_cmd_get_valid_sectors(cmd) < 0)
goto out_invalid_cdb_field;
}
+ cmd->execute_task = target_emulate_synchronize_cache;
break;
case UNMAP:
size = get_unaligned_be16(&cdb[7]);
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_unmap;
break;
case WRITE_SAME_16:
sectors = transport_get_sectors_16(cdb, cmd, §or_ret);
if (target_check_write_same_discard(&cdb[1], dev) < 0)
goto out_invalid_cdb_field;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_write_same;
break;
case WRITE_SAME:
sectors = transport_get_sectors_10(cdb, cmd, §or_ret);
*/
if (target_check_write_same_discard(&cdb[1], dev) < 0)
goto out_invalid_cdb_field;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_write_same;
break;
case ALLOW_MEDIUM_REMOVAL:
- case GPCMD_CLOSE_TRACK:
case ERASE:
- case INITIALIZE_ELEMENT_STATUS:
- case GPCMD_LOAD_UNLOAD:
case REZERO_UNIT:
case SEEK_10:
- case GPCMD_SET_SPEED:
case SPACE:
case START_STOP:
case TEST_UNIT_READY:
case VERIFY:
case WRITE_FILEMARKS:
+ cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
+ if (!passthrough)
+ cmd->execute_task = target_emulate_noop;
+ break;
+ case GPCMD_CLOSE_TRACK:
+ case INITIALIZE_ELEMENT_STATUS:
+ case GPCMD_LOAD_UNLOAD:
+ case GPCMD_SET_SPEED:
case MOVE_MEDIUM:
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
break;
case REPORT_LUNS:
- cmd->transport_emulate_cdb =
- transport_core_report_lun_response;
+ cmd->execute_task = target_report_luns;
size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
/*
* Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
cmd->data_length = size;
}
+ /* reject any command that we don't have a handler for */
+ if (!(passthrough || cmd->execute_task ||
+ (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
+ goto out_unsupported_cdb;
+
/* Let's limit control cdbs to a page, for simplicity's sake. */
if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
size > PAGE_SIZE)
cmd->data_length) {
ret = transport_generic_get_mem(cmd);
if (ret < 0)
- return ret;
+ goto out_fail;
}
/*
else if (ret < 0)
return ret;
- return PYX_TRANSPORT_WRITE_PENDING;
+ return 1;
queue_full:
pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
if (cmd->se_tfo->write_pending_status(cmd) != 0) {
atomic_inc(&cmd->t_transport_aborted);
smp_mb__after_atomic_inc();
- cmd->scsi_status = SAM_STAT_TASK_ABORTED;
- transport_new_cmd_failure(cmd);
- return;
}
}
cmd->scsi_status = SAM_STAT_TASK_ABORTED;
struct se_cmd *cmd;
struct se_device *dev = (struct se_device *) param;
- set_user_nice(current, -20);
-
while (!kthread_should_stop()) {
ret = wait_event_interruptible(dev->dev_queue_obj.thread_wq,
atomic_read(&dev->dev_queue_obj.queue_cnt) ||
}
ret = cmd->se_tfo->new_cmd_map(cmd);
if (ret < 0) {
- cmd->transport_error_status = ret;
- transport_generic_request_failure(cmd,
- 0, (cmd->data_direction !=
- DMA_TO_DEVICE));
+ transport_generic_request_failure(cmd);
break;
}
ret = transport_generic_new_cmd(cmd);
if (ret < 0) {
- cmd->transport_error_status = ret;
- transport_generic_request_failure(cmd,
- 0, (cmd->data_direction !=
- DMA_TO_DEVICE));
+ transport_generic_request_failure(cmd);
+ break;
}
break;
case TRANSPORT_PROCESS_WRITE: