1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/module.h>
4 #include "notifier-error-inject.h"
6 static int debugfs_errno_set(void *data
, u64 val
)
8 *(int *)data
= clamp_t(int, val
, -MAX_ERRNO
, 0);
12 static int debugfs_errno_get(void *data
, u64
*val
)
18 DEFINE_SIMPLE_ATTRIBUTE(fops_errno
, debugfs_errno_get
, debugfs_errno_set
,
21 static struct dentry
*debugfs_create_errno(const char *name
, umode_t mode
,
22 struct dentry
*parent
, int *value
)
24 return debugfs_create_file(name
, mode
, parent
, value
, &fops_errno
);
27 static int notifier_err_inject_callback(struct notifier_block
*nb
,
28 unsigned long val
, void *p
)
31 struct notifier_err_inject
*err_inject
=
32 container_of(nb
, struct notifier_err_inject
, nb
);
33 struct notifier_err_inject_action
*action
;
35 for (action
= err_inject
->actions
; action
->name
; action
++) {
36 if (action
->val
== val
) {
42 pr_info("Injecting error (%d) to %s\n", err
, action
->name
);
44 return notifier_from_errno(err
);
47 struct dentry
*notifier_err_inject_dir
;
48 EXPORT_SYMBOL_GPL(notifier_err_inject_dir
);
50 struct dentry
*notifier_err_inject_init(const char *name
, struct dentry
*parent
,
51 struct notifier_err_inject
*err_inject
, int priority
)
53 struct notifier_err_inject_action
*action
;
54 umode_t mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
56 struct dentry
*actions_dir
;
58 err_inject
->nb
.notifier_call
= notifier_err_inject_callback
;
59 err_inject
->nb
.priority
= priority
;
61 dir
= debugfs_create_dir(name
, parent
);
63 return ERR_PTR(-ENOMEM
);
65 actions_dir
= debugfs_create_dir("actions", dir
);
69 for (action
= err_inject
->actions
; action
->name
; action
++) {
70 struct dentry
*action_dir
;
72 action_dir
= debugfs_create_dir(action
->name
, actions_dir
);
77 * Create debugfs r/w file containing action->error. If
78 * notifier call chain is called with action->val, it will
79 * fail with the error code
81 if (!debugfs_create_errno("error", mode
, action_dir
,
87 debugfs_remove_recursive(dir
);
88 return ERR_PTR(-ENOMEM
);
90 EXPORT_SYMBOL_GPL(notifier_err_inject_init
);
92 static int __init
err_inject_init(void)
94 notifier_err_inject_dir
=
95 debugfs_create_dir("notifier-error-inject", NULL
);
97 if (!notifier_err_inject_dir
)
103 static void __exit
err_inject_exit(void)
105 debugfs_remove_recursive(notifier_err_inject_dir
);
108 module_init(err_inject_init
);
109 module_exit(err_inject_exit
);
111 MODULE_DESCRIPTION("Notifier error injection module");
112 MODULE_LICENSE("GPL");
113 MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");