[PATCH 4/5] tcm: Unify UNMAP and WRITE_SAME w/ UNMAP=1 subsystem plugin handling

From: Nicholas A. Bellinger
Date: Wed Oct 13 2010 - 04:48:31 EST


From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>

This patch adds the following struct se_subsystem_api function pointer
op for UNMAP and WRITE_SAME w/ UNMAP=1 handling mapped to Linux/Block
layer generic Discard to underlying SCSI *_UNMAP and ATA TRIM operation:

/*
* Used by virtual subsystem plugins IBLOCK and FILEIO to emulate
* UNMAP and WRITE_SAME_* w/ UNMAP=1 <-> Linux/Block Discard
*/
int (*do_discard)(struct se_task *, enum blk_discard_type);

and updates IBLOCK and FILEIO to execute their respective -> Linux/Block
DISCARD ops based on the passed blk_discard_type.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
Reported-by: Christoph Hellwig <hch@xxxxxx>
---
drivers/target/target_core_file.c | 17 +++++++++++++++--
drivers/target/target_core_iblock.c | 30 +++++++++++++++++++-----------
drivers/target/target_core_rd.c | 6 ------
drivers/target/target_core_transport.c | 12 ++++++------
include/target/target_core_transport.h | 12 ++++++++++--
5 files changed, 50 insertions(+), 27 deletions(-)

diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index dd7abef..adac070 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -774,6 +774,20 @@ static int fd_do_task(struct se_task *task)
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
}

+static int fd_do_discard(struct se_task *task, enum blk_discard_type type)
+{
+ if (type == DISCARD_UNMAP)
+ return fd_emulate_unmap(task);
+ else if (type == DISCARD_WRITE_SAME_UNMAP)
+ return fd_emulate_write_same_unmap(task);
+ else {
+ printk(KERN_ERR "Unsupported discard_type_t: %d\n", type);
+ return -ENOSYS;
+ }
+
+ return -ENOSYS;
+}
+
/* fd_free_task(): (Part of se_subsystem_api_t template)
*
*
@@ -1158,6 +1172,7 @@ static struct se_subsystem_api fileio_template = {
.transport_complete = fd_transport_complete,
.allocate_request = fd_allocate_request,
.do_task = fd_do_task,
+ .do_discard = fd_do_discard,
.free_task = fd_free_task,
.check_configfs_dev_params = fd_check_configfs_dev_params,
.set_configfs_dev_params = fd_set_configfs_dev_params,
@@ -1183,8 +1198,6 @@ static struct se_subsystem_api fileio_template = {
};

static struct se_subsystem_api_cdb fileio_cdb_template = {
- .emulate_unmap = fd_emulate_unmap,
- .emulate_write_same = fd_emulate_write_same_unmap,
.emulate_sync_cache = fd_emulate_sync_cache,
};

diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index cb53fbf..e1d945f 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -419,15 +419,6 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
return blocks_long;
}

-static int iblock_emulate_unmap(struct se_task *task)
-{
- struct iblock_dev *ibd = task->se_dev->dev_ptr;
- struct block_device *bd = ibd->ibd_bd;
- struct se_cmd *cmd = TASK_CMD(task);
-
- return transport_generic_unmap(cmd, bd);
-}
-
static int iblock_emulate_write_same_unmap(struct se_task *task)
{
struct iblock_dev *ibd = task->se_dev->dev_ptr;
@@ -568,6 +559,24 @@ static int iblock_do_task(struct se_task *task)
return PYX_TRANSPORT_SENT_TO_TRANSPORT;
}

+static int iblock_do_discard(struct se_task *task, enum blk_discard_type type)
+{
+ struct iblock_dev *ibd = task->se_dev->dev_ptr;
+ struct block_device *bd = ibd->ibd_bd;
+ struct se_cmd *cmd = TASK_CMD(task);
+
+ if (type == DISCARD_UNMAP)
+ return transport_generic_unmap(cmd, bd);
+ else if (type == DISCARD_WRITE_SAME_UNMAP)
+ return iblock_emulate_write_same_unmap(task);
+ else {
+ printk(KERN_ERR "Unsupported discard_type_t: %d\n", type);
+ return -ENOSYS;
+ }
+
+ return -ENOSYS;
+}
+
static void iblock_free_task(struct se_task *task)
{
struct iblock_req *req = task->transport_req;
@@ -1078,6 +1087,7 @@ static struct se_subsystem_api iblock_template = {
.transport_complete = iblock_transport_complete,
.allocate_request = iblock_allocate_request,
.do_task = iblock_do_task,
+ .do_discard = iblock_do_discard,
.free_task = iblock_free_task,
.check_configfs_dev_params = iblock_check_configfs_dev_params,
.set_configfs_dev_params = iblock_set_configfs_dev_params,
@@ -1104,8 +1114,6 @@ static struct se_subsystem_api iblock_template = {
};

static struct se_subsystem_api_cdb iblock_cdb_template = {
- .emulate_unmap = iblock_emulate_unmap,
- .emulate_write_same = iblock_emulate_write_same_unmap,
.emulate_sync_cache = iblock_emulate_sync_cache,
};

diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index c84213f..61f4a1c 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -1433,18 +1433,12 @@ static struct se_subsystem_api rd_mcp_template = {
.write_pending = NULL,
};

-static struct se_subsystem_api_cdb rd_cdb_template = {
- .emulate_unmap = NULL,
-};
-
int __init rd_module_init(void)
{
int ret;

INIT_LIST_HEAD(&rd_dr_template.sub_api_list);
- rd_dr_template.sub_cdb = &rd_cdb_template;
INIT_LIST_HEAD(&rd_mcp_template.sub_api_list);
- rd_mcp_template.sub_cdb = &rd_cdb_template;

ret = transport_subsystem_register(&rd_dr_template, NULL);
if (ret < 0)
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 3fb56d5..469f46f 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -5606,22 +5606,22 @@ int transport_emulate_control_cdb(struct se_task *task)
return ret;
break;
case UNMAP:
- if (!(api_cdb->emulate_unmap)) {
+ if (!(TRANSPORT(dev)->do_discard)) {
printk(KERN_ERR "UNMAP emulation not supported for: %s\n",
TRANSPORT(dev)->name);
return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE;
}
- ret = api_cdb->emulate_unmap(task);
+ ret = TRANSPORT(dev)->do_discard(task, DISCARD_UNMAP);
if (ret < 0)
return ret;
break;
case WRITE_SAME_16:
- if (!(api_cdb->emulate_write_same)) {
+ if (!(TRANSPORT(dev)->do_discard)) {
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);
+ ret = TRANSPORT(dev)->do_discard(task, DISCARD_WRITE_SAME_UNMAP);
if (ret < 0)
return ret;
break;
@@ -5629,12 +5629,12 @@ int transport_emulate_control_cdb(struct se_task *task)
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)) {
+ if (!(TRANSPORT(dev)->do_discard)) {
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);
+ ret = TRANSPORT(dev)->do_discard(task, DISCARD_WRITE_SAME_UNMAP);
if (ret < 0)
return ret;
break;
diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h
index 1c62d8c..dd0448b 100644
--- a/include/target/target_core_transport.h
+++ b/include/target/target_core_transport.h
@@ -127,6 +127,11 @@

#define MOD_MAX_SECTORS(ms, bs) (ms % (PAGE_SIZE / bs))

+enum blk_discard_type {
+ DISCARD_UNMAP,
+ DISCARD_WRITE_SAME_UNMAP,
+};
+
struct se_mem;
struct se_subsystem_api;

@@ -318,8 +323,6 @@ struct se_mem {
* subsystem plugins.for those CDBs that cannot be emulated generically.
*/
struct se_subsystem_api_cdb {
- int (*emulate_unmap)(struct se_task *);
- int (*emulate_write_same)(struct se_task *);
void (*emulate_sync_cache)(struct se_task *);
};

@@ -478,6 +481,11 @@ struct se_subsystem_api {
*/
int (*do_task)(struct se_task *);
/*
+ * Used by virtual subsystem plugins IBLOCK and FILEIO to emulate
+ * UNMAP and WRITE_SAME_* w/ UNMAP=1 <-> Linux/Block Discard
+ */
+ int (*do_discard)(struct se_task *, enum blk_discard_type);
+ /*
* free_task():
*/
void (*free_task)(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/