Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge patch series "scsi: scsi_debug: Add error injection for single device"

Wenchao Hao <haowenchao2@huawei.com> says:

The original error injection mechanism was based on scsi_host which
could not inject fault for a single SCSI device.

This patchset provides the ability to inject errors for a single SCSI
device. Now we support inject timeout errors, queuecommand errors, and
hostbyte, driverbyte, statusbyte, and sense data for specific SCSI
Command. Two new error injection is defined to make abort command or
reset LUN failed.

Besides error injection for single device, this patchset add a new
interface to make reset target failed for each scsi_target.

The first two patch add a debugfs interface to add and inquiry single
device's error injection info; the third patch defined how to remove
an injection which has been added. The following 5 patches use the
injection info and generate the related error type. The last two just
add a new interface to make reset target failed and control
scsi_device's allow_restart flag.

Link: https://lore.kernel.org/r/20231010092051.608007-1-haowenchao2@huawei.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+570 -5
+570 -5
drivers/scsi/scsi_debug.c
··· 41 41 #include <linux/random.h> 42 42 #include <linux/xarray.h> 43 43 #include <linux/prefetch.h> 44 + #include <linux/debugfs.h> 45 + #include <linux/async.h> 44 46 45 47 #include <net/checksum.h> 46 48 ··· 287 285 sector_t z_wp; 288 286 }; 289 287 288 + enum sdebug_err_type { 289 + ERR_TMOUT_CMD = 0, /* make specific scsi command timeout */ 290 + ERR_FAIL_QUEUE_CMD = 1, /* make specific scsi command's */ 291 + /* queuecmd return failed */ 292 + ERR_FAIL_CMD = 2, /* make specific scsi command's */ 293 + /* queuecmd return succeed but */ 294 + /* with errors set in scsi_cmnd */ 295 + ERR_ABORT_CMD_FAILED = 3, /* control return FAILED from */ 296 + /* scsi_debug_abort() */ 297 + ERR_LUN_RESET_FAILED = 4, /* control return FAILED from */ 298 + /* scsi_debug_device_reseLUN_RESET_FAILEDt() */ 299 + }; 300 + 301 + struct sdebug_err_inject { 302 + int type; 303 + struct list_head list; 304 + int cnt; 305 + unsigned char cmd; 306 + struct rcu_head rcu; 307 + 308 + union { 309 + /* 310 + * For ERR_FAIL_QUEUE_CMD 311 + */ 312 + int queuecmd_ret; 313 + 314 + /* 315 + * For ERR_FAIL_CMD 316 + */ 317 + struct { 318 + unsigned char host_byte; 319 + unsigned char driver_byte; 320 + unsigned char status_byte; 321 + unsigned char sense_key; 322 + unsigned char asc; 323 + unsigned char asq; 324 + }; 325 + }; 326 + }; 327 + 290 328 struct sdebug_dev_info { 291 329 struct list_head dev_list; 292 330 unsigned int channel; ··· 352 310 unsigned int max_open; 353 311 ktime_t create_ts; /* time since bootup that this device was created */ 354 312 struct sdeb_zone_state *zstate; 313 + 314 + struct dentry *debugfs_entry; 315 + struct spinlock list_lock; 316 + struct list_head inject_err_list; 317 + }; 318 + 319 + struct sdebug_target_info { 320 + bool reset_fail; 321 + struct dentry *debugfs_entry; 355 322 }; 356 323 357 324 struct sdebug_host_info { ··· 843 792 static bool write_since_sync; 844 793 static bool sdebug_statistics = DEF_STATISTICS; 845 794 static bool sdebug_wp; 795 + static bool sdebug_allow_restart; 846 796 /* Following enum: 0: no zbc, def; 1: host aware; 2: host managed */ 847 797 static enum blk_zoned_model sdeb_zbc_model = BLK_ZONED_NONE; 848 798 static char *sdeb_zbc_model_s; ··· 914 862 915 863 static const int condition_met_result = SAM_STAT_CONDITION_MET; 916 864 865 + static struct dentry *sdebug_debugfs_root; 866 + 867 + static void sdebug_err_free(struct rcu_head *head) 868 + { 869 + struct sdebug_err_inject *inject = 870 + container_of(head, typeof(*inject), rcu); 871 + 872 + kfree(inject); 873 + } 874 + 875 + static void sdebug_err_add(struct scsi_device *sdev, struct sdebug_err_inject *new) 876 + { 877 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdev->hostdata; 878 + struct sdebug_err_inject *err; 879 + 880 + spin_lock(&devip->list_lock); 881 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 882 + if (err->type == new->type && err->cmd == new->cmd) { 883 + list_del_rcu(&err->list); 884 + call_rcu(&err->rcu, sdebug_err_free); 885 + } 886 + } 887 + 888 + list_add_tail_rcu(&new->list, &devip->inject_err_list); 889 + spin_unlock(&devip->list_lock); 890 + } 891 + 892 + static int sdebug_err_remove(struct scsi_device *sdev, const char *buf, size_t count) 893 + { 894 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdev->hostdata; 895 + struct sdebug_err_inject *err; 896 + int type; 897 + unsigned char cmd; 898 + 899 + if (sscanf(buf, "- %d %hhx", &type, &cmd) != 2) { 900 + kfree(buf); 901 + return -EINVAL; 902 + } 903 + 904 + spin_lock(&devip->list_lock); 905 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 906 + if (err->type == type && err->cmd == cmd) { 907 + list_del_rcu(&err->list); 908 + call_rcu(&err->rcu, sdebug_err_free); 909 + spin_unlock(&devip->list_lock); 910 + kfree(buf); 911 + return count; 912 + } 913 + } 914 + spin_unlock(&devip->list_lock); 915 + 916 + kfree(buf); 917 + return -EINVAL; 918 + } 919 + 920 + static int sdebug_error_show(struct seq_file *m, void *p) 921 + { 922 + struct scsi_device *sdev = (struct scsi_device *)m->private; 923 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdev->hostdata; 924 + struct sdebug_err_inject *err; 925 + 926 + seq_puts(m, "Type\tCount\tCommand\n"); 927 + 928 + rcu_read_lock(); 929 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 930 + switch (err->type) { 931 + case ERR_TMOUT_CMD: 932 + case ERR_ABORT_CMD_FAILED: 933 + case ERR_LUN_RESET_FAILED: 934 + seq_printf(m, "%d\t%d\t0x%x\n", err->type, err->cnt, 935 + err->cmd); 936 + break; 937 + 938 + case ERR_FAIL_QUEUE_CMD: 939 + seq_printf(m, "%d\t%d\t0x%x\t0x%x\n", err->type, 940 + err->cnt, err->cmd, err->queuecmd_ret); 941 + break; 942 + 943 + case ERR_FAIL_CMD: 944 + seq_printf(m, "%d\t%d\t0x%x\t0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", 945 + err->type, err->cnt, err->cmd, 946 + err->host_byte, err->driver_byte, 947 + err->status_byte, err->sense_key, 948 + err->asc, err->asq); 949 + break; 950 + } 951 + } 952 + rcu_read_unlock(); 953 + 954 + return 0; 955 + } 956 + 957 + static int sdebug_error_open(struct inode *inode, struct file *file) 958 + { 959 + return single_open(file, sdebug_error_show, inode->i_private); 960 + } 961 + 962 + static ssize_t sdebug_error_write(struct file *file, const char __user *ubuf, 963 + size_t count, loff_t *ppos) 964 + { 965 + char *buf; 966 + unsigned int inject_type; 967 + struct sdebug_err_inject *inject; 968 + struct scsi_device *sdev = (struct scsi_device *)file->f_inode->i_private; 969 + 970 + buf = kmalloc(count, GFP_KERNEL); 971 + if (!buf) 972 + return -ENOMEM; 973 + 974 + if (copy_from_user(buf, ubuf, count)) { 975 + kfree(buf); 976 + return -EFAULT; 977 + } 978 + 979 + if (buf[0] == '-') 980 + return sdebug_err_remove(sdev, buf, count); 981 + 982 + if (sscanf(buf, "%d", &inject_type) != 1) { 983 + kfree(buf); 984 + return -EINVAL; 985 + } 986 + 987 + inject = kzalloc(sizeof(struct sdebug_err_inject), GFP_KERNEL); 988 + if (!inject) { 989 + kfree(buf); 990 + return -ENOMEM; 991 + } 992 + 993 + switch (inject_type) { 994 + case ERR_TMOUT_CMD: 995 + case ERR_ABORT_CMD_FAILED: 996 + case ERR_LUN_RESET_FAILED: 997 + if (sscanf(buf, "%d %d %hhx", &inject->type, &inject->cnt, 998 + &inject->cmd) != 3) 999 + goto out_error; 1000 + break; 1001 + 1002 + case ERR_FAIL_QUEUE_CMD: 1003 + if (sscanf(buf, "%d %d %hhx %x", &inject->type, &inject->cnt, 1004 + &inject->cmd, &inject->queuecmd_ret) != 4) 1005 + goto out_error; 1006 + break; 1007 + 1008 + case ERR_FAIL_CMD: 1009 + if (sscanf(buf, "%d %d %hhx %hhx %hhx %hhx %hhx %hhx %hhx", 1010 + &inject->type, &inject->cnt, &inject->cmd, 1011 + &inject->host_byte, &inject->driver_byte, 1012 + &inject->status_byte, &inject->sense_key, 1013 + &inject->asc, &inject->asq) != 9) 1014 + goto out_error; 1015 + break; 1016 + 1017 + default: 1018 + goto out_error; 1019 + break; 1020 + } 1021 + 1022 + kfree(buf); 1023 + sdebug_err_add(sdev, inject); 1024 + 1025 + return count; 1026 + 1027 + out_error: 1028 + kfree(buf); 1029 + kfree(inject); 1030 + return -EINVAL; 1031 + } 1032 + 1033 + static const struct file_operations sdebug_error_fops = { 1034 + .open = sdebug_error_open, 1035 + .read = seq_read, 1036 + .write = sdebug_error_write, 1037 + .release = single_release, 1038 + }; 1039 + 1040 + static int sdebug_target_reset_fail_show(struct seq_file *m, void *p) 1041 + { 1042 + struct scsi_target *starget = (struct scsi_target *)m->private; 1043 + struct sdebug_target_info *targetip = 1044 + (struct sdebug_target_info *)starget->hostdata; 1045 + 1046 + if (targetip) 1047 + seq_printf(m, "%c\n", targetip->reset_fail ? 'Y' : 'N'); 1048 + 1049 + return 0; 1050 + } 1051 + 1052 + static int sdebug_target_reset_fail_open(struct inode *inode, struct file *file) 1053 + { 1054 + return single_open(file, sdebug_target_reset_fail_show, inode->i_private); 1055 + } 1056 + 1057 + static ssize_t sdebug_target_reset_fail_write(struct file *file, 1058 + const char __user *ubuf, size_t count, loff_t *ppos) 1059 + { 1060 + int ret; 1061 + struct scsi_target *starget = 1062 + (struct scsi_target *)file->f_inode->i_private; 1063 + struct sdebug_target_info *targetip = 1064 + (struct sdebug_target_info *)starget->hostdata; 1065 + 1066 + if (targetip) { 1067 + ret = kstrtobool_from_user(ubuf, count, &targetip->reset_fail); 1068 + return ret < 0 ? ret : count; 1069 + } 1070 + return -ENODEV; 1071 + } 1072 + 1073 + static const struct file_operations sdebug_target_reset_fail_fops = { 1074 + .open = sdebug_target_reset_fail_open, 1075 + .read = seq_read, 1076 + .write = sdebug_target_reset_fail_write, 1077 + .release = single_release, 1078 + }; 1079 + 1080 + static int sdebug_target_alloc(struct scsi_target *starget) 1081 + { 1082 + struct sdebug_target_info *targetip; 1083 + struct dentry *dentry; 1084 + 1085 + targetip = kzalloc(sizeof(struct sdebug_target_info), GFP_KERNEL); 1086 + if (!targetip) 1087 + return -ENOMEM; 1088 + 1089 + targetip->debugfs_entry = debugfs_create_dir(dev_name(&starget->dev), 1090 + sdebug_debugfs_root); 1091 + if (IS_ERR_OR_NULL(targetip->debugfs_entry)) 1092 + pr_info("%s: failed to create debugfs directory for target %s\n", 1093 + __func__, dev_name(&starget->dev)); 1094 + 1095 + debugfs_create_file("fail_reset", 0600, targetip->debugfs_entry, starget, 1096 + &sdebug_target_reset_fail_fops); 1097 + if (IS_ERR_OR_NULL(dentry)) 1098 + pr_info("%s: failed to create fail_reset file for target %s\n", 1099 + __func__, dev_name(&starget->dev)); 1100 + 1101 + starget->hostdata = targetip; 1102 + 1103 + return 0; 1104 + } 1105 + 1106 + static void sdebug_tartget_cleanup_async(void *data, async_cookie_t cookie) 1107 + { 1108 + struct sdebug_target_info *targetip = data; 1109 + 1110 + debugfs_remove(targetip->debugfs_entry); 1111 + kfree(targetip); 1112 + } 1113 + 1114 + static void sdebug_target_destroy(struct scsi_target *starget) 1115 + { 1116 + struct sdebug_target_info *targetip; 1117 + 1118 + targetip = (struct sdebug_target_info *)starget->hostdata; 1119 + if (targetip) { 1120 + starget->hostdata = NULL; 1121 + async_schedule(sdebug_tartget_cleanup_async, targetip); 1122 + } 1123 + } 917 1124 918 1125 /* Only do the extra work involved in logical block provisioning if one or 919 1126 * more of the lbpu, lbpws or lbpws10 parameters are given and we are doing ··· 5407 5096 } 5408 5097 devip->create_ts = ktime_get_boottime(); 5409 5098 atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0)); 5099 + spin_lock_init(&devip->list_lock); 5100 + INIT_LIST_HEAD(&devip->inject_err_list); 5410 5101 list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list); 5411 5102 } 5412 5103 return devip; ··· 5454 5141 if (sdebug_verbose) 5455 5142 pr_info("slave_alloc <%u %u %u %llu>\n", 5456 5143 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); 5144 + 5457 5145 return 0; 5458 5146 } 5459 5147 ··· 5462 5148 { 5463 5149 struct sdebug_dev_info *devip = 5464 5150 (struct sdebug_dev_info *)sdp->hostdata; 5151 + struct dentry *dentry; 5465 5152 5466 5153 if (sdebug_verbose) 5467 5154 pr_info("slave_configure <%u %u %u %llu>\n", ··· 5478 5163 if (sdebug_no_uld) 5479 5164 sdp->no_uld_attach = 1; 5480 5165 config_cdb_len(sdp); 5166 + 5167 + if (sdebug_allow_restart) 5168 + sdp->allow_restart = 1; 5169 + 5170 + devip->debugfs_entry = debugfs_create_dir(dev_name(&sdp->sdev_dev), 5171 + sdebug_debugfs_root); 5172 + if (IS_ERR_OR_NULL(devip->debugfs_entry)) 5173 + pr_info("%s: failed to create debugfs directory for device %s\n", 5174 + __func__, dev_name(&sdp->sdev_gendev)); 5175 + 5176 + dentry = debugfs_create_file("error", 0600, devip->debugfs_entry, sdp, 5177 + &sdebug_error_fops); 5178 + if (IS_ERR_OR_NULL(dentry)) 5179 + pr_info("%s: failed to create error file for device %s\n", 5180 + __func__, dev_name(&sdp->sdev_gendev)); 5181 + 5481 5182 return 0; 5482 5183 } 5483 5184 ··· 5501 5170 { 5502 5171 struct sdebug_dev_info *devip = 5503 5172 (struct sdebug_dev_info *)sdp->hostdata; 5173 + struct sdebug_err_inject *err; 5504 5174 5505 5175 if (sdebug_verbose) 5506 5176 pr_info("slave_destroy <%u %u %u %llu>\n", 5507 5177 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); 5508 - if (devip) { 5509 - /* make this slot available for re-use */ 5510 - devip->used = false; 5511 - sdp->hostdata = NULL; 5178 + 5179 + if (!devip) 5180 + return; 5181 + 5182 + spin_lock(&devip->list_lock); 5183 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 5184 + list_del_rcu(&err->list); 5185 + call_rcu(&err->rcu, sdebug_err_free); 5512 5186 } 5187 + spin_unlock(&devip->list_lock); 5188 + 5189 + debugfs_remove(devip->debugfs_entry); 5190 + 5191 + /* make this slot available for re-use */ 5192 + devip->used = false; 5193 + sdp->hostdata = NULL; 5513 5194 } 5514 5195 5515 5196 /* Returns true if we require the queued memory to be freed by the caller. */ ··· 5615 5272 mutex_unlock(&sdebug_host_list_mutex); 5616 5273 } 5617 5274 5275 + static int sdebug_fail_abort(struct scsi_cmnd *cmnd) 5276 + { 5277 + struct scsi_device *sdp = cmnd->device; 5278 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; 5279 + struct sdebug_err_inject *err; 5280 + unsigned char *cmd = cmnd->cmnd; 5281 + int ret = 0; 5282 + 5283 + if (devip == NULL) 5284 + return 0; 5285 + 5286 + rcu_read_lock(); 5287 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 5288 + if (err->type == ERR_ABORT_CMD_FAILED && 5289 + (err->cmd == cmd[0] || err->cmd == 0xff)) { 5290 + ret = !!err->cnt; 5291 + if (err->cnt < 0) 5292 + err->cnt++; 5293 + 5294 + rcu_read_unlock(); 5295 + return ret; 5296 + } 5297 + } 5298 + rcu_read_unlock(); 5299 + 5300 + return 0; 5301 + } 5302 + 5618 5303 static int scsi_debug_abort(struct scsi_cmnd *SCpnt) 5619 5304 { 5620 5305 bool ok = scsi_debug_abort_cmnd(SCpnt); 5306 + u8 *cmd = SCpnt->cmnd; 5307 + u8 opcode = cmd[0]; 5621 5308 5622 5309 ++num_aborts; 5623 5310 ··· 5655 5282 sdev_printk(KERN_INFO, SCpnt->device, 5656 5283 "%s: command%s found\n", __func__, 5657 5284 ok ? "" : " not"); 5285 + 5286 + if (sdebug_fail_abort(SCpnt)) { 5287 + scmd_printk(KERN_INFO, SCpnt, "fail abort command 0x%x\n", 5288 + opcode); 5289 + return FAILED; 5290 + } 5658 5291 5659 5292 return SUCCESS; 5660 5293 } ··· 5685 5306 scsi_debug_stop_all_queued_iter, sdp); 5686 5307 } 5687 5308 5309 + static int sdebug_fail_lun_reset(struct scsi_cmnd *cmnd) 5310 + { 5311 + struct scsi_device *sdp = cmnd->device; 5312 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; 5313 + struct sdebug_err_inject *err; 5314 + unsigned char *cmd = cmnd->cmnd; 5315 + int ret = 0; 5316 + 5317 + if (devip == NULL) 5318 + return 0; 5319 + 5320 + rcu_read_lock(); 5321 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 5322 + if (err->type == ERR_LUN_RESET_FAILED && 5323 + (err->cmd == cmd[0] || err->cmd == 0xff)) { 5324 + ret = !!err->cnt; 5325 + if (err->cnt < 0) 5326 + err->cnt++; 5327 + 5328 + rcu_read_unlock(); 5329 + return ret; 5330 + } 5331 + } 5332 + rcu_read_unlock(); 5333 + 5334 + return 0; 5335 + } 5336 + 5688 5337 static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt) 5689 5338 { 5690 5339 struct scsi_device *sdp = SCpnt->device; 5691 5340 struct sdebug_dev_info *devip = sdp->hostdata; 5341 + u8 *cmd = SCpnt->cmnd; 5342 + u8 opcode = cmd[0]; 5692 5343 5693 5344 ++num_dev_resets; 5694 5345 ··· 5729 5320 if (devip) 5730 5321 set_bit(SDEBUG_UA_POR, devip->uas_bm); 5731 5322 5323 + if (sdebug_fail_lun_reset(SCpnt)) { 5324 + scmd_printk(KERN_INFO, SCpnt, "fail lun reset 0x%x\n", opcode); 5325 + return FAILED; 5326 + } 5327 + 5732 5328 return SUCCESS; 5329 + } 5330 + 5331 + static int sdebug_fail_target_reset(struct scsi_cmnd *cmnd) 5332 + { 5333 + struct scsi_target *starget = scsi_target(cmnd->device); 5334 + struct sdebug_target_info *targetip = 5335 + (struct sdebug_target_info *)starget->hostdata; 5336 + 5337 + if (targetip) 5338 + return targetip->reset_fail; 5339 + 5340 + return 0; 5733 5341 } 5734 5342 5735 5343 static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt) ··· 5754 5328 struct scsi_device *sdp = SCpnt->device; 5755 5329 struct sdebug_host_info *sdbg_host = shost_to_sdebug_host(sdp->host); 5756 5330 struct sdebug_dev_info *devip; 5331 + u8 *cmd = SCpnt->cmnd; 5332 + u8 opcode = cmd[0]; 5757 5333 int k = 0; 5758 5334 5759 5335 ++num_target_resets; ··· 5772 5344 if (SDEBUG_OPT_RESET_NOISE & sdebug_opts) 5773 5345 sdev_printk(KERN_INFO, sdp, 5774 5346 "%s: %d device(s) found in target\n", __func__, k); 5347 + 5348 + if (sdebug_fail_target_reset(SCpnt)) { 5349 + scmd_printk(KERN_INFO, SCpnt, "fail target reset 0x%x\n", 5350 + opcode); 5351 + return FAILED; 5352 + } 5775 5353 5776 5354 return SUCCESS; 5777 5355 } ··· 6206 5772 module_param_named(zone_max_open, sdeb_zbc_max_open, int, S_IRUGO); 6207 5773 module_param_named(zone_nr_conv, sdeb_zbc_nr_conv, int, S_IRUGO); 6208 5774 module_param_named(zone_size_mb, sdeb_zbc_zone_size_mb, int, S_IRUGO); 5775 + module_param_named(allow_restart, sdebug_allow_restart, bool, S_IRUGO | S_IWUSR); 6209 5776 6210 5777 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); 6211 5778 MODULE_DESCRIPTION("SCSI debug adapter driver"); ··· 6279 5844 MODULE_PARM_DESC(zone_max_open, "Maximum number of open zones; [0] for no limit (def=auto)"); 6280 5845 MODULE_PARM_DESC(zone_nr_conv, "Number of conventional zones (def=1)"); 6281 5846 MODULE_PARM_DESC(zone_size_mb, "Zone size in MiB (def=auto)"); 5847 + MODULE_PARM_DESC(allow_restart, "Set scsi_device's allow_restart flag(def=0)"); 6282 5848 6283 5849 #define SDEBUG_INFO_LEN 256 6284 5850 static char sdebug_info[SDEBUG_INFO_LEN]; ··· 7447 7011 goto driver_unreg; 7448 7012 } 7449 7013 7014 + sdebug_debugfs_root = debugfs_create_dir("scsi_debug", NULL); 7015 + if (IS_ERR_OR_NULL(sdebug_debugfs_root)) 7016 + pr_info("%s: failed to create initial debugfs directory\n", __func__); 7017 + 7450 7018 for (k = 0; k < hosts_to_add; k++) { 7451 7019 if (want_store && k == 0) { 7452 7020 ret = sdebug_add_host_helper(idx); ··· 7497 7057 7498 7058 sdebug_erase_all_stores(false); 7499 7059 xa_destroy(per_store_ap); 7060 + debugfs_remove(sdebug_debugfs_root); 7500 7061 } 7501 7062 7502 7063 device_initcall(scsi_debug_init); ··· 7937 7496 return num_entries; 7938 7497 } 7939 7498 7499 + static int sdebug_timeout_cmd(struct scsi_cmnd *cmnd) 7500 + { 7501 + struct scsi_device *sdp = cmnd->device; 7502 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; 7503 + struct sdebug_err_inject *err; 7504 + unsigned char *cmd = cmnd->cmnd; 7505 + int ret = 0; 7506 + 7507 + if (devip == NULL) 7508 + return 0; 7509 + 7510 + rcu_read_lock(); 7511 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 7512 + if (err->type == ERR_TMOUT_CMD && 7513 + (err->cmd == cmd[0] || err->cmd == 0xff)) { 7514 + ret = !!err->cnt; 7515 + if (err->cnt < 0) 7516 + err->cnt++; 7517 + 7518 + rcu_read_unlock(); 7519 + return ret; 7520 + } 7521 + } 7522 + rcu_read_unlock(); 7523 + 7524 + return 0; 7525 + } 7526 + 7527 + static int sdebug_fail_queue_cmd(struct scsi_cmnd *cmnd) 7528 + { 7529 + struct scsi_device *sdp = cmnd->device; 7530 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; 7531 + struct sdebug_err_inject *err; 7532 + unsigned char *cmd = cmnd->cmnd; 7533 + int ret = 0; 7534 + 7535 + if (devip == NULL) 7536 + return 0; 7537 + 7538 + rcu_read_lock(); 7539 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 7540 + if (err->type == ERR_FAIL_QUEUE_CMD && 7541 + (err->cmd == cmd[0] || err->cmd == 0xff)) { 7542 + ret = err->cnt ? err->queuecmd_ret : 0; 7543 + if (err->cnt < 0) 7544 + err->cnt++; 7545 + 7546 + rcu_read_unlock(); 7547 + return ret; 7548 + } 7549 + } 7550 + rcu_read_unlock(); 7551 + 7552 + return 0; 7553 + } 7554 + 7555 + static int sdebug_fail_cmd(struct scsi_cmnd *cmnd, int *retval, 7556 + struct sdebug_err_inject *info) 7557 + { 7558 + struct scsi_device *sdp = cmnd->device; 7559 + struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata; 7560 + struct sdebug_err_inject *err; 7561 + unsigned char *cmd = cmnd->cmnd; 7562 + int ret = 0; 7563 + int result; 7564 + 7565 + if (devip == NULL) 7566 + return 0; 7567 + 7568 + rcu_read_lock(); 7569 + list_for_each_entry_rcu(err, &devip->inject_err_list, list) { 7570 + if (err->type == ERR_FAIL_CMD && 7571 + (err->cmd == cmd[0] || err->cmd == 0xff)) { 7572 + if (!err->cnt) { 7573 + rcu_read_unlock(); 7574 + return 0; 7575 + } 7576 + 7577 + ret = !!err->cnt; 7578 + rcu_read_unlock(); 7579 + goto out_handle; 7580 + } 7581 + } 7582 + rcu_read_unlock(); 7583 + 7584 + return 0; 7585 + 7586 + out_handle: 7587 + if (err->cnt < 0) 7588 + err->cnt++; 7589 + mk_sense_buffer(cmnd, err->sense_key, err->asc, err->asq); 7590 + result = err->status_byte | err->host_byte << 16 | err->driver_byte << 24; 7591 + *info = *err; 7592 + *retval = schedule_resp(cmnd, devip, result, NULL, 0, 0); 7593 + 7594 + return ret; 7595 + } 7596 + 7940 7597 static int scsi_debug_queuecommand(struct Scsi_Host *shost, 7941 7598 struct scsi_cmnd *scp) 7942 7599 { ··· 8054 7515 u8 opcode = cmd[0]; 8055 7516 bool has_wlun_rl; 8056 7517 bool inject_now; 7518 + int ret = 0; 7519 + struct sdebug_err_inject err; 8057 7520 8058 7521 scsi_set_resid(scp, 0); 8059 7522 if (sdebug_statistics) { ··· 8095 7554 if (NULL == devip) 8096 7555 goto err_out; 8097 7556 } 7557 + 7558 + if (sdebug_timeout_cmd(scp)) { 7559 + scmd_printk(KERN_INFO, scp, "timeout command 0x%x\n", opcode); 7560 + return 0; 7561 + } 7562 + 7563 + ret = sdebug_fail_queue_cmd(scp); 7564 + if (ret) { 7565 + scmd_printk(KERN_INFO, scp, "fail queue command 0x%x with 0x%x\n", 7566 + opcode, ret); 7567 + return ret; 7568 + } 7569 + 7570 + if (sdebug_fail_cmd(scp, &ret, &err)) { 7571 + scmd_printk(KERN_INFO, scp, 7572 + "fail command 0x%x with hostbyte=0x%x, " 7573 + "driverbyte=0x%x, statusbyte=0x%x, " 7574 + "sense_key=0x%x, asc=0x%x, asq=0x%x\n", 7575 + opcode, err.host_byte, err.driver_byte, 7576 + err.status_byte, err.sense_key, err.asc, err.asq); 7577 + return ret; 7578 + } 7579 + 8098 7580 if (unlikely(inject_now && !atomic_read(&sdeb_inject_pending))) 8099 7581 atomic_set(&sdeb_inject_pending, 1); 8100 7582 ··· 8236 7672 return 0; 8237 7673 } 8238 7674 8239 - 8240 7675 static struct scsi_host_template sdebug_driver_template = { 8241 7676 .show_info = scsi_debug_show_info, 8242 7677 .write_info = scsi_debug_write_info, ··· 8265 7702 .track_queue_depth = 1, 8266 7703 .cmd_size = sizeof(struct sdebug_scsi_cmd), 8267 7704 .init_cmd_priv = sdebug_init_cmd_priv, 7705 + .target_alloc = sdebug_target_alloc, 7706 + .target_destroy = sdebug_target_destroy, 8268 7707 }; 8269 7708 8270 7709 static int sdebug_driver_probe(struct device *dev)