aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_sbc.c
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2015-02-13 17:49:38 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2015-02-13 21:09:44 -0500
commitf7b7c06f386c5e990acb87a8bc96137b9f978977 (patch)
tree60a15481f0e470257ec72de21a8dd53b81427b93 /drivers/target/target_core_sbc.c
parentaa179935edea9a64dec4b757090c8106a3907ffa (diff)
target: Fail I/O with PROTECT bit when protection is unsupported
This patch adds an explicit check for WRPROTECT + RDPROTECT bit usage within sbc_check_prot(), and fails with TCM_INVALID_CDB_FIELD if the backend device does not have protection enabled. Also, update sbc_check_prot() to return sense_reason_t in order to propigate up the correct sense ASQ. Cc: Martin Petersen <martin.petersen@oracle.com> Cc: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/target_core_sbc.c')
-rw-r--r--drivers/target/target_core_sbc.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 17259c05450e..1bb8b4a93a66 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -626,14 +626,21 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
626 return 0; 626 return 0;
627} 627}
628 628
629static bool 629static sense_reason_t
630sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, 630sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
631 u32 sectors, bool is_write) 631 u32 sectors, bool is_write)
632{ 632{
633 u8 protect = cdb[1] >> 5; 633 u8 protect = cdb[1] >> 5;
634 634
635 if ((!cmd->t_prot_sg || !cmd->t_prot_nents) && cmd->prot_pto) 635 if (!cmd->t_prot_sg || !cmd->t_prot_nents) {
636 return true; 636 if (protect && !dev->dev_attrib.pi_prot_type) {
637 pr_err("CDB contains protect bit, but device does not"
638 " advertise PROTECT=1 feature bit\n");
639 return TCM_INVALID_CDB_FIELD;
640 }
641 if (cmd->prot_pto)
642 return TCM_NO_SENSE;
643 }
637 644
638 switch (dev->dev_attrib.pi_prot_type) { 645 switch (dev->dev_attrib.pi_prot_type) {
639 case TARGET_DIF_TYPE3_PROT: 646 case TARGET_DIF_TYPE3_PROT:
@@ -641,7 +648,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
641 break; 648 break;
642 case TARGET_DIF_TYPE2_PROT: 649 case TARGET_DIF_TYPE2_PROT:
643 if (protect) 650 if (protect)
644 return false; 651 return TCM_INVALID_CDB_FIELD;
645 652
646 cmd->reftag_seed = cmd->t_task_lba; 653 cmd->reftag_seed = cmd->t_task_lba;
647 break; 654 break;
@@ -650,12 +657,12 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
650 break; 657 break;
651 case TARGET_DIF_TYPE0_PROT: 658 case TARGET_DIF_TYPE0_PROT:
652 default: 659 default:
653 return true; 660 return TCM_NO_SENSE;
654 } 661 }
655 662
656 if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type, 663 if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type,
657 is_write, cmd)) 664 is_write, cmd))
658 return false; 665 return TCM_INVALID_CDB_FIELD;
659 666
660 cmd->prot_type = dev->dev_attrib.pi_prot_type; 667 cmd->prot_type = dev->dev_attrib.pi_prot_type;
661 cmd->prot_length = dev->prot_length * sectors; 668 cmd->prot_length = dev->prot_length * sectors;
@@ -674,7 +681,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
674 __func__, cmd->prot_type, cmd->data_length, cmd->prot_length, 681 __func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
675 cmd->prot_op, cmd->prot_checks); 682 cmd->prot_op, cmd->prot_checks);
676 683
677 return true; 684 return TCM_NO_SENSE;
678} 685}
679 686
680sense_reason_t 687sense_reason_t
@@ -698,8 +705,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
698 sectors = transport_get_sectors_10(cdb); 705 sectors = transport_get_sectors_10(cdb);
699 cmd->t_task_lba = transport_lba_32(cdb); 706 cmd->t_task_lba = transport_lba_32(cdb);
700 707
701 if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) 708 ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
702 return TCM_UNSUPPORTED_SCSI_OPCODE; 709 if (ret)
710 return ret;
703 711
704 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 712 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
705 cmd->execute_rw = ops->execute_rw; 713 cmd->execute_rw = ops->execute_rw;
@@ -709,8 +717,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
709 sectors = transport_get_sectors_12(cdb); 717 sectors = transport_get_sectors_12(cdb);
710 cmd->t_task_lba = transport_lba_32(cdb); 718 cmd->t_task_lba = transport_lba_32(cdb);
711 719
712 if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) 720 ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
713 return TCM_UNSUPPORTED_SCSI_OPCODE; 721 if (ret)
722 return ret;
714 723
715 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 724 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
716 cmd->execute_rw = ops->execute_rw; 725 cmd->execute_rw = ops->execute_rw;
@@ -720,8 +729,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
720 sectors = transport_get_sectors_16(cdb); 729 sectors = transport_get_sectors_16(cdb);
721 cmd->t_task_lba = transport_lba_64(cdb); 730 cmd->t_task_lba = transport_lba_64(cdb);
722 731
723 if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) 732 ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
724 return TCM_UNSUPPORTED_SCSI_OPCODE; 733 if (ret)
734 return ret;
725 735
726 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 736 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
727 cmd->execute_rw = ops->execute_rw; 737 cmd->execute_rw = ops->execute_rw;
@@ -739,8 +749,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
739 sectors = transport_get_sectors_10(cdb); 749 sectors = transport_get_sectors_10(cdb);
740 cmd->t_task_lba = transport_lba_32(cdb); 750 cmd->t_task_lba = transport_lba_32(cdb);
741 751
742 if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) 752 ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
743 return TCM_UNSUPPORTED_SCSI_OPCODE; 753 if (ret)
754 return ret;
744 755
745 if (cdb[1] & 0x8) 756 if (cdb[1] & 0x8)
746 cmd->se_cmd_flags |= SCF_FUA; 757 cmd->se_cmd_flags |= SCF_FUA;
@@ -752,8 +763,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
752 sectors = transport_get_sectors_12(cdb); 763 sectors = transport_get_sectors_12(cdb);
753 cmd->t_task_lba = transport_lba_32(cdb); 764 cmd->t_task_lba = transport_lba_32(cdb);
754 765
755 if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) 766 ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
756 return TCM_UNSUPPORTED_SCSI_OPCODE; 767 if (ret)
768 return ret;
757 769
758 if (cdb[1] & 0x8) 770 if (cdb[1] & 0x8)
759 cmd->se_cmd_flags |= SCF_FUA; 771 cmd->se_cmd_flags |= SCF_FUA;
@@ -765,8 +777,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
765 sectors = transport_get_sectors_16(cdb); 777 sectors = transport_get_sectors_16(cdb);
766 cmd->t_task_lba = transport_lba_64(cdb); 778 cmd->t_task_lba = transport_lba_64(cdb);
767 779
768 if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) 780 ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
769 return TCM_UNSUPPORTED_SCSI_OPCODE; 781 if (ret)
782 return ret;
770 783
771 if (cdb[1] & 0x8) 784 if (cdb[1] & 0x8)
772 cmd->se_cmd_flags |= SCF_FUA; 785 cmd->se_cmd_flags |= SCF_FUA;