aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2009-12-14 21:00:06 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-15 11:53:24 -0500
commit0ead0f84e81a41c3e98aeceab04af8ab1bb08d1f (patch)
treeba5d354818d2ec0a8251b3f4a5c9b9bef1092e07
parent4614a696bd1c3a9af3a08f0e5874830a85b889d4 (diff)
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>
-rw-r--r--arch/alpha/kernel/srm_env.c65
1 files changed, 33 insertions, 32 deletions
diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
index d12af472e1c0..dbbf04f9230e 100644
--- a/arch/alpha/kernel/srm_env.c
+++ b/arch/alpha/kernel/srm_env.c
@@ -33,6 +33,7 @@
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/init.h> 34#include <linux/init.h>
35#include <linux/proc_fs.h> 35#include <linux/proc_fs.h>
36#include <linux/seq_file.h>
36#include <asm/console.h> 37#include <asm/console.h>
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
38#include <asm/machvec.h> 39#include <asm/machvec.h>
@@ -79,42 +80,41 @@ static srm_env_t srm_named_entries[] = {
79static srm_env_t srm_numbered_entries[256]; 80static srm_env_t srm_numbered_entries[256];
80 81
81 82
82static int 83static int srm_env_proc_show(struct seq_file *m, void *v)
83srm_env_read(char *page, char **start, off_t off, int count, int *eof,
84 void *data)
85{ 84{
86 int nbytes;
87 unsigned long ret; 85 unsigned long ret;
88 srm_env_t *entry; 86 srm_env_t *entry;
87 char *page;
89 88
90 if (off != 0) { 89 entry = (srm_env_t *)m->private;
91 *eof = 1; 90 page = (char *)__get_free_page(GFP_USER);
92 return 0; 91 if (!page)
93 } 92 return -ENOMEM;
94 93
95 entry = (srm_env_t *) data; 94 ret = callback_getenv(entry->id, page, PAGE_SIZE);
96 ret = callback_getenv(entry->id, page, count);
97 95
98 if ((ret >> 61) == 0) { 96 if ((ret >> 61) == 0) {
99 nbytes = (int) ret; 97 seq_write(m, page, ret);
100 *eof = 1; 98 ret = 0;
101 } else 99 } else
102 nbytes = -EFAULT; 100 ret = -EFAULT;
101 free_page((unsigned long)page);
102 return ret;
103}
103 104
104 return nbytes; 105static 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
107static int 110static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer,
108srm_env_write(struct file *file, const char __user *buffer, unsigned long count, 111 size_t count, loff_t *pos)
109 void *data)
110{ 112{
111 int res; 113 int res;
112 srm_env_t *entry; 114 srm_env_t *entry = PDE(file->f_path.dentry->d_inode)->data;
113 char *buf = (char *) __get_free_page(GFP_USER); 115 char *buf = (char *) __get_free_page(GFP_USER);
114 unsigned long ret1, ret2; 116 unsigned long ret1, ret2;
115 117
116 entry = (srm_env_t *) data;
117
118 if (!buf) 118 if (!buf)
119 return -ENOMEM; 119 return -ENOMEM;
120 120
@@ -140,6 +140,15 @@ srm_env_write(struct file *file, const char __user *buffer, unsigned long count,
140 return res; 140 return res;
141} 141}
142 142
143static 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
143static void 152static void
144srm_env_cleanup(void) 153srm_env_cleanup(void)
145{ 154{
@@ -245,15 +254,10 @@ srm_env_init(void)
245 */ 254 */
246 entry = srm_named_entries; 255 entry = srm_named_entries;
247 while (entry->name && entry->id) { 256 while (entry->name && entry->id) {
248 entry->proc_entry = create_proc_entry(entry->name, 257 entry->proc_entry = proc_create_data(entry->name, 0644, named_dir,
249 0644, named_dir); 258 &srm_env_proc_fops, entry);
250 if (!entry->proc_entry) 259 if (!entry->proc_entry)
251 goto cleanup; 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 entry++; 261 entry++;
258 } 262 }
259 263
@@ -264,15 +268,12 @@ srm_env_init(void)
264 entry = &srm_numbered_entries[var_num]; 268 entry = &srm_numbered_entries[var_num];
265 entry->name = number[var_num]; 269 entry->name = number[var_num];
266 270
267 entry->proc_entry = create_proc_entry(entry->name, 271 entry->proc_entry = proc_create_data(entry->name, 0644, numbered_dir,
268 0644, numbered_dir); 272 &srm_env_proc_fops, entry);
269 if (!entry->proc_entry) 273 if (!entry->proc_entry)
270 goto cleanup; 274 goto cleanup;
271 275
272 entry->id = var_num; 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 printk(KERN_INFO "%s: version %s loaded successfully\n", NAME, 279 printk(KERN_INFO "%s: version %s loaded successfully\n", NAME,