diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-01-30 01:10:06 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-02-13 14:27:51 -0500 |
commit | d0c8b259f8970d39354c1966853363345d401330 (patch) | |
tree | e6739094ba5db9ca88038f0e047e83e82bf21088 /drivers/target/target_core_iblock.c | |
parent | 1be2956d30b2b6200ebb26ffb758ed3c8071303c (diff) |
target/iblock: Use backend REQ_FLUSH hint for WriteCacheEnabled status
This patch allows IBLOCK to check block hints in request_queue->flush_flags
when reporting current backend device WriteCacheEnabled status to a remote
SCSI initiator port.
This is done via a se_subsystem_api->get_write_cache() call instead of a
backend se_device creation time flag, as we expect REQ_FLUSH bits to possibly
change from an underlying blk_queue_flush() by the SCSI disk driver, or
internal raw struct block_device driver usage.
Also go ahead and update iblock_execute_rw() bio I/O path code to use
REQ_FLUSH + REQ_FUA hints when determining WRITE_FUA usage, and make SPC
emulation code use a spc_check_dev_wce() helper to handle both types of
cases for virtual backend subsystem drivers.
(asias: Drop unnecessary comparsion operators)
Reported-by: majianpeng <majianpeng@gmail.com>
Cc: majianpeng <majianpeng@gmail.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: James Bottomley <JBottomley@Parallels.com>
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 | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index b526d23dcd4f..2f74e17ad3e6 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -154,6 +154,7 @@ static int iblock_configure_device(struct se_device *dev) | |||
154 | 154 | ||
155 | if (blk_queue_nonrot(q)) | 155 | if (blk_queue_nonrot(q)) |
156 | dev->dev_attrib.is_nonrot = 1; | 156 | dev->dev_attrib.is_nonrot = 1; |
157 | |||
157 | return 0; | 158 | return 0; |
158 | 159 | ||
159 | out_free_bioset: | 160 | out_free_bioset: |
@@ -654,20 +655,24 @@ iblock_execute_rw(struct se_cmd *cmd) | |||
654 | u32 sg_num = sgl_nents; | 655 | u32 sg_num = sgl_nents; |
655 | sector_t block_lba; | 656 | sector_t block_lba; |
656 | unsigned bio_cnt; | 657 | unsigned bio_cnt; |
657 | int rw; | 658 | int rw = 0; |
658 | int i; | 659 | int i; |
659 | 660 | ||
660 | if (data_direction == DMA_TO_DEVICE) { | 661 | if (data_direction == DMA_TO_DEVICE) { |
662 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); | ||
663 | struct request_queue *q = bdev_get_queue(ib_dev->ibd_bd); | ||
661 | /* | 664 | /* |
662 | * Force data to disk if we pretend to not have a volatile | 665 | * Force writethrough using WRITE_FUA if a volatile write cache |
663 | * write cache, or the initiator set the Force Unit Access bit. | 666 | * is not enabled, or if initiator set the Force Unit Access bit. |
664 | */ | 667 | */ |
665 | if (dev->dev_attrib.emulate_write_cache == 0 || | 668 | if (q->flush_flags & REQ_FUA) { |
666 | (dev->dev_attrib.emulate_fua_write > 0 && | 669 | if (cmd->se_cmd_flags & SCF_FUA) |
667 | (cmd->se_cmd_flags & SCF_FUA))) | 670 | rw = WRITE_FUA; |
668 | rw = WRITE_FUA; | 671 | else if (!(q->flush_flags & REQ_FLUSH)) |
669 | else | 672 | rw = WRITE_FUA; |
673 | } else { | ||
670 | rw = WRITE; | 674 | rw = WRITE; |
675 | } | ||
671 | } else { | 676 | } else { |
672 | rw = READ; | 677 | rw = READ; |
673 | } | 678 | } |
@@ -774,6 +779,15 @@ iblock_parse_cdb(struct se_cmd *cmd) | |||
774 | return sbc_parse_cdb(cmd, &iblock_sbc_ops); | 779 | return sbc_parse_cdb(cmd, &iblock_sbc_ops); |
775 | } | 780 | } |
776 | 781 | ||
782 | bool iblock_get_write_cache(struct se_device *dev) | ||
783 | { | ||
784 | struct iblock_dev *ib_dev = IBLOCK_DEV(dev); | ||
785 | struct block_device *bd = ib_dev->ibd_bd; | ||
786 | struct request_queue *q = bdev_get_queue(bd); | ||
787 | |||
788 | return q->flush_flags & REQ_FLUSH; | ||
789 | } | ||
790 | |||
777 | static struct se_subsystem_api iblock_template = { | 791 | static struct se_subsystem_api iblock_template = { |
778 | .name = "iblock", | 792 | .name = "iblock", |
779 | .inquiry_prod = "IBLOCK", | 793 | .inquiry_prod = "IBLOCK", |
@@ -790,6 +804,7 @@ static struct se_subsystem_api iblock_template = { | |||
790 | .show_configfs_dev_params = iblock_show_configfs_dev_params, | 804 | .show_configfs_dev_params = iblock_show_configfs_dev_params, |
791 | .get_device_type = sbc_get_device_type, | 805 | .get_device_type = sbc_get_device_type, |
792 | .get_blocks = iblock_get_blocks, | 806 | .get_blocks = iblock_get_blocks, |
807 | .get_write_cache = iblock_get_write_cache, | ||
793 | }; | 808 | }; |
794 | 809 | ||
795 | static int __init iblock_module_init(void) | 810 | static int __init iblock_module_init(void) |