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 #include <linux/swap.h>
46
47 #include <asm/segment.h>
48 #include <asm/pgtable.h>
49 #include <asm/io.h>
50
51 #define LOAD_INT(x) ((x) >> FSHIFT)
52 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
53
54 #ifdef CONFIG_DEBUG_MALLOC
55 int get_malloc(char * buffer);
56 #endif
57
58
59 static int read_core(struct inode * inode, struct file * file,char * buf, int count)
60 {
61 unsigned long p = file->f_pos, memsize;
62 int read;
63 int count1;
64 char * pnt;
65 struct user dump;
66 #ifdef __i386__
67 # define FIRST_MAPPED PAGE_SIZE
68 #else
69 # define FIRST_MAPPED 0
70 #endif
71
72 memset(&dump, 0, sizeof(struct user));
73 dump.magic = CMAGIC;
74 dump.u_dsize = MAP_NR(high_memory);
75 #ifdef __alpha__
76 dump.start_data = PAGE_OFFSET;
77 #endif
78
79 if (count < 0)
80 return -EINVAL;
81 memsize = MAP_NR(high_memory + PAGE_SIZE) << PAGE_SHIFT;
82 if (p >= memsize)
83 return 0;
84 if (count > memsize - p)
85 count = memsize - p;
86 read = 0;
87
88 if (p < sizeof(struct user) && count > 0) {
89 count1 = count;
90 if (p + count1 > sizeof(struct user))
91 count1 = sizeof(struct user)-p;
92 pnt = (char *) &dump + p;
93 memcpy_tofs(buf,(void *) pnt, count1);
94 buf += count1;
95 p += count1;
96 count -= count1;
97 read += count1;
98 }
99
100 while (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) {
101 put_user(0,buf);
102 buf++;
103 p++;
104 count--;
105 read++;
106 }
107 memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count);
108 read += count;
109 file->f_pos += read;
110 return read;
111 }
112
113 static struct file_operations proc_kcore_operations = {
114 NULL,
115 read_core,
116 };
117
118 struct inode_operations proc_kcore_inode_operations = {
119 &proc_kcore_operations,
120 };
121
122
123
124
125
126
127
128
129 static int read_profile(struct inode *inode, struct file *file, char *buf, int count)
130 {
131 unsigned long p = file->f_pos;
132 int read;
133 char * pnt;
134 unsigned int sample_step = 1 << prof_shift;
135
136 if (count < 0)
137 return -EINVAL;
138 if (p >= (prof_len+1)*sizeof(unsigned int))
139 return 0;
140 if (count > (prof_len+1)*sizeof(unsigned int) - p)
141 count = (prof_len+1)*sizeof(unsigned int) - p;
142 read = 0;
143
144 while (p < sizeof(unsigned int) && count > 0) {
145 put_user(*((char *)(&sample_step)+p),buf);
146 buf++; p++; count--; read++;
147 }
148 pnt = (char *)prof_buffer + p - sizeof(unsigned int);
149 memcpy_tofs(buf,(void *)pnt,count);
150 read += count;
151 file->f_pos += read;
152 return read;
153 }
154
155
156 static int write_profile(struct inode * inode, struct file * file, const char * buf, int count)
157 {
158 int i=prof_len;
159
160 while (i--)
161 prof_buffer[i]=0UL;
162 return count;
163 }
164
165 static struct file_operations proc_profile_operations = {
166 NULL,
167 read_profile,
168 write_profile,
169 };
170
171 struct inode_operations proc_profile_inode_operations = {
172 &proc_profile_operations,
173 };
174
175
176 static int get_loadavg(char * buffer)
177 {
178 int a, b, c;
179
180 a = avenrun[0] + (FIXED_1/200);
181 b = avenrun[1] + (FIXED_1/200);
182 c = avenrun[2] + (FIXED_1/200);
183 return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d\n",
184 LOAD_INT(a), LOAD_FRAC(a),
185 LOAD_INT(b), LOAD_FRAC(b),
186 LOAD_INT(c), LOAD_FRAC(c),
187 nr_running, nr_tasks);
188 }
189
190 static int get_kstat(char * buffer)
191 {
192 int i, len;
193 unsigned sum = 0;
194 extern unsigned long total_forks;
195
196 for (i = 0 ; i < NR_IRQS ; i++)
197 sum += kstat.interrupts[i];
198 len = sprintf(buffer,
199 "cpu %u %u %u %lu\n"
200 "disk %u %u %u %u\n"
201 "disk_rio %u %u %u %u\n"
202 "disk_wio %u %u %u %u\n"
203 "disk_rblk %u %u %u %u\n"
204 "disk_wblk %u %u %u %u\n"
205 "page %u %u\n"
206 "swap %u %u\n"
207 "intr %u",
208 kstat.cpu_user,
209 kstat.cpu_nice,
210 kstat.cpu_system,
211 jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
212 kstat.dk_drive[0], kstat.dk_drive[1],
213 kstat.dk_drive[2], kstat.dk_drive[3],
214 kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
215 kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
216 kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
217 kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
218 kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
219 kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
220 kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
221 kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
222 kstat.pgpgin,
223 kstat.pgpgout,
224 kstat.pswpin,
225 kstat.pswpout,
226 sum);
227 for (i = 0 ; i < NR_IRQS ; i++)
228 len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
229 len += sprintf(buffer + len,
230 "\nctxt %u\n"
231 "btime %lu\n"
232 "processes %lu\n",
233 kstat.context_swtch,
234 xtime.tv_sec - jiffies / HZ,
235 total_forks);
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 %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
690 %lu %lu %lu %lu %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 tsk->nswap,
727 tsk->cnswap);
728 }
729
730 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
731 int * pages, int * shared, int * dirty, int * total)
732 {
733 pte_t * pte;
734 unsigned long end;
735
736 if (pmd_none(*pmd))
737 return;
738 if (pmd_bad(*pmd)) {
739 printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
740 pmd_clear(pmd);
741 return;
742 }
743 pte = pte_offset(pmd, address);
744 address &= ~PMD_MASK;
745 end = address + size;
746 if (end > PMD_SIZE)
747 end = PMD_SIZE;
748 do {
749 pte_t page = *pte;
750
751 address += PAGE_SIZE;
752 pte++;
753 if (pte_none(page))
754 continue;
755 ++*total;
756 if (!pte_present(page))
757 continue;
758 ++*pages;
759 if (pte_dirty(page))
760 ++*dirty;
761 if (pte_page(page) >= high_memory)
762 continue;
763 if (mem_map[MAP_NR(pte_page(page))].count > 1)
764 ++*shared;
765 } while (address < end);
766 }
767
768 static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
769 int * pages, int * shared, int * dirty, int * total)
770 {
771 pmd_t * pmd;
772 unsigned long end;
773
774 if (pgd_none(*pgd))
775 return;
776 if (pgd_bad(*pgd)) {
777 printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
778 pgd_clear(pgd);
779 return;
780 }
781 pmd = pmd_offset(pgd, address);
782 address &= ~PGDIR_MASK;
783 end = address + size;
784 if (end > PGDIR_SIZE)
785 end = PGDIR_SIZE;
786 do {
787 statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
788 address = (address + PMD_SIZE) & PMD_MASK;
789 pmd++;
790 } while (address < end);
791 }
792
793 static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
794 int * pages, int * shared, int * dirty, int * total)
795 {
796 while (address < end) {
797 statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
798 address = (address + PGDIR_SIZE) & PGDIR_MASK;
799 pgd++;
800 }
801 }
802
803 static int get_statm(int pid, char * buffer)
804 {
805 struct task_struct ** p = get_task(pid), *tsk;
806 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
807
808 if (!p || (tsk = *p) == NULL)
809 return 0;
810 if (tsk->mm && tsk->mm != &init_mm) {
811 struct vm_area_struct * vma = tsk->mm->mmap;
812
813 while (vma) {
814 pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
815 int pages = 0, shared = 0, dirty = 0, total = 0;
816
817 statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
818 resident += pages;
819 share += shared;
820 dt += dirty;
821 size += total;
822 if (vma->vm_flags & VM_EXECUTABLE)
823 trs += pages;
824 else if (vma->vm_flags & VM_GROWSDOWN)
825 drs += pages;
826 else if (vma->vm_end > 0x60000000)
827 lrs += pages;
828 else
829 drs += pages;
830 vma = vma->vm_next;
831 }
832 }
833 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
834 size, resident, share, trs, lrs, drs, dt);
835 }
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853 #define MAPS_LINE_LENGTH 1024
854 #define MAPS_LINE_SHIFT 10
855
856
857
858
859 #define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %s %lu\n"
860 #define MAPS_LINE_MAX 49
861
862 static int read_maps (int pid, struct file * file, char * buf, int count)
863 {
864 struct task_struct ** p = get_task(pid);
865 char * destptr;
866 loff_t lineno;
867 int column;
868 struct vm_area_struct * map;
869 int i;
870
871 if (!p || !*p)
872 return -EINVAL;
873
874 if (!(*p)->mm || (*p)->mm == &init_mm || count == 0)
875 return 0;
876
877
878 lineno = file->f_pos >> MAPS_LINE_SHIFT;
879 column = file->f_pos & (MAPS_LINE_LENGTH-1);
880
881
882 for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
883 continue;
884
885 destptr = buf;
886
887 for ( ; map ; ) {
888
889 char line[MAPS_LINE_MAX+1];
890 char str[5], *cp = str;
891 int flags;
892 kdev_t dev;
893 unsigned long ino;
894 int len;
895
896 flags = map->vm_flags;
897
898 *cp++ = flags & VM_READ ? 'r' : '-';
899 *cp++ = flags & VM_WRITE ? 'w' : '-';
900 *cp++ = flags & VM_EXEC ? 'x' : '-';
901 *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
902 *cp++ = 0;
903
904 if (map->vm_inode != NULL) {
905 dev = map->vm_inode->i_dev;
906 ino = map->vm_inode->i_ino;
907 } else {
908 dev = 0;
909 ino = 0;
910 }
911
912 len = sprintf(line, MAPS_LINE_FORMAT,
913 map->vm_start, map->vm_end, str, map->vm_offset,
914 kdevname(dev), ino);
915
916 if (column >= len) {
917 column = 0;
918 lineno++;
919 map = map->vm_next;
920 continue;
921 }
922
923 i = len-column;
924 if (i > count)
925 i = count;
926 memcpy_tofs(destptr, line+column, i);
927 destptr += i; count -= i;
928 column += i;
929 if (column >= len) {
930 column = 0;
931 lineno++;
932 map = map->vm_next;
933 }
934
935
936 if (count == 0)
937 break;
938
939
940
941
942 if (*p != current)
943 break;
944 }
945
946
947 file->f_pos = (lineno << MAPS_LINE_SHIFT) + column;
948
949 return destptr-buf;
950 }
951
952 #ifdef CONFIG_MODULES
953 extern int get_module_list(char *);
954 extern int get_ksyms_list(char *, char **, off_t, int);
955 #endif
956 extern int get_device_list(char *);
957 extern int get_filesystem_list(char *);
958 extern int get_filesystem_info( char * );
959 extern int get_irq_list(char *);
960 extern int get_dma_list(char *);
961 extern int get_cpuinfo(char *);
962 extern int get_pci_list(char*);
963 extern int get_md_status (char *);
964 extern int get_rtc_status (char *);
965 #ifdef __SMP_PROF__
966 extern int get_smp_prof_list(char *);
967 #endif
968
969 static int get_root_array(char * page, int type, char **start, off_t offset, int length)
970 {
971 switch (type) {
972 case PROC_LOADAVG:
973 return get_loadavg(page);
974
975 case PROC_UPTIME:
976 return get_uptime(page);
977
978 case PROC_MEMINFO:
979 return get_meminfo(page);
980
981 #ifdef CONFIG_PCI
982 case PROC_PCI:
983 return get_pci_list(page);
984 #endif
985
986 case PROC_CPUINFO:
987 return get_cpuinfo(page);
988
989 case PROC_VERSION:
990 return get_version(page);
991
992 #ifdef CONFIG_DEBUG_MALLOC
993 case PROC_MALLOC:
994 return get_malloc(page);
995 #endif
996
997 #ifdef CONFIG_MODULES
998 case PROC_MODULES:
999 return get_module_list(page);
1000
1001 case PROC_KSYMS:
1002 return get_ksyms_list(page, start, offset, length);
1003 #endif
1004
1005 case PROC_STAT:
1006 return get_kstat(page);
1007
1008 case PROC_DEVICES:
1009 return get_device_list(page);
1010
1011 case PROC_INTERRUPTS:
1012 return get_irq_list(page);
1013
1014 case PROC_FILESYSTEMS:
1015 return get_filesystem_list(page);
1016
1017 case PROC_DMA:
1018 return get_dma_list(page);
1019
1020 case PROC_IOPORTS:
1021 return get_ioport_list(page);
1022 #ifdef CONFIG_BLK_DEV_MD
1023 case PROC_MD:
1024 return get_md_status(page);
1025 #endif
1026 #ifdef __SMP_PROF__
1027 case PROC_SMP_PROF:
1028 return get_smp_prof_list(page);
1029 #endif
1030 case PROC_CMDLINE:
1031 return get_cmdline(page);
1032
1033 case PROC_MTAB:
1034 return get_filesystem_info( page );
1035 #ifdef CONFIG_RTC
1036 case PROC_RTC:
1037 return get_rtc_status(page);
1038 #endif
1039 }
1040 return -EBADF;
1041 }
1042
1043 static int get_process_array(char * page, int pid, int type)
1044 {
1045 switch (type) {
1046 case PROC_PID_STATUS:
1047 return get_status(pid, page);
1048 case PROC_PID_ENVIRON:
1049 return get_env(pid, page);
1050 case PROC_PID_CMDLINE:
1051 return get_arg(pid, page);
1052 case PROC_PID_STAT:
1053 return get_stat(pid, page);
1054 case PROC_PID_STATM:
1055 return get_statm(pid, page);
1056 }
1057 return -EBADF;
1058 }
1059
1060
1061 static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
1062 {
1063 if (pid)
1064 return get_process_array(page, pid, type);
1065 return get_root_array(page, type, start, offset, length);
1066 }
1067
1068 #define PROC_BLOCK_SIZE (3*1024)
1069
1070 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
1071 {
1072 unsigned long page;
1073 char *start;
1074 int length;
1075 int end;
1076 unsigned int type, pid;
1077 struct proc_dir_entry *dp;
1078
1079 if (count < 0)
1080 return -EINVAL;
1081 if (count > PROC_BLOCK_SIZE)
1082 count = PROC_BLOCK_SIZE;
1083 if (!(page = __get_free_page(GFP_KERNEL)))
1084 return -ENOMEM;
1085 type = inode->i_ino;
1086 pid = type >> 16;
1087 type &= 0x0000ffff;
1088 start = NULL;
1089 dp = (struct proc_dir_entry *) inode->u.generic_ip;
1090 if (dp->get_info)
1091 length = dp->get_info((char *)page, &start, file->f_pos,
1092 count, 0);
1093 else
1094 length = fill_array((char *) page, pid, type,
1095 &start, file->f_pos, count);
1096 if (length < 0) {
1097 free_page(page);
1098 return length;
1099 }
1100 if (start != NULL) {
1101
1102 memcpy_tofs(buf, start, length);
1103 file->f_pos += length;
1104 count = length;
1105 } else {
1106
1107 if (file->f_pos >= length) {
1108 free_page(page);
1109 return 0;
1110 }
1111 if (count + file->f_pos > length)
1112 count = length - file->f_pos;
1113 end = count + file->f_pos;
1114 memcpy_tofs(buf, (char *) page + file->f_pos, count);
1115 file->f_pos = end;
1116 }
1117 free_page(page);
1118 return count;
1119 }
1120
1121 static struct file_operations proc_array_operations = {
1122 NULL,
1123 array_read,
1124 NULL,
1125 NULL,
1126 NULL,
1127 NULL,
1128 NULL,
1129 NULL,
1130 NULL,
1131 NULL
1132 };
1133
1134 struct inode_operations proc_array_inode_operations = {
1135 &proc_array_operations,
1136 NULL,
1137 NULL,
1138 NULL,
1139 NULL,
1140 NULL,
1141 NULL,
1142 NULL,
1143 NULL,
1144 NULL,
1145 NULL,
1146 NULL,
1147 NULL,
1148 NULL,
1149 NULL,
1150 NULL,
1151 NULL
1152 };
1153
1154 static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
1155 {
1156 unsigned int pid = inode->i_ino >> 16;
1157 unsigned int type = inode->i_ino & 0x0000ffff;
1158
1159 if (count < 0)
1160 return -EINVAL;
1161
1162 switch (type) {
1163 case PROC_PID_MAPS:
1164 return read_maps(pid, file, buf, count);
1165 }
1166 return -EINVAL;
1167 }
1168
1169 static struct file_operations proc_arraylong_operations = {
1170 NULL,
1171 arraylong_read,
1172 NULL,
1173 NULL,
1174 NULL,
1175 NULL,
1176 NULL,
1177 NULL,
1178 NULL,
1179 NULL
1180 };
1181
1182 struct inode_operations proc_arraylong_inode_operations = {
1183 &proc_arraylong_operations,
1184 NULL,
1185 NULL,
1186 NULL,
1187 NULL,
1188 NULL,
1189 NULL,
1190 NULL,
1191 NULL,
1192 NULL,
1193 NULL,
1194 NULL,
1195 NULL,
1196 NULL,
1197 NULL,
1198 NULL,
1199 NULL
1200 };