Commit 0ead0f84e81a41c3e98aeceab04af8ab1bb08d1f
Committed by
Linus Torvalds
1 parent
4614a696bd
Exists in
master
and in
39 other branches
alpha: convert srm code 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: Richard Henderson <rth@twiddle.net> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 33 additions and 32 deletions Side-by-side Diff
arch/alpha/kernel/srm_env.c
... | ... | @@ -33,6 +33,7 @@ |
33 | 33 | #include <linux/module.h> |
34 | 34 | #include <linux/init.h> |
35 | 35 | #include <linux/proc_fs.h> |
36 | +#include <linux/seq_file.h> | |
36 | 37 | #include <asm/console.h> |
37 | 38 | #include <asm/uaccess.h> |
38 | 39 | #include <asm/machvec.h> |
39 | 40 | |
40 | 41 | |
41 | 42 | |
42 | 43 | |
43 | 44 | |
44 | 45 | |
45 | 46 | |
46 | 47 | |
47 | 48 | |
48 | 49 | |
... | ... | @@ -79,42 +80,41 @@ |
79 | 80 | static srm_env_t srm_numbered_entries[256]; |
80 | 81 | |
81 | 82 | |
82 | -static int | |
83 | -srm_env_read(char *page, char **start, off_t off, int count, int *eof, | |
84 | - void *data) | |
83 | +static int srm_env_proc_show(struct seq_file *m, void *v) | |
85 | 84 | { |
86 | - int nbytes; | |
87 | 85 | unsigned long ret; |
88 | 86 | srm_env_t *entry; |
87 | + char *page; | |
89 | 88 | |
90 | - if (off != 0) { | |
91 | - *eof = 1; | |
92 | - return 0; | |
93 | - } | |
89 | + entry = (srm_env_t *)m->private; | |
90 | + page = (char *)__get_free_page(GFP_USER); | |
91 | + if (!page) | |
92 | + return -ENOMEM; | |
94 | 93 | |
95 | - entry = (srm_env_t *) data; | |
96 | - ret = callback_getenv(entry->id, page, count); | |
94 | + ret = callback_getenv(entry->id, page, PAGE_SIZE); | |
97 | 95 | |
98 | 96 | if ((ret >> 61) == 0) { |
99 | - nbytes = (int) ret; | |
100 | - *eof = 1; | |
97 | + seq_write(m, page, ret); | |
98 | + ret = 0; | |
101 | 99 | } else |
102 | - nbytes = -EFAULT; | |
100 | + ret = -EFAULT; | |
101 | + free_page((unsigned long)page); | |
102 | + return ret; | |
103 | +} | |
103 | 104 | |
104 | - return nbytes; | |
105 | +static int srm_env_proc_open(struct inode *inode, struct file *file) | |
106 | +{ | |
107 | + return single_open(file, srm_env_proc_show, PDE(inode)->data); | |
105 | 108 | } |
106 | 109 | |
107 | -static int | |
108 | -srm_env_write(struct file *file, const char __user *buffer, unsigned long count, | |
109 | - void *data) | |
110 | +static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer, | |
111 | + size_t count, loff_t *pos) | |
110 | 112 | { |
111 | 113 | int res; |
112 | - srm_env_t *entry; | |
114 | + srm_env_t *entry = PDE(file->f_path.dentry->d_inode)->data; | |
113 | 115 | char *buf = (char *) __get_free_page(GFP_USER); |
114 | 116 | unsigned long ret1, ret2; |
115 | 117 | |
116 | - entry = (srm_env_t *) data; | |
117 | - | |
118 | 118 | if (!buf) |
119 | 119 | return -ENOMEM; |
120 | 120 | |
... | ... | @@ -140,6 +140,15 @@ |
140 | 140 | return res; |
141 | 141 | } |
142 | 142 | |
143 | +static const struct file_operations srm_env_proc_fops = { | |
144 | + .owner = THIS_MODULE, | |
145 | + .open = srm_env_proc_open, | |
146 | + .read = seq_read, | |
147 | + .llseek = seq_lseek, | |
148 | + .release = single_release, | |
149 | + .write = srm_env_proc_write, | |
150 | +}; | |
151 | + | |
143 | 152 | static void |
144 | 153 | srm_env_cleanup(void) |
145 | 154 | { |
146 | 155 | |
... | ... | @@ -245,15 +254,10 @@ |
245 | 254 | */ |
246 | 255 | entry = srm_named_entries; |
247 | 256 | while (entry->name && entry->id) { |
248 | - entry->proc_entry = create_proc_entry(entry->name, | |
249 | - 0644, named_dir); | |
257 | + entry->proc_entry = proc_create_data(entry->name, 0644, named_dir, | |
258 | + &srm_env_proc_fops, entry); | |
250 | 259 | if (!entry->proc_entry) |
251 | 260 | goto cleanup; |
252 | - | |
253 | - entry->proc_entry->data = (void *) entry; | |
254 | - entry->proc_entry->read_proc = srm_env_read; | |
255 | - entry->proc_entry->write_proc = srm_env_write; | |
256 | - | |
257 | 261 | entry++; |
258 | 262 | } |
259 | 263 | |
260 | 264 | |
... | ... | @@ -264,15 +268,12 @@ |
264 | 268 | entry = &srm_numbered_entries[var_num]; |
265 | 269 | entry->name = number[var_num]; |
266 | 270 | |
267 | - entry->proc_entry = create_proc_entry(entry->name, | |
268 | - 0644, numbered_dir); | |
271 | + entry->proc_entry = proc_create_data(entry->name, 0644, numbered_dir, | |
272 | + &srm_env_proc_fops, entry); | |
269 | 273 | if (!entry->proc_entry) |
270 | 274 | goto cleanup; |
271 | 275 | |
272 | 276 | entry->id = var_num; |
273 | - entry->proc_entry->data = (void *) entry; | |
274 | - entry->proc_entry->read_proc = srm_env_read; | |
275 | - entry->proc_entry->write_proc = srm_env_write; | |
276 | 277 | } |
277 | 278 | |
278 | 279 | printk(KERN_INFO "%s: version %s loaded successfully\n", NAME, |