Skip to content

Commit

Permalink
nvme: prepare for fault injection into admin commands
Browse files Browse the repository at this point in the history
Currenlty fault injection support for nvme only enables to inject errors
into the commands submitted to I/O queues.

In preparation for fault injection into the admin commands, this makes
the helper functions independent of struct nvme_ns.

Signed-off-by: Akinobu Mita <[email protected]>
Reviewed-by: Minwoo Im <[email protected]>
Reviewed-by: Sagi Grimberg <[email protected]>
Reviewed-by: Chaitanya Kulkarni <[email protected]>
Signed-off-by: Christoph Hellwig <[email protected]>
  • Loading branch information
mita authored and Christoph Hellwig committed Jun 21, 2019
1 parent a5448fd commit a364645
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 33 deletions.
4 changes: 2 additions & 2 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3336,7 +3336,7 @@ static int nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
device_add_disk(ctrl->device, ns->disk, nvme_ns_id_attr_groups);

nvme_mpath_add_disk(ns, id);
nvme_fault_inject_init(ns);
nvme_fault_inject_init(&ns->fault_inject, ns->disk->disk_name);
kfree(id);

return 0;
Expand All @@ -3361,7 +3361,7 @@ static void nvme_ns_remove(struct nvme_ns *ns)
if (test_and_set_bit(NVME_NS_REMOVING, &ns->flags))
return;

nvme_fault_inject_fini(ns);
nvme_fault_inject_fini(&ns->fault_inject);

mutex_lock(&ns->ctrl->subsys->lock);
list_del_rcu(&ns->siblings);
Expand Down
36 changes: 20 additions & 16 deletions drivers/nvme/host/fault_inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,31 @@ static DECLARE_FAULT_ATTR(fail_default_attr);
static char *fail_request;
module_param(fail_request, charp, 0000);

void nvme_fault_inject_init(struct nvme_ns *ns)
void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
const char *dev_name)
{
struct dentry *dir, *parent;
char *name = ns->disk->disk_name;
struct nvme_fault_inject *fault_inj = &ns->fault_inject;
struct fault_attr *attr = &fault_inj->attr;

/* set default fault injection attribute */
if (fail_request)
setup_fault_attr(&fail_default_attr, fail_request);

/* create debugfs directory and attribute */
parent = debugfs_create_dir(name, NULL);
parent = debugfs_create_dir(dev_name, NULL);
if (!parent) {
pr_warn("%s: failed to create debugfs directory\n", name);
pr_warn("%s: failed to create debugfs directory\n", dev_name);
return;
}

*attr = fail_default_attr;
dir = fault_create_debugfs_attr("fault_inject", parent, attr);
if (IS_ERR(dir)) {
pr_warn("%s: failed to create debugfs attr\n", name);
pr_warn("%s: failed to create debugfs attr\n", dev_name);
debugfs_remove_recursive(parent);
return;
}
ns->fault_inject.parent = parent;
fault_inj->parent = parent;

/* create debugfs for status code and dont_retry */
fault_inj->status = NVME_SC_INVALID_OPCODE;
Expand All @@ -49,29 +48,34 @@ void nvme_fault_inject_init(struct nvme_ns *ns)
debugfs_create_bool("dont_retry", 0600, dir, &fault_inj->dont_retry);
}

void nvme_fault_inject_fini(struct nvme_ns *ns)
void nvme_fault_inject_fini(struct nvme_fault_inject *fault_inject)
{
/* remove debugfs directories */
debugfs_remove_recursive(ns->fault_inject.parent);
debugfs_remove_recursive(fault_inject->parent);
}

void nvme_should_fail(struct request *req)
{
struct gendisk *disk = req->rq_disk;
struct nvme_ns *ns = NULL;
struct nvme_fault_inject *fault_inject = NULL;
u16 status;

/*
* make sure this request is coming from a valid namespace
*/
if (!disk)
return;
if (disk) {
struct nvme_ns *ns = disk->private_data;

if (ns)
fault_inject = &ns->fault_inject;
else
WARN_ONCE(1, "No namespace found for request\n");
}

ns = disk->private_data;
if (ns && should_fail(&ns->fault_inject.attr, 1)) {
if (fault_inject && should_fail(&fault_inject->attr, 1)) {
/* inject status code and DNR bit */
status = ns->fault_inject.status;
if (ns->fault_inject.dont_retry)
status = fault_inject->status;
if (fault_inject->dont_retry)
status |= NVME_SC_DNR;
nvme_req(req)->status = status;
}
Expand Down
34 changes: 19 additions & 15 deletions drivers/nvme/host/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ enum nvme_ctrl_state {
NVME_CTRL_DEAD,
};

struct nvme_fault_inject {
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
struct fault_attr attr;
struct dentry *parent;
bool dont_retry; /* DNR, do not retry */
u16 status; /* status code */
#endif
};

struct nvme_ctrl {
bool comp_seen;
enum nvme_ctrl_state state;
Expand Down Expand Up @@ -313,15 +322,6 @@ struct nvme_ns_head {
#endif
};

#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
struct nvme_fault_inject {
struct fault_attr attr;
struct dentry *parent;
bool dont_retry; /* DNR, do not retry */
u16 status; /* status code */
};
#endif

struct nvme_ns {
struct list_head list;

Expand Down Expand Up @@ -349,9 +349,7 @@ struct nvme_ns {
#define NVME_NS_ANA_PENDING 2
u16 noiob;

#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
struct nvme_fault_inject fault_inject;
#endif

};

Expand All @@ -372,12 +370,18 @@ struct nvme_ctrl_ops {
};

#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
void nvme_fault_inject_init(struct nvme_ns *ns);
void nvme_fault_inject_fini(struct nvme_ns *ns);
void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
const char *dev_name);
void nvme_fault_inject_fini(struct nvme_fault_inject *fault_inject);
void nvme_should_fail(struct request *req);
#else
static inline void nvme_fault_inject_init(struct nvme_ns *ns) {}
static inline void nvme_fault_inject_fini(struct nvme_ns *ns) {}
static inline void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
const char *dev_name)
{
}
static inline void nvme_fault_inject_fini(struct nvme_fault_inject *fault_inj)
{
}
static inline void nvme_should_fail(struct request *req) {}
#endif

Expand Down

0 comments on commit a364645

Please sign in to comment.