fault_inject.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * fault injection support for nvme.
  3. *
  4. * Copyright (c) 2018, Oracle and/or its affiliates
  5. *
  6. */
  7. #include <linux/moduleparam.h>
  8. #include "nvme.h"
  9. static DECLARE_FAULT_ATTR(fail_default_attr);
  10. /* optional fault injection attributes boot time option:
  11. * nvme_core.fail_request=<interval>,<probability>,<space>,<times>
  12. */
  13. static char *fail_request;
  14. module_param(fail_request, charp, 0000);
  15. void nvme_fault_inject_init(struct nvme_ns *ns)
  16. {
  17. struct dentry *dir, *parent;
  18. char *name = ns->disk->disk_name;
  19. struct nvme_fault_inject *fault_inj = &ns->fault_inject;
  20. struct fault_attr *attr = &fault_inj->attr;
  21. /* set default fault injection attribute */
  22. if (fail_request)
  23. setup_fault_attr(&fail_default_attr, fail_request);
  24. /* create debugfs directory and attribute */
  25. parent = debugfs_create_dir(name, NULL);
  26. if (!parent) {
  27. pr_warn("%s: failed to create debugfs directory\n", name);
  28. return;
  29. }
  30. *attr = fail_default_attr;
  31. dir = fault_create_debugfs_attr("fault_inject", parent, attr);
  32. if (IS_ERR(dir)) {
  33. pr_warn("%s: failed to create debugfs attr\n", name);
  34. debugfs_remove_recursive(parent);
  35. return;
  36. }
  37. ns->fault_inject.parent = parent;
  38. /* create debugfs for status code and dont_retry */
  39. fault_inj->status = NVME_SC_INVALID_OPCODE;
  40. fault_inj->dont_retry = true;
  41. debugfs_create_x16("status", 0600, dir, &fault_inj->status);
  42. debugfs_create_bool("dont_retry", 0600, dir, &fault_inj->dont_retry);
  43. }
  44. void nvme_fault_inject_fini(struct nvme_ns *ns)
  45. {
  46. /* remove debugfs directories */
  47. debugfs_remove_recursive(ns->fault_inject.parent);
  48. }
  49. void nvme_should_fail(struct request *req)
  50. {
  51. struct gendisk *disk = req->rq_disk;
  52. struct nvme_ns *ns = NULL;
  53. u16 status;
  54. /*
  55. * make sure this request is coming from a valid namespace
  56. */
  57. if (!disk)
  58. return;
  59. ns = disk->private_data;
  60. if (ns && should_fail(&ns->fault_inject.attr, 1)) {
  61. /* inject status code and DNR bit */
  62. status = ns->fault_inject.status;
  63. if (ns->fault_inject.dont_retry)
  64. status |= NVME_SC_DNR;
  65. nvme_req(req)->status = status;
  66. }
  67. }
  68. EXPORT_SYMBOL_GPL(nvme_should_fail);