target: use ->exectute_task for all CDB emulation
Instead of calling into transport_emulate_control_cdb from __transport_execute_tasks for some CDBs always set up ->exectute_tasks in the command sequence and use it uniformly. (nab: Add default passthrough break for SERVICE_ACTION_IN) Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
committed by
Nicholas Bellinger
parent
d29a5b6acc
commit
5bda90c8f2
@@ -32,6 +32,7 @@
|
|||||||
#include <target/target_core_transport.h>
|
#include <target/target_core_transport.h>
|
||||||
#include <target/target_core_fabric_ops.h>
|
#include <target/target_core_fabric_ops.h>
|
||||||
#include "target_core_ua.h"
|
#include "target_core_ua.h"
|
||||||
|
#include "target_core_cdb.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
target_fill_alua_data(struct se_port *port, unsigned char *buf)
|
target_fill_alua_data(struct se_port *port, unsigned char *buf)
|
||||||
@@ -679,8 +680,7 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int target_emulate_inquiry(struct se_task *task)
|
||||||
target_emulate_inquiry(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
struct se_cmd *cmd = task->task_se_cmd;
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct se_device *dev = cmd->se_dev;
|
||||||
@@ -731,8 +731,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int target_emulate_readcapacity(struct se_task *task)
|
||||||
target_emulate_readcapacity(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
struct se_cmd *cmd = task->task_se_cmd;
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct se_device *dev = cmd->se_dev;
|
||||||
@@ -768,8 +767,7 @@ target_emulate_readcapacity(struct se_task *task)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int target_emulate_readcapacity_16(struct se_task *task)
|
||||||
target_emulate_readcapacity_16(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
struct se_cmd *cmd = task->task_se_cmd;
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct se_device *dev = cmd->se_dev;
|
||||||
@@ -939,8 +937,7 @@ target_modesense_dpofua(unsigned char *buf, int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int target_emulate_modesense(struct se_task *task)
|
||||||
target_emulate_modesense(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
struct se_cmd *cmd = task->task_se_cmd;
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct se_device *dev = cmd->se_dev;
|
||||||
@@ -1019,8 +1016,7 @@ target_emulate_modesense(struct se_task *task)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int target_emulate_request_sense(struct se_task *task)
|
||||||
target_emulate_request_sense(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
struct se_cmd *cmd = task->task_se_cmd;
|
||||||
unsigned char *cdb = cmd->t_task_cdb;
|
unsigned char *cdb = cmd->t_task_cdb;
|
||||||
@@ -1090,8 +1086,7 @@ end:
|
|||||||
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
|
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
|
||||||
* Note this is not used for TCM/pSCSI passthrough
|
* Note this is not used for TCM/pSCSI passthrough
|
||||||
*/
|
*/
|
||||||
static int
|
int target_emulate_unmap(struct se_task *task)
|
||||||
target_emulate_unmap(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
struct se_cmd *cmd = task->task_se_cmd;
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct se_device *dev = cmd->se_dev;
|
||||||
@@ -1150,8 +1145,7 @@ err:
|
|||||||
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
|
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
|
||||||
* Note this is not used for TCM/pSCSI passthrough
|
* Note this is not used for TCM/pSCSI passthrough
|
||||||
*/
|
*/
|
||||||
static int
|
int target_emulate_write_same(struct se_task *task)
|
||||||
target_emulate_write_same(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
struct se_cmd *cmd = task->task_se_cmd;
|
||||||
struct se_device *dev = cmd->se_dev;
|
struct se_device *dev = cmd->se_dev;
|
||||||
@@ -1196,8 +1190,7 @@ target_emulate_write_same(struct se_task *task)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int target_emulate_synchronize_cache(struct se_task *task)
|
||||||
target_emulate_synchronize_cache(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
struct se_device *dev = task->task_se_cmd->se_dev;
|
struct se_device *dev = task->task_se_cmd->se_dev;
|
||||||
|
|
||||||
@@ -1211,97 +1204,13 @@ target_emulate_synchronize_cache(struct se_task *task)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int target_emulate_noop(struct se_task *task)
|
||||||
target_emulate_noop(struct se_task *task)
|
|
||||||
{
|
{
|
||||||
task->task_scsi_status = GOOD;
|
task->task_scsi_status = GOOD;
|
||||||
transport_complete_task(task, 1);
|
transport_complete_task(task, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
transport_emulate_control_cdb(struct se_task *task)
|
|
||||||
{
|
|
||||||
struct se_cmd *cmd = task->task_se_cmd;
|
|
||||||
struct se_device *dev = cmd->se_dev;
|
|
||||||
unsigned short service_action;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
switch (cmd->t_task_cdb[0]) {
|
|
||||||
case INQUIRY:
|
|
||||||
ret = target_emulate_inquiry(task);
|
|
||||||
break;
|
|
||||||
case READ_CAPACITY:
|
|
||||||
ret = target_emulate_readcapacity(task);
|
|
||||||
break;
|
|
||||||
case MODE_SENSE:
|
|
||||||
ret = target_emulate_modesense(task);
|
|
||||||
break;
|
|
||||||
case MODE_SENSE_10:
|
|
||||||
ret = target_emulate_modesense(task);
|
|
||||||
break;
|
|
||||||
case SERVICE_ACTION_IN:
|
|
||||||
switch (cmd->t_task_cdb[1] & 0x1f) {
|
|
||||||
case SAI_READ_CAPACITY_16:
|
|
||||||
ret = target_emulate_readcapacity_16(task);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_err("Unsupported SA: 0x%02x\n",
|
|
||||||
cmd->t_task_cdb[1] & 0x1f);
|
|
||||||
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case REQUEST_SENSE:
|
|
||||||
ret = target_emulate_request_sense(task);
|
|
||||||
break;
|
|
||||||
case UNMAP:
|
|
||||||
ret = target_emulate_unmap(task);
|
|
||||||
break;
|
|
||||||
case WRITE_SAME:
|
|
||||||
ret = target_emulate_write_same(task);
|
|
||||||
break;
|
|
||||||
case WRITE_SAME_16:
|
|
||||||
ret = target_emulate_write_same(task);
|
|
||||||
break;
|
|
||||||
case VARIABLE_LENGTH_CMD:
|
|
||||||
service_action =
|
|
||||||
get_unaligned_be16(&cmd->t_task_cdb[8]);
|
|
||||||
switch (service_action) {
|
|
||||||
case WRITE_SAME_32:
|
|
||||||
ret = target_emulate_write_same(task);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_err("Unsupported VARIABLE_LENGTH_CMD SA:"
|
|
||||||
" 0x%02x\n", service_action);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SYNCHRONIZE_CACHE:
|
|
||||||
case 0x91: /* SYNCHRONIZE_CACHE_16: */
|
|
||||||
ret = target_emulate_synchronize_cache(task);
|
|
||||||
break;
|
|
||||||
case ALLOW_MEDIUM_REMOVAL:
|
|
||||||
case ERASE:
|
|
||||||
case REZERO_UNIT:
|
|
||||||
case SEEK_10:
|
|
||||||
case SPACE:
|
|
||||||
case START_STOP:
|
|
||||||
case TEST_UNIT_READY:
|
|
||||||
case VERIFY:
|
|
||||||
case WRITE_FILEMARKS:
|
|
||||||
ret = target_emulate_noop(task);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_err("Unsupported SCSI Opcode: 0x%02x for %s\n",
|
|
||||||
cmd->t_task_cdb[0], dev->transport->name);
|
|
||||||
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write a CDB into @cdb that is based on the one the intiator sent us,
|
* Write a CDB into @cdb that is based on the one the intiator sent us,
|
||||||
* but updated to only cover the sectors that the current task handles.
|
* but updated to only cover the sectors that the current task handles.
|
||||||
|
14
drivers/target/target_core_cdb.h
Normal file
14
drivers/target/target_core_cdb.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef TARGET_CORE_CDB_H
|
||||||
|
#define TARGET_CORE_CDB_H
|
||||||
|
|
||||||
|
int target_emulate_inquiry(struct se_task *task);
|
||||||
|
int target_emulate_readcapacity(struct se_task *task);
|
||||||
|
int target_emulate_readcapacity_16(struct se_task *task);
|
||||||
|
int target_emulate_modesense(struct se_task *task);
|
||||||
|
int target_emulate_request_sense(struct se_task *task);
|
||||||
|
int target_emulate_unmap(struct se_task *task);
|
||||||
|
int target_emulate_write_same(struct se_task *task);
|
||||||
|
int target_emulate_synchronize_cache(struct se_task *task);
|
||||||
|
int target_emulate_noop(struct se_task *task);
|
||||||
|
|
||||||
|
#endif /* TARGET_CORE_CDB_H */
|
@@ -52,6 +52,7 @@
|
|||||||
#include <target/target_core_configfs.h>
|
#include <target/target_core_configfs.h>
|
||||||
|
|
||||||
#include "target_core_alua.h"
|
#include "target_core_alua.h"
|
||||||
|
#include "target_core_cdb.h"
|
||||||
#include "target_core_hba.h"
|
#include "target_core_hba.h"
|
||||||
#include "target_core_pr.h"
|
#include "target_core_pr.h"
|
||||||
#include "target_core_ua.h"
|
#include "target_core_ua.h"
|
||||||
@@ -2155,31 +2156,11 @@ check_depth:
|
|||||||
atomic_set(&cmd->t_transport_sent, 1);
|
atomic_set(&cmd->t_transport_sent, 1);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||||
/*
|
|
||||||
* The struct se_cmd->execute_task() 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->execute_task) {
|
|
||||||
error = cmd->execute_task(task);
|
|
||||||
} 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 (cmd->execute_task)
|
||||||
|
error = cmd->execute_task(task);
|
||||||
|
else
|
||||||
|
error = dev->transport->do_task(task);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
cmd->transport_error_status = error;
|
cmd->transport_error_status = error;
|
||||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||||
@@ -2622,6 +2603,13 @@ static int transport_generic_cmd_sequencer(
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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]) {
|
switch (cdb[0]) {
|
||||||
case READ_6:
|
case READ_6:
|
||||||
sectors = transport_get_sectors_6(cdb, cmd, §or_ret);
|
sectors = transport_get_sectors_6(cdb, cmd, §or_ret);
|
||||||
@@ -2701,9 +2689,12 @@ static int transport_generic_cmd_sequencer(
|
|||||||
cmd->t_task_lba = transport_lba_32(cdb);
|
cmd->t_task_lba = transport_lba_32(cdb);
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_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;
|
goto out_unsupported_cdb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup BIDI XOR callback to be run after I/O completion.
|
* Setup BIDI XOR callback to be run after I/O completion.
|
||||||
*/
|
*/
|
||||||
@@ -2712,13 +2703,6 @@ static int transport_generic_cmd_sequencer(
|
|||||||
break;
|
break;
|
||||||
case VARIABLE_LENGTH_CMD:
|
case VARIABLE_LENGTH_CMD:
|
||||||
service_action = get_unaligned_be16(&cdb[8]);
|
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) {
|
switch (service_action) {
|
||||||
case XDWRITEREAD_32:
|
case XDWRITEREAD_32:
|
||||||
sectors = transport_get_sectors_32(cdb, cmd, §or_ret);
|
sectors = transport_get_sectors_32(cdb, cmd, §or_ret);
|
||||||
@@ -2732,8 +2716,12 @@ static int transport_generic_cmd_sequencer(
|
|||||||
cmd->t_task_lba = transport_lba_64_ext(cdb);
|
cmd->t_task_lba = transport_lba_64_ext(cdb);
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do now allow BIDI commands for passthrough mode.
|
||||||
|
*/
|
||||||
if (passthrough)
|
if (passthrough)
|
||||||
goto out_unsupported_cdb;
|
goto out_unsupported_cdb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup BIDI XOR callback to be run during after I/O
|
* Setup BIDI XOR callback to be run during after I/O
|
||||||
* completion.
|
* completion.
|
||||||
@@ -2759,7 +2747,8 @@ static int transport_generic_cmd_sequencer(
|
|||||||
|
|
||||||
if (target_check_write_same_discard(&cdb[10], dev) < 0)
|
if (target_check_write_same_discard(&cdb[10], dev) < 0)
|
||||||
goto out_invalid_cdb_field;
|
goto out_invalid_cdb_field;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_write_same;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("VARIABLE_LENGTH_CMD service action"
|
pr_err("VARIABLE_LENGTH_CMD service action"
|
||||||
@@ -2797,8 +2786,15 @@ static int transport_generic_cmd_sequencer(
|
|||||||
case MODE_SENSE:
|
case MODE_SENSE:
|
||||||
size = cdb[4];
|
size = cdb[4];
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_modesense;
|
||||||
break;
|
break;
|
||||||
case MODE_SENSE_10:
|
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_READ_BUFFER_CAPACITY:
|
||||||
case GPCMD_SEND_OPC:
|
case GPCMD_SEND_OPC:
|
||||||
case LOG_SELECT:
|
case LOG_SELECT:
|
||||||
@@ -2867,6 +2863,8 @@ static int transport_generic_cmd_sequencer(
|
|||||||
if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
|
if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
|
||||||
cmd->sam_task_attr = MSG_HEAD_TAG;
|
cmd->sam_task_attr = MSG_HEAD_TAG;
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_inquiry;
|
||||||
break;
|
break;
|
||||||
case READ_BUFFER:
|
case READ_BUFFER:
|
||||||
size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
|
size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
|
||||||
@@ -2875,6 +2873,8 @@ static int transport_generic_cmd_sequencer(
|
|||||||
case READ_CAPACITY:
|
case READ_CAPACITY:
|
||||||
size = READ_CAP_LEN;
|
size = READ_CAP_LEN;
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_readcapacity;
|
||||||
break;
|
break;
|
||||||
case READ_MEDIA_SERIAL_NUMBER:
|
case READ_MEDIA_SERIAL_NUMBER:
|
||||||
case SECURITY_PROTOCOL_IN:
|
case SECURITY_PROTOCOL_IN:
|
||||||
@@ -2883,6 +2883,21 @@ static int transport_generic_cmd_sequencer(
|
|||||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||||
break;
|
break;
|
||||||
case SERVICE_ACTION_IN:
|
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_IN:
|
||||||
case ACCESS_CONTROL_OUT:
|
case ACCESS_CONTROL_OUT:
|
||||||
case EXTENDED_COPY:
|
case EXTENDED_COPY:
|
||||||
@@ -2913,6 +2928,8 @@ static int transport_generic_cmd_sequencer(
|
|||||||
case REQUEST_SENSE:
|
case REQUEST_SENSE:
|
||||||
size = cdb[4];
|
size = cdb[4];
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_request_sense;
|
||||||
break;
|
break;
|
||||||
case READ_ELEMENT_STATUS:
|
case READ_ELEMENT_STATUS:
|
||||||
size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
|
size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
|
||||||
@@ -2977,8 +2994,9 @@ static int transport_generic_cmd_sequencer(
|
|||||||
size = transport_get_size(sectors, cdb, cmd);
|
size = transport_get_size(sectors, cdb, cmd);
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
|
||||||
|
|
||||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
|
if (passthrough)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to ensure that LBA + Range does not exceed past end of
|
* Check to ensure that LBA + Range does not exceed past end of
|
||||||
* device for IBLOCK and FILEIO ->do_sync_cache() backend calls
|
* device for IBLOCK and FILEIO ->do_sync_cache() backend calls
|
||||||
@@ -2987,10 +3005,13 @@ static int transport_generic_cmd_sequencer(
|
|||||||
if (transport_cmd_get_valid_sectors(cmd) < 0)
|
if (transport_cmd_get_valid_sectors(cmd) < 0)
|
||||||
goto out_invalid_cdb_field;
|
goto out_invalid_cdb_field;
|
||||||
}
|
}
|
||||||
|
cmd->execute_task = target_emulate_synchronize_cache;
|
||||||
break;
|
break;
|
||||||
case UNMAP:
|
case UNMAP:
|
||||||
size = get_unaligned_be16(&cdb[7]);
|
size = get_unaligned_be16(&cdb[7]);
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_unmap;
|
||||||
break;
|
break;
|
||||||
case WRITE_SAME_16:
|
case WRITE_SAME_16:
|
||||||
sectors = transport_get_sectors_16(cdb, cmd, §or_ret);
|
sectors = transport_get_sectors_16(cdb, cmd, §or_ret);
|
||||||
@@ -3009,6 +3030,8 @@ static int transport_generic_cmd_sequencer(
|
|||||||
|
|
||||||
if (target_check_write_same_discard(&cdb[1], dev) < 0)
|
if (target_check_write_same_discard(&cdb[1], dev) < 0)
|
||||||
goto out_invalid_cdb_field;
|
goto out_invalid_cdb_field;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_write_same;
|
||||||
break;
|
break;
|
||||||
case WRITE_SAME:
|
case WRITE_SAME:
|
||||||
sectors = transport_get_sectors_10(cdb, cmd, §or_ret);
|
sectors = transport_get_sectors_10(cdb, cmd, §or_ret);
|
||||||
@@ -3030,20 +3053,26 @@ static int transport_generic_cmd_sequencer(
|
|||||||
*/
|
*/
|
||||||
if (target_check_write_same_discard(&cdb[1], dev) < 0)
|
if (target_check_write_same_discard(&cdb[1], dev) < 0)
|
||||||
goto out_invalid_cdb_field;
|
goto out_invalid_cdb_field;
|
||||||
|
if (!passthrough)
|
||||||
|
cmd->execute_task = target_emulate_write_same;
|
||||||
break;
|
break;
|
||||||
case ALLOW_MEDIUM_REMOVAL:
|
case ALLOW_MEDIUM_REMOVAL:
|
||||||
case GPCMD_CLOSE_TRACK:
|
|
||||||
case ERASE:
|
case ERASE:
|
||||||
case INITIALIZE_ELEMENT_STATUS:
|
|
||||||
case GPCMD_LOAD_UNLOAD:
|
|
||||||
case REZERO_UNIT:
|
case REZERO_UNIT:
|
||||||
case SEEK_10:
|
case SEEK_10:
|
||||||
case GPCMD_SET_SPEED:
|
|
||||||
case SPACE:
|
case SPACE:
|
||||||
case START_STOP:
|
case START_STOP:
|
||||||
case TEST_UNIT_READY:
|
case TEST_UNIT_READY:
|
||||||
case VERIFY:
|
case VERIFY:
|
||||||
case WRITE_FILEMARKS:
|
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:
|
case MOVE_MEDIUM:
|
||||||
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
|
cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
|
||||||
break;
|
break;
|
||||||
@@ -3100,6 +3129,11 @@ static int transport_generic_cmd_sequencer(
|
|||||||
cmd->data_length = size;
|
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. */
|
/* Let's limit control cdbs to a page, for simplicity's sake. */
|
||||||
if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
|
if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
|
||||||
size > PAGE_SIZE)
|
size > PAGE_SIZE)
|
||||||
|
Reference in New Issue
Block a user