[PATCH 3/4] tcm: Move WRITE_SAME_* emulation into transport_emulate_control_cdb()

From: Nicholas A. Bellinger
Date: Sat Oct 09 2010 - 23:48:59 EST


From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch updates TCM Core to perform WRITE_SAME_16 and WRITE_SAME_32
w/ UNMAP=1 emulation using the unified control CDB infrastructure. This
includes adding a new struct se_subsystem_api_cdb->emulate_write_same() caller
used in transport_emulate_control_cdb(), changing transport_generic_cmd_sequencer()
to return type TGCS_CONTROL_SG_IO_CDB and removing the now unnecessary
struct se_transport_task->t_tasks_unmap and SCF_ECDB_ALLOCATION define.

This patch also updates IBLOCK and FILEIO to set ->emulate_write_same()
and hooks up the existing WRITE_SAME_* -> Block Discard logic to the new
caller.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
drivers/target/target_core_file.c | 3 +-
drivers/target/target_core_iblock.c | 3 +-
drivers/target/target_core_transport.c | 67 +++++++++++++++++--------------
include/target/target_core_base.h | 4 +-
include/target/target_core_transport.h | 1 +
5 files changed, 41 insertions(+), 37 deletions(-)

diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 33c6510..55e9ad5 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -782,8 +782,6 @@ static int fd_do_task(struct se_task *task)

if (!(TASK_CMD(task)->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))
return transport_emulate_control_cdb(task);
- else if (T_TASK(cmd)->t_tasks_unmap)
- return fd_emulate_write_same_unmap(task);

req->fd_lba = task->task_lba;
req->fd_size = task->task_size;
@@ -1218,6 +1216,7 @@ static struct se_subsystem_api_cdb fileio_cdb_template = {
.emulate_read_cap = fd_emulate_read_cap,
.emulate_read_cap16 = fd_emulate_read_cap16,
.emulate_unmap = fd_emulate_unmap,
+ .emulate_write_same = fd_emulate_write_same_unmap,
};

int __init fileio_module_init(void)
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index d102e0b..a0a9ea3 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -584,8 +584,6 @@ static int iblock_do_task(struct se_task *task)

if (!(TASK_CMD(task)->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))
return transport_emulate_control_cdb(task);
- else if (T_TASK(task->task_se_cmd)->t_tasks_unmap)
- return iblock_emulate_write_same_unmap(task);

while (bio) {
nbio = bio->bi_next;
@@ -1139,6 +1137,7 @@ static struct se_subsystem_api_cdb iblock_cdb_template = {
.emulate_read_cap = iblock_emulate_read_cap,
.emulate_read_cap16 = iblock_emulate_read_cap16,
.emulate_unmap = iblock_emulate_unmap,
+ .emulate_write_same = iblock_emulate_write_same_unmap,
};

int __init iblock_module_init(void)
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 2c86d0f..ae3ce18 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -5552,13 +5552,6 @@ int transport_generic_write_same(struct se_cmd *cmd, struct block_device *bdev)
sector_t lba;
unsigned int range;
int barrier = 0, ret;
- /*
- * If the UNMAP bit was not set, we should not be calling this to being with..
- */
- if (!(T_TASK(cmd)->t_tasks_unmap)) {
- dump_stack();
- return -1;
- }

lba = T_TASK(cmd)->t_task_lba;
range = (cmd->data_length / TRANSPORT(dev)->get_blocksize(dev));
@@ -5584,6 +5577,7 @@ int transport_emulate_control_cdb(struct se_task *task)
struct se_device *dev = SE_DEV(cmd);
struct se_subsystem_api_cdb *api_cdb = TRANSPORT(dev)->sub_cdb;
int ret;
+ unsigned short service_action;

switch (T_TASK(cmd)->t_task_cdb[0]) {
case INQUIRY:
@@ -5639,6 +5633,35 @@ int transport_emulate_control_cdb(struct se_task *task)
if (ret < 0)
return ret;
break;
+ case WRITE_SAME_16:
+ if (!(api_cdb->emulate_write_same)) {
+ printk(KERN_ERR "WRITE_SAME_16 emulation not supported"
+ " for: %s\n", TRANSPORT(dev)->name);
+ return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ }
+ ret = api_cdb->emulate_write_same(task);
+ if (ret < 0)
+ return ret;
+ break;
+ case VARIABLE_LENGTH_CMD:
+ service_action = get_unaligned_be16(&T_TASK(cmd)->t_task_cdb[8]);
+ switch (service_action) {
+ case WRITE_SAME_32:
+ if (!(api_cdb->emulate_write_same)) {
+ printk(KERN_ERR "WRITE_SAME_32 SA emulation not"
+ " supported for: %s\n", TRANSPORT(dev)->name);
+ return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
+ }
+ ret = api_cdb->emulate_write_same(task);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ printk(KERN_ERR "Unsupported VARIABLE_LENGTH_CMD SA:"
+ " 0x%02x\n", service_action);
+ break;
+ }
+ break;
case ALLOW_MEDIUM_REMOVAL:
case ERASE:
case REZERO_UNIT:
@@ -5951,13 +5974,12 @@ static int transport_generic_cmd_sequencer(
size = transport_get_size(sectors, cdb, cmd);
transport_dev_get_mem_SG(cmd->se_orig_obj_ptr, cmd);
transport_get_maps(cmd);
- cmd->transport_split_cdb = &split_cdb_XX_32;
- cmd->transport_get_long_lba = &transport_lba_64_ext;
+ T_TASK(cmd)->t_task_lba = get_unaligned_be64(&cdb[12]);
/*
* Skip the remaining assignments for TCM/PSCSI passthrough
*/
if (passthrough) {
- ret = TGCS_DATA_SG_IO_CDB;
+ ret = TGCS_CONTROL_SG_IO_CDB;
break;
}
if ((cdb[10] & 0x04) || (cdb[10] & 0x02)) {
@@ -5971,18 +5993,11 @@ static int transport_generic_cmd_sequencer(
* tpws with the UNMAP=1 bit set.
*/
if (!(cdb[10] & 0x08)) {
- printk(KERN_ERR "WRITE_SAME w/ UNMAP bit not"
+ printk(KERN_ERR "WRITE_SAME w/o UNMAP bit not"
" supported for Block Discard Emulation\n");
return TGCS_INVALID_CDB_FIELD;
}
-
- cmd->se_cmd_flags |= SCF_EMULATE_SYNC_WRITE_SAME;
- /*
- * Signal to TCM IBLOCK+FILEIO subsystem plugins that WRITE
- * tasks will be translated to SCSI UNMAP -> Block Discard
- */
- T_TASK(cmd)->t_tasks_unmap = 1;
- ret = TGCS_DATA_SG_IO_CDB;
+ ret = TGCS_CONTROL_SG_IO_CDB;
break;
default:
printk(KERN_ERR "VARIABLE_LENGTH_CMD service action"
@@ -6332,8 +6347,7 @@ static int transport_generic_cmd_sequencer(
size = transport_get_size(sectors, cdb, cmd);
transport_dev_get_mem_SG(cmd->se_orig_obj_ptr, cmd);
transport_get_maps(cmd);
- cmd->transport_split_cdb = &split_cdb_XX_16;
- cmd->transport_get_long_lba = &transport_lba_64;
+ T_TASK(cmd)->t_task_lba = get_unaligned_be16(&cdb[2]);
passthrough = (TRANSPORT(dev)->transport_type ==
TRANSPORT_PLUGIN_PHBA_PDEV);
/*
@@ -6355,19 +6369,12 @@ static int transport_generic_cmd_sequencer(
* tpws with the UNMAP=1 bit set.
*/
if (!(cdb[1] & 0x08)) {
- printk(KERN_ERR "WRITE_SAME w/ UNMAP bit not "
+ printk(KERN_ERR "WRITE_SAME w/o UNMAP bit not "
" supported for Block Discard Emulation\n");
return TGCS_INVALID_CDB_FIELD;
}
-
- cmd->se_cmd_flags |= SCF_EMULATE_SYNC_WRITE_SAME;
- /*
- * Signal to TCM IBLOCK+FILEIO subsystem plugins that WRITE
- * tasks will be translated to SCSI UNMAP -> Block Discard
- */
- T_TASK(cmd)->t_tasks_unmap = 1;
}
- ret = TGCS_DATA_SG_IO_CDB;
+ ret = TGCS_CONTROL_SG_IO_CDB;
break;
case ALLOW_MEDIUM_REMOVAL:
case GPCMD_CLOSE_TRACK:
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index f13193a..eb546f4 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -138,8 +138,7 @@ enum se_cmd_flags_table {
SCF_EMULATE_SYNC_CACHE = 0x01000000,
SCF_EMULATE_CDB_ASYNC = 0x02000000,
SCF_EMULATE_SYNC_UNMAP = 0x04000000,
- SCF_ECDB_ALLOCATION = 0x08000000,
- SCF_EMULATE_SYNC_WRITE_SAME = 0x10000000
+ SCF_ECDB_ALLOCATION = 0x08000000
};

/* struct se_device->type for known subsystem plugins */
@@ -432,7 +431,6 @@ struct se_transport_task {
int t_tasks_failed;
int t_tasks_fua;
int t_tasks_bidi:1;
- int t_tasks_unmap:1;
u32 t_task_cdbs;
u32 t_tasks_check;
u32 t_tasks_no;
diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h
index 0374876..31e726f 100644
--- a/include/target/target_core_transport.h
+++ b/include/target/target_core_transport.h
@@ -323,6 +323,7 @@ struct se_subsystem_api_cdb {
int (*emulate_read_cap)(struct se_task *);
int (*emulate_read_cap16)(struct se_task *);
int (*emulate_unmap)(struct se_task *);
+ int (*emulate_write_same)(struct se_task *);
};

/*
--
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/