Import 2.3.48
[davej-history.git] / fs / proc / proc_misc.c
blobdb58636722fe4f304ebed3003ba6d441adaab183
1 /*
2 * linux/fs/proc/proc_misc.c
4 * linux/fs/proc/array.c
5 * Copyright (C) 1992 by Linus Torvalds
6 * based on ideas by Darren Senn
8 * This used to be the part of array.c. See the rest of history and credits
9 * there. I took this into a separate file and switched the thing to generic
10 * proc_file_inode_operations, leaving in array.c only per-process stuff.
11 * Inumbers allocation made dynamic (via create_proc_entry()). AV, May 1999.
14 #include <linux/types.h>
15 #include <linux/errno.h>
16 #include <linux/sched.h>
17 #include <linux/kernel.h>
18 #include <linux/kernel_stat.h>
19 #include <linux/tty.h>
20 #include <linux/string.h>
21 #include <linux/mman.h>
22 #include <linux/proc_fs.h>
23 #include <linux/ioport.h>
24 #include <linux/config.h>
25 #include <linux/mm.h>
26 #include <linux/pagemap.h>
27 #include <linux/swap.h>
28 #include <linux/slab.h>
29 #include <linux/smp.h>
30 #include <linux/signal.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
34 #include <asm/uaccess.h>
35 #include <asm/pgtable.h>
36 #include <asm/io.h>
39 #define LOAD_INT(x) ((x) >> FSHIFT)
40 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
42 * Warning: stuff below (imported functions) assumes that its output will fit
43 * into one page. For some of those functions it may be wrong. Moreover, we
44 * have a way to deal with that gracefully. Right now I used straightforward
45 * wrappers, but this needs further analysis wrt potential overflows.
47 extern int get_cpuinfo(char *);
48 extern int get_hardware_list(char *);
49 extern int get_stram_list(char *);
50 #ifdef CONFIG_DEBUG_MALLOC
51 extern int get_malloc(char * buffer);
52 #endif
53 #ifdef CONFIG_MODULES
54 extern int get_module_list(char *);
55 extern int get_ksyms_list(char *, char **, off_t, int);
56 #endif
57 extern int get_device_list(char *);
58 extern int get_partition_list(char *);
59 extern int get_filesystem_list(char *);
60 extern int get_filesystem_info(char *);
61 extern int get_exec_domain_list(char *);
62 extern int get_irq_list(char *);
63 extern int get_dma_list(char *);
64 extern int get_locks_status (char *, char **, off_t, int);
65 extern int get_swaparea_info (char *);
66 #ifdef CONFIG_SGI_DS1286
67 extern int get_ds1286_status(char *);
68 #endif
70 static int loadavg_read_proc(char *page, char **start, off_t off,
71 int count, int *eof, void *data)
73 int a, b, c;
74 int len;
76 a = avenrun[0] + (FIXED_1/200);
77 b = avenrun[1] + (FIXED_1/200);
78 c = avenrun[2] + (FIXED_1/200);
79 len = sprintf(page,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
80 LOAD_INT(a), LOAD_FRAC(a),
81 LOAD_INT(b), LOAD_FRAC(b),
82 LOAD_INT(c), LOAD_FRAC(c),
83 nr_running, nr_threads, last_pid);
84 if (len <= off+count) *eof = 1;
85 *start = page + off;
86 len -= off;
87 if (len>count) len = count;
88 if (len<0) len = 0;
89 return len;
92 static int uptime_read_proc(char *page, char **start, off_t off,
93 int count, int *eof, void *data)
95 unsigned long uptime;
96 unsigned long idle;
97 int len;
99 uptime = jiffies;
100 idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
102 /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
103 that would overflow about every five days at HZ == 100.
104 Therefore the identity a = (a / b) * b + a % b is used so that it is
105 calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
106 The part in front of the '+' always evaluates as 0 (mod 100). All divisions
107 in the above formulas are truncating. For HZ being a power of 10, the
108 calculations simplify to the version in the #else part (if the printf
109 format is adapted to the same number of digits as zeroes in HZ.
111 #if HZ!=100
112 len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
113 uptime / HZ,
114 (((uptime % HZ) * 100) / HZ) % 100,
115 idle / HZ,
116 (((idle % HZ) * 100) / HZ) % 100);
117 #else
118 len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
119 uptime / HZ,
120 uptime % HZ,
121 idle / HZ,
122 idle % HZ);
123 #endif
124 if (len <= off+count) *eof = 1;
125 *start = page + off;
126 len -= off;
127 if (len>count) len = count;
128 if (len<0) len = 0;
129 return len;
132 static int meminfo_read_proc(char *page, char **start, off_t off,
133 int count, int *eof, void *data)
135 struct sysinfo i;
136 int len;
139 * display in kilobytes.
141 #define K(x) ((x) << (PAGE_SHIFT - 10))
142 #define B(x) ((x) << PAGE_SHIFT)
143 si_meminfo(&i);
144 si_swapinfo(&i);
145 len = sprintf(page, " total: used: free: shared: buffers: cached:\n"
146 "Mem: %8lu %8lu %8lu %8lu %8lu %8u\n"
147 "Swap: %8lu %8lu %8lu\n",
148 B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
149 B(i.sharedram), B(i.bufferram),
150 B(atomic_read(&page_cache_size)), B(i.totalswap),
151 B(i.totalswap-i.freeswap), B(i.freeswap));
153 * Tagged format, for easy grepping and expansion.
154 * The above will go away eventually, once the tools
155 * have been updated.
157 len += sprintf(page+len,
158 "MemTotal: %8lu kB\n"
159 "MemFree: %8lu kB\n"
160 "MemShared: %8lu kB\n"
161 "Buffers: %8lu kB\n"
162 "Cached: %8u kB\n"
163 "HighTotal: %8lu kB\n"
164 "HighFree: %8lu kB\n"
165 "LowTotal: %8lu kB\n"
166 "LowFree: %8lu kB\n"
167 "SwapTotal: %8lu kB\n"
168 "SwapFree: %8lu kB\n",
169 K(i.totalram),
170 K(i.freeram),
171 K(i.sharedram),
172 K(i.bufferram),
173 K(atomic_read(&page_cache_size)),
174 K(i.totalhigh),
175 K(i.freehigh),
176 K(i.totalram-i.totalhigh),
177 K(i.freeram-i.freehigh),
178 K(i.totalswap),
179 K(i.freeswap));
181 if (len <= off+count) *eof = 1;
182 *start = page + off;
183 len -= off;
184 if (len>count) len = count;
185 if (len<0) len = 0;
186 return len;
187 #undef B
188 #undef K
191 static int version_read_proc(char *page, char **start, off_t off,
192 int count, int *eof, void *data)
194 extern char *linux_banner;
195 int len;
197 strcpy(page, linux_banner);
198 len = strlen(page);
199 if (len <= off+count) *eof = 1;
200 *start = page + off;
201 len -= off;
202 if (len>count) len = count;
203 if (len<0) len = 0;
204 return len;
207 static int cpuinfo_read_proc(char *page, char **start, off_t off,
208 int count, int *eof, void *data)
210 int len = get_cpuinfo(page);
211 if (len <= off+count) *eof = 1;
212 *start = page + off;
213 len -= off;
214 if (len>count) len = count;
215 if (len<0) len = 0;
216 return len;
219 #ifdef CONFIG_PROC_HARDWARE
220 static int hardware_read_proc(char *page, char **start, off_t off,
221 int count, int *eof, void *data)
223 int len = get_hardware_list(page);
224 if (len <= off+count) *eof = 1;
225 *start = page + off;
226 len -= off;
227 if (len>count) len = count;
228 if (len<0) len = 0;
229 return len;
231 #endif
233 #ifdef CONFIG_STRAM_PROC
234 static int stram_read_proc(char *page, char **start, off_t off,
235 int count, int *eof, void *data)
237 int len = get_stram_list(page);
238 if (len <= off+count) *eof = 1;
239 *start = page + off;
240 len -= off;
241 if (len>count) len = count;
242 if (len<0) len = 0;
243 return len;
245 #endif
247 #ifdef CONFIG_DEBUG_MALLOC
248 static int malloc_read_proc(char *page, char **start, off_t off,
249 int count, int *eof, void *data)
251 int len = get_malloc(page);
252 if (len <= off+count) *eof = 1;
253 *start = page + off;
254 len -= off;
255 if (len>count) len = count;
256 if (len<0) len = 0;
257 return len;
259 #endif
261 #ifdef CONFIG_MODULES
262 static int modules_read_proc(char *page, char **start, off_t off,
263 int count, int *eof, void *data)
265 int len = get_module_list(page);
266 if (len <= off+count) *eof = 1;
267 *start = page + off;
268 len -= off;
269 if (len>count) len = count;
270 if (len<0) len = 0;
271 return len;
274 static int ksyms_read_proc(char *page, char **start, off_t off,
275 int count, int *eof, void *data)
277 int len = get_ksyms_list(page, start, off, count);
278 if (len < count) *eof = 1;
279 return len;
281 #endif
283 static int kstat_read_proc(char *page, char **start, off_t off,
284 int count, int *eof, void *data)
286 int i, len;
287 unsigned sum = 0;
288 extern unsigned long total_forks;
289 unsigned long jif = jiffies;
291 for (i = 0 ; i < NR_IRQS ; i++)
292 sum += kstat_irqs(i);
294 #ifdef __SMP__
295 len = sprintf(page,
296 "cpu %u %u %u %lu\n",
297 kstat.cpu_user,
298 kstat.cpu_nice,
299 kstat.cpu_system,
300 jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
301 for (i = 0 ; i < smp_num_cpus; i++)
302 len += sprintf(page + len, "cpu%d %u %u %u %lu\n",
304 kstat.per_cpu_user[cpu_logical_map(i)],
305 kstat.per_cpu_nice[cpu_logical_map(i)],
306 kstat.per_cpu_system[cpu_logical_map(i)],
307 jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
308 + kstat.per_cpu_nice[cpu_logical_map(i)] \
309 + kstat.per_cpu_system[cpu_logical_map(i)]));
310 len += sprintf(page + len,
311 "disk %u %u %u %u\n"
312 "disk_rio %u %u %u %u\n"
313 "disk_wio %u %u %u %u\n"
314 "disk_rblk %u %u %u %u\n"
315 "disk_wblk %u %u %u %u\n"
316 "page %u %u\n"
317 "swap %u %u\n"
318 "intr %u",
319 #else
320 len = sprintf(page,
321 "cpu %u %u %u %lu\n"
322 "disk %u %u %u %u\n"
323 "disk_rio %u %u %u %u\n"
324 "disk_wio %u %u %u %u\n"
325 "disk_rblk %u %u %u %u\n"
326 "disk_wblk %u %u %u %u\n"
327 "page %u %u\n"
328 "swap %u %u\n"
329 "intr %u",
330 kstat.cpu_user,
331 kstat.cpu_nice,
332 kstat.cpu_system,
333 jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
334 #endif
335 kstat.dk_drive[0], kstat.dk_drive[1],
336 kstat.dk_drive[2], kstat.dk_drive[3],
337 kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
338 kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
339 kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
340 kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
341 kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
342 kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
343 kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
344 kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
345 kstat.pgpgin,
346 kstat.pgpgout,
347 kstat.pswpin,
348 kstat.pswpout,
349 sum);
350 for (i = 0 ; i < NR_IRQS ; i++)
351 len += sprintf(page + len, " %u", kstat_irqs(i));
352 len += sprintf(page + len,
353 "\nctxt %u\n"
354 "btime %lu\n"
355 "processes %lu\n",
356 kstat.context_swtch,
357 xtime.tv_sec - jif / HZ,
358 total_forks);
359 if (len <= off+count) *eof = 1;
360 *start = page + off;
361 len -= off;
362 if (len>count) len = count;
363 if (len<0) len = 0;
364 return len;
367 static int devices_read_proc(char *page, char **start, off_t off,
368 int count, int *eof, void *data)
370 int len = get_device_list(page);
371 if (len <= off+count) *eof = 1;
372 *start = page + off;
373 len -= off;
374 if (len>count) len = count;
375 if (len<0) len = 0;
376 return len;
379 static int partitions_read_proc(char *page, char **start, off_t off,
380 int count, int *eof, void *data)
382 int len = get_partition_list(page);
383 if (len <= off+count) *eof = 1;
384 *start = page + off;
385 len -= off;
386 if (len>count) len = count;
387 if (len<0) len = 0;
388 return len;
391 static int interrupts_read_proc(char *page, char **start, off_t off,
392 int count, int *eof, void *data)
394 int len = get_irq_list(page);
395 if (len <= off+count) *eof = 1;
396 *start = page + off;
397 len -= off;
398 if (len>count) len = count;
399 if (len<0) len = 0;
400 return len;
403 static int filesystems_read_proc(char *page, char **start, off_t off,
404 int count, int *eof, void *data)
406 int len = get_filesystem_list(page);
407 if (len <= off+count) *eof = 1;
408 *start = page + off;
409 len -= off;
410 if (len>count) len = count;
411 if (len<0) len = 0;
412 return len;
415 static int dma_read_proc(char *page, char **start, off_t off,
416 int count, int *eof, void *data)
418 int len = get_dma_list(page);
419 if (len <= off+count) *eof = 1;
420 *start = page + off;
421 len -= off;
422 if (len>count) len = count;
423 if (len<0) len = 0;
424 return len;
427 static int ioports_read_proc(char *page, char **start, off_t off,
428 int count, int *eof, void *data)
430 int len = get_ioport_list(page);
431 if (len <= off+count) *eof = 1;
432 *start = page + off;
433 len -= off;
434 if (len>count) len = count;
435 if (len<0) len = 0;
436 return len;
439 static int cmdline_read_proc(char *page, char **start, off_t off,
440 int count, int *eof, void *data)
442 extern char saved_command_line[];
443 int len;
445 len = sprintf(page, "%s\n", saved_command_line);
446 len = strlen(page);
447 if (len <= off+count) *eof = 1;
448 *start = page + off;
449 len -= off;
450 if (len>count) len = count;
451 if (len<0) len = 0;
452 return len;
455 #ifdef CONFIG_SGI_DS1286
456 static int ds1286_read_proc(char *page, char **start, off_t off,
457 int count, int *eof, void *data)
459 int len = get_ds1286_status(page);
460 if (len <= off+count) *eof = 1;
461 *start = page + off;
462 len -= off;
463 if (len>count) len = count;
464 if (len<0) len = 0;
465 return len;
467 #endif
469 static int locks_read_proc(char *page, char **start, off_t off,
470 int count, int *eof, void *data)
472 int len = get_locks_status(page, start, off, count);
473 if (len < count) *eof = 1;
474 return len;
477 static int mounts_read_proc(char *page, char **start, off_t off,
478 int count, int *eof, void *data)
480 int len = get_filesystem_info(page);
481 if (len <= off+count) *eof = 1;
482 *start = page + off;
483 len -= off;
484 if (len>count) len = count;
485 if (len<0) len = 0;
486 return len;
489 static int execdomains_read_proc(char *page, char **start, off_t off,
490 int count, int *eof, void *data)
492 int len = get_exec_domain_list(page);
493 if (len <= off+count) *eof = 1;
494 *start = page + off;
495 len -= off;
496 if (len>count) len = count;
497 if (len<0) len = 0;
498 return len;
501 static int swaps_read_proc(char *page, char **start, off_t off,
502 int count, int *eof, void *data)
504 int len = get_swaparea_info(page);
505 if (len <= off+count) *eof = 1;
506 *start = page + off;
507 len -= off;
508 if (len>count) len = count;
509 if (len<0) len = 0;
510 return len;
513 static int slabinfo_read_proc(char *page, char **start, off_t off,
514 int count, int *eof, void *data)
516 int len = get_slabinfo(page);
517 if (len <= off+count) *eof = 1;
518 *start = page + off;
519 len -= off;
520 if (len>count) len = count;
521 if (len<0) len = 0;
522 return len;
525 static int memory_read_proc(char *page, char **start, off_t off,
526 int count, int *eof, void *data)
528 int len = get_mem_list(page);
529 if (len <= off+count) *eof = 1;
530 *start = page + off;
531 len -= off;
532 if (len>count) len = count;
533 if (len<0) len = 0;
534 return len;
538 * This function accesses profiling information. The returned data is
539 * binary: the sampling step and the actual contents of the profile
540 * buffer. Use of the program readprofile is recommended in order to
541 * get meaningful info out of these data.
543 static ssize_t read_profile(struct file *file, char *buf,
544 size_t count, loff_t *ppos)
546 unsigned long p = *ppos;
547 ssize_t read;
548 char * pnt;
549 unsigned int sample_step = 1 << prof_shift;
551 if (p >= (prof_len+1)*sizeof(unsigned int))
552 return 0;
553 if (count > (prof_len+1)*sizeof(unsigned int) - p)
554 count = (prof_len+1)*sizeof(unsigned int) - p;
555 read = 0;
557 while (p < sizeof(unsigned int) && count > 0) {
558 put_user(*((char *)(&sample_step)+p),buf);
559 buf++; p++; count--; read++;
561 pnt = (char *)prof_buffer + p - sizeof(unsigned int);
562 copy_to_user(buf,(void *)pnt,count);
563 read += count;
564 *ppos += read;
565 return read;
569 * Writing to /proc/profile resets the counters
571 * Writing a 'profiling multiplier' value into it also re-sets the profiling
572 * interrupt frequency, on architectures that support this.
574 static ssize_t write_profile(struct file * file, const char * buf,
575 size_t count, loff_t *ppos)
577 #ifdef __SMP__
578 extern int setup_profiling_timer (unsigned int multiplier);
580 if (count==sizeof(int)) {
581 unsigned int multiplier;
583 if (copy_from_user(&multiplier, buf, sizeof(int)))
584 return -EFAULT;
586 if (setup_profiling_timer(multiplier))
587 return -EINVAL;
589 #endif
591 memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
592 return count;
595 static struct file_operations proc_profile_operations = {
596 read: read_profile,
597 write: write_profile,
600 struct proc_dir_entry *proc_root_kcore;
602 void __init proc_misc_init(void)
604 struct proc_dir_entry *entry;
605 static struct {
606 char *name;
607 int (*read_proc)(char*,char**,off_t,int,int*,void*);
608 } *p, simple_ones[] = {
609 {"loadavg", loadavg_read_proc},
610 {"uptime", uptime_read_proc},
611 {"meminfo", meminfo_read_proc},
612 {"version", version_read_proc},
613 {"cpuinfo", cpuinfo_read_proc},
614 #ifdef CONFIG_PROC_HARDWARE
615 {"hardware", hardware_read_proc},
616 #endif
617 #ifdef CONFIG_STRAM_PROC
618 {"stram", stram_read_proc},
619 #endif
620 #ifdef CONFIG_DEBUG_MALLOC
621 {"malloc", malloc_read_proc},
622 #endif
623 #ifdef CONFIG_MODULES
624 {"modules", modules_read_proc},
625 {"ksyms", ksyms_read_proc},
626 #endif
627 {"stat", kstat_read_proc},
628 {"devices", devices_read_proc},
629 {"partitions", partitions_read_proc},
630 {"interrupts", interrupts_read_proc},
631 {"filesystems", filesystems_read_proc},
632 {"dma", dma_read_proc},
633 {"ioports", ioports_read_proc},
634 {"cmdline", cmdline_read_proc},
635 #ifdef CONFIG_SGI_DS1286
636 {"rtc", ds1286_read_proc},
637 #endif
638 {"locks", locks_read_proc},
639 {"mounts", mounts_read_proc},
640 {"swaps", swaps_read_proc},
641 {"slabinfo", slabinfo_read_proc},
642 {"iomem", memory_read_proc},
643 {"execdomains", execdomains_read_proc},
644 {NULL,NULL}
646 for(p=simple_ones;p->name;p++)
647 create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
649 /* And now for trickier ones */
650 entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
651 if (entry)
652 entry->proc_fops = &proc_kmsg_operations;
653 proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
654 if (proc_root_kcore) {
655 proc_root_kcore->proc_fops = &proc_kcore_operations;
656 proc_root_kcore->size =
657 (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
659 if (prof_shift) {
660 entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
661 if (entry) {
662 entry->proc_fops = &proc_profile_operations;
663 entry->size = (1+prof_len) * sizeof(unsigned int);
666 #ifdef __powerpc__
667 entry = create_proc_entry("ppc_htab", S_IRUGO|S_IWUSR, NULL);
668 if (entry)
669 entry->proc_fops = &ppc_htab_operations;
670 #endif