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 %s %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 kdevname(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 extern int get_md_status (char *);
962 #ifdef __SMP_PROF__
963 extern int get_smp_prof_list(char *);
964 #endif
965
966 static int get_root_array(char * page, int type, char **start, off_t offset, int length)
967 {
968 switch (type) {
969 case PROC_LOADAVG:
970 return get_loadavg(page);
971
972 case PROC_UPTIME:
973 return get_uptime(page);
974
975 case PROC_MEMINFO:
976 return get_meminfo(page);
977
978 #ifdef CONFIG_PCI
979 case PROC_PCI:
980 return get_pci_list(page);
981 #endif
982
983 case PROC_CPUINFO:
984 return get_cpuinfo(page);
985
986 case PROC_VERSION:
987 return get_version(page);
988
989 #ifdef CONFIG_DEBUG_MALLOC
990 case PROC_MALLOC:
991 return get_malloc(page);
992 #endif
993
994 #ifdef CONFIG_MODULES
995 case PROC_MODULES:
996 return get_module_list(page);
997
998 case PROC_KSYMS:
999 return get_ksyms_list(page, start, offset, length);
1000 #endif
1001
1002 case PROC_STAT:
1003 return get_kstat(page);
1004
1005 case PROC_DEVICES:
1006 return get_device_list(page);
1007
1008 case PROC_INTERRUPTS:
1009 return get_irq_list(page);
1010
1011 case PROC_FILESYSTEMS:
1012 return get_filesystem_list(page);
1013
1014 case PROC_DMA:
1015 return get_dma_list(page);
1016
1017 case PROC_IOPORTS:
1018 return get_ioport_list(page);
1019 #ifdef CONFIG_BLK_DEV_MD
1020 case PROC_MD:
1021 return get_md_status(page);
1022 #endif
1023 #ifdef CONFIG_APM
1024 case PROC_APM:
1025 return apm_proc(page);
1026 #endif
1027 #ifdef __SMP_PROF__
1028 case PROC_SMP_PROF:
1029 return get_smp_prof_list(page);
1030 #endif
1031 case PROC_CMDLINE:
1032 return get_cmdline(page);
1033
1034 case PROC_MTAB:
1035 return get_filesystem_info( page );
1036 }
1037 return -EBADF;
1038 }
1039
1040 static int get_process_array(char * page, int pid, int type)
1041 {
1042 switch (type) {
1043 case PROC_PID_STATUS:
1044 return get_status(pid, page);
1045 case PROC_PID_ENVIRON:
1046 return get_env(pid, page);
1047 case PROC_PID_CMDLINE:
1048 return get_arg(pid, page);
1049 case PROC_PID_STAT:
1050 return get_stat(pid, page);
1051 case PROC_PID_STATM:
1052 return get_statm(pid, page);
1053 }
1054 return -EBADF;
1055 }
1056
1057
1058 static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
1059 {
1060 if (pid)
1061 return get_process_array(page, pid, type);
1062 return get_root_array(page, type, start, offset, length);
1063 }
1064
1065 #define PROC_BLOCK_SIZE (3*1024)
1066
1067 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
1068 {
1069 unsigned long page;
1070 char *start;
1071 int length;
1072 int end;
1073 unsigned int type, pid;
1074
1075 if (count < 0)
1076 return -EINVAL;
1077 if (count > PROC_BLOCK_SIZE)
1078 count = PROC_BLOCK_SIZE;
1079 if (!(page = __get_free_page(GFP_KERNEL)))
1080 return -ENOMEM;
1081 type = inode->i_ino;
1082 pid = type >> 16;
1083 type &= 0x0000ffff;
1084 start = NULL;
1085 length = fill_array((char *) page, pid, type,
1086 &start, file->f_pos, count);
1087 if (length < 0) {
1088 free_page(page);
1089 return length;
1090 }
1091 if (start != NULL) {
1092
1093 memcpy_tofs(buf, start, length);
1094 file->f_pos += length;
1095 count = length;
1096 } else {
1097
1098 if (file->f_pos >= length) {
1099 free_page(page);
1100 return 0;
1101 }
1102 if (count + file->f_pos > length)
1103 count = length - file->f_pos;
1104 end = count + file->f_pos;
1105 memcpy_tofs(buf, (char *) page + file->f_pos, count);
1106 file->f_pos = end;
1107 }
1108 free_page(page);
1109 return count;
1110 }
1111
1112 static struct file_operations proc_array_operations = {
1113 NULL,
1114 array_read,
1115 NULL,
1116 NULL,
1117 NULL,
1118 NULL,
1119 NULL,
1120 NULL,
1121 NULL,
1122 NULL
1123 };
1124
1125 struct inode_operations proc_array_inode_operations = {
1126 &proc_array_operations,
1127 NULL,
1128 NULL,
1129 NULL,
1130 NULL,
1131 NULL,
1132 NULL,
1133 NULL,
1134 NULL,
1135 NULL,
1136 NULL,
1137 NULL,
1138 NULL,
1139 NULL,
1140 NULL,
1141 NULL,
1142 NULL
1143 };
1144
1145 static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
1146 {
1147 unsigned int pid = inode->i_ino >> 16;
1148 unsigned int type = inode->i_ino & 0x0000ffff;
1149
1150 if (count < 0)
1151 return -EINVAL;
1152
1153 switch (type) {
1154 case PROC_PID_MAPS:
1155 return read_maps(pid, file, buf, count);
1156 }
1157 return -EINVAL;
1158 }
1159
1160 static struct file_operations proc_arraylong_operations = {
1161 NULL,
1162 arraylong_read,
1163 NULL,
1164 NULL,
1165 NULL,
1166 NULL,
1167 NULL,
1168 NULL,
1169 NULL,
1170 NULL
1171 };
1172
1173 struct inode_operations proc_arraylong_inode_operations = {
1174 &proc_arraylong_operations,
1175 NULL,
1176 NULL,
1177 NULL,
1178 NULL,
1179 NULL,
1180 NULL,
1181 NULL,
1182 NULL,
1183 NULL,
1184 NULL,
1185 NULL,
1186 NULL,
1187 NULL,
1188 NULL,
1189 NULL,
1190 NULL
1191 };