Back to home page

LXR

 
 

    


0001 #include <linux/module.h>
0002 
0003 #include "notifier-error-inject.h"
0004 
0005 static int debugfs_errno_set(void *data, u64 val)
0006 {
0007     *(int *)data = clamp_t(int, val, -MAX_ERRNO, 0);
0008     return 0;
0009 }
0010 
0011 static int debugfs_errno_get(void *data, u64 *val)
0012 {
0013     *val = *(int *)data;
0014     return 0;
0015 }
0016 
0017 DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set,
0018             "%lld\n");
0019 
0020 static struct dentry *debugfs_create_errno(const char *name, umode_t mode,
0021                 struct dentry *parent, int *value)
0022 {
0023     return debugfs_create_file(name, mode, parent, value, &fops_errno);
0024 }
0025 
0026 static int notifier_err_inject_callback(struct notifier_block *nb,
0027                 unsigned long val, void *p)
0028 {
0029     int err = 0;
0030     struct notifier_err_inject *err_inject =
0031         container_of(nb, struct notifier_err_inject, nb);
0032     struct notifier_err_inject_action *action;
0033 
0034     for (action = err_inject->actions; action->name; action++) {
0035         if (action->val == val) {
0036             err = action->error;
0037             break;
0038         }
0039     }
0040     if (err)
0041         pr_info("Injecting error (%d) to %s\n", err, action->name);
0042 
0043     return notifier_from_errno(err);
0044 }
0045 
0046 struct dentry *notifier_err_inject_dir;
0047 EXPORT_SYMBOL_GPL(notifier_err_inject_dir);
0048 
0049 struct dentry *notifier_err_inject_init(const char *name, struct dentry *parent,
0050             struct notifier_err_inject *err_inject, int priority)
0051 {
0052     struct notifier_err_inject_action *action;
0053     umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
0054     struct dentry *dir;
0055     struct dentry *actions_dir;
0056 
0057     err_inject->nb.notifier_call = notifier_err_inject_callback;
0058     err_inject->nb.priority = priority;
0059 
0060     dir = debugfs_create_dir(name, parent);
0061     if (!dir)
0062         return ERR_PTR(-ENOMEM);
0063 
0064     actions_dir = debugfs_create_dir("actions", dir);
0065     if (!actions_dir)
0066         goto fail;
0067 
0068     for (action = err_inject->actions; action->name; action++) {
0069         struct dentry *action_dir;
0070 
0071         action_dir = debugfs_create_dir(action->name, actions_dir);
0072         if (!action_dir)
0073             goto fail;
0074 
0075         /*
0076          * Create debugfs r/w file containing action->error. If
0077          * notifier call chain is called with action->val, it will
0078          * fail with the error code
0079          */
0080         if (!debugfs_create_errno("error", mode, action_dir,
0081                     &action->error))
0082             goto fail;
0083     }
0084     return dir;
0085 fail:
0086     debugfs_remove_recursive(dir);
0087     return ERR_PTR(-ENOMEM);
0088 }
0089 EXPORT_SYMBOL_GPL(notifier_err_inject_init);
0090 
0091 static int __init err_inject_init(void)
0092 {
0093     notifier_err_inject_dir =
0094         debugfs_create_dir("notifier-error-inject", NULL);
0095 
0096     if (!notifier_err_inject_dir)
0097         return -ENOMEM;
0098 
0099     return 0;
0100 }
0101 
0102 static void __exit err_inject_exit(void)
0103 {
0104     debugfs_remove_recursive(notifier_err_inject_dir);
0105 }
0106 
0107 module_init(err_inject_init);
0108 module_exit(err_inject_exit);
0109 
0110 MODULE_DESCRIPTION("Notifier error injection module");
0111 MODULE_LICENSE("GPL");
0112 MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");