This source file includes following definitions.
- read_core
- read_profile
- write_profile
- get_loadavg
- get_kstat
- get_uptime
- get_meminfo
- get_version
- get_cmdline
- get_task
- get_phys_addr
- get_array
- get_env
- get_arg
- get_wchan
- get_stat
- statm_pte_range
- statm_pmd_range
- statm_pgd_range
- get_statm
- read_maps
- get_root_array
- get_process_array
- fill_array
- array_read
- arraylong_read
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <linux/types.h>
31 #include <linux/errno.h>
32 #include <linux/sched.h>
33 #include <linux/kernel.h>
34 #include <linux/kernel_stat.h>
35 #include <linux/tty.h>
36 #include <linux/user.h>
37 #include <linux/a.out.h>
38 #include <linux/string.h>
39 #include <linux/mman.h>
40 #include <linux/proc_fs.h>
41 #include <linux/ioport.h>
42 #include <linux/config.h>
43 #include <linux/mm.h>
44 #include <linux/pagemap.h>
45 #ifdef CONFIG_APM
46 #include <linux/apm_bios.h>
47 #endif
48 #include <linux/swap.h>
49
50 #include <asm/segment.h>
51 #include <asm/pgtable.h>
52 #include <asm/io.h>
53
54 #define LOAD_INT(x) ((x) >> FSHIFT)
55 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
56
57 #ifdef CONFIG_DEBUG_MALLOC
58 int get_malloc(char * buffer);
59 #endif
60
61
62 static int read_core(struct inode * inode, struct file * file,char * buf, int count)
63 {
64 unsigned long p = file->f_pos, memsize;
65 int read;
66 int count1;
67 char * pnt;
68 struct user dump;
69 #ifdef __i386__
70 # define FIRST_MAPPED PAGE_SIZE
71 #else
72 # define FIRST_MAPPED 0
73 #endif
74
75 memset(&dump, 0, sizeof(struct user));
76 dump.magic = CMAGIC;
77 dump.u_dsize = MAP_NR(high_memory);
78 #ifdef __alpha__
79 dump.start_data = PAGE_OFFSET;
80 #endif
81
82 if (count < 0)
83 return -EINVAL;
84 memsize = MAP_NR(high_memory + PAGE_SIZE) << PAGE_SHIFT;
85 if (p >= memsize)
86 return 0;
87 if (count > memsize - p)
88 count = memsize - p;
89 read = 0;
90
91 if (p < sizeof(struct user) && count > 0) {
92 count1 = count;
93 if (p + count1 > sizeof(struct user))
94 count1 = sizeof(struct user)-p;
95 pnt = (char *) &dump + p;
96 memcpy_tofs(buf,(void *) pnt, count1);
97 buf += count1;
98 p += count1;
99 count -= count1;
100 read += count1;
101 }
102
103 while (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) {
104 put_user(0,buf);
105 buf++;
106 p++;
107 count--;
108 read++;
109 }
110 memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count);
111 read += count;
112 file->f_pos += read;
113 return read;
114 }
115
116 static struct file_operations proc_kcore_operations = {
117 NULL,
118 read_core,
119 };
120
121 struct inode_operations proc_kcore_inode_operations = {
122 &proc_kcore_operations,
123 };
124
125
126
127
128
129
130
131
132 static int read_profile(struct inode *inode, struct file *file, char *buf, int count)
133 {
134 unsigned long p = file->f_pos;
135 int read;
136 char * pnt;
137 unsigned int sample_step = 1 << prof_shift;
138
139 if (count < 0)
140 return -EINVAL;
141 if (p >= (prof_len+1)*sizeof(unsigned int))
142 return 0;
143 if (count > (prof_len+1)*sizeof(unsigned int) - p)
144 count = (prof_len+1)*sizeof(unsigned int) - p;
145 read = 0;
146
147 while (p < sizeof(unsigned int) && count > 0) {
148 put_user(*((char *)(&sample_step)+p),buf);
149 buf++; p++; count--; read++;
150 }
151 pnt = (char *)prof_buffer + p - sizeof(unsigned int);
152 memcpy_tofs(buf,(void *)pnt,count);
153 read += count;
154 file->f_pos += read;
155 return read;
156 }
157
158
159 static int write_profile(struct inode * inode, struct file * file, const char * buf, int count)
160 {
161 int i=prof_len;
162
163 while (i--)
164 prof_buffer[i]=0UL;
165 return count;
166 }
167
168 static struct file_operations proc_profile_operations = {
169 NULL,
170 read_profile,
171 write_profile,
172 };
173
174 struct inode_operations proc_profile_inode_operations = {
175 &proc_profile_operations,
176 };
177
178
179 static int get_loadavg(char * buffer)
180 {
181 int a, b, c;
182
183 a = avenrun[0] + (FIXED_1/200);
184 b = avenrun[1] + (FIXED_1/200);
185 c = avenrun[2] + (FIXED_1/200);
186 return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d\n",
187 LOAD_INT(a), LOAD_FRAC(a),
188 LOAD_INT(b), LOAD_FRAC(b),
189 LOAD_INT(c), LOAD_FRAC(c),
190 nr_running, nr_tasks);
191 }
192
193 static int get_kstat(char * buffer)
194 {
195 int i, len;
196 unsigned sum = 0;
197
198 for (i = 0 ; i < NR_IRQS ; i++)
199 sum += kstat.interrupts[i];
200 len = sprintf(buffer,
201 "cpu %u %u %u %lu\n"
202 "disk %u %u %u %u\n"
203 "disk_rio %u %u %u %u\n"
204 "disk_wio %u %u %u %u\n"
205 "disk_rblk %u %u %u %u\n"
206 "disk_wblk %u %u %u %u\n"
207 "page %u %u\n"
208 "swap %u %u\n"
209 "intr %u",
210 kstat.cpu_user,
211 kstat.cpu_nice,
212 kstat.cpu_system,
213 jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
214 kstat.dk_drive[0], kstat.dk_drive[1],
215 kstat.dk_drive[2], kstat.dk_drive[3],
216 kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
217 kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
218 kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
219 kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
220 kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
221 kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
222 kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
223 kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
224 kstat.pgpgin,
225 kstat.pgpgout,
226 kstat.pswpin,
227 kstat.pswpout,
228 sum);
229 for (i = 0 ; i < NR_IRQS ; i++)
230 len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
231 len += sprintf(buffer + len,
232 "\nctxt %u\n"
233 "btime %lu\n",
234 kstat.context_swtch,
235 xtime.tv_sec - jiffies / HZ);
236 return len;
237 }
238
239
240 static int get_uptime(char * buffer)
241 {
242 unsigned long uptime;
243 unsigned long idle;
244
245 uptime = jiffies;
246 idle = task[0]->utime + task[0]->stime;
247
248
249
250
251
252
253
254
255
256
257 #if HZ!=100
258 return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
259 uptime / HZ,
260 (((uptime % HZ) * 100) / HZ) % 100,
261 idle / HZ,
262 (((idle % HZ) * 100) / HZ) % 100);
263 #else
264 return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
265 uptime / HZ,
266 uptime % HZ,
267 idle / HZ,
268 idle % HZ);
269 #endif
270 }
271
272 static int get_meminfo(char * buffer)
273 {
274 struct sysinfo i;
275
276 si_meminfo(&i);
277 si_swapinfo(&i);
278 return sprintf(buffer, " total: used: free: shared: buffers: cached:\n"
279 "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n"
280 "Swap: %8lu %8lu %8lu\n",
281 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE,
282 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
283 }
284
285 static int get_version(char * buffer)
286 {
287 extern char *linux_banner;
288
289 strcpy(buffer, linux_banner);
290 return strlen(buffer);
291 }
292
293 static int get_cmdline(char * buffer)
294 {
295 extern char saved_command_line[];
296
297 return sprintf(buffer, "%s\n", saved_command_line);
298 }
299
300 static struct task_struct ** get_task(pid_t pid)
301 {
302 struct task_struct ** p;
303
304 p = task;
305 while (++p < task+NR_TASKS) {
306 if (*p && (*p)->pid == pid)
307 return p;
308 }
309 return NULL;
310 }
311
312 static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
313 {
314 pgd_t *page_dir;
315 pmd_t *page_middle;
316 pte_t pte;
317
318 if (!p || !p->mm || ptr >= TASK_SIZE)
319 return 0;
320 page_dir = pgd_offset(p->mm,ptr);
321 if (pgd_none(*page_dir))
322 return 0;
323 if (pgd_bad(*page_dir)) {
324 printk("bad page directory entry %08lx\n", pgd_val(*page_dir));
325 pgd_clear(page_dir);
326 return 0;
327 }
328 page_middle = pmd_offset(page_dir,ptr);
329 if (pmd_none(*page_middle))
330 return 0;
331 if (pmd_bad(*page_middle)) {
332 printk("bad page middle entry %08lx\n", pmd_val(*page_middle));
333 pmd_clear(page_middle);
334 return 0;
335 }
336 pte = *pte_offset(page_middle,ptr);
337 if (!pte_present(pte))
338 return 0;
339 return pte_page(pte) + (ptr & ~PAGE_MASK);
340 }
341
342 static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
343 {
344 unsigned long addr;
345 int size = 0, result = 0;
346 char c;
347
348 if (start >= end)
349 return result;
350 for (;;) {
351 addr = get_phys_addr(*p, start);
352 if (!addr)
353 goto ready;
354 do {
355 c = *(char *) addr;
356 if (!c)
357 result = size;
358 if (size < PAGE_SIZE)
359 buffer[size++] = c;
360 else
361 goto ready;
362 addr++;
363 start++;
364 if (!c && start >= end)
365 goto ready;
366 } while (addr & ~PAGE_MASK);
367 }
368 ready:
369
370 while (result>0 && buffer[result-1]==' ')
371 result--;
372 return result;
373 }
374
375 static int get_env(int pid, char * buffer)
376 {
377 struct task_struct ** p = get_task(pid);
378
379 if (!p || !*p || !(*p)->mm)
380 return 0;
381 return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer);
382 }
383
384 static int get_arg(int pid, char * buffer)
385 {
386 struct task_struct ** p = get_task(pid);
387
388 if (!p || !*p || !(*p)->mm)
389 return 0;
390 return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer);
391 }
392
393 static unsigned long get_wchan(struct task_struct *p)
394 {
395 if (!p || p == current || p->state == TASK_RUNNING)
396 return 0;
397 #if defined(__i386__)
398 {
399 unsigned long ebp, eip;
400 unsigned long stack_page;
401 int count = 0;
402
403 stack_page = p->kernel_stack_page;
404 if (!stack_page)
405 return 0;
406 ebp = p->tss.ebp;
407 do {
408 if (ebp < stack_page || ebp >= 4092+stack_page)
409 return 0;
410 eip = *(unsigned long *) (ebp+4);
411 if ((void *)eip != sleep_on &&
412 (void *)eip != interruptible_sleep_on)
413 return eip;
414 ebp = *(unsigned long *) ebp;
415 } while (count++ < 16);
416 }
417 #elif defined(__alpha__)
418
419
420
421
422
423
424
425
426
427 {
428 unsigned long schedule_frame;
429 unsigned long pc;
430
431 pc = thread_saved_pc(&p->tss);
432 if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
433 schedule_frame = ((unsigned long *)p->tss.ksp)[6];
434 return ((unsigned long *)schedule_frame)[12];
435 }
436 return pc;
437 }
438 #endif
439 return 0;
440 }
441
442 #if defined(__i386__)
443 # define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019])
444 # define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022])
445 #elif defined(__alpha__)
446
447
448
449 # define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
450 + (long)&((struct pt_regs *)0)->reg)
451 # define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
452 # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
453 #endif
454
455 static int get_stat(int pid, char * buffer)
456 {
457 struct task_struct ** p = get_task(pid), *tsk;
458 unsigned long sigignore=0, sigcatch=0, wchan;
459 unsigned long vsize, eip, esp;
460 long priority, nice;
461 int i,tty_pgrp;
462 char state;
463
464 if (!p || (tsk = *p) == NULL)
465 return 0;
466 if (tsk->state < 0 || tsk->state > 5)
467 state = '.';
468 else
469 state = "RSDZTW"[tsk->state];
470 vsize = eip = esp = 0;
471 if (tsk->mm && tsk->mm != &init_mm) {
472 struct vm_area_struct *vma = tsk->mm->mmap;
473 while (vma) {
474 vsize += vma->vm_end - vma->vm_start;
475 vma = vma->vm_next;
476 }
477 if (tsk->kernel_stack_page) {
478 eip = KSTK_EIP(tsk);
479 esp = KSTK_ESP(tsk);
480 }
481 }
482 wchan = get_wchan(tsk);
483 if (tsk->sig) {
484 unsigned long bit = 1;
485 for(i=0; i<32; ++i) {
486 switch((unsigned long) tsk->sig->action[i].sa_handler) {
487 case 0:
488 break;
489 case 1:
490 sigignore |= bit;
491 break;
492 default:
493 sigcatch |= bit;
494 }
495 bit <<= 1;
496 }
497 }
498 if (tsk->tty)
499 tty_pgrp = tsk->tty->pgrp;
500 else
501 tty_pgrp = -1;
502
503
504
505 priority = tsk->counter;
506 priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
507 nice = tsk->priority;
508 nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
509
510 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
511 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu \
512 %lu %lu %lu %lu\n",
513 pid,
514 tsk->comm,
515 state,
516 tsk->p_pptr->pid,
517 tsk->pgrp,
518 tsk->session,
519 tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
520 tty_pgrp,
521 tsk->flags,
522 tsk->min_flt,
523 tsk->cmin_flt,
524 tsk->maj_flt,
525 tsk->cmaj_flt,
526 tsk->utime,
527 tsk->stime,
528 tsk->cutime,
529 tsk->cstime,
530 priority,
531 nice,
532 tsk->timeout,
533 tsk->it_real_value,
534 tsk->start_time,
535 vsize,
536 tsk->mm ? tsk->mm->rss : 0,
537 tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
538 tsk->mm ? tsk->mm->start_code : 0,
539 tsk->mm ? tsk->mm->end_code : 0,
540 tsk->mm ? tsk->mm->start_stack : 0,
541 esp,
542 eip,
543 tsk->signal,
544 tsk->blocked,
545 sigignore,
546 sigcatch,
547 wchan);
548 }
549
550 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
551 int * pages, int * shared, int * dirty, int * total)
552 {
553 pte_t * pte;
554 unsigned long end;
555
556 if (pmd_none(*pmd))
557 return;
558 if (pmd_bad(*pmd)) {
559 printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
560 pmd_clear(pmd);
561 return;
562 }
563 pte = pte_offset(pmd, address);
564 address &= ~PMD_MASK;
565 end = address + size;
566 if (end > PMD_SIZE)
567 end = PMD_SIZE;
568 do {
569 pte_t page = *pte;
570
571 address += PAGE_SIZE;
572 pte++;
573 if (pte_none(page))
574 continue;
575 ++*total;
576 if (!pte_present(page))
577 continue;
578 ++*pages;
579 if (pte_dirty(page))
580 ++*dirty;
581 if (pte_page(page) >= high_memory)
582 continue;
583 if (mem_map[MAP_NR(pte_page(page))].count > 1)
584 ++*shared;
585 } while (address < end);
586 }
587
588 static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
589 int * pages, int * shared, int * dirty, int * total)
590 {
591 pmd_t * pmd;
592 unsigned long end;
593
594 if (pgd_none(*pgd))
595 return;
596 if (pgd_bad(*pgd)) {
597 printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
598 pgd_clear(pgd);
599 return;
600 }
601 pmd = pmd_offset(pgd, address);
602 address &= ~PGDIR_MASK;
603 end = address + size;
604 if (end > PGDIR_SIZE)
605 end = PGDIR_SIZE;
606 do {
607 statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
608 address = (address + PMD_SIZE) & PMD_MASK;
609 pmd++;
610 } while (address < end);
611 }
612
613 static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
614 int * pages, int * shared, int * dirty, int * total)
615 {
616 while (address < end) {
617 statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
618 address = (address + PGDIR_SIZE) & PGDIR_MASK;
619 pgd++;
620 }
621 }
622
623 static int get_statm(int pid, char * buffer)
624 {
625 struct task_struct ** p = get_task(pid), *tsk;
626 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
627
628 if (!p || (tsk = *p) == NULL)
629 return 0;
630 if (tsk->mm && tsk->mm != &init_mm) {
631 struct vm_area_struct * vma = tsk->mm->mmap;
632
633 while (vma) {
634 pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
635 int pages = 0, shared = 0, dirty = 0, total = 0;
636
637 statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
638 resident += pages;
639 share += shared;
640 dt += dirty;
641 size += total;
642 if (vma->vm_flags & VM_EXECUTABLE)
643 trs += pages;
644 else if (vma->vm_flags & VM_GROWSDOWN)
645 drs += pages;
646 else if (vma->vm_end > 0x60000000)
647 lrs += pages;
648 else
649 drs += pages;
650 vma = vma->vm_next;
651 }
652 }
653 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
654 size, resident, share, trs, lrs, drs, dt);
655 }
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673 #define MAPS_LINE_LENGTH 1024
674 #define MAPS_LINE_SHIFT 10
675
676
677
678
679 #define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %02x:%02x %lu\n"
680 #define MAPS_LINE_MAX 49
681
682 static int read_maps (int pid, struct file * file, char * buf, int count)
683 {
684 struct task_struct ** p = get_task(pid);
685 char * destptr;
686 loff_t lineno;
687 int column;
688 struct vm_area_struct * map;
689 int i;
690
691 if (!p || !*p)
692 return -EINVAL;
693
694 if (!(*p)->mm || (*p)->mm == &init_mm || count == 0)
695 return 0;
696
697
698 lineno = file->f_pos >> MAPS_LINE_SHIFT;
699 column = file->f_pos & (MAPS_LINE_LENGTH-1);
700
701
702 for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
703 continue;
704
705 destptr = buf;
706
707 for ( ; map ; ) {
708
709 char line[MAPS_LINE_MAX+1];
710 char str[5], *cp = str;
711 int flags;
712 kdev_t dev;
713 unsigned long ino;
714 int len;
715
716 flags = map->vm_flags;
717
718 *cp++ = flags & VM_READ ? 'r' : '-';
719 *cp++ = flags & VM_WRITE ? 'w' : '-';
720 *cp++ = flags & VM_EXEC ? 'x' : '-';
721 *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
722 *cp++ = 0;
723
724 if (map->vm_inode != NULL) {
725 dev = map->vm_inode->i_dev;
726 ino = map->vm_inode->i_ino;
727 } else {
728 dev = 0;
729 ino = 0;
730 }
731
732 len = sprintf(line, MAPS_LINE_FORMAT,
733 map->vm_start, map->vm_end, str, map->vm_offset,
734 MAJOR(dev),MINOR(dev), ino);
735
736 if (column >= len) {
737 column = 0;
738 lineno++;
739 map = map->vm_next;
740 continue;
741 }
742
743 i = len-column;
744 if (i > count)
745 i = count;
746 memcpy_tofs(destptr, line+column, i);
747 destptr += i; count -= i;
748 column += i;
749 if (column >= len) {
750 column = 0;
751 lineno++;
752 map = map->vm_next;
753 }
754
755
756 if (count == 0)
757 break;
758
759
760
761
762 if (*p != current)
763 break;
764 }
765
766
767 file->f_pos = (lineno << MAPS_LINE_SHIFT) + column;
768
769 return destptr-buf;
770 }
771
772 #ifdef CONFIG_MODULES
773 extern int get_module_list(char *);
774 extern int get_ksyms_list(char *, char **, off_t, int);
775 #endif
776 extern int get_device_list(char *);
777 extern int get_filesystem_list(char *);
778 extern int get_irq_list(char *);
779 extern int get_dma_list(char *);
780 extern int get_cpuinfo(char *);
781 extern int get_pci_list(char*);
782 #ifdef __SMP_PROF__
783 extern int get_smp_prof_list(char *);
784 #endif
785
786 static int get_root_array(char * page, int type, char **start, off_t offset, int length)
787 {
788 switch (type) {
789 case PROC_LOADAVG:
790 return get_loadavg(page);
791
792 case PROC_UPTIME:
793 return get_uptime(page);
794
795 case PROC_MEMINFO:
796 return get_meminfo(page);
797
798 #ifdef CONFIG_PCI
799 case PROC_PCI:
800 return get_pci_list(page);
801 #endif
802
803 case PROC_CPUINFO:
804 return get_cpuinfo(page);
805
806 case PROC_VERSION:
807 return get_version(page);
808
809 #ifdef CONFIG_DEBUG_MALLOC
810 case PROC_MALLOC:
811 return get_malloc(page);
812 #endif
813
814 #ifdef CONFIG_MODULES
815 case PROC_MODULES:
816 return get_module_list(page);
817
818 case PROC_KSYMS:
819 return get_ksyms_list(page, start, offset, length);
820 #endif
821
822 case PROC_STAT:
823 return get_kstat(page);
824
825 case PROC_DEVICES:
826 return get_device_list(page);
827
828 case PROC_INTERRUPTS:
829 return get_irq_list(page);
830
831 case PROC_FILESYSTEMS:
832 return get_filesystem_list(page);
833
834 case PROC_DMA:
835 return get_dma_list(page);
836
837 case PROC_IOPORTS:
838 return get_ioport_list(page);
839 #ifdef CONFIG_APM
840 case PROC_APM:
841 return apm_proc(page);
842 #endif
843 #ifdef __SMP_PROF__
844 case PROC_SMP_PROF:
845 return get_smp_prof_list(page);
846 #endif
847 case PROC_CMDLINE:
848 return get_cmdline(page);
849 }
850 return -EBADF;
851 }
852
853 static int get_process_array(char * page, int pid, int type)
854 {
855 switch (type) {
856 case PROC_PID_ENVIRON:
857 return get_env(pid, page);
858 case PROC_PID_CMDLINE:
859 return get_arg(pid, page);
860 case PROC_PID_STAT:
861 return get_stat(pid, page);
862 case PROC_PID_STATM:
863 return get_statm(pid, page);
864 }
865 return -EBADF;
866 }
867
868
869 static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
870 {
871 if (pid)
872 return get_process_array(page, pid, type);
873 return get_root_array(page, type, start, offset, length);
874 }
875
876 #define PROC_BLOCK_SIZE (3*1024)
877
878 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
879 {
880 unsigned long page;
881 char *start;
882 int length;
883 int end;
884 unsigned int type, pid;
885
886 if (count < 0)
887 return -EINVAL;
888 if (count > PROC_BLOCK_SIZE)
889 count = PROC_BLOCK_SIZE;
890 if (!(page = __get_free_page(GFP_KERNEL)))
891 return -ENOMEM;
892 type = inode->i_ino;
893 pid = type >> 16;
894 type &= 0x0000ffff;
895 start = NULL;
896 length = fill_array((char *) page, pid, type,
897 &start, file->f_pos, count);
898 if (length < 0) {
899 free_page(page);
900 return length;
901 }
902 if (start != NULL) {
903
904 memcpy_tofs(buf, start, length);
905 file->f_pos += length;
906 count = length;
907 } else {
908
909 if (file->f_pos >= length) {
910 free_page(page);
911 return 0;
912 }
913 if (count + file->f_pos > length)
914 count = length - file->f_pos;
915 end = count + file->f_pos;
916 memcpy_tofs(buf, (char *) page + file->f_pos, count);
917 file->f_pos = end;
918 }
919 free_page(page);
920 return count;
921 }
922
923 static struct file_operations proc_array_operations = {
924 NULL,
925 array_read,
926 NULL,
927 NULL,
928 NULL,
929 NULL,
930 NULL,
931 NULL,
932 NULL,
933 NULL
934 };
935
936 struct inode_operations proc_array_inode_operations = {
937 &proc_array_operations,
938 NULL,
939 NULL,
940 NULL,
941 NULL,
942 NULL,
943 NULL,
944 NULL,
945 NULL,
946 NULL,
947 NULL,
948 NULL,
949 NULL,
950 NULL,
951 NULL,
952 NULL,
953 NULL
954 };
955
956 static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
957 {
958 unsigned int pid = inode->i_ino >> 16;
959 unsigned int type = inode->i_ino & 0x0000ffff;
960
961 if (count < 0)
962 return -EINVAL;
963
964 switch (type) {
965 case PROC_PID_MAPS:
966 return read_maps(pid, file, buf, count);
967 }
968 return -EINVAL;
969 }
970
971 static struct file_operations proc_arraylong_operations = {
972 NULL,
973 arraylong_read,
974 NULL,
975 NULL,
976 NULL,
977 NULL,
978 NULL,
979 NULL,
980 NULL,
981 NULL
982 };
983
984 struct inode_operations proc_arraylong_inode_operations = {
985 &proc_arraylong_operations,
986 NULL,
987 NULL,
988 NULL,
989 NULL,
990 NULL,
991 NULL,
992 NULL,
993 NULL,
994 NULL,
995 NULL,
996 NULL,
997 NULL,
998 NULL,
999 NULL,
1000 NULL,
1001 NULL
1002 };