0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/moduleparam.h>
0009 #include "nvme.h"
0010
0011 static DECLARE_FAULT_ATTR(fail_default_attr);
0012
0013
0014
0015 static char *fail_request;
0016 module_param(fail_request, charp, 0000);
0017
0018 void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
0019 const char *dev_name)
0020 {
0021 struct dentry *dir, *parent;
0022 struct fault_attr *attr = &fault_inj->attr;
0023
0024
0025 if (fail_request)
0026 setup_fault_attr(&fail_default_attr, fail_request);
0027
0028
0029 parent = debugfs_create_dir(dev_name, NULL);
0030 if (!parent) {
0031 pr_warn("%s: failed to create debugfs directory\n", dev_name);
0032 return;
0033 }
0034
0035 *attr = fail_default_attr;
0036 dir = fault_create_debugfs_attr("fault_inject", parent, attr);
0037 if (IS_ERR(dir)) {
0038 pr_warn("%s: failed to create debugfs attr\n", dev_name);
0039 debugfs_remove_recursive(parent);
0040 return;
0041 }
0042 fault_inj->parent = parent;
0043
0044
0045 fault_inj->status = NVME_SC_INVALID_OPCODE;
0046 fault_inj->dont_retry = true;
0047 debugfs_create_x16("status", 0600, dir, &fault_inj->status);
0048 debugfs_create_bool("dont_retry", 0600, dir, &fault_inj->dont_retry);
0049 }
0050
0051 void nvme_fault_inject_fini(struct nvme_fault_inject *fault_inject)
0052 {
0053
0054 debugfs_remove_recursive(fault_inject->parent);
0055 }
0056
0057 void nvme_should_fail(struct request *req)
0058 {
0059 struct gendisk *disk = req->q->disk;
0060 struct nvme_fault_inject *fault_inject = NULL;
0061 u16 status;
0062
0063 if (disk) {
0064 struct nvme_ns *ns = disk->private_data;
0065
0066 if (ns)
0067 fault_inject = &ns->fault_inject;
0068 else
0069 WARN_ONCE(1, "No namespace found for request\n");
0070 } else {
0071 fault_inject = &nvme_req(req)->ctrl->fault_inject;
0072 }
0073
0074 if (fault_inject && should_fail(&fault_inject->attr, 1)) {
0075
0076 status = fault_inject->status;
0077 if (fault_inject->dont_retry)
0078 status |= NVME_SC_DNR;
0079 nvme_req(req)->status = status;
0080 }
0081 }
0082 EXPORT_SYMBOL_GPL(nvme_should_fail);