This source file includes following definitions.
- read_core
- read_profile
- write_profile
- get_loadavg
- get_kstat
- get_uptime
- get_meminfo
- get_version
- 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 struct task_struct ** get_task(pid_t pid)
295 {
296 struct task_struct ** p;
297
298 p = task;
299 while (++p < task+NR_TASKS) {
300 if (*p && (*p)->pid == pid)
301 return p;
302 }
303 return NULL;
304 }
305
306 static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
307 {
308 pgd_t *page_dir;
309 pmd_t *page_middle;
310 pte_t pte;
311
312 if (!p || !p->mm || ptr >= TASK_SIZE)
313 return 0;
314 page_dir = pgd_offset(p->mm,ptr);
315 if (pgd_none(*page_dir))
316 return 0;
317 if (pgd_bad(*page_dir)) {
318 printk("bad page directory entry %08lx\n", pgd_val(*page_dir));
319 pgd_clear(page_dir);
320 return 0;
321 }
322 page_middle = pmd_offset(page_dir,ptr);
323 if (pmd_none(*page_middle))
324 return 0;
325 if (pmd_bad(*page_middle)) {
326 printk("bad page middle entry %08lx\n", pmd_val(*page_middle));
327 pmd_clear(page_middle);
328 return 0;
329 }
330 pte = *pte_offset(page_middle,ptr);
331 if (!pte_present(pte))
332 return 0;
333 return pte_page(pte) + (ptr & ~PAGE_MASK);
334 }
335
336 static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
337 {
338 unsigned long addr;
339 int size = 0, result = 0;
340 char c;
341
342 if (start >= end)
343 return result;
344 for (;;) {
345 addr = get_phys_addr(*p, start);
346 if (!addr)
347 goto ready;
348 do {
349 c = *(char *) addr;
350 if (!c)
351 result = size;
352 if (size < PAGE_SIZE)
353 buffer[size++] = c;
354 else
355 goto ready;
356 addr++;
357 start++;
358 if (!c && start >= end)
359 goto ready;
360 } while (addr & ~PAGE_MASK);
361 }
362 ready:
363
364 while (result>0 && buffer[result-1]==' ')
365 result--;
366 return result;
367 }
368
369 static int get_env(int pid, char * buffer)
370 {
371 struct task_struct ** p = get_task(pid);
372
373 if (!p || !*p || !(*p)->mm)
374 return 0;
375 return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer);
376 }
377
378 static int get_arg(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->arg_start, (*p)->mm->arg_end, buffer);
385 }
386
387 static unsigned long get_wchan(struct task_struct *p)
388 {
389 if (!p || p == current || p->state == TASK_RUNNING)
390 return 0;
391 #if defined(__i386__)
392 {
393 unsigned long ebp, eip;
394 unsigned long stack_page;
395 int count = 0;
396
397 stack_page = p->kernel_stack_page;
398 if (!stack_page)
399 return 0;
400 ebp = p->tss.ebp;
401 do {
402 if (ebp < stack_page || ebp >= 4092+stack_page)
403 return 0;
404 eip = *(unsigned long *) (ebp+4);
405 if ((void *)eip != sleep_on &&
406 (void *)eip != interruptible_sleep_on)
407 return eip;
408 ebp = *(unsigned long *) ebp;
409 } while (count++ < 16);
410 }
411 #elif defined(__alpha__)
412
413
414
415
416
417
418
419
420
421 {
422 unsigned long schedule_frame;
423 unsigned long pc;
424
425 pc = thread_saved_pc(&p->tss);
426 if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
427 schedule_frame = ((unsigned long *)p->tss.ksp)[6];
428 return ((unsigned long *)schedule_frame)[12];
429 }
430 return pc;
431 }
432 #endif
433 return 0;
434 }
435
436 #if defined(__i386__)
437 # define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019])
438 # define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022])
439 #elif defined(__alpha__)
440
441
442
443 # define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
444 + (long)&((struct pt_regs *)0)->reg)
445 # define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
446 # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
447 #endif
448
449 static int get_stat(int pid, char * buffer)
450 {
451 struct task_struct ** p = get_task(pid), *tsk;
452 unsigned long sigignore=0, sigcatch=0, wchan;
453 unsigned long vsize, eip, esp;
454 long priority, nice;
455 int i,tty_pgrp;
456 char state;
457
458 if (!p || (tsk = *p) == NULL)
459 return 0;
460 if (tsk->state < 0 || tsk->state > 5)
461 state = '.';
462 else
463 state = "RSDZTW"[tsk->state];
464 vsize = eip = esp = 0;
465 if (tsk->mm) {
466 struct vm_area_struct *vma = tsk->mm->mmap;
467 while (vma) {
468 vsize += vma->vm_end - vma->vm_start;
469 vma = vma->vm_next;
470 }
471 if (tsk->kernel_stack_page) {
472 eip = KSTK_EIP(tsk);
473 esp = KSTK_ESP(tsk);
474 }
475 }
476 wchan = get_wchan(tsk);
477 if (tsk->sig) {
478 unsigned long bit = 1;
479 for(i=0; i<32; ++i) {
480 switch((unsigned long) tsk->sig->action[i].sa_handler) {
481 case 0:
482 break;
483 case 1:
484 sigignore |= bit;
485 break;
486 default:
487 sigcatch |= bit;
488 }
489 bit <<= 1;
490 }
491 }
492 if (tsk->tty)
493 tty_pgrp = tsk->tty->pgrp;
494 else
495 tty_pgrp = -1;
496
497
498
499 priority = tsk->counter;
500 priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
501 nice = tsk->priority;
502 nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
503
504 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
505 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu \
506 %lu %lu %lu %lu\n",
507 pid,
508 tsk->comm,
509 state,
510 tsk->p_pptr->pid,
511 tsk->pgrp,
512 tsk->session,
513 tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
514 tty_pgrp,
515 tsk->flags,
516 tsk->min_flt,
517 tsk->cmin_flt,
518 tsk->maj_flt,
519 tsk->cmaj_flt,
520 tsk->utime,
521 tsk->stime,
522 tsk->cutime,
523 tsk->cstime,
524 priority,
525 nice,
526 tsk->timeout,
527 tsk->it_real_value,
528 tsk->start_time,
529 vsize,
530 tsk->mm ? tsk->mm->rss : 0,
531 tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
532 tsk->mm ? tsk->mm->start_code : 0,
533 tsk->mm ? tsk->mm->end_code : 0,
534 tsk->mm ? tsk->mm->start_stack : 0,
535 esp,
536 eip,
537 tsk->signal,
538 tsk->blocked,
539 sigignore,
540 sigcatch,
541 wchan);
542 }
543
544 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
545 int * pages, int * shared, int * dirty, int * total)
546 {
547 pte_t * pte;
548 unsigned long end;
549
550 if (pmd_none(*pmd))
551 return;
552 if (pmd_bad(*pmd)) {
553 printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
554 pmd_clear(pmd);
555 return;
556 }
557 pte = pte_offset(pmd, address);
558 address &= ~PMD_MASK;
559 end = address + size;
560 if (end > PMD_SIZE)
561 end = PMD_SIZE;
562 do {
563 pte_t page = *pte;
564
565 address += PAGE_SIZE;
566 pte++;
567 if (pte_none(page))
568 continue;
569 ++*total;
570 if (!pte_present(page))
571 continue;
572 ++*pages;
573 if (pte_dirty(page))
574 ++*dirty;
575 if (pte_page(page) >= high_memory)
576 continue;
577 if (mem_map[MAP_NR(pte_page(page))].count > 1)
578 ++*shared;
579 } while (address < end);
580 }
581
582 static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
583 int * pages, int * shared, int * dirty, int * total)
584 {
585 pmd_t * pmd;
586 unsigned long end;
587
588 if (pgd_none(*pgd))
589 return;
590 if (pgd_bad(*pgd)) {
591 printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
592 pgd_clear(pgd);
593 return;
594 }
595 pmd = pmd_offset(pgd, address);
596 address &= ~PGDIR_MASK;
597 end = address + size;
598 if (end > PGDIR_SIZE)
599 end = PGDIR_SIZE;
600 do {
601 statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
602 address = (address + PMD_SIZE) & PMD_MASK;
603 pmd++;
604 } while (address < end);
605 }
606
607 static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
608 int * pages, int * shared, int * dirty, int * total)
609 {
610 while (address < end) {
611 statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
612 address = (address + PGDIR_SIZE) & PGDIR_MASK;
613 pgd++;
614 }
615 }
616
617 static int get_statm(int pid, char * buffer)
618 {
619 struct task_struct ** p = get_task(pid), *tsk;
620 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
621
622 if (!p || (tsk = *p) == NULL)
623 return 0;
624 if (tsk->mm) {
625 struct vm_area_struct * vma = tsk->mm->mmap;
626
627 while (vma) {
628 pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
629 int pages = 0, shared = 0, dirty = 0, total = 0;
630
631 statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
632 resident += pages;
633 share += shared;
634 dt += dirty;
635 size += total;
636 if (vma->vm_flags & VM_EXECUTABLE)
637 trs += pages;
638 else if (vma->vm_flags & VM_GROWSDOWN)
639 drs += pages;
640 else if (vma->vm_end > 0x60000000)
641 lrs += pages;
642 else
643 drs += pages;
644 vma = vma->vm_next;
645 }
646 }
647 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
648 size, resident, share, trs, lrs, drs, dt);
649 }
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667 #define MAPS_LINE_LENGTH 1024
668 #define MAPS_LINE_SHIFT 10
669
670
671
672
673 #define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %02x:%02x %lu\n"
674 #define MAPS_LINE_MAX 49
675
676 static int read_maps (int pid, struct file * file, char * buf, int count)
677 {
678 struct task_struct ** p = get_task(pid);
679 char * destptr;
680 loff_t lineno;
681 int column;
682 struct vm_area_struct * map;
683 int i;
684
685 if (!p || !*p)
686 return -EINVAL;
687
688 if (!(*p)->mm || count == 0)
689 return 0;
690
691
692 lineno = file->f_pos >> MAPS_LINE_SHIFT;
693 column = file->f_pos & (MAPS_LINE_LENGTH-1);
694
695
696 for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
697 continue;
698
699 destptr = buf;
700
701 for ( ; map ; ) {
702
703 char line[MAPS_LINE_MAX+1];
704 char str[5], *cp = str;
705 int flags;
706 kdev_t dev;
707 unsigned long ino;
708 int len;
709
710 flags = map->vm_flags;
711
712 *cp++ = flags & VM_READ ? 'r' : '-';
713 *cp++ = flags & VM_WRITE ? 'w' : '-';
714 *cp++ = flags & VM_EXEC ? 'x' : '-';
715 *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
716 *cp++ = 0;
717
718 if (map->vm_inode != NULL) {
719 dev = map->vm_inode->i_dev;
720 ino = map->vm_inode->i_ino;
721 } else {
722 dev = 0;
723 ino = 0;
724 }
725
726 len = sprintf(line, MAPS_LINE_FORMAT,
727 map->vm_start, map->vm_end, str, map->vm_offset,
728 MAJOR(dev),MINOR(dev), ino);
729
730 if (column >= len) {
731 column = 0;
732 lineno++;
733 map = map->vm_next;
734 continue;
735 }
736
737 i = len-column;
738 if (i > count)
739 i = count;
740 memcpy_tofs(destptr, line+column, i);
741 destptr += i; count -= i;
742 column += i;
743 if (column >= len) {
744 column = 0;
745 lineno++;
746 map = map->vm_next;
747 }
748
749
750 if (count == 0)
751 break;
752
753
754
755
756 if (*p != current)
757 break;
758 }
759
760
761 file->f_pos = (lineno << MAPS_LINE_SHIFT) + column;
762
763 return destptr-buf;
764 }
765
766 extern int get_module_list(char *);
767 extern int get_device_list(char *);
768 extern int get_filesystem_list(char *);
769 extern int get_ksyms_list(char *, char **, off_t, int);
770 extern int get_irq_list(char *);
771 extern int get_dma_list(char *);
772 extern int get_cpuinfo(char *);
773 extern int get_pci_list(char*);
774
775 static int get_root_array(char * page, int type, char **start, off_t offset, int length)
776 {
777 switch (type) {
778 case PROC_LOADAVG:
779 return get_loadavg(page);
780
781 case PROC_UPTIME:
782 return get_uptime(page);
783
784 case PROC_MEMINFO:
785 return get_meminfo(page);
786
787 #ifdef CONFIG_PCI
788 case PROC_PCI:
789 return get_pci_list(page);
790 #endif
791
792 case PROC_CPUINFO:
793 return get_cpuinfo(page);
794
795 case PROC_VERSION:
796 return get_version(page);
797
798 #ifdef CONFIG_DEBUG_MALLOC
799 case PROC_MALLOC:
800 return get_malloc(page);
801 #endif
802
803 case PROC_MODULES:
804 return get_module_list(page);
805
806 case PROC_STAT:
807 return get_kstat(page);
808
809 case PROC_DEVICES:
810 return get_device_list(page);
811
812 case PROC_INTERRUPTS:
813 return get_irq_list(page);
814
815 case PROC_FILESYSTEMS:
816 return get_filesystem_list(page);
817
818 case PROC_KSYMS:
819 return get_ksyms_list(page, start, offset, length);
820
821 case PROC_DMA:
822 return get_dma_list(page);
823
824 case PROC_IOPORTS:
825 return get_ioport_list(page);
826 #ifdef CONFIG_APM
827 case PROC_APM:
828 return apm_proc(page);
829 #endif
830 }
831 return -EBADF;
832 }
833
834 static int get_process_array(char * page, int pid, int type)
835 {
836 switch (type) {
837 case PROC_PID_ENVIRON:
838 return get_env(pid, page);
839 case PROC_PID_CMDLINE:
840 return get_arg(pid, page);
841 case PROC_PID_STAT:
842 return get_stat(pid, page);
843 case PROC_PID_STATM:
844 return get_statm(pid, page);
845 }
846 return -EBADF;
847 }
848
849
850 static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
851 {
852 if (pid)
853 return get_process_array(page, pid, type);
854 return get_root_array(page, type, start, offset, length);
855 }
856
857 #define PROC_BLOCK_SIZE (3*1024)
858
859 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
860 {
861 unsigned long page;
862 char *start;
863 int length;
864 int end;
865 unsigned int type, pid;
866
867 if (count < 0)
868 return -EINVAL;
869 if (count > PROC_BLOCK_SIZE)
870 count = PROC_BLOCK_SIZE;
871 if (!(page = __get_free_page(GFP_KERNEL)))
872 return -ENOMEM;
873 type = inode->i_ino;
874 pid = type >> 16;
875 type &= 0x0000ffff;
876 start = NULL;
877 length = fill_array((char *) page, pid, type,
878 &start, file->f_pos, count);
879 if (length < 0) {
880 free_page(page);
881 return length;
882 }
883 if (start != NULL) {
884
885 memcpy_tofs(buf, start, length);
886 file->f_pos += length;
887 count = length;
888 } else {
889
890 if (file->f_pos >= length) {
891 free_page(page);
892 return 0;
893 }
894 if (count + file->f_pos > length)
895 count = length - file->f_pos;
896 end = count + file->f_pos;
897 memcpy_tofs(buf, (char *) page + file->f_pos, count);
898 file->f_pos = end;
899 }
900 free_page(page);
901 return count;
902 }
903
904 static struct file_operations proc_array_operations = {
905 NULL,
906 array_read,
907 NULL,
908 NULL,
909 NULL,
910 NULL,
911 NULL,
912 NULL,
913 NULL,
914 NULL
915 };
916
917 struct inode_operations proc_array_inode_operations = {
918 &proc_array_operations,
919 NULL,
920 NULL,
921 NULL,
922 NULL,
923 NULL,
924 NULL,
925 NULL,
926 NULL,
927 NULL,
928 NULL,
929 NULL,
930 NULL,
931 NULL,
932 NULL
933 };
934
935 static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
936 {
937 unsigned int pid = inode->i_ino >> 16;
938 unsigned int type = inode->i_ino & 0x0000ffff;
939
940 if (count < 0)
941 return -EINVAL;
942
943 switch (type) {
944 case PROC_PID_MAPS:
945 return read_maps(pid, file, buf, count);
946 }
947 return -EINVAL;
948 }
949
950 static struct file_operations proc_arraylong_operations = {
951 NULL,
952 arraylong_read,
953 NULL,
954 NULL,
955 NULL,
956 NULL,
957 NULL,
958 NULL,
959 NULL,
960 NULL
961 };
962
963 struct inode_operations proc_arraylong_inode_operations = {
964 &proc_arraylong_operations,
965 NULL,
966 NULL,
967 NULL,
968 NULL,
969 NULL,
970 NULL,
971 NULL,
972 NULL,
973 NULL,
974 NULL,
975 NULL,
976 NULL,
977 NULL,
978 NULL
979 };