Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * fault injection support for nvme.
0004  *
0005  * Copyright (c) 2018, Oracle and/or its affiliates
0006  */
0007 
0008 #include <linux/moduleparam.h>
0009 #include "nvme.h"
0010 
0011 static DECLARE_FAULT_ATTR(fail_default_attr);
0012 /* optional fault injection attributes boot time option:
0013  * nvme_core.fail_request=<interval>,<probability>,<space>,<times>
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     /* set default fault injection attribute */
0025     if (fail_request)
0026         setup_fault_attr(&fail_default_attr, fail_request);
0027 
0028     /* create debugfs directory and attribute */
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     /* create debugfs for status code and dont_retry */
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     /* remove debugfs directories */
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         /* inject status code and DNR bit */
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);