Commit | Line | Data |
---|---|---|
994025ca JF |
1 | #include <linux/init.h> |
2 | #include <linux/debugfs.h> | |
5a0e3ad6 | 3 | #include <linux/slab.h> |
994025ca JF |
4 | #include <linux/module.h> |
5 | ||
6 | #include "debugfs.h" | |
7 | ||
8 | static struct dentry *d_xen_debug; | |
9 | ||
10 | struct dentry * __init xen_init_debugfs(void) | |
11 | { | |
12 | if (!d_xen_debug) { | |
13 | d_xen_debug = debugfs_create_dir("xen", NULL); | |
14 | ||
15 | if (!d_xen_debug) | |
16 | pr_warning("Could not create 'xen' debugfs directory\n"); | |
17 | } | |
18 | ||
19 | return d_xen_debug; | |
20 | } | |
21 | ||
22 | struct array_data | |
23 | { | |
24 | void *array; | |
25 | unsigned elements; | |
26 | }; | |
27 | ||
28 | static int u32_array_open(struct inode *inode, struct file *file) | |
29 | { | |
30 | file->private_data = NULL; | |
31 | return nonseekable_open(inode, file); | |
32 | } | |
33 | ||
34 | static size_t format_array(char *buf, size_t bufsize, const char *fmt, | |
35 | u32 *array, unsigned array_size) | |
36 | { | |
37 | size_t ret = 0; | |
38 | unsigned i; | |
39 | ||
40 | for(i = 0; i < array_size; i++) { | |
41 | size_t len; | |
42 | ||
43 | len = snprintf(buf, bufsize, fmt, array[i]); | |
44 | len++; /* ' ' or '\n' */ | |
45 | ret += len; | |
46 | ||
47 | if (buf) { | |
48 | buf += len; | |
49 | bufsize -= len; | |
50 | buf[-1] = (i == array_size-1) ? '\n' : ' '; | |
51 | } | |
52 | } | |
53 | ||
54 | ret++; /* \0 */ | |
55 | if (buf) | |
56 | *buf = '\0'; | |
57 | ||
58 | return ret; | |
59 | } | |
60 | ||
61 | static char *format_array_alloc(const char *fmt, u32 *array, unsigned array_size) | |
62 | { | |
63 | size_t len = format_array(NULL, 0, fmt, array, array_size); | |
64 | char *ret; | |
65 | ||
66 | ret = kmalloc(len, GFP_KERNEL); | |
67 | if (ret == NULL) | |
68 | return NULL; | |
69 | ||
70 | format_array(ret, len, fmt, array, array_size); | |
71 | return ret; | |
72 | } | |
73 | ||
74 | static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len, | |
75 | loff_t *ppos) | |
76 | { | |
77 | struct inode *inode = file->f_path.dentry->d_inode; | |
78 | struct array_data *data = inode->i_private; | |
79 | size_t size; | |
80 | ||
81 | if (*ppos == 0) { | |
82 | if (file->private_data) { | |
83 | kfree(file->private_data); | |
84 | file->private_data = NULL; | |
85 | } | |
86 | ||
87 | file->private_data = format_array_alloc("%u", data->array, data->elements); | |
88 | } | |
89 | ||
90 | size = 0; | |
91 | if (file->private_data) | |
92 | size = strlen(file->private_data); | |
93 | ||
94 | return simple_read_from_buffer(buf, len, ppos, file->private_data, size); | |
95 | } | |
96 | ||
97 | static int xen_array_release(struct inode *inode, struct file *file) | |
98 | { | |
99 | kfree(file->private_data); | |
100 | ||
101 | return 0; | |
102 | } | |
103 | ||
828c0950 | 104 | static const struct file_operations u32_array_fops = { |
994025ca JF |
105 | .owner = THIS_MODULE, |
106 | .open = u32_array_open, | |
107 | .release= xen_array_release, | |
108 | .read = u32_array_read, | |
6038f373 | 109 | .llseek = no_llseek, |
994025ca JF |
110 | }; |
111 | ||
112 | struct dentry *xen_debugfs_create_u32_array(const char *name, mode_t mode, | |
113 | struct dentry *parent, | |
114 | u32 *array, unsigned elements) | |
115 | { | |
116 | struct array_data *data = kmalloc(sizeof(*data), GFP_KERNEL); | |
117 | ||
118 | if (data == NULL) | |
119 | return NULL; | |
120 | ||
121 | data->array = array; | |
122 | data->elements = elements; | |
123 | ||
124 | return debugfs_create_file(name, mode, parent, data, &u32_array_fops); | |
125 | } |