Message ID | 20241008020437.78788-5-michael.christie@oracle.com |
---|---|
State | New |
Headers | show |
Series | scsi: target: Add WRITE_ATOMIC_16 support | expand |
Hi Mike, kernel test robot noticed the following build warnings: [auto build test WARNING on mkp-scsi/for-next] [also build test WARNING on jejb-scsi/for-next linus/master v6.12-rc2 next-20241008] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Mike-Christie/scsi-target-Rename-target_configure_unmap_from_queue/20241008-101218 base: https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next patch link: https://lore.kernel.org/r/20241008020437.78788-5-michael.christie%40oracle.com patch subject: [PATCH 4/7] scsi: target: Add WRITE_ATOMIC_16 handler config: x86_64-randconfig-123-20241009 (https://download.01.org/0day-ci/archive/20241009/202410091340.dQ10fC3u-lkp@intel.com/config) compiler: gcc-12 (Debian 12.2.0-14) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241009/202410091340.dQ10fC3u-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202410091340.dQ10fC3u-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/target/target_core_sbc.c:775:24: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted sense_reason_t @@ drivers/target/target_core_sbc.c:775:24: sparse: expected int drivers/target/target_core_sbc.c:775:24: sparse: got restricted sense_reason_t drivers/target/target_core_sbc.c:783:32: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted sense_reason_t @@ drivers/target/target_core_sbc.c:783:32: sparse: expected int drivers/target/target_core_sbc.c:783:32: sparse: got restricted sense_reason_t drivers/target/target_core_sbc.c:786:32: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted sense_reason_t @@ drivers/target/target_core_sbc.c:786:32: sparse: expected int drivers/target/target_core_sbc.c:786:32: sparse: got restricted sense_reason_t drivers/target/target_core_sbc.c:789:32: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted sense_reason_t @@ drivers/target/target_core_sbc.c:789:32: sparse: expected int drivers/target/target_core_sbc.c:789:32: sparse: got restricted sense_reason_t drivers/target/target_core_sbc.c:794:32: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted sense_reason_t @@ drivers/target/target_core_sbc.c:794:32: sparse: expected int drivers/target/target_core_sbc.c:794:32: sparse: got restricted sense_reason_t drivers/target/target_core_sbc.c:797:32: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted sense_reason_t @@ drivers/target/target_core_sbc.c:797:32: sparse: expected int drivers/target/target_core_sbc.c:797:32: sparse: got restricted sense_reason_t drivers/target/target_core_sbc.c:802:24: sparse: sparse: incorrect type in return expression (different base types) @@ expected int @@ got restricted sense_reason_t @@ drivers/target/target_core_sbc.c:802:24: sparse: expected int drivers/target/target_core_sbc.c:802:24: sparse: got restricted sense_reason_t >> drivers/target/target_core_sbc.c:919:29: sparse: sparse: incorrect type in assignment (different base types) @@ expected restricted sense_reason_t [assigned] [usertype] ret @@ got int @@ drivers/target/target_core_sbc.c:919:29: sparse: expected restricted sense_reason_t [assigned] [usertype] ret drivers/target/target_core_sbc.c:919:29: sparse: got int vim +775 drivers/target/target_core_sbc.c 766 767 static int 768 sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) 769 { 770 struct se_dev_attrib *attrib = &dev->dev_attrib; 771 u16 boundary, transfer_len; 772 u32 lba; 773 774 if (!attrib->atomic_supported) > 775 return TCM_UNSUPPORTED_SCSI_OPCODE; 776 777 lba = transport_lba_32(cdb); 778 boundary = get_unaligned_be16(&cdb[10]); 779 transfer_len = get_unaligned_be16(&cdb[12]); 780 781 if (!boundary) { 782 if (transfer_len > attrib->atomic_max_len) 783 return TCM_INVALID_CDB_FIELD; 784 } else { 785 if (transfer_len > attrib->atomic_max_with_boundary) 786 return TCM_INVALID_CDB_FIELD; 787 788 if (boundary > attrib->atomic_max_boundary) 789 return TCM_INVALID_CDB_FIELD; 790 } 791 792 if (attrib->atomic_granularity) { 793 if (transfer_len % attrib->atomic_granularity) 794 return TCM_INVALID_CDB_FIELD; 795 796 if (boundary && boundary % attrib->atomic_granularity) 797 return TCM_INVALID_CDB_FIELD; 798 } 799 800 if (dev->dev_attrib.atomic_alignment && 801 lba % dev->dev_attrib.atomic_alignment) 802 return TCM_INVALID_CDB_FIELD; 803 804 return 0; 805 } 806 807 sense_reason_t 808 sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) 809 { 810 struct se_device *dev = cmd->se_dev; 811 unsigned char *cdb = cmd->t_task_cdb; 812 unsigned int size; 813 u32 sectors = 0; 814 sense_reason_t ret; 815 816 cmd->protocol_data = ops; 817 818 switch (cdb[0]) { 819 case READ_6: 820 sectors = transport_get_sectors_6(cdb); 821 cmd->t_task_lba = transport_lba_21(cdb); 822 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 823 cmd->execute_cmd = sbc_execute_rw; 824 break; 825 case READ_10: 826 sectors = transport_get_sectors_10(cdb); 827 cmd->t_task_lba = transport_lba_32(cdb); 828 829 if (sbc_check_dpofua(dev, cmd, cdb)) 830 return TCM_INVALID_CDB_FIELD; 831 832 ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false); 833 if (ret) 834 return ret; 835 836 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 837 cmd->execute_cmd = sbc_execute_rw; 838 break; 839 case READ_12: 840 sectors = transport_get_sectors_12(cdb); 841 cmd->t_task_lba = transport_lba_32(cdb); 842 843 if (sbc_check_dpofua(dev, cmd, cdb)) 844 return TCM_INVALID_CDB_FIELD; 845 846 ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false); 847 if (ret) 848 return ret; 849 850 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 851 cmd->execute_cmd = sbc_execute_rw; 852 break; 853 case READ_16: 854 sectors = transport_get_sectors_16(cdb); 855 cmd->t_task_lba = transport_lba_64(cdb); 856 857 if (sbc_check_dpofua(dev, cmd, cdb)) 858 return TCM_INVALID_CDB_FIELD; 859 860 ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, false); 861 if (ret) 862 return ret; 863 864 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 865 cmd->execute_cmd = sbc_execute_rw; 866 break; 867 case WRITE_6: 868 sectors = transport_get_sectors_6(cdb); 869 cmd->t_task_lba = transport_lba_21(cdb); 870 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 871 cmd->execute_cmd = sbc_execute_rw; 872 break; 873 case WRITE_10: 874 case WRITE_VERIFY: 875 sectors = transport_get_sectors_10(cdb); 876 cmd->t_task_lba = transport_lba_32(cdb); 877 878 if (sbc_check_dpofua(dev, cmd, cdb)) 879 return TCM_INVALID_CDB_FIELD; 880 881 ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true); 882 if (ret) 883 return ret; 884 885 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 886 cmd->execute_cmd = sbc_execute_rw; 887 break; 888 case WRITE_12: 889 sectors = transport_get_sectors_12(cdb); 890 cmd->t_task_lba = transport_lba_32(cdb); 891 892 if (sbc_check_dpofua(dev, cmd, cdb)) 893 return TCM_INVALID_CDB_FIELD; 894 895 ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true); 896 if (ret) 897 return ret; 898 899 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 900 cmd->execute_cmd = sbc_execute_rw; 901 break; 902 case WRITE_16: 903 case WRITE_VERIFY_16: 904 case WRITE_ATOMIC_16: 905 sectors = transport_get_sectors_16(cdb); 906 cmd->t_task_lba = transport_lba_64(cdb); 907 908 if (sbc_check_dpofua(dev, cmd, cdb)) 909 return TCM_INVALID_CDB_FIELD; 910 911 ret = sbc_check_prot(dev, cmd, cdb[1] >> 5, sectors, true); 912 if (ret) 913 return ret; 914 915 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; 916 if (cdb[0] == WRITE_ATOMIC_16) { 917 cmd->se_cmd_flags |= SCF_ATOMIC; 918 > 919 ret = sbc_check_atomic(dev, cmd, cdb); 920 if (ret) 921 return ret; 922 } 923 cmd->execute_cmd = sbc_execute_rw; 924 break; 925 case VARIABLE_LENGTH_CMD: 926 { 927 u16 service_action = get_unaligned_be16(&cdb[8]); 928 switch (service_action) { 929 case WRITE_SAME_32: 930 sectors = transport_get_sectors_32(cdb); 931 if (!sectors) { 932 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" 933 " supported\n"); 934 return TCM_INVALID_CDB_FIELD; 935 } 936 937 size = sbc_get_size(cmd, 1); 938 cmd->t_task_lba = get_unaligned_be64(&cdb[12]); 939 940 ret = sbc_setup_write_same(cmd, cdb[10], ops); 941 if (ret) 942 return ret; 943 break; 944 default: 945 pr_err("VARIABLE_LENGTH_CMD service action" 946 " 0x%04x not supported\n", service_action); 947 return TCM_UNSUPPORTED_SCSI_OPCODE; 948 } 949 break; 950 } 951 case COMPARE_AND_WRITE: 952 if (!dev->dev_attrib.emulate_caw) { 953 pr_err_ratelimited("se_device %s/%s (vpd_unit_serial %s) reject COMPARE_AND_WRITE\n", 954 dev->se_hba->backend->ops->name, 955 config_item_name(&dev->dev_group.cg_item), 956 dev->t10_wwn.unit_serial); 957 return TCM_UNSUPPORTED_SCSI_OPCODE; 958 } 959 sectors = cdb[13]; 960 /* 961 * Currently enforce COMPARE_AND_WRITE for a single sector 962 */ 963 if (sectors > 1) { 964 pr_err("COMPARE_AND_WRITE contains NoLB: %u greater" 965 " than 1\n", sectors); 966 return TCM_INVALID_CDB_FIELD; 967 } 968 if (sbc_check_dpofua(dev, cmd, cdb)) 969 return TCM_INVALID_CDB_FIELD; 970 971 /* 972 * Double size because we have two buffers, note that 973 * zero is not an error.. 974 */ 975 size = 2 * sbc_get_size(cmd, sectors); 976 cmd->t_task_lba = get_unaligned_be64(&cdb[2]); 977 cmd->t_task_nolb = sectors; 978 cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB | SCF_COMPARE_AND_WRITE; 979 cmd->execute_cmd = sbc_compare_and_write; 980 cmd->transport_complete_callback = compare_and_write_callback; 981 break; 982 case READ_CAPACITY: 983 size = READ_CAP_LEN; 984 cmd->execute_cmd = sbc_emulate_readcapacity; 985 break; 986 case SERVICE_ACTION_IN_16: 987 switch (cmd->t_task_cdb[1] & 0x1f) { 988 case SAI_READ_CAPACITY_16: 989 cmd->execute_cmd = sbc_emulate_readcapacity_16; 990 break; 991 case SAI_REPORT_REFERRALS: 992 cmd->execute_cmd = target_emulate_report_referrals; 993 break; 994 default: 995 pr_err("Unsupported SA: 0x%02x\n", 996 cmd->t_task_cdb[1] & 0x1f); 997 return TCM_INVALID_CDB_FIELD; 998 } 999 size = get_unaligned_be32(&cdb[10]); 1000 break; 1001 case SYNCHRONIZE_CACHE: 1002 case SYNCHRONIZE_CACHE_16: 1003 if (cdb[0] == SYNCHRONIZE_CACHE) { 1004 sectors = transport_get_sectors_10(cdb); 1005 cmd->t_task_lba = transport_lba_32(cdb); 1006 } else { 1007 sectors = transport_get_sectors_16(cdb); 1008 cmd->t_task_lba = transport_lba_64(cdb); 1009 } 1010 if (ops->execute_sync_cache) { 1011 cmd->execute_cmd = ops->execute_sync_cache; 1012 goto check_lba; 1013 } 1014 size = 0; 1015 cmd->execute_cmd = sbc_emulate_noop; 1016 break; 1017 case UNMAP: 1018 if (!ops->execute_unmap) 1019 return TCM_UNSUPPORTED_SCSI_OPCODE; 1020 1021 if (!dev->dev_attrib.emulate_tpu) { 1022 pr_err("Got UNMAP, but backend device has" 1023 " emulate_tpu disabled\n"); 1024 return TCM_UNSUPPORTED_SCSI_OPCODE; 1025 } 1026 size = get_unaligned_be16(&cdb[7]); 1027 cmd->execute_cmd = sbc_execute_unmap; 1028 break; 1029 case WRITE_SAME_16: 1030 sectors = transport_get_sectors_16(cdb); 1031 if (!sectors) { 1032 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); 1033 return TCM_INVALID_CDB_FIELD; 1034 } 1035 1036 size = sbc_get_size(cmd, 1); 1037 cmd->t_task_lba = get_unaligned_be64(&cdb[2]); 1038 1039 ret = sbc_setup_write_same(cmd, cdb[1], ops); 1040 if (ret) 1041 return ret; 1042 break; 1043 case WRITE_SAME: 1044 sectors = transport_get_sectors_10(cdb); 1045 if (!sectors) { 1046 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); 1047 return TCM_INVALID_CDB_FIELD; 1048 } 1049 1050 size = sbc_get_size(cmd, 1); 1051 cmd->t_task_lba = get_unaligned_be32(&cdb[2]); 1052 1053 /* 1054 * Follow sbcr26 with WRITE_SAME (10) and check for the existence 1055 * of byte 1 bit 3 UNMAP instead of original reserved field 1056 */ 1057 ret = sbc_setup_write_same(cmd, cdb[1], ops); 1058 if (ret) 1059 return ret; 1060 break; 1061 case VERIFY: 1062 case VERIFY_16: 1063 size = 0; 1064 if (cdb[0] == VERIFY) { 1065 sectors = transport_get_sectors_10(cdb); 1066 cmd->t_task_lba = transport_lba_32(cdb); 1067 } else { 1068 sectors = transport_get_sectors_16(cdb); 1069 cmd->t_task_lba = transport_lba_64(cdb); 1070 } 1071 cmd->execute_cmd = sbc_emulate_noop; 1072 goto check_lba; 1073 case REZERO_UNIT: 1074 case SEEK_6: 1075 case SEEK_10: 1076 /* 1077 * There are still clients out there which use these old SCSI-2 1078 * commands. This mainly happens when running VMs with legacy 1079 * guest systems, connected via SCSI command pass-through to 1080 * iSCSI targets. Make them happy and return status GOOD. 1081 */ 1082 size = 0; 1083 cmd->execute_cmd = sbc_emulate_noop; 1084 break; 1085 case START_STOP: 1086 size = 0; 1087 cmd->execute_cmd = sbc_emulate_startstop; 1088 break; 1089 default: 1090 ret = spc_parse_cdb(cmd, &size); 1091 if (ret) 1092 return ret; 1093 } 1094 1095 /* reject any command that we don't have a handler for */ 1096 if (!cmd->execute_cmd) 1097 return TCM_UNSUPPORTED_SCSI_OPCODE; 1098 1099 if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) { 1100 unsigned long long end_lba; 1101 check_lba: 1102 end_lba = dev->transport->get_blocks(dev) + 1; 1103 if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) || 1104 ((cmd->t_task_lba + sectors) > end_lba)) { 1105 pr_err("cmd exceeds last lba %llu " 1106 "(lba %llu, sectors %u)\n", 1107 end_lba, cmd->t_task_lba, sectors); 1108 return TCM_ADDRESS_OUT_OF_RANGE; 1109 } 1110 1111 if (!(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) 1112 size = sbc_get_size(cmd, sectors); 1113 } 1114 1115 return target_cmd_size_check(cmd, size); 1116 } 1117 EXPORT_SYMBOL(sbc_parse_cdb); 1118
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index fe8beb7dbab1..0ae0d4ec0ac3 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -764,6 +764,46 @@ sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) return 0; } +static int +sbc_check_atomic(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb) +{ + struct se_dev_attrib *attrib = &dev->dev_attrib; + u16 boundary, transfer_len; + u32 lba; + + if (!attrib->atomic_supported) + return TCM_UNSUPPORTED_SCSI_OPCODE; + + lba = transport_lba_32(cdb); + boundary = get_unaligned_be16(&cdb[10]); + transfer_len = get_unaligned_be16(&cdb[12]); + + if (!boundary) { + if (transfer_len > attrib->atomic_max_len) + return TCM_INVALID_CDB_FIELD; + } else { + if (transfer_len > attrib->atomic_max_with_boundary) + return TCM_INVALID_CDB_FIELD; + + if (boundary > attrib->atomic_max_boundary) + return TCM_INVALID_CDB_FIELD; + } + + if (attrib->atomic_granularity) { + if (transfer_len % attrib->atomic_granularity) + return TCM_INVALID_CDB_FIELD; + + if (boundary && boundary % attrib->atomic_granularity) + return TCM_INVALID_CDB_FIELD; + } + + if (dev->dev_attrib.atomic_alignment && + lba % dev->dev_attrib.atomic_alignment) + return TCM_INVALID_CDB_FIELD; + + return 0; +} + sense_reason_t sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) { @@ -861,6 +901,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) break; case WRITE_16: case WRITE_VERIFY_16: + case WRITE_ATOMIC_16: sectors = transport_get_sectors_16(cdb); cmd->t_task_lba = transport_lba_64(cdb); @@ -872,6 +913,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct exec_cmd_ops *ops) return ret; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; + if (cdb[0] == WRITE_ATOMIC_16) { + cmd->se_cmd_flags |= SCF_ATOMIC; + + ret = sbc_check_atomic(dev, cmd, cdb); + if (ret) + return ret; + } cmd->execute_cmd = sbc_execute_rw; break; case VARIABLE_LENGTH_CMD: diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 6c87bd018983..7b8ed21bea03 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -157,6 +157,7 @@ enum se_cmd_flags_table { SCF_USE_CPUID = (1 << 16), SCF_TASK_ATTR_SET = (1 << 17), SCF_TREAT_READ_AS_NORMAL = (1 << 18), + SCF_ATOMIC = (1 << 19), }; /*
This adds the core LIO code to process the WRITE_ATOMIC_16 command. Signed-off-by: Mike Christie <michael.christie@oracle.com> --- drivers/target/target_core_sbc.c | 48 +++++++++++++++++++++++++++++++ include/target/target_core_base.h | 1 + 2 files changed, 49 insertions(+)