Commit 5bda90c8 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nicholas Bellinger

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent d29a5b6a
...@@ -32,6 +32,7 @@ ...@@ -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) ...@@ -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 @@ target_emulate_inquiry(struct se_task *task) ...@@ -731,8 +731,7 @@ target_emulate_inquiry(struct se_task *task)
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) ...@@ -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) ...@@ -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) ...@@ -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 @@ target_emulate_request_sense(struct se_task *task) ...@@ -1090,8 +1086,7 @@ target_emulate_request_sense(struct se_task *task)
* 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 @@ target_emulate_unmap(struct se_task *task) ...@@ -1150,8 +1145,7 @@ target_emulate_unmap(struct se_task *task)
* 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) ...@@ -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) ...@@ -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.
......
#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 @@ ...@@ -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 @@ static int __transport_execute_tasks(struct se_device *dev) ...@@ -2155,31 +2156,11 @@ static int __transport_execute_tasks(struct se_device *dev)
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 if (cmd->execute_task)
* 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); 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 else
error = dev->transport->do_task(task); 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( ...@@ -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, &sector_ret); sectors = transport_get_sectors_6(cdb, cmd, &sector_ret);
...@@ -2701,9 +2689,12 @@ static int transport_generic_cmd_sequencer( ...@@ -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( ...@@ -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, &sector_ret); sectors = transport_get_sectors_32(cdb, cmd, &sector_ret);
...@@ -2732,8 +2716,12 @@ static int transport_generic_cmd_sequencer( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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, &sector_ret); sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
...@@ -3009,6 +3030,8 @@ static int transport_generic_cmd_sequencer( ...@@ -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, &sector_ret); sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
...@@ -3030,20 +3053,26 @@ static int transport_generic_cmd_sequencer( ...@@ -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( ...@@ -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)
......
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