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/target_core_iblock.c | |
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/target_core_iblock.c')
-rw-r--r-- | drivers/target/target_core_iblock.c | 50 |
1 files changed, 45 insertions, 5 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, |