diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2009-11-27 01:51:12 -0500 |
---|---|---|
committer | Kyle McMartin <kyle@mcmartin.ca> | 2009-12-15 22:48:55 -0500 |
commit | 217bfb5190813d97e6003f7692f8014655ffc02a (patch) | |
tree | b5eef7041fc0b3137be20505f9d07c2abaa3bfd5 /drivers/parisc/led.c | |
parent | 05920797ca4c55b3c0629bc0eeb6fe634c196952 (diff) |
parisc: convert /proc/pdc/{lcd,led} 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>
Reviewed-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>
Diffstat (limited to 'drivers/parisc/led.c')
-rw-r--r-- | drivers/parisc/led.c | 59 |
1 files changed, 29 insertions, 30 deletions
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 79caf1ca4a29..188bc8496a26 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/kernel_stat.h> | 38 | #include <linux/kernel_stat.h> |
39 | #include <linux/reboot.h> | 39 | #include <linux/reboot.h> |
40 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
41 | #include <linux/seq_file.h> | ||
41 | #include <linux/ctype.h> | 42 | #include <linux/ctype.h> |
42 | #include <linux/blkdev.h> | 43 | #include <linux/blkdev.h> |
43 | #include <linux/workqueue.h> | 44 | #include <linux/workqueue.h> |
@@ -147,41 +148,34 @@ device_initcall(start_task); | |||
147 | static void (*led_func_ptr) (unsigned char) __read_mostly; | 148 | static void (*led_func_ptr) (unsigned char) __read_mostly; |
148 | 149 | ||
149 | #ifdef CONFIG_PROC_FS | 150 | #ifdef CONFIG_PROC_FS |
150 | static int led_proc_read(char *page, char **start, off_t off, int count, | 151 | static int led_proc_show(struct seq_file *m, void *v) |
151 | int *eof, void *data) | ||
152 | { | 152 | { |
153 | char *out = page; | 153 | switch ((long)m->private) |
154 | int len; | ||
155 | |||
156 | switch ((long)data) | ||
157 | { | 154 | { |
158 | case LED_NOLCD: | 155 | case LED_NOLCD: |
159 | out += sprintf(out, "Heartbeat: %d\n", led_heartbeat); | 156 | seq_printf(m, "Heartbeat: %d\n", led_heartbeat); |
160 | out += sprintf(out, "Disk IO: %d\n", led_diskio); | 157 | seq_printf(m, "Disk IO: %d\n", led_diskio); |
161 | out += sprintf(out, "LAN Rx/Tx: %d\n", led_lanrxtx); | 158 | seq_printf(m, "LAN Rx/Tx: %d\n", led_lanrxtx); |
162 | break; | 159 | break; |
163 | case LED_HASLCD: | 160 | case LED_HASLCD: |
164 | out += sprintf(out, "%s\n", lcd_text); | 161 | seq_printf(m, "%s\n", lcd_text); |
165 | break; | 162 | break; |
166 | default: | 163 | default: |
167 | *eof = 1; | ||
168 | return 0; | 164 | return 0; |
169 | } | 165 | } |
166 | return 0; | ||
167 | } | ||
170 | 168 | ||
171 | len = out - page - off; | 169 | static int led_proc_open(struct inode *inode, struct file *file) |
172 | if (len < count) { | 170 | { |
173 | *eof = 1; | 171 | return single_open(file, led_proc_show, PDE(inode)->data); |
174 | if (len <= 0) return 0; | ||
175 | } else { | ||
176 | len = count; | ||
177 | } | ||
178 | *start = page + off; | ||
179 | return len; | ||
180 | } | 172 | } |
181 | 173 | ||
182 | static int led_proc_write(struct file *file, const char *buf, | 174 | |
183 | unsigned long count, void *data) | 175 | static ssize_t led_proc_write(struct file *file, const char *buf, |
176 | size_t count, loff_t *pos) | ||
184 | { | 177 | { |
178 | void *data = PDE(file->f_path.dentry->d_inode)->data; | ||
185 | char *cur, lbuf[count + 1]; | 179 | char *cur, lbuf[count + 1]; |
186 | int d; | 180 | int d; |
187 | 181 | ||
@@ -234,6 +228,15 @@ parse_error: | |||
234 | return -EINVAL; | 228 | return -EINVAL; |
235 | } | 229 | } |
236 | 230 | ||
231 | static const struct file_operations led_proc_fops = { | ||
232 | .owner = THIS_MODULE, | ||
233 | .open = led_proc_open, | ||
234 | .read = seq_read, | ||
235 | .llseek = seq_lseek, | ||
236 | .release = single_release, | ||
237 | .write = led_proc_write, | ||
238 | }; | ||
239 | |||
237 | static int __init led_create_procfs(void) | 240 | static int __init led_create_procfs(void) |
238 | { | 241 | { |
239 | struct proc_dir_entry *proc_pdc_root = NULL; | 242 | struct proc_dir_entry *proc_pdc_root = NULL; |
@@ -243,19 +246,15 @@ static int __init led_create_procfs(void) | |||
243 | 246 | ||
244 | proc_pdc_root = proc_mkdir("pdc", 0); | 247 | proc_pdc_root = proc_mkdir("pdc", 0); |
245 | if (!proc_pdc_root) return -1; | 248 | if (!proc_pdc_root) return -1; |
246 | ent = create_proc_entry("led", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root); | 249 | ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root, |
250 | &led_proc_fops, (void *)LED_NOLCD); /* LED */ | ||
247 | if (!ent) return -1; | 251 | if (!ent) return -1; |
248 | ent->data = (void *)LED_NOLCD; /* LED */ | ||
249 | ent->read_proc = led_proc_read; | ||
250 | ent->write_proc = led_proc_write; | ||
251 | 252 | ||
252 | if (led_type == LED_HASLCD) | 253 | if (led_type == LED_HASLCD) |
253 | { | 254 | { |
254 | ent = create_proc_entry("lcd", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root); | 255 | ent = proc_create_data("lcd", S_IRUGO|S_IWUSR, proc_pdc_root, |
256 | &led_proc_fops, (void *)LED_HASLCD); /* LCD */ | ||
255 | if (!ent) return -1; | 257 | if (!ent) return -1; |
256 | ent->data = (void *)LED_HASLCD; /* LCD */ | ||
257 | ent->read_proc = led_proc_read; | ||
258 | ent->write_proc = led_proc_write; | ||
259 | } | 258 | } |
260 | 259 | ||
261 | return 0; | 260 | return 0; |