aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2012-11-29 11:40:45 -0500
committerJ. Bruce Fields <bfields@redhat.com>2012-12-03 09:59:02 -0500
commitd7cc431edd0a6c69a88b5ff1e304af50bfb2270e (patch)
tree1dd7af589286e5beac9b5f0b94e167f2af229e0a /fs/nfsd
parent184c18471f7d0963ad5752692c4b441a546d88f1 (diff)
NFSD: Add a custom file operations structure for fault injection
Controlling the read and write functions allows me to add in "forget client w.x.y.z", since we won't be limited to reading and writing only u64 values. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/fault_inject.c56
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[] = {
48static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op); 49static long int NUM_INJECT_OPS = sizeof(inject_ops) / sizeof(struct nfsd_fault_inject_op);
49static struct dentry *debug_dir; 50static struct dentry *debug_dir;
50 51
51static int nfsd_inject_set(void *op_ptr, u64 val) 52static 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
68static int nfsd_inject_get(void *op_ptr, u64 *val) 67static 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
77DEFINE_SIMPLE_ATTRIBUTE(fops_nfsd, nfsd_inject_get, nfsd_inject_set, "%llu\n"); 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};
78 120
79void nfsd_fault_inject_cleanup(void) 121void nfsd_fault_inject_cleanup(void)
80{ 122{