Message ID | 20250210191232.185207-3-Kai.Makisara@kolumbus.fi (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | scsi: scsi_debug: Add more tape support | expand |
Hi Kai, kernel test robot noticed the following build warnings: [auto build test WARNING on jejb-scsi/for-next] [also build test WARNING on mkp-scsi/for-next linus/master v6.14-rc2 next-20250210] [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/Kai-M-kisara/scsi-scsi_debug-First-fixes-for-tapes/20250211-031623 base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next patch link: https://lore.kernel.org/r/20250210191232.185207-3-Kai.Makisara%40kolumbus.fi patch subject: [PATCH v1 2/7] scsi: scsi_debug: Add READ BLOCK LIMITS and modify LOAD for tapes config: x86_64-kexec (https://download.01.org/0day-ci/archive/20250211/202502111805.dXd61ARr-lkp@intel.com/config) compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250211/202502111805.dXd61ARr-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/202502111805.dXd61ARr-lkp@intel.com/ All warnings (new ones prefixed by >>): In file included from drivers/scsi/scsi_debug.c:31: In file included from include/linux/scatterlist.h:8: In file included from include/linux/mm.h:2224: include/linux/vmstat.h:504:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 504 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 505 | item]; | ~~~~ include/linux/vmstat.h:511:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 511 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 512 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ include/linux/vmstat.h:524:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion] 524 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~ ^ 525 | NR_VM_NUMA_EVENT_ITEMS + | ~~~~~~~~~~~~~~~~~~~~~~ >> drivers/scsi/scsi_debug.c:2926:3: warning: variable 'len' is uninitialized when used here [-Wuninitialized] 2926 | len += resp_partition_m_pg(ap, pcontrol, target); | ^~~ drivers/scsi/scsi_debug.c:2791:28: note: initialize the variable 'len' to silence this warning 2791 | u32 alloc_len, offset, len; | ^ | = 0 4 warnings generated. vim +/len +2926 drivers/scsi/scsi_debug.c 2785 2786 static int resp_mode_sense(struct scsi_cmnd *scp, 2787 struct sdebug_dev_info *devip) 2788 { 2789 int pcontrol, pcode, subpcode, bd_len; 2790 unsigned char dev_spec; 2791 u32 alloc_len, offset, len; 2792 int target_dev_id; 2793 int target = scp->device->id; 2794 unsigned char *ap; 2795 unsigned char *arr __free(kfree); 2796 unsigned char *cmd = scp->cmnd; 2797 bool dbd, llbaa, msense_6, is_disk, is_zbc, is_tape; 2798 2799 arr = kzalloc(SDEBUG_MAX_MSENSE_SZ, GFP_ATOMIC); 2800 if (!arr) 2801 return -ENOMEM; 2802 dbd = !!(cmd[1] & 0x8); /* disable block descriptors */ 2803 pcontrol = (cmd[2] & 0xc0) >> 6; 2804 pcode = cmd[2] & 0x3f; 2805 subpcode = cmd[3]; 2806 msense_6 = (MODE_SENSE == cmd[0]); 2807 llbaa = msense_6 ? false : !!(cmd[1] & 0x10); 2808 is_disk = (sdebug_ptype == TYPE_DISK); 2809 is_zbc = devip->zoned; 2810 is_tape = (sdebug_ptype == TYPE_TAPE); 2811 if ((is_disk || is_zbc || is_tape) && !dbd) 2812 bd_len = llbaa ? 16 : 8; 2813 else 2814 bd_len = 0; 2815 alloc_len = msense_6 ? cmd[4] : get_unaligned_be16(cmd + 7); 2816 if (0x3 == pcontrol) { /* Saving values not supported */ 2817 mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0); 2818 return check_condition_result; 2819 } 2820 target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + 2821 (devip->target * 1000) - 3; 2822 /* for disks+zbc set DPOFUA bit and clear write protect (WP) bit */ 2823 if (is_disk || is_zbc) { 2824 dev_spec = 0x10; /* =0x90 if WP=1 implies read-only */ 2825 if (sdebug_wp) 2826 dev_spec |= 0x80; 2827 } else 2828 dev_spec = 0x0; 2829 if (msense_6) { 2830 arr[2] = dev_spec; 2831 arr[3] = bd_len; 2832 offset = 4; 2833 } else { 2834 arr[3] = dev_spec; 2835 if (16 == bd_len) 2836 arr[4] = 0x1; /* set LONGLBA bit */ 2837 arr[7] = bd_len; /* assume 255 or less */ 2838 offset = 8; 2839 } 2840 ap = arr + offset; 2841 if ((bd_len > 0) && (!sdebug_capacity)) 2842 sdebug_capacity = get_sdebug_capacity(); 2843 2844 if (8 == bd_len) { 2845 if (sdebug_capacity > 0xfffffffe) 2846 put_unaligned_be32(0xffffffff, ap + 0); 2847 else 2848 put_unaligned_be32(sdebug_capacity, ap + 0); 2849 if (is_tape) { 2850 ap[0] = devip->tape_density; 2851 put_unaligned_be16(devip->tape_blksize, ap + 6); 2852 } else 2853 put_unaligned_be16(sdebug_sector_size, ap + 6); 2854 offset += bd_len; 2855 ap = arr + offset; 2856 } else if (16 == bd_len) { 2857 if (is_tape) { 2858 mk_sense_invalid_fld(scp, SDEB_IN_DATA, 1, 4); 2859 return check_condition_result; 2860 } 2861 put_unaligned_be64((u64)sdebug_capacity, ap + 0); 2862 put_unaligned_be32(sdebug_sector_size, ap + 12); 2863 offset += bd_len; 2864 ap = arr + offset; 2865 } 2866 if (cmd[2] == 0) 2867 goto only_bd; /* Only block descriptor requested */ 2868 2869 /* 2870 * N.B. If len>0 before resp_*_pg() call, then form of that call should be: 2871 * len += resp_*_pg(ap + len, pcontrol, target); 2872 */ 2873 switch (pcode) { 2874 case 0x1: /* Read-Write error recovery page, direct access */ 2875 if (subpcode > 0x0 && subpcode < 0xff) 2876 goto bad_subpcode; 2877 len = resp_err_recov_pg(ap, pcontrol, target); 2878 offset += len; 2879 break; 2880 case 0x2: /* Disconnect-Reconnect page, all devices */ 2881 if (subpcode > 0x0 && subpcode < 0xff) 2882 goto bad_subpcode; 2883 len = resp_disconnect_pg(ap, pcontrol, target); 2884 offset += len; 2885 break; 2886 case 0x3: /* Format device page, direct access */ 2887 if (subpcode > 0x0 && subpcode < 0xff) 2888 goto bad_subpcode; 2889 if (is_disk) { 2890 len = resp_format_pg(ap, pcontrol, target); 2891 offset += len; 2892 } else { 2893 goto bad_pcode; 2894 } 2895 break; 2896 case 0x8: /* Caching page, direct access */ 2897 if (subpcode > 0x0 && subpcode < 0xff) 2898 goto bad_subpcode; 2899 if (is_disk || is_zbc) { 2900 len = resp_caching_pg(ap, pcontrol, target); 2901 offset += len; 2902 } else { 2903 goto bad_pcode; 2904 } 2905 break; 2906 case 0xa: /* Control Mode page, all devices */ 2907 switch (subpcode) { 2908 case 0: 2909 len = resp_ctrl_m_pg(ap, pcontrol, target); 2910 break; 2911 case 0x05: 2912 len = resp_grouping_m_pg(ap, pcontrol, target); 2913 break; 2914 case 0xff: 2915 len = resp_ctrl_m_pg(ap, pcontrol, target); 2916 len += resp_grouping_m_pg(ap + len, pcontrol, target); 2917 break; 2918 default: 2919 goto bad_subpcode; 2920 } 2921 offset += len; 2922 break; 2923 case 0x11: /* Partition Mode Page (tape) */ 2924 if (!is_tape) 2925 goto bad_pcode; > 2926 len += resp_partition_m_pg(ap, pcontrol, target); 2927 offset += len; 2928 break; 2929 case 0x19: /* if spc==1 then sas phy, control+discover */ 2930 if (subpcode > 0x2 && subpcode < 0xff) 2931 goto bad_subpcode; 2932 len = 0; 2933 if ((0x0 == subpcode) || (0xff == subpcode)) 2934 len += resp_sas_sf_m_pg(ap + len, pcontrol, target); 2935 if ((0x1 == subpcode) || (0xff == subpcode)) 2936 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target, 2937 target_dev_id); 2938 if ((0x2 == subpcode) || (0xff == subpcode)) 2939 len += resp_sas_sha_m_spg(ap + len, pcontrol); 2940 offset += len; 2941 break; 2942 case 0x1c: /* Informational Exceptions Mode page, all devices */ 2943 if (subpcode > 0x0 && subpcode < 0xff) 2944 goto bad_subpcode; 2945 len = resp_iec_m_pg(ap, pcontrol, target); 2946 offset += len; 2947 break; 2948 case 0x3f: /* Read all Mode pages */ 2949 if (subpcode > 0x0 && subpcode < 0xff) 2950 goto bad_subpcode; 2951 len = resp_err_recov_pg(ap, pcontrol, target); 2952 len += resp_disconnect_pg(ap + len, pcontrol, target); 2953 if (is_disk) { 2954 len += resp_format_pg(ap + len, pcontrol, target); 2955 len += resp_caching_pg(ap + len, pcontrol, target); 2956 } else if (is_zbc) { 2957 len += resp_caching_pg(ap + len, pcontrol, target); 2958 } 2959 len += resp_ctrl_m_pg(ap + len, pcontrol, target); 2960 if (0xff == subpcode) 2961 len += resp_grouping_m_pg(ap + len, pcontrol, target); 2962 len += resp_sas_sf_m_pg(ap + len, pcontrol, target); 2963 if (0xff == subpcode) { 2964 len += resp_sas_pcd_m_spg(ap + len, pcontrol, target, 2965 target_dev_id); 2966 len += resp_sas_sha_m_spg(ap + len, pcontrol); 2967 } 2968 len += resp_iec_m_pg(ap + len, pcontrol, target); 2969 offset += len; 2970 break; 2971 default: 2972 goto bad_pcode; 2973 } 2974 only_bd: 2975 if (msense_6) 2976 arr[0] = offset - 1; 2977 else 2978 put_unaligned_be16((offset - 2), arr + 0); 2979 return fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, offset)); 2980 2981 bad_pcode: 2982 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5); 2983 return check_condition_result; 2984 2985 bad_subpcode: 2986 mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1); 2987 return check_condition_result; 2988 } 2989
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 4da0c259390b..5c662f3d97e3 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -80,6 +80,7 @@ static const char *sdebug_version_date = "20210520"; #define INVALID_FIELD_IN_CDB 0x24 #define INVALID_FIELD_IN_PARAM_LIST 0x26 #define WRITE_PROTECTED 0x27 +#define UA_READY_ASC 0x28 #define UA_RESET_ASC 0x29 #define UA_CHANGED_ASC 0x2a #define TARGET_CHANGED_ASC 0x3f @@ -175,7 +176,11 @@ static const char *sdebug_version_date = "20210520"; /* Default parameters for tape drives */ #define TAPE_DEF_DENSITY 0x0 +#define TAPE_BAD_DENSITY 0x65 #define TAPE_DEF_BLKSIZE 0 +#define TAPE_MIN_BLKSIZE 512 +#define TAPE_MAX_BLKSIZE 1048576 +#define TAPE_MAX_PARTITIONS 2 #define SDEBUG_LUN_0_VAL 0 @@ -220,7 +225,8 @@ static const char *sdebug_version_date = "20210520"; #define SDEBUG_UA_LUNS_CHANGED 5 #define SDEBUG_UA_MICROCODE_CHANGED 6 /* simulate firmware change */ #define SDEBUG_UA_MICROCODE_CHANGED_WO_RESET 7 -#define SDEBUG_NUM_UAS 8 +#define SDEBUG_UA_NOT_READY_TO_READY 8 +#define SDEBUG_NUM_UAS 9 /* when 1==SDEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this * sector on read commands: */ @@ -370,6 +376,8 @@ struct sdebug_dev_info { /* For tapes */ unsigned int tape_blksize; unsigned int tape_density; + unsigned char tape_partition; + unsigned int tape_location[TAPE_MAX_PARTITIONS]; struct dentry *debugfs_entry; struct spinlock list_lock; @@ -491,14 +499,16 @@ enum sdeb_opcode_index { SDEB_I_ZONE_OUT = 30, /* 0x94+SA; includes no data xfer */ SDEB_I_ZONE_IN = 31, /* 0x95+SA; all have data-in */ SDEB_I_ATOMIC_WRITE_16 = 32, - SDEB_I_LAST_ELEM_P1 = 33, /* keep this last (previous + 1) */ + SDEB_I_READ_BLOCK_LIMITS = 33, + SDEB_I_LOCATE = 34, + SDEB_I_LAST_ELEM_P1 = 35, /* keep this last (previous + 1) */ }; static const unsigned char opcode_ind_arr[256] = { /* 0x0; 0x0->0x1f: 6 byte cdbs */ SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE, - 0, 0, 0, 0, + 0, SDEB_I_READ_BLOCK_LIMITS, 0, 0, SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0, 0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE, SDEB_I_RELEASE, @@ -506,7 +516,7 @@ static const unsigned char opcode_ind_arr[256] = { SDEB_I_ALLOW_REMOVAL, 0, /* 0x20; 0x20->0x3f: 10 byte cdbs */ 0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0, - SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY, + SDEB_I_READ, 0, SDEB_I_WRITE, SDEB_I_LOCATE, 0, 0, 0, SDEB_I_VERIFY, 0, 0, 0, 0, SDEB_I_PRE_FETCH, SDEB_I_SYNC_CACHE, 0, 0, 0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0, /* 0x40; 0x40->0x5f: 10 byte cdbs */ @@ -581,6 +591,8 @@ static int resp_open_zone(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_close_zone(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_finish_zone(struct scsi_cmnd *, struct sdebug_dev_info *); static int resp_rwp_zone(struct scsi_cmnd *, struct sdebug_dev_info *); +static int resp_read_blklimits(struct scsi_cmnd *, struct sdebug_dev_info *); +static int resp_locate(struct scsi_cmnd *, struct sdebug_dev_info *); static int sdebug_do_add_host(bool mk_new_store); static int sdebug_add_host_helper(int per_host_idx); @@ -808,6 +820,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = { resp_pre_fetch, pre_fetch_iarr, {10, 0x2, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} }, /* PRE-FETCH (10) */ + /* READ POSITION (10) */ /* 30 */ {ARRAY_SIZE(zone_out_iarr), 0x94, 0x3, F_SA_LOW | F_M_ACCESS, @@ -823,6 +836,12 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = { resp_atomic_write, NULL, /* ATOMIC WRITE 16 */ {16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} }, + {0, 0x05, 0, F_D_IN, resp_read_blklimits, NULL, /* READ BLOCK LIMITS (6) */ + {6, 0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, + {0, 0x2b, 0, F_D_UNKN, resp_locate, NULL, /* LOCATE (10) */ + {10, 0x2, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0, + 0, 0, 0, 0} }, + /* sentinel */ {0xff, 0, 0, 0, NULL, NULL, /* terminating element */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, @@ -1501,6 +1520,12 @@ static int make_ua(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) if (sdebug_verbose) cp = "reported luns data has changed"; break; + case SDEBUG_UA_NOT_READY_TO_READY: + mk_sense_buffer(scp, UNIT_ATTENTION, UA_READY_ASC, + 0); + if (sdebug_verbose) + cp = "not ready to ready transition/media change"; + break; default: pr_warn("unexpected unit attention code=%d\n", k); if (sdebug_verbose) @@ -2204,6 +2229,14 @@ static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) changing = (stopped_state != want_stop); if (changing) atomic_xchg(&devip->stopped, want_stop); + if (sdebug_ptype == TYPE_TAPE && !want_stop) { + int i; + + set_bit(SDEBUG_UA_NOT_READY_TO_READY, devip->uas_bm); /* not legal! */ + for (i = 0; i < TAPE_MAX_PARTITIONS; i++) + devip->tape_location[i] = 0; + devip->tape_partition = 0; + } if (!changing || (cmd[1] & 0x1)) /* state unchanged or IMMED bit set in cdb */ return SDEG_RES_IMMED_MASK; else @@ -2736,6 +2769,17 @@ static int resp_sas_sha_m_spg(unsigned char *p, int pcontrol) return sizeof(sas_sha_m_pg); } +static unsigned char partition_pg[] = {0x11, 12, 1, 0, 0x24, 3, 9, 0, + 0xff, 0xff, 0x00, 0x00}; + +static int resp_partition_m_pg(unsigned char *p, int pcontrol, int target) +{ /* Partition page for mode_sense (tape) */ + memcpy(p, partition_pg, sizeof(partition_pg)); + if (pcontrol == 1) + memset(p + 2, 0, sizeof(partition_pg) - 2); + return sizeof(partition_pg); +} + /* PAGE_SIZE is more than necessary but provides room for future expansion. */ #define SDEBUG_MAX_MSENSE_SZ PAGE_SIZE @@ -2876,6 +2920,12 @@ static int resp_mode_sense(struct scsi_cmnd *scp, } offset += len; break; + case 0x11: /* Partition Mode Page (tape) */ + if (!is_tape) + goto bad_pcode; + len += resp_partition_m_pg(ap, pcontrol, target); + offset += len; + break; case 0x19: /* if spc==1 then sas phy, control+discover */ if (subpcode > 0x2 && subpcode < 0xff) goto bad_subpcode; @@ -2974,9 +3024,16 @@ static int resp_mode_select(struct scsi_cmnd *scp, mselect6 ? 3 : 6, -1); return check_condition_result; } + if (arr[off] == TAPE_BAD_DENSITY) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1); + return check_condition_result; + } blksize = get_unaligned_be16(arr + off + 6); - if ((blksize % 4) != 0) { - mk_sense_invalid_fld(scp, SDEB_IN_DATA, off + 6, -1); + if (blksize != 0 && + (blksize < TAPE_MIN_BLKSIZE || + blksize > TAPE_MAX_BLKSIZE || + (blksize % 4) != 0)) { + mk_sense_invalid_fld(scp, SDEB_IN_DATA, 1, -1); return check_condition_result; } devip->tape_density = arr[off]; @@ -3177,6 +3234,36 @@ static int resp_log_sense(struct scsi_cmnd *scp, min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ)); } +enum {SDEBUG_READ_BLOCK_LIMITS_ARR_SZ = 6}; +static int resp_read_blklimits(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) +{ + unsigned char arr[SDEBUG_READ_BLOCK_LIMITS_ARR_SZ]; + + arr[0] = 4; + put_unaligned_be24(TAPE_MAX_BLKSIZE, arr + 1); + put_unaligned_be16(TAPE_MIN_BLKSIZE, arr + 4); + return fill_from_dev_buffer(scp, arr, SDEBUG_READ_BLOCK_LIMITS_ARR_SZ); +} + +static int resp_locate(struct scsi_cmnd *scp, + struct sdebug_dev_info *devip) +{ + unsigned char *cmd = scp->cmnd; + + if ((cmd[1] & 0x02) != 0) { + if (cmd[8] >= TAPE_MAX_PARTITIONS) { + mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, -1); + return check_condition_result; + } + devip->tape_partition = cmd[8]; + } + devip->tape_location[devip->tape_partition] = + get_unaligned_be32(cmd + 3); + + return 0; +} + static inline bool sdebug_dev_is_zoned(struct sdebug_dev_info *devip) { return devip->nr_zones != 0; @@ -4957,7 +5044,10 @@ static int resp_sync_cache(struct scsi_cmnd *scp, * a GOOD status otherwise. Model a disk with a big cache and yield * CONDITION MET. Actually tries to bring range in main memory into the * cache associated with the CPU(s). + * + * The pcode 0x34 is also used for READ POSITION by tape devices. */ +enum {SDEBUG_READ_POSITION_ARR_SZ = 20}; static int resp_pre_fetch(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) { @@ -4969,6 +5059,31 @@ static int resp_pre_fetch(struct scsi_cmnd *scp, struct sdeb_store_info *sip = devip2sip(devip, true); u8 *fsp = sip->storep; + if (sdebug_ptype == TYPE_TAPE) { + if (cmd[0] == PRE_FETCH) { /* READ POSITION (10) */ + int all_length; + unsigned char arr[20]; + unsigned int pos; + + all_length = get_unaligned_be16(cmd + 7); + if ((cmd[1] & 0xfe) != 0 || + all_length != 0) { /* only short form */ + mk_sense_invalid_fld(scp, SDEB_IN_CDB, + all_length ? 7 : 1, 0); + return check_condition_result; + } + memset(arr, 0, SDEBUG_READ_POSITION_ARR_SZ); + arr[1] = devip->tape_partition; + pos = devip->tape_location[devip->tape_partition]; + put_unaligned_be32(pos, arr + 4); + put_unaligned_be32(pos, arr + 8); + return fill_from_dev_buffer(scp, arr, + SDEBUG_READ_POSITION_ARR_SZ); + } + mk_sense_invalid_opcode(scp); + return check_condition_result; + } + if (cmd[0] == PRE_FETCH) { /* 10 byte cdb */ lba = get_unaligned_be32(cmd + 2); nblks = get_unaligned_be16(cmd + 7);
The changes: - add READ BLOCK LIMITS (512 - 1048576 bytes) - make LOAD send New Media UA (not correct by the standard, but makes possible to test also this UA) Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi> --- drivers/scsi/scsi_debug.c | 127 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 6 deletions(-)