NFSD: Add a custom file operations structure for fault injection
[deliverable/linux.git] / fs / nfsd / fault_inject.c
CommitLineData
65178db4
BS
1/*
2 * Copyright (c) 2011 Bryan Schumaker <bjschuma@netapp.com>
3 *
4 * Uses debugfs to create fault injection points for client testing
5 */
6
7#include <linux/types.h>
8#include <linux/fs.h>
9#include <linux/debugfs.h>
10#include <linux/module.h>
d7cc431e 11#include <asm/uaccess.h>
65178db4
BS
12
13#include "state.h"
65178db4
BS
14
15struct nfsd_fault_inject_op {
16 char *file;
8ce54e0d 17 u64 (*forget)(struct nfs4_client *, u64);
184c1847 18 u64 (*print)(struct nfs4_client *, u64);
65178db4
BS
19};
20
21static struct nfsd_fault_inject_op inject_ops[] = {
22 {
23 .file = "forget_clients",
8ce54e0d 24 .forget = nfsd_forget_client,
184c1847 25 .print = nfsd_print_client,
65178db4
BS
26 },
27 {
28 .file = "forget_locks",
8ce54e0d 29 .forget = nfsd_forget_client_locks,
184c1847 30 .print = nfsd_print_client_locks,
65178db4
BS
31 },
32 {
33 .file = "forget_openowners",
8ce54e0d 34 .forget = nfsd_forget_client_openowners,
184c1847 35 .print = nfsd_print_client_openowners,
65178db4
BS
36 },
37 {
38 .file = "forget_delegations",
8ce54e0d 39 .forget = nfsd_forget_client_delegations,
184c1847 40 .print = nfsd_print_client_delegations,
65178db4
BS
41 },
42 {
43 .file = "recall_delegations",
8ce54e0d 44 .forget = nfsd_recall_client_delegations,
184c1847 45 .print = nfsd_print_client_delegations,
65178db4
BS
46 },
47};
48
49static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
50static struct dentry *debug_dir;
51
d7cc431e 52static void nfsd_inject_set(struct nfsd_fault_inject_op *op, u64 val)
65178db4 53{
8ce54e0d 54 u64 count = 0;
65178db4
BS
55
56 if (val == 0)
57 printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file);
58 else
59 printk(KERN_INFO "NFSD Fault Injection: %s (n = %llu)", op->file, val);
60
04395839 61 nfs4_lock_state();
8ce54e0d 62 count = nfsd_for_n_state(val, op->forget);
04395839 63 nfs4_unlock_state();
8ce54e0d 64 printk(KERN_INFO "NFSD: %s: found %llu", op->file, count);
65178db4
BS
65}
66
d7cc431e 67static void nfsd_inject_get(struct nfsd_fault_inject_op *op, u64 *val)
65178db4 68{
184c1847
BS
69 nfs4_lock_state();
70 *val = nfsd_for_n_state(0, op->print);
71 nfs4_unlock_state();
65178db4
BS
72}
73
d7cc431e
BS
74static ssize_t fault_inject_read(struct file *file, char __user *buf,
75 size_t len, loff_t *ppos)
76{
77 static u64 val;
78 char read_buf[25];
79 size_t size, ret;
80 loff_t pos = *ppos;
81
82 if (!pos)
83 nfsd_inject_get(file->f_dentry->d_inode->i_private, &val);
84 size = scnprintf(read_buf, sizeof(read_buf), "%llu\n", val);
85
86 if (pos < 0)
87 return -EINVAL;
88 if (pos >= size || !len)
89 return 0;
90 if (len > size - pos)
91 len = size - pos;
92 ret = copy_to_user(buf, read_buf + pos, len);
93 if (ret == len)
94 return -EFAULT;
95 len -= ret;
96 *ppos = pos + len;
97 return len;
98}
99
100static ssize_t fault_inject_write(struct file *file, const char __user *buf,
101 size_t len, loff_t *ppos)
102{
103 char write_buf[24];
104 size_t size = min(sizeof(write_buf), len) - 1;
105 u64 val;
106
107 if (copy_from_user(write_buf, buf, size))
108 return -EFAULT;
109
110 val = simple_strtoll(write_buf, NULL, 0);
111 nfsd_inject_set(file->f_dentry->d_inode->i_private, val);
112 return len; /* on success, claim we got the whole input */
113}
114
115static const struct file_operations fops_nfsd = {
116 .owner = THIS_MODULE,
117 .read = fault_inject_read,
118 .write = fault_inject_write,
119};
65178db4
BS
120
121void nfsd_fault_inject_cleanup(void)
122{
123 debugfs_remove_recursive(debug_dir);
124}
125
126int nfsd_fault_inject_init(void)
127{
128 unsigned int i;
129 struct nfsd_fault_inject_op *op;
88187398 130 umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
65178db4
BS
131
132 debug_dir = debugfs_create_dir("nfsd", NULL);
133 if (!debug_dir)
134 goto fail;
135
136 for (i = 0; i < NUM_INJECT_OPS; i++) {
137 op = &inject_ops[i];
138 if (!debugfs_create_file(op->file, mode, debug_dir, op, &fops_nfsd))
139 goto fail;
140 }
141 return 0;
142
143fail:
144 nfsd_fault_inject_cleanup();
145 return -ENOMEM;
146}
This page took 0.071184 seconds and 5 git commands to generate.