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