diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-06-17 18:40:55 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-07-16 20:35:14 -0400 |
commit | 14150a6bbe9e15ce8e7a4f79047c2b4284a51b3d (patch) | |
tree | 1a77a526359e6159ed367ac3b1e8f1e13de6bb37 /drivers/target | |
parent | 6f974e8ce7b3f661910a49c7c2ba095631f341e9 (diff) |
target: move unmap to struct spc_ops
Having all the unmap payload parsing in the backed is a bit ugly, but until
more drivers support it and we can find a good interface for all of them
that seems the way to go.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_iblock.c | 50 | ||||
-rw-r--r-- | drivers/target/target_core_sbc.c | 62 |
2 files changed, 49 insertions, 63 deletions
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index ee70cc9f6a64..8a12e29009c1 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/module.h> | 40 | #include <linux/module.h> |
41 | #include <scsi/scsi.h> | 41 | #include <scsi/scsi.h> |
42 | #include <scsi/scsi_host.h> | 42 | #include <scsi/scsi_host.h> |
43 | #include <asm/unaligned.h> | ||
43 | 44 | ||
44 | #include <target/target_core_base.h> | 45 | #include <target/target_core_base.h> |
45 | #include <target/target_core_backend.h> | 46 | #include <target/target_core_backend.h> |
@@ -318,13 +319,52 @@ static int iblock_execute_sync_cache(struct se_cmd *cmd) | |||
318 | return 0; | 319 | return 0; |
319 | } | 320 | } |
320 | 321 | ||
321 | static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range) | 322 | static int iblock_execute_unmap(struct se_cmd *cmd) |
322 | { | 323 | { |
324 | struct se_device *dev = cmd->se_dev; | ||
323 | struct iblock_dev *ibd = dev->dev_ptr; | 325 | struct iblock_dev *ibd = dev->dev_ptr; |
324 | struct block_device *bd = ibd->ibd_bd; | 326 | unsigned char *buf, *ptr = NULL; |
325 | int barrier = 0; | 327 | unsigned char *cdb = &cmd->t_task_cdb[0]; |
328 | sector_t lba; | ||
329 | unsigned int size = cmd->data_length, range; | ||
330 | int ret = 0, offset; | ||
331 | unsigned short dl, bd_dl; | ||
332 | |||
333 | /* First UNMAP block descriptor starts at 8 byte offset */ | ||
334 | offset = 8; | ||
335 | size -= 8; | ||
336 | dl = get_unaligned_be16(&cdb[0]); | ||
337 | bd_dl = get_unaligned_be16(&cdb[2]); | ||
338 | |||
339 | buf = transport_kmap_data_sg(cmd); | ||
340 | |||
341 | ptr = &buf[offset]; | ||
342 | pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" | ||
343 | " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); | ||
344 | |||
345 | while (size) { | ||
346 | lba = get_unaligned_be64(&ptr[0]); | ||
347 | range = get_unaligned_be32(&ptr[8]); | ||
348 | pr_debug("UNMAP: Using lba: %llu and range: %u\n", | ||
349 | (unsigned long long)lba, range); | ||
350 | |||
351 | ret = blkdev_issue_discard(ibd->ibd_bd, lba, range, | ||
352 | GFP_KERNEL, 0); | ||
353 | if (ret < 0) { | ||
354 | pr_err("blkdev_issue_discard() failed: %d\n", | ||
355 | ret); | ||
356 | goto err; | ||
357 | } | ||
358 | |||
359 | ptr += 16; | ||
360 | size -= 16; | ||
361 | } | ||
326 | 362 | ||
327 | return blkdev_issue_discard(bd, lba, range, GFP_KERNEL, barrier); | 363 | err: |
364 | transport_kunmap_data_sg(cmd); | ||
365 | if (!ret) | ||
366 | target_complete_cmd(cmd, GOOD); | ||
367 | return ret; | ||
328 | } | 368 | } |
329 | 369 | ||
330 | static int iblock_execute_write_same(struct se_cmd *cmd) | 370 | static int iblock_execute_write_same(struct se_cmd *cmd) |
@@ -687,6 +727,7 @@ static struct spc_ops iblock_spc_ops = { | |||
687 | .execute_rw = iblock_execute_rw, | 727 | .execute_rw = iblock_execute_rw, |
688 | .execute_sync_cache = iblock_execute_sync_cache, | 728 | .execute_sync_cache = iblock_execute_sync_cache, |
689 | .execute_write_same = iblock_execute_write_same, | 729 | .execute_write_same = iblock_execute_write_same, |
730 | .execute_unmap = iblock_execute_unmap, | ||
690 | }; | 731 | }; |
691 | 732 | ||
692 | static int iblock_parse_cdb(struct se_cmd *cmd) | 733 | static int iblock_parse_cdb(struct se_cmd *cmd) |
@@ -706,7 +747,6 @@ static struct se_subsystem_api iblock_template = { | |||
706 | .create_virtdevice = iblock_create_virtdevice, | 747 | .create_virtdevice = iblock_create_virtdevice, |
707 | .free_device = iblock_free_device, | 748 | .free_device = iblock_free_device, |
708 | .parse_cdb = iblock_parse_cdb, | 749 | .parse_cdb = iblock_parse_cdb, |
709 | .do_discard = iblock_do_discard, | ||
710 | .check_configfs_dev_params = iblock_check_configfs_dev_params, | 750 | .check_configfs_dev_params = iblock_check_configfs_dev_params, |
711 | .set_configfs_dev_params = iblock_set_configfs_dev_params, | 751 | .set_configfs_dev_params = iblock_set_configfs_dev_params, |
712 | .show_configfs_dev_params = iblock_show_configfs_dev_params, | 752 | .show_configfs_dev_params = iblock_show_configfs_dev_params, |
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 146ca372489b..a9dd9469e3bd 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -99,63 +99,6 @@ static int sbc_emulate_readcapacity_16(struct se_cmd *cmd) | |||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | 101 | ||
102 | /* | ||
103 | * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. | ||
104 | * Note this is not used for TCM/pSCSI passthrough | ||
105 | */ | ||
106 | static int sbc_emulate_unmap(struct se_cmd *cmd) | ||
107 | { | ||
108 | struct se_device *dev = cmd->se_dev; | ||
109 | unsigned char *buf, *ptr = NULL; | ||
110 | unsigned char *cdb = &cmd->t_task_cdb[0]; | ||
111 | sector_t lba; | ||
112 | unsigned int size = cmd->data_length, range; | ||
113 | int ret = 0, offset; | ||
114 | unsigned short dl, bd_dl; | ||
115 | |||
116 | if (!dev->transport->do_discard) { | ||
117 | pr_err("UNMAP emulation not supported for: %s\n", | ||
118 | dev->transport->name); | ||
119 | cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; | ||
120 | return -ENOSYS; | ||
121 | } | ||
122 | |||
123 | /* First UNMAP block descriptor starts at 8 byte offset */ | ||
124 | offset = 8; | ||
125 | size -= 8; | ||
126 | dl = get_unaligned_be16(&cdb[0]); | ||
127 | bd_dl = get_unaligned_be16(&cdb[2]); | ||
128 | |||
129 | buf = transport_kmap_data_sg(cmd); | ||
130 | |||
131 | ptr = &buf[offset]; | ||
132 | pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" | ||
133 | " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); | ||
134 | |||
135 | while (size) { | ||
136 | lba = get_unaligned_be64(&ptr[0]); | ||
137 | range = get_unaligned_be32(&ptr[8]); | ||
138 | pr_debug("UNMAP: Using lba: %llu and range: %u\n", | ||
139 | (unsigned long long)lba, range); | ||
140 | |||
141 | ret = dev->transport->do_discard(dev, lba, range); | ||
142 | if (ret < 0) { | ||
143 | pr_err("blkdev_issue_discard() failed: %d\n", | ||
144 | ret); | ||
145 | goto err; | ||
146 | } | ||
147 | |||
148 | ptr += 16; | ||
149 | size -= 16; | ||
150 | } | ||
151 | |||
152 | err: | ||
153 | transport_kunmap_data_sg(cmd); | ||
154 | if (!ret) | ||
155 | target_complete_cmd(cmd, GOOD); | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | int spc_get_write_same_sectors(struct se_cmd *cmd) | 102 | int spc_get_write_same_sectors(struct se_cmd *cmd) |
160 | { | 103 | { |
161 | u32 num_blocks; | 104 | u32 num_blocks; |
@@ -533,8 +476,11 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) | |||
533 | cmd->execute_cmd = ops->execute_sync_cache; | 476 | cmd->execute_cmd = ops->execute_sync_cache; |
534 | break; | 477 | break; |
535 | case UNMAP: | 478 | case UNMAP: |
479 | if (!ops->execute_unmap) | ||
480 | goto out_unsupported_cdb; | ||
481 | |||
536 | size = get_unaligned_be16(&cdb[7]); | 482 | size = get_unaligned_be16(&cdb[7]); |
537 | cmd->execute_cmd = sbc_emulate_unmap; | 483 | cmd->execute_cmd = ops->execute_unmap; |
538 | break; | 484 | break; |
539 | case WRITE_SAME_16: | 485 | case WRITE_SAME_16: |
540 | if (!ops->execute_write_same) | 486 | if (!ops->execute_write_same) |