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
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 case PROC_CMDLINE:
844 return get_cmdline(page);
845 }
846 return -EBADF;
847 }
848
849 static int get_process_array(char * page, int pid, int type)
850 {
851 switch (type) {
852 case PROC_PID_ENVIRON:
853 return get_env(pid, page);
854 case PROC_PID_CMDLINE:
855 return get_arg(pid, page);
856 case PROC_PID_STAT:
857 return get_stat(pid, page);
858 case PROC_PID_STATM:
859 return get_statm(pid, page);
860 }
861 return -EBADF;
862 }
863
864
865 static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
866 {
867 if (pid)
868 return get_process_array(page, pid, type);
869 return get_root_array(page, type, start, offset, length);
870 }
871
872 #define PROC_BLOCK_SIZE (3*1024)
873
874 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
875 {
876 unsigned long page;
877 char *start;
878 int length;
879 int end;
880 unsigned int type, pid;
881
882 if (count < 0)
883 return -EINVAL;
884 if (count > PROC_BLOCK_SIZE)
885 count = PROC_BLOCK_SIZE;
886 if (!(page = __get_free_page(GFP_KERNEL)))
887 return -ENOMEM;
888 type = inode->i_ino;
889 pid = type >> 16;
890 type &= 0x0000ffff;
891 start = NULL;
892 length = fill_array((char *) page, pid, type,
893 &start, file->f_pos, count);
894 if (length < 0) {
895 free_page(page);
896 return length;
897 }
898 if (start != NULL) {
899
900 memcpy_tofs(buf, start, length);
901 file->f_pos += length;
902 count = length;
903 } else {
904
905 if (file->f_pos >= length) {
906 free_page(page);
907 return 0;
908 }
909 if (count + file->f_pos > length)
910 count = length - file->f_pos;
911 end = count + file->f_pos;
912 memcpy_tofs(buf, (char *) page + file->f_pos, count);
913 file->f_pos = end;
914 }
915 free_page(page);
916 return count;
917 }
918
919 static struct file_operations proc_array_operations = {
920 NULL,
921 array_read,
922 NULL,
923 NULL,
924 NULL,
925 NULL,
926 NULL,
927 NULL,
928 NULL,
929 NULL
930 };
931
932 struct inode_operations proc_array_inode_operations = {
933 &proc_array_operations,
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 NULL
950 };
951
952 static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
953 {
954 unsigned int pid = inode->i_ino >> 16;
955 unsigned int type = inode->i_ino & 0x0000ffff;
956
957 if (count < 0)
958 return -EINVAL;
959
960 switch (type) {
961 case PROC_PID_MAPS:
962 return read_maps(pid, file, buf, count);
963 }
964 return -EINVAL;
965 }
966
967 static struct file_operations proc_arraylong_operations = {
968 NULL,
969 arraylong_read,
970 NULL,
971 NULL,
972 NULL,
973 NULL,
974 NULL,
975 NULL,
976 NULL,
977 NULL
978 };
979
980 struct inode_operations proc_arraylong_inode_operations = {
981 &proc_arraylong_operations,
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 NULL
998 };