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