Commit 6ed5a557 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nicholas Bellinger

target: refactor transport_emulate_control_cdb

Encapsulate each CDB emulation into a function of its own, to prepare
setting ->exectute_task to these routines.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent e76a35d6
...@@ -680,8 +680,9 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) ...@@ -680,8 +680,9 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
} }
static int static int
target_emulate_inquiry(struct se_cmd *cmd) target_emulate_inquiry(struct se_task *task)
{ {
struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *buf; unsigned char *buf;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
...@@ -721,8 +722,9 @@ target_emulate_inquiry(struct se_cmd *cmd) ...@@ -721,8 +722,9 @@ target_emulate_inquiry(struct se_cmd *cmd)
} }
static int static int
target_emulate_readcapacity(struct se_cmd *cmd) target_emulate_readcapacity(struct se_task *task)
{ {
struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *buf; unsigned char *buf;
unsigned long long blocks_long = dev->transport->get_blocks(dev); unsigned long long blocks_long = dev->transport->get_blocks(dev);
...@@ -755,8 +757,9 @@ target_emulate_readcapacity(struct se_cmd *cmd) ...@@ -755,8 +757,9 @@ target_emulate_readcapacity(struct se_cmd *cmd)
} }
static int static int
target_emulate_readcapacity_16(struct se_cmd *cmd) target_emulate_readcapacity_16(struct se_task *task)
{ {
struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
unsigned char *buf; unsigned char *buf;
unsigned long long blocks = dev->transport->get_blocks(dev); unsigned long long blocks = dev->transport->get_blocks(dev);
...@@ -923,13 +926,15 @@ target_modesense_dpofua(unsigned char *buf, int type) ...@@ -923,13 +926,15 @@ target_modesense_dpofua(unsigned char *buf, int type)
} }
static int static int
target_emulate_modesense(struct se_cmd *cmd, int ten) target_emulate_modesense(struct se_task *task)
{ {
struct se_cmd *cmd = task->task_se_cmd;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
char *cdb = cmd->t_task_cdb; char *cdb = cmd->t_task_cdb;
unsigned char *rbuf; unsigned char *rbuf;
int type = dev->transport->get_device_type(dev); int type = dev->transport->get_device_type(dev);
int offset = (ten) ? 8 : 4; int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
int offset = ten ? 8 : 4;
int length = 0; int length = 0;
unsigned char buf[SE_MODE_PAGE_BUF]; unsigned char buf[SE_MODE_PAGE_BUF];
...@@ -999,8 +1004,9 @@ target_emulate_modesense(struct se_cmd *cmd, int ten) ...@@ -999,8 +1004,9 @@ target_emulate_modesense(struct se_cmd *cmd, int ten)
} }
static int static int
target_emulate_request_sense(struct se_cmd *cmd) target_emulate_request_sense(struct se_task *task)
{ {
struct se_cmd *cmd = task->task_se_cmd;
unsigned char *cdb = cmd->t_task_cdb; unsigned char *cdb = cmd->t_task_cdb;
unsigned char *buf; unsigned char *buf;
u8 ua_asc = 0, ua_ascq = 0; u8 ua_asc = 0, ua_ascq = 0;
...@@ -1079,6 +1085,12 @@ target_emulate_unmap(struct se_task *task) ...@@ -1079,6 +1085,12 @@ target_emulate_unmap(struct se_task *task)
int ret = 0, offset; int ret = 0, offset;
unsigned short dl, bd_dl; unsigned short dl, bd_dl;
if (!dev->transport->do_discard) {
pr_err("UNMAP emulation not supported for: %s\n",
dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
/* First UNMAP block descriptor starts at 8 byte offset */ /* First UNMAP block descriptor starts at 8 byte offset */
offset = 8; offset = 8;
size -= 8; size -= 8;
...@@ -1119,13 +1131,28 @@ target_emulate_unmap(struct se_task *task) ...@@ -1119,13 +1131,28 @@ target_emulate_unmap(struct se_task *task)
* Note this is not used for TCM/pSCSI passthrough * Note this is not used for TCM/pSCSI passthrough
*/ */
static int static int
target_emulate_write_same(struct se_task *task, u32 num_blocks) 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;
sector_t range; sector_t range;
sector_t lba = cmd->t_task_lba; sector_t lba = cmd->t_task_lba;
u32 num_blocks;
int ret; int ret;
if (!dev->transport->do_discard) {
pr_err("WRITE_SAME emulation not supported"
" for: %s\n", dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
if (cmd->t_task_cdb[0] == WRITE_SAME)
num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);
else if (cmd->t_task_cdb[0] == WRITE_SAME_16)
num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */
num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
/* /*
* Use the explicit range when non zero is supplied, otherwise calculate * Use the explicit range when non zero is supplied, otherwise calculate
* the remaining range based on ->get_blocks() - starting LBA. * the remaining range based on ->get_blocks() - starting LBA.
...@@ -1147,6 +1174,21 @@ target_emulate_write_same(struct se_task *task, u32 num_blocks) ...@@ -1147,6 +1174,21 @@ target_emulate_write_same(struct se_task *task, u32 num_blocks)
return 0; return 0;
} }
static int
target_emulate_synchronize_cache(struct se_task *task)
{
struct se_device *dev = task->task_se_cmd->se_dev;
if (!dev->transport->do_sync_cache) {
pr_err("SYNCHRONIZE_CACHE emulation not supported"
" for: %s\n", dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
dev->transport->do_sync_cache(task);
return 0;
}
int int
transport_emulate_control_cdb(struct se_task *task) transport_emulate_control_cdb(struct se_task *task)
{ {
...@@ -1157,21 +1199,21 @@ transport_emulate_control_cdb(struct se_task *task) ...@@ -1157,21 +1199,21 @@ transport_emulate_control_cdb(struct se_task *task)
switch (cmd->t_task_cdb[0]) { switch (cmd->t_task_cdb[0]) {
case INQUIRY: case INQUIRY:
ret = target_emulate_inquiry(cmd); ret = target_emulate_inquiry(task);
break; break;
case READ_CAPACITY: case READ_CAPACITY:
ret = target_emulate_readcapacity(cmd); ret = target_emulate_readcapacity(task);
break; break;
case MODE_SENSE: case MODE_SENSE:
ret = target_emulate_modesense(cmd, 0); ret = target_emulate_modesense(task);
break; break;
case MODE_SENSE_10: case MODE_SENSE_10:
ret = target_emulate_modesense(cmd, 1); ret = target_emulate_modesense(task);
break; break;
case SERVICE_ACTION_IN: case SERVICE_ACTION_IN:
switch (cmd->t_task_cdb[1] & 0x1f) { switch (cmd->t_task_cdb[1] & 0x1f) {
case SAI_READ_CAPACITY_16: case SAI_READ_CAPACITY_16:
ret = target_emulate_readcapacity_16(cmd); ret = target_emulate_readcapacity_16(task);
break; break;
default: default:
pr_err("Unsupported SA: 0x%02x\n", pr_err("Unsupported SA: 0x%02x\n",
...@@ -1180,47 +1222,23 @@ transport_emulate_control_cdb(struct se_task *task) ...@@ -1180,47 +1222,23 @@ transport_emulate_control_cdb(struct se_task *task)
} }
break; break;
case REQUEST_SENSE: case REQUEST_SENSE:
ret = target_emulate_request_sense(cmd); ret = target_emulate_request_sense(task);
break; break;
case UNMAP: case UNMAP:
if (!dev->transport->do_discard) {
pr_err("UNMAP emulation not supported for: %s\n",
dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
ret = target_emulate_unmap(task); ret = target_emulate_unmap(task);
break; break;
case WRITE_SAME: case WRITE_SAME:
if (!dev->transport->do_discard) { ret = target_emulate_write_same(task);
pr_err("WRITE_SAME emulation not supported"
" for: %s\n", dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
ret = target_emulate_write_same(task,
get_unaligned_be16(&cmd->t_task_cdb[7]));
break; break;
case WRITE_SAME_16: case WRITE_SAME_16:
if (!dev->transport->do_discard) { ret = target_emulate_write_same(task);
pr_err("WRITE_SAME_16 emulation not supported"
" for: %s\n", dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
ret = target_emulate_write_same(task,
get_unaligned_be32(&cmd->t_task_cdb[10]));
break; break;
case VARIABLE_LENGTH_CMD: case VARIABLE_LENGTH_CMD:
service_action = service_action =
get_unaligned_be16(&cmd->t_task_cdb[8]); get_unaligned_be16(&cmd->t_task_cdb[8]);
switch (service_action) { switch (service_action) {
case WRITE_SAME_32: case WRITE_SAME_32:
if (!dev->transport->do_discard) { ret = target_emulate_write_same(task);
pr_err("WRITE_SAME_32 SA emulation not"
" supported for: %s\n",
dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
ret = target_emulate_write_same(task,
get_unaligned_be32(&cmd->t_task_cdb[28]));
break; break;
default: default:
pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" pr_err("Unsupported VARIABLE_LENGTH_CMD SA:"
...@@ -1230,12 +1248,7 @@ transport_emulate_control_cdb(struct se_task *task) ...@@ -1230,12 +1248,7 @@ transport_emulate_control_cdb(struct se_task *task)
break; break;
case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE:
case 0x91: /* SYNCHRONIZE_CACHE_16: */ case 0x91: /* SYNCHRONIZE_CACHE_16: */
if (!dev->transport->do_sync_cache) { ret = target_emulate_synchronize_cache(task);
pr_err("SYNCHRONIZE_CACHE emulation not supported"
" for: %s\n", dev->transport->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
dev->transport->do_sync_cache(task);
break; break;
case ALLOW_MEDIUM_REMOVAL: case ALLOW_MEDIUM_REMOVAL:
case ERASE: case ERASE:
......
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