diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-02-13 18:28:27 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-02-13 21:09:46 -0500 |
commit | fde9f50f80fe89a9115b4bfa773017272597d85d (patch) | |
tree | 8b1a67b39f2e3b64aafd32b95ccd8fb4a96314f4 | |
parent | afd73f1b60fc5883ea4982f68e9522e77b28f1e5 (diff) |
target: Add sanity checks for DPO/FUA bit usage
This patch adds a sbc_check_dpofua() function that performs sanity
checks for DPO/FUA command bits.
It introduces checks to fail when either bit is set, but the backend
device is not advertising support for them.
It also moves the existing cmd->se_cmd_flags |= SCF_FUA assignement
into the new helper function.
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/target/target_core_sbc.c | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 87cbbe220151..856e800926b8 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -692,6 +692,29 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, | |||
692 | return TCM_NO_SENSE; | 692 | return TCM_NO_SENSE; |
693 | } | 693 | } |
694 | 694 | ||
695 | static int | ||
696 | sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) | ||
697 | { | ||
698 | if (cdb[1] & 0x10) { | ||
699 | if (!dev->dev_attrib.emulate_dpo) { | ||
700 | pr_err("Got CDB: 0x%02x with DPO bit set, but device" | ||
701 | " does not advertise support for DPO\n", cdb[0]); | ||
702 | return -EINVAL; | ||
703 | } | ||
704 | } | ||
705 | if (cdb[1] & 0x8) { | ||
706 | if (!dev->dev_attrib.emulate_fua_write || | ||
707 | !dev->dev_attrib.emulate_write_cache) { | ||
708 | pr_err("Got CDB: 0x%02x with FUA bit set, but device" | ||
709 | " does not advertise support for FUA write\n", | ||
710 | cdb[0]); | ||
711 | return -EINVAL; | ||
712 | } | ||
713 | cmd->se_cmd_flags |= SCF_FUA; | ||
714 | } | ||
715 | return 0; | ||
716 | } | ||
717 | |||
695 | sense_reason_t | 718 | sense_reason_t |
696 | sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | 719 | sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) |
697 | { | 720 | { |
@@ -713,6 +736,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
713 | sectors = transport_get_sectors_10(cdb); | 736 | sectors = transport_get_sectors_10(cdb); |
714 | cmd->t_task_lba = transport_lba_32(cdb); | 737 | cmd->t_task_lba = transport_lba_32(cdb); |
715 | 738 | ||
739 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
740 | return TCM_INVALID_CDB_FIELD; | ||
741 | |||
716 | ret = sbc_check_prot(dev, cmd, cdb, sectors, false); | 742 | ret = sbc_check_prot(dev, cmd, cdb, sectors, false); |
717 | if (ret) | 743 | if (ret) |
718 | return ret; | 744 | return ret; |
@@ -725,6 +751,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
725 | sectors = transport_get_sectors_12(cdb); | 751 | sectors = transport_get_sectors_12(cdb); |
726 | cmd->t_task_lba = transport_lba_32(cdb); | 752 | cmd->t_task_lba = transport_lba_32(cdb); |
727 | 753 | ||
754 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
755 | return TCM_INVALID_CDB_FIELD; | ||
756 | |||
728 | ret = sbc_check_prot(dev, cmd, cdb, sectors, false); | 757 | ret = sbc_check_prot(dev, cmd, cdb, sectors, false); |
729 | if (ret) | 758 | if (ret) |
730 | return ret; | 759 | return ret; |
@@ -737,6 +766,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
737 | sectors = transport_get_sectors_16(cdb); | 766 | sectors = transport_get_sectors_16(cdb); |
738 | cmd->t_task_lba = transport_lba_64(cdb); | 767 | cmd->t_task_lba = transport_lba_64(cdb); |
739 | 768 | ||
769 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
770 | return TCM_INVALID_CDB_FIELD; | ||
771 | |||
740 | ret = sbc_check_prot(dev, cmd, cdb, sectors, false); | 772 | ret = sbc_check_prot(dev, cmd, cdb, sectors, false); |
741 | if (ret) | 773 | if (ret) |
742 | return ret; | 774 | return ret; |
@@ -757,12 +789,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
757 | sectors = transport_get_sectors_10(cdb); | 789 | sectors = transport_get_sectors_10(cdb); |
758 | cmd->t_task_lba = transport_lba_32(cdb); | 790 | cmd->t_task_lba = transport_lba_32(cdb); |
759 | 791 | ||
792 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
793 | return TCM_INVALID_CDB_FIELD; | ||
794 | |||
760 | ret = sbc_check_prot(dev, cmd, cdb, sectors, true); | 795 | ret = sbc_check_prot(dev, cmd, cdb, sectors, true); |
761 | if (ret) | 796 | if (ret) |
762 | return ret; | 797 | return ret; |
763 | 798 | ||
764 | if (cdb[1] & 0x8) | ||
765 | cmd->se_cmd_flags |= SCF_FUA; | ||
766 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 799 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
767 | cmd->execute_rw = ops->execute_rw; | 800 | cmd->execute_rw = ops->execute_rw; |
768 | cmd->execute_cmd = sbc_execute_rw; | 801 | cmd->execute_cmd = sbc_execute_rw; |
@@ -771,12 +804,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
771 | sectors = transport_get_sectors_12(cdb); | 804 | sectors = transport_get_sectors_12(cdb); |
772 | cmd->t_task_lba = transport_lba_32(cdb); | 805 | cmd->t_task_lba = transport_lba_32(cdb); |
773 | 806 | ||
807 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
808 | return TCM_INVALID_CDB_FIELD; | ||
809 | |||
774 | ret = sbc_check_prot(dev, cmd, cdb, sectors, true); | 810 | ret = sbc_check_prot(dev, cmd, cdb, sectors, true); |
775 | if (ret) | 811 | if (ret) |
776 | return ret; | 812 | return ret; |
777 | 813 | ||
778 | if (cdb[1] & 0x8) | ||
779 | cmd->se_cmd_flags |= SCF_FUA; | ||
780 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 814 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
781 | cmd->execute_rw = ops->execute_rw; | 815 | cmd->execute_rw = ops->execute_rw; |
782 | cmd->execute_cmd = sbc_execute_rw; | 816 | cmd->execute_cmd = sbc_execute_rw; |
@@ -785,12 +819,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
785 | sectors = transport_get_sectors_16(cdb); | 819 | sectors = transport_get_sectors_16(cdb); |
786 | cmd->t_task_lba = transport_lba_64(cdb); | 820 | cmd->t_task_lba = transport_lba_64(cdb); |
787 | 821 | ||
822 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
823 | return TCM_INVALID_CDB_FIELD; | ||
824 | |||
788 | ret = sbc_check_prot(dev, cmd, cdb, sectors, true); | 825 | ret = sbc_check_prot(dev, cmd, cdb, sectors, true); |
789 | if (ret) | 826 | if (ret) |
790 | return ret; | 827 | return ret; |
791 | 828 | ||
792 | if (cdb[1] & 0x8) | ||
793 | cmd->se_cmd_flags |= SCF_FUA; | ||
794 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 829 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
795 | cmd->execute_rw = ops->execute_rw; | 830 | cmd->execute_rw = ops->execute_rw; |
796 | cmd->execute_cmd = sbc_execute_rw; | 831 | cmd->execute_cmd = sbc_execute_rw; |
@@ -801,6 +836,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
801 | return TCM_INVALID_CDB_FIELD; | 836 | return TCM_INVALID_CDB_FIELD; |
802 | sectors = transport_get_sectors_10(cdb); | 837 | sectors = transport_get_sectors_10(cdb); |
803 | 838 | ||
839 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
840 | return TCM_INVALID_CDB_FIELD; | ||
841 | |||
804 | cmd->t_task_lba = transport_lba_32(cdb); | 842 | cmd->t_task_lba = transport_lba_32(cdb); |
805 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; | 843 | cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; |
806 | 844 | ||
@@ -810,8 +848,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
810 | cmd->execute_rw = ops->execute_rw; | 848 | cmd->execute_rw = ops->execute_rw; |
811 | cmd->execute_cmd = sbc_execute_rw; | 849 | cmd->execute_cmd = sbc_execute_rw; |
812 | cmd->transport_complete_callback = &xdreadwrite_callback; | 850 | cmd->transport_complete_callback = &xdreadwrite_callback; |
813 | if (cdb[1] & 0x8) | ||
814 | cmd->se_cmd_flags |= SCF_FUA; | ||
815 | break; | 851 | break; |
816 | case VARIABLE_LENGTH_CMD: | 852 | case VARIABLE_LENGTH_CMD: |
817 | { | 853 | { |
@@ -820,6 +856,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
820 | case XDWRITEREAD_32: | 856 | case XDWRITEREAD_32: |
821 | sectors = transport_get_sectors_32(cdb); | 857 | sectors = transport_get_sectors_32(cdb); |
822 | 858 | ||
859 | if (sbc_check_dpofua(dev, cmd, cdb)) | ||
860 | return TCM_INVALID_CDB_FIELD; | ||
823 | /* | 861 | /* |
824 | * Use WRITE_32 and READ_32 opcodes for the emulated | 862 | * Use WRITE_32 and READ_32 opcodes for the emulated |
825 | * XDWRITE_READ_32 logic. | 863 | * XDWRITE_READ_32 logic. |
@@ -834,8 +872,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
834 | cmd->execute_rw = ops->execute_rw; | 872 | cmd->execute_rw = ops->execute_rw; |
835 | cmd->execute_cmd = sbc_execute_rw; | 873 | cmd->execute_cmd = sbc_execute_rw; |
836 | cmd->transport_complete_callback = &xdreadwrite_callback; | 874 | cmd->transport_complete_callback = &xdreadwrite_callback; |
837 | if (cdb[1] & 0x8) | ||
838 | cmd->se_cmd_flags |= SCF_FUA; | ||
839 | break; | 875 | break; |
840 | case WRITE_SAME_32: | 876 | case WRITE_SAME_32: |
841 | sectors = transport_get_sectors_32(cdb); | 877 | sectors = transport_get_sectors_32(cdb); |