diff options
-rw-r--r-- | fs/nfsd/fault_inject.c | 56 |
1 files changed, 49 insertions, 7 deletions
diff --git a/fs/nfsd/fault_inject.c b/fs/nfsd/fault_inject.c index 545f8e4ed101..19f9094bbb07 100644 --- a/fs/nfsd/fault_inject.c +++ b/fs/nfsd/fault_inject.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
9 | #include <linux/debugfs.h> | 9 | #include <linux/debugfs.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <asm/uaccess.h> | ||
11 | 12 | ||
12 | #include "state.h" | 13 | #include "state.h" |
13 | 14 | ||
@@ -48,10 +49,9 @@ static struct nfsd_fault_inject_op inject_ops[] = { | |||
48 | static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op); | 49 | static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op); |
49 | static struct dentry *debug_dir; | 50 | static struct dentry *debug_dir; |
50 | 51 | ||
51 | static int nfsd_inject_set(void *op_ptr, u64 val) | 52 | static void nfsd_inject_set(struct nfsd_fault_inject_op *op, u64 val) |
52 | { | 53 | { |
53 | u64 count = 0; | 54 | u64 count = 0; |
54 | struct nfsd_fault_inject_op *op = op_ptr; | ||
55 | 55 | ||
56 | if (val == 0) | 56 | if (val == 0) |
57 | printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file); | 57 | printk(KERN_INFO "NFSD Fault Injection: %s (all)", op->file); |
@@ -62,19 +62,61 @@ static int nfsd_inject_set(void *op_ptr, u64 val) | |||
62 | count = nfsd_for_n_state(val, op->forget); | 62 | count = nfsd_for_n_state(val, op->forget); |
63 | nfs4_unlock_state(); | 63 | nfs4_unlock_state(); |
64 | printk(KERN_INFO "NFSD: %s: found %llu", op->file, count); | 64 | printk(KERN_INFO "NFSD: %s: found %llu", op->file, count); |
65 | return 0; | ||
66 | } | 65 | } |
67 | 66 | ||
68 | static int nfsd_inject_get(void *op_ptr, u64 *val) | 67 | static void nfsd_inject_get(struct nfsd_fault_inject_op *op, u64 *val) |
69 | { | 68 | { |
70 | struct nfsd_fault_inject_op *op = op_ptr; | ||
71 | nfs4_lock_state(); | 69 | nfs4_lock_state(); |
72 | *val = nfsd_for_n_state(0, op->print); | 70 | *val = nfsd_for_n_state(0, op->print); |
73 | nfs4_unlock_state(); | 71 | nfs4_unlock_state(); |
74 | return 0; | ||
75 | } | 72 | } |
76 | 73 | ||
77 | DEFINE_SIMPLE_ATTRIBUTE(fops_nfsd, nfsd_inject_get, nfsd_inject_set, "%llu\n"); | 74 | static 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 | |||
100 | static 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 | |||
115 | static const struct file_operations fops_nfsd = { | ||
116 | .owner = THIS_MODULE, | ||
117 | .read = fault_inject_read, | ||
118 | .write = fault_inject_write, | ||
119 | }; | ||
78 | 120 | ||
79 | void nfsd_fault_inject_cleanup(void) | 121 | void nfsd_fault_inject_cleanup(void) |
80 | { | 122 | { |