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