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