1*4b1a29a7SMasami Hiramatsu // SPDX-License-Identifier: GPL-2.0 2*4b1a29a7SMasami Hiramatsu /* 3*4b1a29a7SMasami Hiramatsu * fail_function.c: Function-based error injection 4*4b1a29a7SMasami Hiramatsu */ 5*4b1a29a7SMasami Hiramatsu #include <linux/error-injection.h> 6*4b1a29a7SMasami Hiramatsu #include <linux/debugfs.h> 7*4b1a29a7SMasami Hiramatsu #include <linux/fault-inject.h> 8*4b1a29a7SMasami Hiramatsu #include <linux/kallsyms.h> 9*4b1a29a7SMasami Hiramatsu #include <linux/kprobes.h> 10*4b1a29a7SMasami Hiramatsu #include <linux/module.h> 11*4b1a29a7SMasami Hiramatsu #include <linux/mutex.h> 12*4b1a29a7SMasami Hiramatsu #include <linux/slab.h> 13*4b1a29a7SMasami Hiramatsu #include <linux/uaccess.h> 14*4b1a29a7SMasami Hiramatsu 15*4b1a29a7SMasami Hiramatsu static int fei_kprobe_handler(struct kprobe *kp, struct pt_regs *regs); 16*4b1a29a7SMasami Hiramatsu 17*4b1a29a7SMasami Hiramatsu struct fei_attr { 18*4b1a29a7SMasami Hiramatsu struct list_head list; 19*4b1a29a7SMasami Hiramatsu struct kprobe kp; 20*4b1a29a7SMasami Hiramatsu unsigned long retval; 21*4b1a29a7SMasami Hiramatsu }; 22*4b1a29a7SMasami Hiramatsu static DEFINE_MUTEX(fei_lock); 23*4b1a29a7SMasami Hiramatsu static LIST_HEAD(fei_attr_list); 24*4b1a29a7SMasami Hiramatsu static DECLARE_FAULT_ATTR(fei_fault_attr); 25*4b1a29a7SMasami Hiramatsu static struct dentry *fei_debugfs_dir; 26*4b1a29a7SMasami Hiramatsu 27*4b1a29a7SMasami Hiramatsu static unsigned long adjust_error_retval(unsigned long addr, unsigned long retv) 28*4b1a29a7SMasami Hiramatsu { 29*4b1a29a7SMasami Hiramatsu switch (get_injectable_error_type(addr)) { 30*4b1a29a7SMasami Hiramatsu case EI_ETYPE_NULL: 31*4b1a29a7SMasami Hiramatsu if (retv != 0) 32*4b1a29a7SMasami Hiramatsu return 0; 33*4b1a29a7SMasami Hiramatsu break; 34*4b1a29a7SMasami Hiramatsu case EI_ETYPE_ERRNO: 35*4b1a29a7SMasami Hiramatsu if (retv < (unsigned long)-MAX_ERRNO) 36*4b1a29a7SMasami Hiramatsu return (unsigned long)-EINVAL; 37*4b1a29a7SMasami Hiramatsu break; 38*4b1a29a7SMasami Hiramatsu case EI_ETYPE_ERRNO_NULL: 39*4b1a29a7SMasami Hiramatsu if (retv != 0 && retv < (unsigned long)-MAX_ERRNO) 40*4b1a29a7SMasami Hiramatsu return (unsigned long)-EINVAL; 41*4b1a29a7SMasami Hiramatsu break; 42*4b1a29a7SMasami Hiramatsu } 43*4b1a29a7SMasami Hiramatsu 44*4b1a29a7SMasami Hiramatsu return retv; 45*4b1a29a7SMasami Hiramatsu } 46*4b1a29a7SMasami Hiramatsu 47*4b1a29a7SMasami Hiramatsu static struct fei_attr *fei_attr_new(const char *sym, unsigned long addr) 48*4b1a29a7SMasami Hiramatsu { 49*4b1a29a7SMasami Hiramatsu struct fei_attr *attr; 50*4b1a29a7SMasami Hiramatsu 51*4b1a29a7SMasami Hiramatsu attr = kzalloc(sizeof(*attr), GFP_KERNEL); 52*4b1a29a7SMasami Hiramatsu if (attr) { 53*4b1a29a7SMasami Hiramatsu attr->kp.symbol_name = kstrdup(sym, GFP_KERNEL); 54*4b1a29a7SMasami Hiramatsu if (!attr->kp.symbol_name) { 55*4b1a29a7SMasami Hiramatsu kfree(attr); 56*4b1a29a7SMasami Hiramatsu return NULL; 57*4b1a29a7SMasami Hiramatsu } 58*4b1a29a7SMasami Hiramatsu attr->kp.pre_handler = fei_kprobe_handler; 59*4b1a29a7SMasami Hiramatsu attr->retval = adjust_error_retval(addr, 0); 60*4b1a29a7SMasami Hiramatsu INIT_LIST_HEAD(&attr->list); 61*4b1a29a7SMasami Hiramatsu } 62*4b1a29a7SMasami Hiramatsu return attr; 63*4b1a29a7SMasami Hiramatsu } 64*4b1a29a7SMasami Hiramatsu 65*4b1a29a7SMasami Hiramatsu static void fei_attr_free(struct fei_attr *attr) 66*4b1a29a7SMasami Hiramatsu { 67*4b1a29a7SMasami Hiramatsu if (attr) { 68*4b1a29a7SMasami Hiramatsu kfree(attr->kp.symbol_name); 69*4b1a29a7SMasami Hiramatsu kfree(attr); 70*4b1a29a7SMasami Hiramatsu } 71*4b1a29a7SMasami Hiramatsu } 72*4b1a29a7SMasami Hiramatsu 73*4b1a29a7SMasami Hiramatsu static struct fei_attr *fei_attr_lookup(const char *sym) 74*4b1a29a7SMasami Hiramatsu { 75*4b1a29a7SMasami Hiramatsu struct fei_attr *attr; 76*4b1a29a7SMasami Hiramatsu 77*4b1a29a7SMasami Hiramatsu list_for_each_entry(attr, &fei_attr_list, list) { 78*4b1a29a7SMasami Hiramatsu if (!strcmp(attr->kp.symbol_name, sym)) 79*4b1a29a7SMasami Hiramatsu return attr; 80*4b1a29a7SMasami Hiramatsu } 81*4b1a29a7SMasami Hiramatsu 82*4b1a29a7SMasami Hiramatsu return NULL; 83*4b1a29a7SMasami Hiramatsu } 84*4b1a29a7SMasami Hiramatsu 85*4b1a29a7SMasami Hiramatsu static bool fei_attr_is_valid(struct fei_attr *_attr) 86*4b1a29a7SMasami Hiramatsu { 87*4b1a29a7SMasami Hiramatsu struct fei_attr *attr; 88*4b1a29a7SMasami Hiramatsu 89*4b1a29a7SMasami Hiramatsu list_for_each_entry(attr, &fei_attr_list, list) { 90*4b1a29a7SMasami Hiramatsu if (attr == _attr) 91*4b1a29a7SMasami Hiramatsu return true; 92*4b1a29a7SMasami Hiramatsu } 93*4b1a29a7SMasami Hiramatsu 94*4b1a29a7SMasami Hiramatsu return false; 95*4b1a29a7SMasami Hiramatsu } 96*4b1a29a7SMasami Hiramatsu 97*4b1a29a7SMasami Hiramatsu static int fei_retval_set(void *data, u64 val) 98*4b1a29a7SMasami Hiramatsu { 99*4b1a29a7SMasami Hiramatsu struct fei_attr *attr = data; 100*4b1a29a7SMasami Hiramatsu unsigned long retv = (unsigned long)val; 101*4b1a29a7SMasami Hiramatsu int err = 0; 102*4b1a29a7SMasami Hiramatsu 103*4b1a29a7SMasami Hiramatsu mutex_lock(&fei_lock); 104*4b1a29a7SMasami Hiramatsu /* 105*4b1a29a7SMasami Hiramatsu * Since this operation can be done after retval file is removed, 106*4b1a29a7SMasami Hiramatsu * It is safer to check the attr is still valid before accessing 107*4b1a29a7SMasami Hiramatsu * its member. 108*4b1a29a7SMasami Hiramatsu */ 109*4b1a29a7SMasami Hiramatsu if (!fei_attr_is_valid(attr)) { 110*4b1a29a7SMasami Hiramatsu err = -ENOENT; 111*4b1a29a7SMasami Hiramatsu goto out; 112*4b1a29a7SMasami Hiramatsu } 113*4b1a29a7SMasami Hiramatsu 114*4b1a29a7SMasami Hiramatsu if (attr->kp.addr) { 115*4b1a29a7SMasami Hiramatsu if (adjust_error_retval((unsigned long)attr->kp.addr, 116*4b1a29a7SMasami Hiramatsu val) != retv) 117*4b1a29a7SMasami Hiramatsu err = -EINVAL; 118*4b1a29a7SMasami Hiramatsu } 119*4b1a29a7SMasami Hiramatsu if (!err) 120*4b1a29a7SMasami Hiramatsu attr->retval = val; 121*4b1a29a7SMasami Hiramatsu out: 122*4b1a29a7SMasami Hiramatsu mutex_unlock(&fei_lock); 123*4b1a29a7SMasami Hiramatsu 124*4b1a29a7SMasami Hiramatsu return err; 125*4b1a29a7SMasami Hiramatsu } 126*4b1a29a7SMasami Hiramatsu 127*4b1a29a7SMasami Hiramatsu static int fei_retval_get(void *data, u64 *val) 128*4b1a29a7SMasami Hiramatsu { 129*4b1a29a7SMasami Hiramatsu struct fei_attr *attr = data; 130*4b1a29a7SMasami Hiramatsu int err = 0; 131*4b1a29a7SMasami Hiramatsu 132*4b1a29a7SMasami Hiramatsu mutex_lock(&fei_lock); 133*4b1a29a7SMasami Hiramatsu /* Here we also validate @attr to ensure it still exists. */ 134*4b1a29a7SMasami Hiramatsu if (!fei_attr_is_valid(attr)) 135*4b1a29a7SMasami Hiramatsu err = -ENOENT; 136*4b1a29a7SMasami Hiramatsu else 137*4b1a29a7SMasami Hiramatsu *val = attr->retval; 138*4b1a29a7SMasami Hiramatsu mutex_unlock(&fei_lock); 139*4b1a29a7SMasami Hiramatsu 140*4b1a29a7SMasami Hiramatsu return err; 141*4b1a29a7SMasami Hiramatsu } 142*4b1a29a7SMasami Hiramatsu DEFINE_DEBUGFS_ATTRIBUTE(fei_retval_ops, fei_retval_get, fei_retval_set, 143*4b1a29a7SMasami Hiramatsu "%llx\n"); 144*4b1a29a7SMasami Hiramatsu 145*4b1a29a7SMasami Hiramatsu static int fei_debugfs_add_attr(struct fei_attr *attr) 146*4b1a29a7SMasami Hiramatsu { 147*4b1a29a7SMasami Hiramatsu struct dentry *dir; 148*4b1a29a7SMasami Hiramatsu 149*4b1a29a7SMasami Hiramatsu dir = debugfs_create_dir(attr->kp.symbol_name, fei_debugfs_dir); 150*4b1a29a7SMasami Hiramatsu if (!dir) 151*4b1a29a7SMasami Hiramatsu return -ENOMEM; 152*4b1a29a7SMasami Hiramatsu 153*4b1a29a7SMasami Hiramatsu if (!debugfs_create_file("retval", 0600, dir, attr, &fei_retval_ops)) { 154*4b1a29a7SMasami Hiramatsu debugfs_remove_recursive(dir); 155*4b1a29a7SMasami Hiramatsu return -ENOMEM; 156*4b1a29a7SMasami Hiramatsu } 157*4b1a29a7SMasami Hiramatsu 158*4b1a29a7SMasami Hiramatsu return 0; 159*4b1a29a7SMasami Hiramatsu } 160*4b1a29a7SMasami Hiramatsu 161*4b1a29a7SMasami Hiramatsu static void fei_debugfs_remove_attr(struct fei_attr *attr) 162*4b1a29a7SMasami Hiramatsu { 163*4b1a29a7SMasami Hiramatsu struct dentry *dir; 164*4b1a29a7SMasami Hiramatsu 165*4b1a29a7SMasami Hiramatsu dir = debugfs_lookup(attr->kp.symbol_name, fei_debugfs_dir); 166*4b1a29a7SMasami Hiramatsu if (dir) 167*4b1a29a7SMasami Hiramatsu debugfs_remove_recursive(dir); 168*4b1a29a7SMasami Hiramatsu } 169*4b1a29a7SMasami Hiramatsu 170*4b1a29a7SMasami Hiramatsu static int fei_kprobe_handler(struct kprobe *kp, struct pt_regs *regs) 171*4b1a29a7SMasami Hiramatsu { 172*4b1a29a7SMasami Hiramatsu struct fei_attr *attr = container_of(kp, struct fei_attr, kp); 173*4b1a29a7SMasami Hiramatsu 174*4b1a29a7SMasami Hiramatsu if (should_fail(&fei_fault_attr, 1)) { 175*4b1a29a7SMasami Hiramatsu regs_set_return_value(regs, attr->retval); 176*4b1a29a7SMasami Hiramatsu override_function_with_return(regs); 177*4b1a29a7SMasami Hiramatsu /* Kprobe specific fixup */ 178*4b1a29a7SMasami Hiramatsu reset_current_kprobe(); 179*4b1a29a7SMasami Hiramatsu preempt_enable_no_resched(); 180*4b1a29a7SMasami Hiramatsu return 1; 181*4b1a29a7SMasami Hiramatsu } 182*4b1a29a7SMasami Hiramatsu 183*4b1a29a7SMasami Hiramatsu return 0; 184*4b1a29a7SMasami Hiramatsu } 185*4b1a29a7SMasami Hiramatsu NOKPROBE_SYMBOL(fei_kprobe_handler) 186*4b1a29a7SMasami Hiramatsu 187*4b1a29a7SMasami Hiramatsu static void *fei_seq_start(struct seq_file *m, loff_t *pos) 188*4b1a29a7SMasami Hiramatsu { 189*4b1a29a7SMasami Hiramatsu mutex_lock(&fei_lock); 190*4b1a29a7SMasami Hiramatsu return seq_list_start(&fei_attr_list, *pos); 191*4b1a29a7SMasami Hiramatsu } 192*4b1a29a7SMasami Hiramatsu 193*4b1a29a7SMasami Hiramatsu static void fei_seq_stop(struct seq_file *m, void *v) 194*4b1a29a7SMasami Hiramatsu { 195*4b1a29a7SMasami Hiramatsu mutex_unlock(&fei_lock); 196*4b1a29a7SMasami Hiramatsu } 197*4b1a29a7SMasami Hiramatsu 198*4b1a29a7SMasami Hiramatsu static void *fei_seq_next(struct seq_file *m, void *v, loff_t *pos) 199*4b1a29a7SMasami Hiramatsu { 200*4b1a29a7SMasami Hiramatsu return seq_list_next(v, &fei_attr_list, pos); 201*4b1a29a7SMasami Hiramatsu } 202*4b1a29a7SMasami Hiramatsu 203*4b1a29a7SMasami Hiramatsu static int fei_seq_show(struct seq_file *m, void *v) 204*4b1a29a7SMasami Hiramatsu { 205*4b1a29a7SMasami Hiramatsu struct fei_attr *attr = list_entry(v, struct fei_attr, list); 206*4b1a29a7SMasami Hiramatsu 207*4b1a29a7SMasami Hiramatsu seq_printf(m, "%pf\n", attr->kp.addr); 208*4b1a29a7SMasami Hiramatsu return 0; 209*4b1a29a7SMasami Hiramatsu } 210*4b1a29a7SMasami Hiramatsu 211*4b1a29a7SMasami Hiramatsu static const struct seq_operations fei_seq_ops = { 212*4b1a29a7SMasami Hiramatsu .start = fei_seq_start, 213*4b1a29a7SMasami Hiramatsu .next = fei_seq_next, 214*4b1a29a7SMasami Hiramatsu .stop = fei_seq_stop, 215*4b1a29a7SMasami Hiramatsu .show = fei_seq_show, 216*4b1a29a7SMasami Hiramatsu }; 217*4b1a29a7SMasami Hiramatsu 218*4b1a29a7SMasami Hiramatsu static int fei_open(struct inode *inode, struct file *file) 219*4b1a29a7SMasami Hiramatsu { 220*4b1a29a7SMasami Hiramatsu return seq_open(file, &fei_seq_ops); 221*4b1a29a7SMasami Hiramatsu } 222*4b1a29a7SMasami Hiramatsu 223*4b1a29a7SMasami Hiramatsu static void fei_attr_remove(struct fei_attr *attr) 224*4b1a29a7SMasami Hiramatsu { 225*4b1a29a7SMasami Hiramatsu fei_debugfs_remove_attr(attr); 226*4b1a29a7SMasami Hiramatsu unregister_kprobe(&attr->kp); 227*4b1a29a7SMasami Hiramatsu list_del(&attr->list); 228*4b1a29a7SMasami Hiramatsu fei_attr_free(attr); 229*4b1a29a7SMasami Hiramatsu } 230*4b1a29a7SMasami Hiramatsu 231*4b1a29a7SMasami Hiramatsu static void fei_attr_remove_all(void) 232*4b1a29a7SMasami Hiramatsu { 233*4b1a29a7SMasami Hiramatsu struct fei_attr *attr, *n; 234*4b1a29a7SMasami Hiramatsu 235*4b1a29a7SMasami Hiramatsu list_for_each_entry_safe(attr, n, &fei_attr_list, list) { 236*4b1a29a7SMasami Hiramatsu fei_attr_remove(attr); 237*4b1a29a7SMasami Hiramatsu } 238*4b1a29a7SMasami Hiramatsu } 239*4b1a29a7SMasami Hiramatsu 240*4b1a29a7SMasami Hiramatsu static ssize_t fei_write(struct file *file, const char __user *buffer, 241*4b1a29a7SMasami Hiramatsu size_t count, loff_t *ppos) 242*4b1a29a7SMasami Hiramatsu { 243*4b1a29a7SMasami Hiramatsu struct fei_attr *attr; 244*4b1a29a7SMasami Hiramatsu unsigned long addr; 245*4b1a29a7SMasami Hiramatsu char *buf, *sym; 246*4b1a29a7SMasami Hiramatsu int ret; 247*4b1a29a7SMasami Hiramatsu 248*4b1a29a7SMasami Hiramatsu /* cut off if it is too long */ 249*4b1a29a7SMasami Hiramatsu if (count > KSYM_NAME_LEN) 250*4b1a29a7SMasami Hiramatsu count = KSYM_NAME_LEN; 251*4b1a29a7SMasami Hiramatsu buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL); 252*4b1a29a7SMasami Hiramatsu if (!buf) 253*4b1a29a7SMasami Hiramatsu return -ENOMEM; 254*4b1a29a7SMasami Hiramatsu 255*4b1a29a7SMasami Hiramatsu if (copy_from_user(buf, buffer, count)) { 256*4b1a29a7SMasami Hiramatsu ret = -EFAULT; 257*4b1a29a7SMasami Hiramatsu goto out; 258*4b1a29a7SMasami Hiramatsu } 259*4b1a29a7SMasami Hiramatsu buf[count] = '\0'; 260*4b1a29a7SMasami Hiramatsu sym = strstrip(buf); 261*4b1a29a7SMasami Hiramatsu 262*4b1a29a7SMasami Hiramatsu mutex_lock(&fei_lock); 263*4b1a29a7SMasami Hiramatsu 264*4b1a29a7SMasami Hiramatsu /* Writing just spaces will remove all injection points */ 265*4b1a29a7SMasami Hiramatsu if (sym[0] == '\0') { 266*4b1a29a7SMasami Hiramatsu fei_attr_remove_all(); 267*4b1a29a7SMasami Hiramatsu ret = count; 268*4b1a29a7SMasami Hiramatsu goto out; 269*4b1a29a7SMasami Hiramatsu } 270*4b1a29a7SMasami Hiramatsu /* Writing !function will remove one injection point */ 271*4b1a29a7SMasami Hiramatsu if (sym[0] == '!') { 272*4b1a29a7SMasami Hiramatsu attr = fei_attr_lookup(sym + 1); 273*4b1a29a7SMasami Hiramatsu if (!attr) { 274*4b1a29a7SMasami Hiramatsu ret = -ENOENT; 275*4b1a29a7SMasami Hiramatsu goto out; 276*4b1a29a7SMasami Hiramatsu } 277*4b1a29a7SMasami Hiramatsu fei_attr_remove(attr); 278*4b1a29a7SMasami Hiramatsu ret = count; 279*4b1a29a7SMasami Hiramatsu goto out; 280*4b1a29a7SMasami Hiramatsu } 281*4b1a29a7SMasami Hiramatsu 282*4b1a29a7SMasami Hiramatsu addr = kallsyms_lookup_name(sym); 283*4b1a29a7SMasami Hiramatsu if (!addr) { 284*4b1a29a7SMasami Hiramatsu ret = -EINVAL; 285*4b1a29a7SMasami Hiramatsu goto out; 286*4b1a29a7SMasami Hiramatsu } 287*4b1a29a7SMasami Hiramatsu if (!within_error_injection_list(addr)) { 288*4b1a29a7SMasami Hiramatsu ret = -ERANGE; 289*4b1a29a7SMasami Hiramatsu goto out; 290*4b1a29a7SMasami Hiramatsu } 291*4b1a29a7SMasami Hiramatsu if (fei_attr_lookup(sym)) { 292*4b1a29a7SMasami Hiramatsu ret = -EBUSY; 293*4b1a29a7SMasami Hiramatsu goto out; 294*4b1a29a7SMasami Hiramatsu } 295*4b1a29a7SMasami Hiramatsu attr = fei_attr_new(sym, addr); 296*4b1a29a7SMasami Hiramatsu if (!attr) { 297*4b1a29a7SMasami Hiramatsu ret = -ENOMEM; 298*4b1a29a7SMasami Hiramatsu goto out; 299*4b1a29a7SMasami Hiramatsu } 300*4b1a29a7SMasami Hiramatsu 301*4b1a29a7SMasami Hiramatsu ret = register_kprobe(&attr->kp); 302*4b1a29a7SMasami Hiramatsu if (!ret) 303*4b1a29a7SMasami Hiramatsu ret = fei_debugfs_add_attr(attr); 304*4b1a29a7SMasami Hiramatsu if (ret < 0) 305*4b1a29a7SMasami Hiramatsu fei_attr_remove(attr); 306*4b1a29a7SMasami Hiramatsu else { 307*4b1a29a7SMasami Hiramatsu list_add_tail(&attr->list, &fei_attr_list); 308*4b1a29a7SMasami Hiramatsu ret = count; 309*4b1a29a7SMasami Hiramatsu } 310*4b1a29a7SMasami Hiramatsu out: 311*4b1a29a7SMasami Hiramatsu kfree(buf); 312*4b1a29a7SMasami Hiramatsu mutex_unlock(&fei_lock); 313*4b1a29a7SMasami Hiramatsu return ret; 314*4b1a29a7SMasami Hiramatsu } 315*4b1a29a7SMasami Hiramatsu 316*4b1a29a7SMasami Hiramatsu static const struct file_operations fei_ops = { 317*4b1a29a7SMasami Hiramatsu .open = fei_open, 318*4b1a29a7SMasami Hiramatsu .read = seq_read, 319*4b1a29a7SMasami Hiramatsu .write = fei_write, 320*4b1a29a7SMasami Hiramatsu .llseek = seq_lseek, 321*4b1a29a7SMasami Hiramatsu .release = seq_release, 322*4b1a29a7SMasami Hiramatsu }; 323*4b1a29a7SMasami Hiramatsu 324*4b1a29a7SMasami Hiramatsu static int __init fei_debugfs_init(void) 325*4b1a29a7SMasami Hiramatsu { 326*4b1a29a7SMasami Hiramatsu struct dentry *dir; 327*4b1a29a7SMasami Hiramatsu 328*4b1a29a7SMasami Hiramatsu dir = fault_create_debugfs_attr("fail_function", NULL, 329*4b1a29a7SMasami Hiramatsu &fei_fault_attr); 330*4b1a29a7SMasami Hiramatsu if (IS_ERR(dir)) 331*4b1a29a7SMasami Hiramatsu return PTR_ERR(dir); 332*4b1a29a7SMasami Hiramatsu 333*4b1a29a7SMasami Hiramatsu /* injectable attribute is just a symlink of error_inject/list */ 334*4b1a29a7SMasami Hiramatsu if (!debugfs_create_symlink("injectable", dir, 335*4b1a29a7SMasami Hiramatsu "../error_injection/list")) 336*4b1a29a7SMasami Hiramatsu goto error; 337*4b1a29a7SMasami Hiramatsu 338*4b1a29a7SMasami Hiramatsu if (!debugfs_create_file("inject", 0600, dir, NULL, &fei_ops)) 339*4b1a29a7SMasami Hiramatsu goto error; 340*4b1a29a7SMasami Hiramatsu 341*4b1a29a7SMasami Hiramatsu fei_debugfs_dir = dir; 342*4b1a29a7SMasami Hiramatsu 343*4b1a29a7SMasami Hiramatsu return 0; 344*4b1a29a7SMasami Hiramatsu error: 345*4b1a29a7SMasami Hiramatsu debugfs_remove_recursive(dir); 346*4b1a29a7SMasami Hiramatsu return -ENOMEM; 347*4b1a29a7SMasami Hiramatsu } 348*4b1a29a7SMasami Hiramatsu 349*4b1a29a7SMasami Hiramatsu late_initcall(fei_debugfs_init); 350