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