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_filesystem_info( char * );
779 extern int get_irq_list(char *);
780 extern int get_dma_list(char *);
781 extern int get_cpuinfo(char *);
782 extern int get_pci_list(char*);
783 #ifdef __SMP_PROF__
784 extern int get_smp_prof_list(char *);
785 #endif
786
787 static int get_root_array(char * page, int type, char **start, off_t offset, int length)
788 {
789 switch (type) {
790 case PROC_LOADAVG:
791 return get_loadavg(page);
792
793 case PROC_UPTIME:
794 return get_uptime(page);
795
796 case PROC_MEMINFO:
797 return get_meminfo(page);
798
799 #ifdef CONFIG_PCI
800 case PROC_PCI:
801 return get_pci_list(page);
802 #endif
803
804 case PROC_CPUINFO:
805 return get_cpuinfo(page);
806
807 case PROC_VERSION:
808 return get_version(page);
809
810 #ifdef CONFIG_DEBUG_MALLOC
811 case PROC_MALLOC:
812 return get_malloc(page);
813 #endif
814
815 #ifdef CONFIG_MODULES
816 case PROC_MODULES:
817 return get_module_list(page);
818
819 case PROC_KSYMS:
820 return get_ksyms_list(page, start, offset, length);
821 #endif
822
823 case PROC_STAT:
824 return get_kstat(page);
825
826 case PROC_DEVICES:
827 return get_device_list(page);
828
829 case PROC_INTERRUPTS:
830 return get_irq_list(page);
831
832 case PROC_FILESYSTEMS:
833 return get_filesystem_list(page);
834
835 case PROC_DMA:
836 return get_dma_list(page);
837
838 case PROC_IOPORTS:
839 return get_ioport_list(page);
840 #ifdef CONFIG_APM
841 case PROC_APM:
842 return apm_proc(page);
843 #endif
844 #ifdef __SMP_PROF__
845 case PROC_SMP_PROF:
846 return get_smp_prof_list(page);
847 #endif
848 case PROC_CMDLINE:
849 return get_cmdline(page);
850
851 case PROC_MTAB:
852 return get_filesystem_info( page );
853 }
854 return -EBADF;
855 }
856
857 static int get_process_array(char * page, int pid, int type)
858 {
859 switch (type) {
860 case PROC_PID_ENVIRON:
861 return get_env(pid, page);
862 case PROC_PID_CMDLINE:
863 return get_arg(pid, page);
864 case PROC_PID_STAT:
865 return get_stat(pid, page);
866 case PROC_PID_STATM:
867 return get_statm(pid, page);
868 }
869 return -EBADF;
870 }
871
872
873 static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
874 {
875 if (pid)
876 return get_process_array(page, pid, type);
877 return get_root_array(page, type, start, offset, length);
878 }
879
880 #define PROC_BLOCK_SIZE (3*1024)
881
882 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
883 {
884 unsigned long page;
885 char *start;
886 int length;
887 int end;
888 unsigned int type, pid;
889
890 if (count < 0)
891 return -EINVAL;
892 if (count > PROC_BLOCK_SIZE)
893 count = PROC_BLOCK_SIZE;
894 if (!(page = __get_free_page(GFP_KERNEL)))
895 return -ENOMEM;
896 type = inode->i_ino;
897 pid = type >> 16;
898 type &= 0x0000ffff;
899 start = NULL;
900 length = fill_array((char *) page, pid, type,
901 &start, file->f_pos, count);
902 if (length < 0) {
903 free_page(page);
904 return length;
905 }
906 if (start != NULL) {
907
908 memcpy_tofs(buf, start, length);
909 file->f_pos += length;
910 count = length;
911 } else {
912
913 if (file->f_pos >= length) {
914 free_page(page);
915 return 0;
916 }
917 if (count + file->f_pos > length)
918 count = length - file->f_pos;
919 end = count + file->f_pos;
920 memcpy_tofs(buf, (char *) page + file->f_pos, count);
921 file->f_pos = end;
922 }
923 free_page(page);
924 return count;
925 }
926
927 static struct file_operations proc_array_operations = {
928 NULL,
929 array_read,
930 NULL,
931 NULL,
932 NULL,
933 NULL,
934 NULL,
935 NULL,
936 NULL,
937 NULL
938 };
939
940 struct inode_operations proc_array_inode_operations = {
941 &proc_array_operations,
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 NULL,
955 NULL,
956 NULL,
957 NULL
958 };
959
960 static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
961 {
962 unsigned int pid = inode->i_ino >> 16;
963 unsigned int type = inode->i_ino & 0x0000ffff;
964
965 if (count < 0)
966 return -EINVAL;
967
968 switch (type) {
969 case PROC_PID_MAPS:
970 return read_maps(pid, file, buf, count);
971 }
972 return -EINVAL;
973 }
974
975 static struct file_operations proc_arraylong_operations = {
976 NULL,
977 arraylong_read,
978 NULL,
979 NULL,
980 NULL,
981 NULL,
982 NULL,
983 NULL,
984 NULL,
985 NULL
986 };
987
988 struct inode_operations proc_arraylong_inode_operations = {
989 &proc_arraylong_operations,
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 NULL,
1003 NULL,
1004 NULL,
1005 NULL
1006 };