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 | |
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')
-rw-r--r-- | drivers/target/target_core_device.c | 6 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.c | 31 | ||||
-rw-r--r-- | drivers/target/target_core_spc.c | 21 |
3 files changed, 47 insertions, 11 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index f2aa7543d20a..d10cbed23472 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -772,6 +772,12 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag) | |||
772 | pr_err("emulate_write_cache not supported for pSCSI\n"); | 772 | pr_err("emulate_write_cache not supported for pSCSI\n"); |
773 | return -EINVAL; | 773 | return -EINVAL; |
774 | } | 774 | } |
775 | if (dev->transport->get_write_cache) { | ||
776 | pr_warn("emulate_write_cache cannot be changed when underlying" | ||
777 | " HW reports WriteCacheEnabled, ignoring request\n"); | ||
778 | return 0; | ||
779 | } | ||
780 | |||
775 | dev->dev_attrib.emulate_write_cache = flag; | 781 | dev->dev_attrib.emulate_write_cache = flag; |
776 | pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n", | 782 | pr_debug("dev[%p]: SE Device WRITE_CACHE_EMULATION flag: %d\n", |
777 | dev, dev->dev_attrib.emulate_write_cache); | 783 | dev, dev->dev_attrib.emulate_write_cache); |
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) |
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index fa2447004006..803339516fb9 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c | |||
@@ -407,16 +407,31 @@ check_scsi_name: | |||
407 | } | 407 | } |
408 | EXPORT_SYMBOL(spc_emulate_evpd_83); | 408 | EXPORT_SYMBOL(spc_emulate_evpd_83); |
409 | 409 | ||
410 | static bool | ||
411 | spc_check_dev_wce(struct se_device *dev) | ||
412 | { | ||
413 | bool wce = false; | ||
414 | |||
415 | if (dev->transport->get_write_cache) | ||
416 | wce = dev->transport->get_write_cache(dev); | ||
417 | else if (dev->dev_attrib.emulate_write_cache > 0) | ||
418 | wce = true; | ||
419 | |||
420 | return wce; | ||
421 | } | ||
422 | |||
410 | /* Extended INQUIRY Data VPD Page */ | 423 | /* Extended INQUIRY Data VPD Page */ |
411 | static sense_reason_t | 424 | static sense_reason_t |
412 | spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) | 425 | spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) |
413 | { | 426 | { |
427 | struct se_device *dev = cmd->se_dev; | ||
428 | |||
414 | buf[3] = 0x3c; | 429 | buf[3] = 0x3c; |
415 | /* Set HEADSUP, ORDSUP, SIMPSUP */ | 430 | /* Set HEADSUP, ORDSUP, SIMPSUP */ |
416 | buf[5] = 0x07; | 431 | buf[5] = 0x07; |
417 | 432 | ||
418 | /* If WriteCache emulation is enabled, set V_SUP */ | 433 | /* If WriteCache emulation is enabled, set V_SUP */ |
419 | if (cmd->se_dev->dev_attrib.emulate_write_cache > 0) | 434 | if (spc_check_dev_wce(dev)) |
420 | buf[6] = 0x01; | 435 | buf[6] = 0x01; |
421 | return 0; | 436 | return 0; |
422 | } | 437 | } |
@@ -766,7 +781,7 @@ static int spc_modesense_caching(struct se_device *dev, u8 pc, u8 *p) | |||
766 | if (pc == 1) | 781 | if (pc == 1) |
767 | goto out; | 782 | goto out; |
768 | 783 | ||
769 | if (dev->dev_attrib.emulate_write_cache > 0) | 784 | if (spc_check_dev_wce(dev)) |
770 | p[2] = 0x04; /* Write Cache Enable */ | 785 | p[2] = 0x04; /* Write Cache Enable */ |
771 | p[12] = 0x20; /* Disabled Read Ahead */ | 786 | p[12] = 0x20; /* Disabled Read Ahead */ |
772 | 787 | ||
@@ -878,7 +893,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
878 | (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) | 893 | (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY))) |
879 | spc_modesense_write_protect(&buf[length], type); | 894 | spc_modesense_write_protect(&buf[length], type); |
880 | 895 | ||
881 | if ((dev->dev_attrib.emulate_write_cache > 0) && | 896 | if ((spc_check_dev_wce(dev)) && |
882 | (dev->dev_attrib.emulate_fua_write > 0)) | 897 | (dev->dev_attrib.emulate_fua_write > 0)) |
883 | spc_modesense_dpofua(&buf[length], type); | 898 | spc_modesense_dpofua(&buf[length], type); |
884 | 899 | ||