scsi: scsi_debug: Define grammar to remove added error injection
authorWenchao Hao <haowenchao2@huawei.com>
Tue, 10 Oct 2023 09:20:44 +0000 (17:20 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 17 Oct 2023 00:50:11 +0000 (20:50 -0400)
The grammar to remove error injection is a line with fixed 3 columns
separated by spaces.

First column is fixed to "-". It tells this is a removal operation.  Second
column is the error code to match.  Third column is the scsi command to
match.

For example the following command would remove timeout injection of inquiry
command:

    echo "- 0 0x12" > /sys/kernel/debug/scsi_debug/0:0:0:1/error

Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Wenchao Hao <haowenchao2@huawei.com>
Link: https://lore.kernel.org/r/20231010092051.608007-4-haowenchao2@huawei.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_debug.c

index 46f1ee647b15faa8ba3aace7767fdce13b6935d9..0d5a179dbd970d363cf793296a8cabd0c38b0b84 100644 (file)
@@ -930,6 +930,34 @@ static void sdebug_err_add(struct scsi_device *sdev, struct sdebug_err_inject *n
        spin_unlock(&devip->list_lock);
 }
 
+static int sdebug_err_remove(struct scsi_device *sdev, const char *buf, size_t count)
+{
+       struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdev->hostdata;
+       struct sdebug_err_inject *err;
+       int type;
+       unsigned char cmd;
+
+       if (sscanf(buf, "- %d %hhx", &type, &cmd) != 2) {
+               kfree(buf);
+               return -EINVAL;
+       }
+
+       spin_lock(&devip->list_lock);
+       list_for_each_entry_rcu(err, &devip->inject_err_list, list) {
+               if (err->type == type && err->cmd == cmd) {
+                       list_del_rcu(&err->list);
+                       call_rcu(&err->rcu, sdebug_err_free);
+                       spin_unlock(&devip->list_lock);
+                       kfree(buf);
+                       return count;
+               }
+       }
+       spin_unlock(&devip->list_lock);
+
+       kfree(buf);
+       return -EINVAL;
+}
+
 static int sdebug_error_show(struct seq_file *m, void *p)
 {
        struct scsi_device *sdev = (struct scsi_device *)m->private;
@@ -987,6 +1015,9 @@ static ssize_t sdebug_error_write(struct file *file, const char __user *ubuf,
                return -EFAULT;
        }
 
+       if (buf[0] == '-')
+               return sdebug_err_remove(sdev, buf, count);
+
        if (sscanf(buf, "%d", &inject_type) != 1) {
                kfree(buf);
                return -EINVAL;