aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2009-12-15 19:46:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 10:20:05 -0500
commit5116fa2b3a0a3ec625a10445ae45667f094c125b (patch)
tree78981f73d8db331915f80ba68f65ece523521245
parentd52f235f17a588c132a2aaf1e7fc49bb5707fe36 (diff)
pnpbios: convert to seq_file
Convert code away from ->read_proc/->write_proc interfaces. Switch to proc_create()/proc_create_data() which make addition of proc entries reliable wrt NULL ->proc_fops, NULL ->data and so on. Problem with ->read_proc et al is described here commit 786d7e1612f0b0adb6046f19b906609e4fe8b1ba "Fix rmmod/read/write races in /proc entries" Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Cc: Adam Belay <abelay@mit.edu> Cc: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/pnp/pnpbios/proc.c204
1 files changed, 129 insertions, 75 deletions
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index b35d921bac6e..2d8ac43f78e8 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -24,6 +24,7 @@
24#include <linux/types.h> 24#include <linux/types.h>
25#include <linux/proc_fs.h> 25#include <linux/proc_fs.h>
26#include <linux/pnp.h> 26#include <linux/pnp.h>
27#include <linux/seq_file.h>
27#include <linux/init.h> 28#include <linux/init.h>
28 29
29#include <asm/uaccess.h> 30#include <asm/uaccess.h>
@@ -33,42 +34,65 @@
33static struct proc_dir_entry *proc_pnp = NULL; 34static struct proc_dir_entry *proc_pnp = NULL;
34static struct proc_dir_entry *proc_pnp_boot = NULL; 35static struct proc_dir_entry *proc_pnp_boot = NULL;
35 36
36static int proc_read_pnpconfig(char *buf, char **start, off_t pos, 37static int pnpconfig_proc_show(struct seq_file *m, void *v)
37 int count, int *eof, void *data)
38{ 38{
39 struct pnp_isa_config_struc pnps; 39 struct pnp_isa_config_struc pnps;
40 40
41 if (pnp_bios_isapnp_config(&pnps)) 41 if (pnp_bios_isapnp_config(&pnps))
42 return -EIO; 42 return -EIO;
43 return snprintf(buf, count, 43 seq_printf(m, "structure_revision %d\n"
44 "structure_revision %d\n" 44 "number_of_CSNs %d\n"
45 "number_of_CSNs %d\n" 45 "ISA_read_data_port 0x%x\n",
46 "ISA_read_data_port 0x%x\n", 46 pnps.revision, pnps.no_csns, pnps.isa_rd_data_port);
47 pnps.revision, pnps.no_csns, pnps.isa_rd_data_port); 47 return 0;
48} 48}
49 49
50static int proc_read_escdinfo(char *buf, char **start, off_t pos, 50static int pnpconfig_proc_open(struct inode *inode, struct file *file)
51 int count, int *eof, void *data) 51{
52 return single_open(file, pnpconfig_proc_show, NULL);
53}
54
55static const struct file_operations pnpconfig_proc_fops = {
56 .owner = THIS_MODULE,
57 .open = pnpconfig_proc_open,
58 .read = seq_read,
59 .llseek = seq_lseek,
60 .release = single_release,
61};
62
63static int escd_info_proc_show(struct seq_file *m, void *v)
52{ 64{
53 struct escd_info_struc escd; 65 struct escd_info_struc escd;
54 66
55 if (pnp_bios_escd_info(&escd)) 67 if (pnp_bios_escd_info(&escd))
56 return -EIO; 68 return -EIO;
57 return snprintf(buf, count, 69 seq_printf(m, "min_ESCD_write_size %d\n"
58 "min_ESCD_write_size %d\n"
59 "ESCD_size %d\n" 70 "ESCD_size %d\n"
60 "NVRAM_base 0x%x\n", 71 "NVRAM_base 0x%x\n",
61 escd.min_escd_write_size, 72 escd.min_escd_write_size,
62 escd.escd_size, escd.nv_storage_base); 73 escd.escd_size, escd.nv_storage_base);
74 return 0;
63} 75}
64 76
77static int escd_info_proc_open(struct inode *inode, struct file *file)
78{
79 return single_open(file, escd_info_proc_show, NULL);
80}
81
82static const struct file_operations escd_info_proc_fops = {
83 .owner = THIS_MODULE,
84 .open = escd_info_proc_open,
85 .read = seq_read,
86 .llseek = seq_lseek,
87 .release = single_release,
88};
89
65#define MAX_SANE_ESCD_SIZE (32*1024) 90#define MAX_SANE_ESCD_SIZE (32*1024)
66static int proc_read_escd(char *buf, char **start, off_t pos, 91static int escd_proc_show(struct seq_file *m, void *v)
67 int count, int *eof, void *data)
68{ 92{
69 struct escd_info_struc escd; 93 struct escd_info_struc escd;
70 char *tmpbuf; 94 char *tmpbuf;
71 int escd_size, escd_left_to_read, n; 95 int escd_size;
72 96
73 if (pnp_bios_escd_info(&escd)) 97 if (pnp_bios_escd_info(&escd))
74 return -EIO; 98 return -EIO;
@@ -76,7 +100,7 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
76 /* sanity check */ 100 /* sanity check */
77 if (escd.escd_size > MAX_SANE_ESCD_SIZE) { 101 if (escd.escd_size > MAX_SANE_ESCD_SIZE) {
78 printk(KERN_ERR 102 printk(KERN_ERR
79 "PnPBIOS: proc_read_escd: ESCD size reported by BIOS escd_info call is too great\n"); 103 "PnPBIOS: %s: ESCD size reported by BIOS escd_info call is too great\n", __func__);
80 return -EFBIG; 104 return -EFBIG;
81 } 105 }
82 106
@@ -94,56 +118,75 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
94 118
95 /* sanity check */ 119 /* sanity check */
96 if (escd_size > MAX_SANE_ESCD_SIZE) { 120 if (escd_size > MAX_SANE_ESCD_SIZE) {
97 printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by" 121 printk(KERN_ERR "PnPBIOS: %s: ESCD size reported by"
98 " BIOS read_escd call is too great\n"); 122 " BIOS read_escd call is too great\n", __func__);
99 kfree(tmpbuf); 123 kfree(tmpbuf);
100 return -EFBIG; 124 return -EFBIG;
101 } 125 }
102 126
103 escd_left_to_read = escd_size - pos; 127 seq_write(m, tmpbuf, escd_size);
104 if (escd_left_to_read < 0)
105 escd_left_to_read = 0;
106 if (escd_left_to_read == 0)
107 *eof = 1;
108 n = min(count, escd_left_to_read);
109 memcpy(buf, tmpbuf + pos, n);
110 kfree(tmpbuf); 128 kfree(tmpbuf);
111 *start = buf; 129 return 0;
112 return n;
113} 130}
114 131
115static int proc_read_legacyres(char *buf, char **start, off_t pos, 132static int escd_proc_open(struct inode *inode, struct file *file)
116 int count, int *eof, void *data) 133{
134 return single_open(file, escd_proc_show, NULL);
135}
136
137static const struct file_operations escd_proc_fops = {
138 .owner = THIS_MODULE,
139 .open = escd_proc_open,
140 .read = seq_read,
141 .llseek = seq_lseek,
142 .release = single_release,
143};
144
145static int pnp_legacyres_proc_show(struct seq_file *m, void *v)
117{ 146{
118 /* Assume that the following won't overflow the buffer */ 147 void *buf;
119 if (pnp_bios_get_stat_res(buf)) 148
149 buf = kmalloc(65536, GFP_KERNEL);
150 if (!buf)
151 return -ENOMEM;
152 if (pnp_bios_get_stat_res(buf)) {
153 kfree(buf);
120 return -EIO; 154 return -EIO;
155 }
156
157 seq_write(m, buf, 65536);
158 kfree(buf);
159 return 0;
160}
121 161
122 return count; // FIXME: Return actual length 162static int pnp_legacyres_proc_open(struct inode *inode, struct file *file)
163{
164 return single_open(file, pnp_legacyres_proc_show, NULL);
123} 165}
124 166
125static int proc_read_devices(char *buf, char **start, off_t pos, 167static const struct file_operations pnp_legacyres_proc_fops = {
126 int count, int *eof, void *data) 168 .owner = THIS_MODULE,
169 .open = pnp_legacyres_proc_open,
170 .read = seq_read,
171 .llseek = seq_lseek,
172 .release = single_release,
173};
174
175static int pnp_devices_proc_show(struct seq_file *m, void *v)
127{ 176{
128 struct pnp_bios_node *node; 177 struct pnp_bios_node *node;
129 u8 nodenum; 178 u8 nodenum;
130 char *p = buf;
131
132 if (pos >= 0xff)
133 return 0;
134 179
135 node = kzalloc(node_info.max_node_size, GFP_KERNEL); 180 node = kzalloc(node_info.max_node_size, GFP_KERNEL);
136 if (!node) 181 if (!node)
137 return -ENOMEM; 182 return -ENOMEM;
138 183
139 for (nodenum = pos; nodenum < 0xff;) { 184 for (nodenum = 0; nodenum < 0xff;) {
140 u8 thisnodenum = nodenum; 185 u8 thisnodenum = nodenum;
141 /* 26 = the number of characters per line sprintf'ed */ 186
142 if ((p - buf + 26) > count)
143 break;
144 if (pnp_bios_get_dev_node(&nodenum, PNPMODE_DYNAMIC, node)) 187 if (pnp_bios_get_dev_node(&nodenum, PNPMODE_DYNAMIC, node))
145 break; 188 break;
146 p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n", 189 seq_printf(m, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
147 node->handle, node->eisa_id, 190 node->handle, node->eisa_id,
148 node->type_code[0], node->type_code[1], 191 node->type_code[0], node->type_code[1],
149 node->type_code[2], node->flags); 192 node->type_code[2], node->flags);
@@ -153,20 +196,29 @@ static int proc_read_devices(char *buf, char **start, off_t pos,
153 "PnPBIOS: proc_read_devices:", 196 "PnPBIOS: proc_read_devices:",
154 (unsigned int)nodenum, 197 (unsigned int)nodenum,
155 (unsigned int)thisnodenum); 198 (unsigned int)thisnodenum);
156 *eof = 1;
157 break; 199 break;
158 } 200 }
159 } 201 }
160 kfree(node); 202 kfree(node);
161 if (nodenum == 0xff) 203 return 0;
162 *eof = 1; 204}
163 *start = (char *)((off_t) nodenum - pos); 205
164 return p - buf; 206static int pnp_devices_proc_open(struct inode *inode, struct file *file)
207{
208 return single_open(file, pnp_devices_proc_show, NULL);
165} 209}
166 210
167static int proc_read_node(char *buf, char **start, off_t pos, 211static const struct file_operations pnp_devices_proc_fops = {
168 int count, int *eof, void *data) 212 .owner = THIS_MODULE,
213 .open = pnp_devices_proc_open,
214 .read = seq_read,
215 .llseek = seq_lseek,
216 .release = single_release,
217};
218
219static int pnpbios_proc_show(struct seq_file *m, void *v)
169{ 220{
221 void *data = m->private;
170 struct pnp_bios_node *node; 222 struct pnp_bios_node *node;
171 int boot = (long)data >> 8; 223 int boot = (long)data >> 8;
172 u8 nodenum = (long)data; 224 u8 nodenum = (long)data;
@@ -180,14 +232,20 @@ static int proc_read_node(char *buf, char **start, off_t pos,
180 return -EIO; 232 return -EIO;
181 } 233 }
182 len = node->size - sizeof(struct pnp_bios_node); 234 len = node->size - sizeof(struct pnp_bios_node);
183 memcpy(buf, node->data, len); 235 seq_write(m, node->data, len);
184 kfree(node); 236 kfree(node);
185 return len; 237 return 0;
238}
239
240static int pnpbios_proc_open(struct inode *inode, struct file *file)
241{
242 return single_open(file, pnpbios_proc_show, PDE(inode)->data);
186} 243}
187 244
188static int proc_write_node(struct file *file, const char __user * buf, 245static ssize_t pnpbios_proc_write(struct file *file, const char __user *buf,
189 unsigned long count, void *data) 246 size_t count, loff_t *pos)
190{ 247{
248 void *data = PDE(file->f_path.dentry->d_inode)->data;
191 struct pnp_bios_node *node; 249 struct pnp_bios_node *node;
192 int boot = (long)data >> 8; 250 int boot = (long)data >> 8;
193 u8 nodenum = (long)data; 251 u8 nodenum = (long)data;
@@ -218,34 +276,33 @@ out:
218 return ret; 276 return ret;
219} 277}
220 278
279static const struct file_operations pnpbios_proc_fops = {
280 .owner = THIS_MODULE,
281 .open = pnpbios_proc_open,
282 .read = seq_read,
283 .llseek = seq_lseek,
284 .release = single_release,
285 .write = pnpbios_proc_write,
286};
287
221int pnpbios_interface_attach_device(struct pnp_bios_node *node) 288int pnpbios_interface_attach_device(struct pnp_bios_node *node)
222{ 289{
223 char name[3]; 290 char name[3];
224 struct proc_dir_entry *ent;
225 291
226 sprintf(name, "%02x", node->handle); 292 sprintf(name, "%02x", node->handle);
227 293
228 if (!proc_pnp) 294 if (!proc_pnp)
229 return -EIO; 295 return -EIO;
230 if (!pnpbios_dont_use_current_config) { 296 if (!pnpbios_dont_use_current_config) {
231 ent = create_proc_entry(name, 0, proc_pnp); 297 proc_create_data(name, 0644, proc_pnp, &pnpbios_proc_fops,
232 if (ent) { 298 (void *)(long)(node->handle));
233 ent->read_proc = proc_read_node;
234 ent->write_proc = proc_write_node;
235 ent->data = (void *)(long)(node->handle);
236 }
237 } 299 }
238 300
239 if (!proc_pnp_boot) 301 if (!proc_pnp_boot)
240 return -EIO; 302 return -EIO;
241 ent = create_proc_entry(name, 0, proc_pnp_boot); 303 if (proc_create_data(name, 0644, proc_pnp_boot, &pnpbios_proc_fops,
242 if (ent) { 304 (void *)(long)(node->handle + 0x100)))
243 ent->read_proc = proc_read_node;
244 ent->write_proc = proc_write_node;
245 ent->data = (void *)(long)(node->handle + 0x100);
246 return 0; 305 return 0;
247 }
248
249 return -EIO; 306 return -EIO;
250} 307}
251 308
@@ -262,14 +319,11 @@ int __init pnpbios_proc_init(void)
262 proc_pnp_boot = proc_mkdir("boot", proc_pnp); 319 proc_pnp_boot = proc_mkdir("boot", proc_pnp);
263 if (!proc_pnp_boot) 320 if (!proc_pnp_boot)
264 return -EIO; 321 return -EIO;
265 create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL); 322 proc_create("devices", 0, proc_pnp, &pnp_devices_proc_fops);
266 create_proc_read_entry("configuration_info", 0, proc_pnp, 323 proc_create("configuration_info", 0, proc_pnp, &pnpconfig_proc_fops);
267 proc_read_pnpconfig, NULL); 324 proc_create("escd_info", 0, proc_pnp, &escd_info_proc_fops);
268 create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, 325 proc_create("escd", S_IRUSR, proc_pnp, &escd_proc_fops);
269 NULL); 326 proc_create("legacy_device_resources", 0, proc_pnp, &pnp_legacyres_proc_fops);
270 create_proc_read_entry("escd", S_IRUSR, proc_pnp, proc_read_escd, NULL);
271 create_proc_read_entry("legacy_device_resources", 0, proc_pnp,
272 proc_read_legacyres, NULL);
273 327
274 return 0; 328 return 0;
275} 329}