diff options
Diffstat (limited to 'fs/debugfs/file.c')
-rw-r--r-- | fs/debugfs/file.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c new file mode 100644 index 000000000000..548556ff2506 --- /dev/null +++ b/fs/debugfs/file.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * file.c - part of debugfs, a tiny little debug file system | ||
3 | * | ||
4 | * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> | ||
5 | * Copyright (C) 2004 IBM Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * debugfs is for people to use instead of /proc or /sys. | ||
12 | * See Documentation/DocBook/kernel-api for more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/pagemap.h> | ||
20 | #include <linux/debugfs.h> | ||
21 | |||
22 | static ssize_t default_read_file(struct file *file, char __user *buf, | ||
23 | size_t count, loff_t *ppos) | ||
24 | { | ||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | static ssize_t default_write_file(struct file *file, const char __user *buf, | ||
29 | size_t count, loff_t *ppos) | ||
30 | { | ||
31 | return count; | ||
32 | } | ||
33 | |||
34 | static int default_open(struct inode *inode, struct file *file) | ||
35 | { | ||
36 | if (inode->u.generic_ip) | ||
37 | file->private_data = inode->u.generic_ip; | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | struct file_operations debugfs_file_operations = { | ||
43 | .read = default_read_file, | ||
44 | .write = default_write_file, | ||
45 | .open = default_open, | ||
46 | }; | ||
47 | |||
48 | #define simple_type(type, format, temptype, strtolfn) \ | ||
49 | static ssize_t read_file_##type(struct file *file, char __user *user_buf, \ | ||
50 | size_t count, loff_t *ppos) \ | ||
51 | { \ | ||
52 | char buf[32]; \ | ||
53 | type *val = file->private_data; \ | ||
54 | \ | ||
55 | snprintf(buf, sizeof(buf), format "\n", *val); \ | ||
56 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\ | ||
57 | } \ | ||
58 | static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\ | ||
59 | size_t count, loff_t *ppos) \ | ||
60 | { \ | ||
61 | char *endp; \ | ||
62 | char buf[32]; \ | ||
63 | int buf_size; \ | ||
64 | type *val = file->private_data; \ | ||
65 | temptype tmp; \ | ||
66 | \ | ||
67 | memset(buf, 0x00, sizeof(buf)); \ | ||
68 | buf_size = min(count, (sizeof(buf)-1)); \ | ||
69 | if (copy_from_user(buf, user_buf, buf_size)) \ | ||
70 | return -EFAULT; \ | ||
71 | \ | ||
72 | tmp = strtolfn(buf, &endp, 0); \ | ||
73 | if ((endp == buf) || ((type)tmp != tmp)) \ | ||
74 | return -EINVAL; \ | ||
75 | *val = tmp; \ | ||
76 | return count; \ | ||
77 | } \ | ||
78 | static struct file_operations fops_##type = { \ | ||
79 | .read = read_file_##type, \ | ||
80 | .write = write_file_##type, \ | ||
81 | .open = default_open, \ | ||
82 | }; | ||
83 | simple_type(u8, "%c", unsigned long, simple_strtoul); | ||
84 | simple_type(u16, "%hi", unsigned long, simple_strtoul); | ||
85 | simple_type(u32, "%i", unsigned long, simple_strtoul); | ||
86 | |||
87 | /** | ||
88 | * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. | ||
89 | * | ||
90 | * @name: a pointer to a string containing the name of the file to create. | ||
91 | * @mode: the permission that the file should have | ||
92 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
93 | * directory dentry if set. If this paramater is NULL, then the | ||
94 | * file will be created in the root of the debugfs filesystem. | ||
95 | * @value: a pointer to the variable that the file should read to and write | ||
96 | * from. | ||
97 | * | ||
98 | * This function creates a file in debugfs with the given name that | ||
99 | * contains the value of the variable @value. If the @mode variable is so | ||
100 | * set, it can be read from, and written to. | ||
101 | * | ||
102 | * This function will return a pointer to a dentry if it succeeds. This | ||
103 | * pointer must be passed to the debugfs_remove() function when the file is | ||
104 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
105 | * you are responsible here.) If an error occurs, NULL will be returned. | ||
106 | * | ||
107 | * If debugfs is not enabled in the kernel, the value -ENODEV will be | ||
108 | * returned. It is not wise to check for this value, but rather, check for | ||
109 | * NULL or !NULL instead as to eliminate the need for #ifdef in the calling | ||
110 | * code. | ||
111 | */ | ||
112 | struct dentry *debugfs_create_u8(const char *name, mode_t mode, | ||
113 | struct dentry *parent, u8 *value) | ||
114 | { | ||
115 | return debugfs_create_file(name, mode, parent, value, &fops_u8); | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(debugfs_create_u8); | ||
118 | |||
119 | /** | ||
120 | * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. | ||
121 | * | ||
122 | * @name: a pointer to a string containing the name of the file to create. | ||
123 | * @mode: the permission that the file should have | ||
124 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
125 | * directory dentry if set. If this paramater is NULL, then the | ||
126 | * file will be created in the root of the debugfs filesystem. | ||
127 | * @value: a pointer to the variable that the file should read to and write | ||
128 | * from. | ||
129 | * | ||
130 | * This function creates a file in debugfs with the given name that | ||
131 | * contains the value of the variable @value. If the @mode variable is so | ||
132 | * set, it can be read from, and written to. | ||
133 | * | ||
134 | * This function will return a pointer to a dentry if it succeeds. This | ||
135 | * pointer must be passed to the debugfs_remove() function when the file is | ||
136 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
137 | * you are responsible here.) If an error occurs, NULL will be returned. | ||
138 | * | ||
139 | * If debugfs is not enabled in the kernel, the value -ENODEV will be | ||
140 | * returned. It is not wise to check for this value, but rather, check for | ||
141 | * NULL or !NULL instead as to eliminate the need for #ifdef in the calling | ||
142 | * code. | ||
143 | */ | ||
144 | struct dentry *debugfs_create_u16(const char *name, mode_t mode, | ||
145 | struct dentry *parent, u16 *value) | ||
146 | { | ||
147 | return debugfs_create_file(name, mode, parent, value, &fops_u16); | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(debugfs_create_u16); | ||
150 | |||
151 | /** | ||
152 | * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value. | ||
153 | * | ||
154 | * @name: a pointer to a string containing the name of the file to create. | ||
155 | * @mode: the permission that the file should have | ||
156 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
157 | * directory dentry if set. If this paramater is NULL, then the | ||
158 | * file will be created in the root of the debugfs filesystem. | ||
159 | * @value: a pointer to the variable that the file should read to and write | ||
160 | * from. | ||
161 | * | ||
162 | * This function creates a file in debugfs with the given name that | ||
163 | * contains the value of the variable @value. If the @mode variable is so | ||
164 | * set, it can be read from, and written to. | ||
165 | * | ||
166 | * This function will return a pointer to a dentry if it succeeds. This | ||
167 | * pointer must be passed to the debugfs_remove() function when the file is | ||
168 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
169 | * you are responsible here.) If an error occurs, NULL will be returned. | ||
170 | * | ||
171 | * If debugfs is not enabled in the kernel, the value -ENODEV will be | ||
172 | * returned. It is not wise to check for this value, but rather, check for | ||
173 | * NULL or !NULL instead as to eliminate the need for #ifdef in the calling | ||
174 | * code. | ||
175 | */ | ||
176 | struct dentry *debugfs_create_u32(const char *name, mode_t mode, | ||
177 | struct dentry *parent, u32 *value) | ||
178 | { | ||
179 | return debugfs_create_file(name, mode, parent, value, &fops_u32); | ||
180 | } | ||
181 | EXPORT_SYMBOL_GPL(debugfs_create_u32); | ||
182 | |||
183 | static ssize_t read_file_bool(struct file *file, char __user *user_buf, | ||
184 | size_t count, loff_t *ppos) | ||
185 | { | ||
186 | char buf[3]; | ||
187 | u32 *val = file->private_data; | ||
188 | |||
189 | if (*val) | ||
190 | buf[0] = 'Y'; | ||
191 | else | ||
192 | buf[0] = 'N'; | ||
193 | buf[1] = '\n'; | ||
194 | buf[2] = 0x00; | ||
195 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
196 | } | ||
197 | |||
198 | static ssize_t write_file_bool(struct file *file, const char __user *user_buf, | ||
199 | size_t count, loff_t *ppos) | ||
200 | { | ||
201 | char buf[32]; | ||
202 | int buf_size; | ||
203 | u32 *val = file->private_data; | ||
204 | |||
205 | buf_size = min(count, (sizeof(buf)-1)); | ||
206 | if (copy_from_user(buf, user_buf, buf_size)) | ||
207 | return -EFAULT; | ||
208 | |||
209 | switch (buf[0]) { | ||
210 | case 'y': | ||
211 | case 'Y': | ||
212 | case '1': | ||
213 | *val = 1; | ||
214 | break; | ||
215 | case 'n': | ||
216 | case 'N': | ||
217 | case '0': | ||
218 | *val = 0; | ||
219 | break; | ||
220 | } | ||
221 | |||
222 | return count; | ||
223 | } | ||
224 | |||
225 | static struct file_operations fops_bool = { | ||
226 | .read = read_file_bool, | ||
227 | .write = write_file_bool, | ||
228 | .open = default_open, | ||
229 | }; | ||
230 | |||
231 | /** | ||
232 | * debugfs_create_bool - create a file in the debugfs filesystem that is used to read and write a boolean value. | ||
233 | * | ||
234 | * @name: a pointer to a string containing the name of the file to create. | ||
235 | * @mode: the permission that the file should have | ||
236 | * @parent: a pointer to the parent dentry for this file. This should be a | ||
237 | * directory dentry if set. If this paramater is NULL, then the | ||
238 | * file will be created in the root of the debugfs filesystem. | ||
239 | * @value: a pointer to the variable that the file should read to and write | ||
240 | * from. | ||
241 | * | ||
242 | * This function creates a file in debugfs with the given name that | ||
243 | * contains the value of the variable @value. If the @mode variable is so | ||
244 | * set, it can be read from, and written to. | ||
245 | * | ||
246 | * This function will return a pointer to a dentry if it succeeds. This | ||
247 | * pointer must be passed to the debugfs_remove() function when the file is | ||
248 | * to be removed (no automatic cleanup happens if your module is unloaded, | ||
249 | * you are responsible here.) If an error occurs, NULL will be returned. | ||
250 | * | ||
251 | * If debugfs is not enabled in the kernel, the value -ENODEV will be | ||
252 | * returned. It is not wise to check for this value, but rather, check for | ||
253 | * NULL or !NULL instead as to eliminate the need for #ifdef in the calling | ||
254 | * code. | ||
255 | */ | ||
256 | struct dentry *debugfs_create_bool(const char *name, mode_t mode, | ||
257 | struct dentry *parent, u32 *value) | ||
258 | { | ||
259 | return debugfs_create_file(name, mode, parent, value, &fops_bool); | ||
260 | } | ||
261 | EXPORT_SYMBOL_GPL(debugfs_create_bool); | ||
262 | |||