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 extern unsigned long total_forks;
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 "processes %lu\n",
236 kstat.context_swtch,
237 xtime.tv_sec - jiffies / HZ,
238 total_forks);
239 return len;
240 }
241
242
243 static int get_uptime(char * buffer)
244 {
245 unsigned long uptime;
246 unsigned long idle;
247
248 uptime = jiffies;
249 idle = task[0]->utime + task[0]->stime;
250
251
252
253
254
255
256
257
258
259
260 #if HZ!=100
261 return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
262 uptime / HZ,
263 (((uptime % HZ) * 100) / HZ) % 100,
264 idle / HZ,
265 (((idle % HZ) * 100) / HZ) % 100);
266 #else
267 return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
268 uptime / HZ,
269 uptime % HZ,
270 idle / HZ,
271 idle % HZ);
272 #endif
273 }
274
275 static int get_meminfo(char * buffer)
276 {
277 struct sysinfo i;
278 int len;
279
280 si_meminfo(&i);
281 si_swapinfo(&i);
282 len = sprintf(buffer, " total: used: free: shared: buffers: cached:\n"
283 "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n"
284 "Swap: %8lu %8lu %8lu\n",
285 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE,
286 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
287
288
289
290
291 return len + sprintf(buffer+len,
292 "MemTotal: %8lu kB\n"
293 "MemFree: %8lu kB\n"
294 "MemShared: %8lu kB\n"
295 "Buffers: %8lu kB\n"
296 "Cached: %8lu kB\n"
297 "SwapTotal: %8lu kB\n"
298 "SwapFree: %8lu kB\n",
299 i.totalram >> 10,
300 i.freeram >> 10,
301 i.sharedram >> 10,
302 i.bufferram >> 10,
303 page_cache_size << (PAGE_SHIFT - 10),
304 i.totalswap >> 10,
305 i.freeswap >> 10);
306 }
307
308 static int get_version(char * buffer)
309 {
310 extern char *linux_banner;
311
312 strcpy(buffer, linux_banner);
313 return strlen(buffer);
314 }
315
316 static int get_cmdline(char * buffer)
317 {
318 extern char saved_command_line[];
319
320 return sprintf(buffer, "%s\n", saved_command_line);
321 }
322
323 static struct task_struct ** get_task(pid_t pid)
324 {
325 struct task_struct ** p;
326
327 p = task;
328 while (++p < task+NR_TASKS) {
329 if (*p && (*p)->pid == pid)
330 return p;
331 }
332 return NULL;
333 }
334
335 static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
336 {
337 pgd_t *page_dir;
338 pmd_t *page_middle;
339 pte_t pte;
340
341 if (!p || !p->mm || ptr >= TASK_SIZE)
342 return 0;
343 page_dir = pgd_offset(p->mm,ptr);
344 if (pgd_none(*page_dir))
345 return 0;
346 if (pgd_bad(*page_dir)) {
347 printk("bad page directory entry %08lx\n", pgd_val(*page_dir));
348 pgd_clear(page_dir);
349 return 0;
350 }
351 page_middle = pmd_offset(page_dir,ptr);
352 if (pmd_none(*page_middle))
353 return 0;
354 if (pmd_bad(*page_middle)) {
355 printk("bad page middle entry %08lx\n", pmd_val(*page_middle));
356 pmd_clear(page_middle);
357 return 0;
358 }
359 pte = *pte_offset(page_middle,ptr);
360 if (!pte_present(pte))
361 return 0;
362 return pte_page(pte) + (ptr & ~PAGE_MASK);
363 }
364
365 static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
366 {
367 unsigned long addr;
368 int size = 0, result = 0;
369 char c;
370
371 if (start >= end)
372 return result;
373 for (;;) {
374 addr = get_phys_addr(*p, start);
375 if (!addr)
376 goto ready;
377 do {
378 c = *(char *) addr;
379 if (!c)
380 result = size;
381 if (size < PAGE_SIZE)
382 buffer[size++] = c;
383 else
384 goto ready;
385 addr++;
386 start++;
387 if (!c && start >= end)
388 goto ready;
389 } while (addr & ~PAGE_MASK);
390 }
391 ready:
392
393 while (result>0 && buffer[result-1]==' ')
394 result--;
395 return result;
396 }
397
398 static int get_env(int pid, char * buffer)
399 {
400 struct task_struct ** p = get_task(pid);
401
402 if (!p || !*p || !(*p)->mm)
403 return 0;
404 return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer);
405 }
406
407 static int get_arg(int pid, char * buffer)
408 {
409 struct task_struct ** p = get_task(pid);
410
411 if (!p || !*p || !(*p)->mm)
412 return 0;
413 return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer);
414 }
415
416 static unsigned long get_wchan(struct task_struct *p)
417 {
418 if (!p || p == current || p->state == TASK_RUNNING)
419 return 0;
420 #if defined(__i386__)
421 {
422 unsigned long ebp, eip;
423 unsigned long stack_page;
424 int count = 0;
425
426 stack_page = p->kernel_stack_page;
427 if (!stack_page)
428 return 0;
429 ebp = p->tss.ebp;
430 do {
431 if (ebp < stack_page || ebp >= 4092+stack_page)
432 return 0;
433 eip = *(unsigned long *) (ebp+4);
434 if ((void *)eip != sleep_on &&
435 (void *)eip != interruptible_sleep_on)
436 return eip;
437 ebp = *(unsigned long *) ebp;
438 } while (count++ < 16);
439 }
440 #elif defined(__alpha__)
441
442
443
444
445
446
447
448
449
450 {
451 unsigned long schedule_frame;
452 unsigned long pc;
453
454 pc = thread_saved_pc(&p->tss);
455 if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
456 schedule_frame = ((unsigned long *)p->tss.ksp)[6];
457 return ((unsigned long *)schedule_frame)[12];
458 }
459 return pc;
460 }
461 #endif
462 return 0;
463 }
464
465 #if defined(__i386__)
466 # define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019])
467 # define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022])
468 #elif defined(__alpha__)
469
470
471
472 # define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
473 + (long)&((struct pt_regs *)0)->reg)
474 # define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
475 # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
476 #endif
477
478
479 #define ADDBUF(buffer, string) \
480 do { memcpy(buffer, string, strlen(string)); \
481 buffer += strlen(string); } while (0)
482
483 static inline char * task_name(struct task_struct *p, char * buf)
484 {
485 int i;
486 char * name;
487
488 ADDBUF(buf, "Name:\t");
489 name = p->comm;
490 i = sizeof(p->comm);
491 do {
492 unsigned char c = *name;
493 name++;
494 i--;
495 *buf = c;
496 if (!c)
497 break;
498 if (c == '\\') {
499 buf[1] = c;
500 buf += 2;
501 continue;
502 }
503 if (c == '\n') {
504 buf[0] = '\\';
505 buf[1] = 'n';
506 buf += 2;
507 continue;
508 }
509 buf++;
510 } while (i);
511 *buf = '\n';
512 return buf+1;
513 }
514
515 static inline char * task_state(struct task_struct *p, char *buffer)
516 {
517 #define NR_STATES (sizeof(states)/sizeof(const char *))
518 unsigned int n = p->state;
519 static const char * states[] = {
520 "R (running)",
521 "S (sleeping)",
522 "D (disk sleep)",
523 "Z (zombie)",
524 "T (stopped)",
525 "W (paging)",
526 ". Huh?"
527 };
528
529 if (n >= NR_STATES)
530 n = NR_STATES-1;
531
532 buffer += sprintf(buffer,
533 "State:\t%s\n"
534 "Pid:\t%d\n"
535 "PPid:\t%d\n"
536 "Uid:\t%d\t%d\t%d\t%d\n"
537 "Gid:\t%d\t%d\t%d\t%d\n",
538 states[n],
539 p->pid, p->p_pptr->pid,
540 p->uid, p->euid, p->suid, p->fsuid,
541 p->gid, p->egid, p->sgid, p->fsgid);
542 return buffer;
543 }
544
545 static inline char * task_mem(struct task_struct *p, char *buffer)
546 {
547 struct mm_struct * mm = p->mm;
548
549 if (mm && mm != &init_mm) {
550 struct vm_area_struct * vma = mm->mmap;
551 unsigned long data = 0, stack = 0;
552 unsigned long exec = 0, lib = 0;
553
554 for (vma = mm->mmap; vma; vma = vma->vm_next) {
555 unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
556 if (!vma->vm_inode) {
557 data += len;
558 if (vma->vm_flags & VM_GROWSDOWN)
559 stack += len;
560 continue;
561 }
562 if (vma->vm_flags & VM_WRITE)
563 continue;
564 if (vma->vm_flags & VM_EXEC) {
565 exec += len;
566 if (vma->vm_flags & VM_EXECUTABLE)
567 continue;
568 lib += len;
569 }
570 }
571 buffer += sprintf(buffer,
572 "VmSize:\t%8lu kB\n"
573 "VmLck:\t%8lu kB\n"
574 "VmRSS:\t%8lu kB\n"
575 "VmData:\t%8lu kB\n"
576 "VmStk:\t%8lu kB\n"
577 "VmExe:\t%8lu kB\n"
578 "VmLib:\t%8lu kB\n",
579 mm->total_vm << (PAGE_SHIFT-10),
580 mm->locked_vm << (PAGE_SHIFT-10),
581 mm->rss << (PAGE_SHIFT-10),
582 data - stack, stack,
583 exec - lib, lib);
584 }
585 return buffer;
586 }
587
588 static inline char * task_sig(struct task_struct *p, char *buffer)
589 {
590 buffer += sprintf(buffer,
591 "SigPnd:\t%08lx\n"
592 "SigBlk:\t%08lx\n",
593 p->signal, p->blocked);
594 if (p->sig) {
595 struct sigaction * action = p->sig->action;
596 unsigned long sig_ign = 0, sig_caught = 0;
597 unsigned long bit = 1;
598 int i;
599
600 for (i = 0; i < 32; i++) {
601 switch((unsigned long) action->sa_handler) {
602 case 0:
603 break;
604 case 1:
605 sig_ign |= bit;
606 break;
607 default:
608 sig_caught |= bit;
609 }
610 bit <<= 1;
611 action++;
612 }
613
614 buffer += sprintf(buffer,
615 "SigIgn:\t%08lx\n"
616 "SigCgt:\t%08lx\n",
617 sig_ign, sig_caught);
618 }
619 return buffer;
620 }
621
622 static int get_status(int pid, char * buffer)
623 {
624 char * orig = buffer;
625 struct task_struct ** p = get_task(pid), *tsk;
626
627 if (!p || (tsk = *p) == NULL)
628 return 0;
629 buffer = task_name(tsk, buffer);
630 buffer = task_state(tsk, buffer);
631 buffer = task_mem(tsk, buffer);
632 buffer = task_sig(tsk, buffer);
633 return buffer - orig;
634 }
635
636 static int get_stat(int pid, char * buffer)
637 {
638 struct task_struct ** p = get_task(pid), *tsk;
639 unsigned long sigignore=0, sigcatch=0, wchan;
640 unsigned long vsize, eip, esp;
641 long priority, nice;
642 int i,tty_pgrp;
643 char state;
644
645 if (!p || (tsk = *p) == NULL)
646 return 0;
647 if (tsk->state < 0 || tsk->state > 5)
648 state = '.';
649 else
650 state = "RSDZTW"[tsk->state];
651 vsize = eip = esp = 0;
652 if (tsk->mm && tsk->mm != &init_mm) {
653 struct vm_area_struct *vma = tsk->mm->mmap;
654 while (vma) {
655 vsize += vma->vm_end - vma->vm_start;
656 vma = vma->vm_next;
657 }
658 if (tsk->kernel_stack_page) {
659 eip = KSTK_EIP(tsk);
660 esp = KSTK_ESP(tsk);
661 }
662 }
663 wchan = get_wchan(tsk);
664 if (tsk->sig) {
665 unsigned long bit = 1;
666 for(i=0; i<32; ++i) {
667 switch((unsigned long) tsk->sig->action[i].sa_handler) {
668 case 0:
669 break;
670 case 1:
671 sigignore |= bit;
672 break;
673 default:
674 sigcatch |= bit;
675 }
676 bit <<= 1;
677 }
678 }
679 if (tsk->tty)
680 tty_pgrp = tsk->tty->pgrp;
681 else
682 tty_pgrp = -1;
683
684
685
686 priority = tsk->counter;
687 priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
688 nice = tsk->priority;
689 nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
690
691 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
692 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu \
693 %lu %lu %lu %lu\n",
694 pid,
695 tsk->comm,
696 state,
697 tsk->p_pptr->pid,
698 tsk->pgrp,
699 tsk->session,
700 tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
701 tty_pgrp,
702 tsk->flags,
703 tsk->min_flt,
704 tsk->cmin_flt,
705 tsk->maj_flt,
706 tsk->cmaj_flt,
707 tsk->utime,
708 tsk->stime,
709 tsk->cutime,
710 tsk->cstime,
711 priority,
712 nice,
713 tsk->timeout,
714 tsk->it_real_value,
715 tsk->start_time,
716 vsize,
717 tsk->mm ? tsk->mm->rss : 0,
718 tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
719 tsk->mm ? tsk->mm->start_code : 0,
720 tsk->mm ? tsk->mm->end_code : 0,
721 tsk->mm ? tsk->mm->start_stack : 0,
722 esp,
723 eip,
724 tsk->signal,
725 tsk->blocked,
726 sigignore,
727 sigcatch,
728 wchan);
729 }
730
731 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
732 int * pages, int * shared, int * dirty, int * total)
733 {
734 pte_t * pte;
735 unsigned long end;
736
737 if (pmd_none(*pmd))
738 return;
739 if (pmd_bad(*pmd)) {
740 printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
741 pmd_clear(pmd);
742 return;
743 }
744 pte = pte_offset(pmd, address);
745 address &= ~PMD_MASK;
746 end = address + size;
747 if (end > PMD_SIZE)
748 end = PMD_SIZE;
749 do {
750 pte_t page = *pte;
751
752 address += PAGE_SIZE;
753 pte++;
754 if (pte_none(page))
755 continue;
756 ++*total;
757 if (!pte_present(page))
758 continue;
759 ++*pages;
760 if (pte_dirty(page))
761 ++*dirty;
762 if (pte_page(page) >= high_memory)
763 continue;
764 if (mem_map[MAP_NR(pte_page(page))].count > 1)
765 ++*shared;
766 } while (address < end);
767 }
768
769 static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
770 int * pages, int * shared, int * dirty, int * total)
771 {
772 pmd_t * pmd;
773 unsigned long end;
774
775 if (pgd_none(*pgd))
776 return;
777 if (pgd_bad(*pgd)) {
778 printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
779 pgd_clear(pgd);
780 return;
781 }
782 pmd = pmd_offset(pgd, address);
783 address &= ~PGDIR_MASK;
784 end = address + size;
785 if (end > PGDIR_SIZE)
786 end = PGDIR_SIZE;
787 do {
788 statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
789 address = (address + PMD_SIZE) & PMD_MASK;
790 pmd++;
791 } while (address < end);
792 }
793
794 static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
795 int * pages, int * shared, int * dirty, int * total)
796 {
797 while (address < end) {
798 statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
799 address = (address + PGDIR_SIZE) & PGDIR_MASK;
800 pgd++;
801 }
802 }
803
804 static int get_statm(int pid, char * buffer)
805 {
806 struct task_struct ** p = get_task(pid), *tsk;
807 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
808
809 if (!p || (tsk = *p) == NULL)
810 return 0;
811 if (tsk->mm && tsk->mm != &init_mm) {
812 struct vm_area_struct * vma = tsk->mm->mmap;
813
814 while (vma) {
815 pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
816 int pages = 0, shared = 0, dirty = 0, total = 0;
817
818 statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
819 resident += pages;
820 share += shared;
821 dt += dirty;
822 size += total;
823 if (vma->vm_flags & VM_EXECUTABLE)
824 trs += pages;
825 else if (vma->vm_flags & VM_GROWSDOWN)
826 drs += pages;
827 else if (vma->vm_end > 0x60000000)
828 lrs += pages;
829 else
830 drs += pages;
831 vma = vma->vm_next;
832 }
833 }
834 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
835 size, resident, share, trs, lrs, drs, dt);
836 }
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854 #define MAPS_LINE_LENGTH 1024
855 #define MAPS_LINE_SHIFT 10
856
857
858
859
860 #define MAPS_LINE_FORMAT "%08lx-%08lx %s %08lx %s %lu\n"
861 #define MAPS_LINE_MAX 49
862
863 static int read_maps (int pid, struct file * file, char * buf, int count)
864 {
865 struct task_struct ** p = get_task(pid);
866 char * destptr;
867 loff_t lineno;
868 int column;
869 struct vm_area_struct * map;
870 int i;
871
872 if (!p || !*p)
873 return -EINVAL;
874
875 if (!(*p)->mm || (*p)->mm == &init_mm || count == 0)
876 return 0;
877
878
879 lineno = file->f_pos >> MAPS_LINE_SHIFT;
880 column = file->f_pos & (MAPS_LINE_LENGTH-1);
881
882
883 for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
884 continue;
885
886 destptr = buf;
887
888 for ( ; map ; ) {
889
890 char line[MAPS_LINE_MAX+1];
891 char str[5], *cp = str;
892 int flags;
893 kdev_t dev;
894 unsigned long ino;
895 int len;
896
897 flags = map->vm_flags;
898
899 *cp++ = flags & VM_READ ? 'r' : '-';
900 *cp++ = flags & VM_WRITE ? 'w' : '-';
901 *cp++ = flags & VM_EXEC ? 'x' : '-';
902 *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
903 *cp++ = 0;
904
905 if (map->vm_inode != NULL) {
906 dev = map->vm_inode->i_dev;
907 ino = map->vm_inode->i_ino;
908 } else {
909 dev = 0;
910 ino = 0;
911 }
912
913 len = sprintf(line, MAPS_LINE_FORMAT,
914 map->vm_start, map->vm_end, str, map->vm_offset,
915 kdevname(dev), ino);
916
917 if (column >= len) {
918 column = 0;
919 lineno++;
920 map = map->vm_next;
921 continue;
922 }
923
924 i = len-column;
925 if (i > count)
926 i = count;
927 memcpy_tofs(destptr, line+column, i);
928 destptr += i; count -= i;
929 column += i;
930 if (column >= len) {
931 column = 0;
932 lineno++;
933 map = map->vm_next;
934 }
935
936
937 if (count == 0)
938 break;
939
940
941
942
943 if (*p != current)
944 break;
945 }
946
947
948 file->f_pos = (lineno << MAPS_LINE_SHIFT) + column;
949
950 return destptr-buf;
951 }
952
953 #ifdef CONFIG_MODULES
954 extern int get_module_list(char *);
955 extern int get_ksyms_list(char *, char **, off_t, int);
956 #endif
957 extern int get_device_list(char *);
958 extern int get_filesystem_list(char *);
959 extern int get_filesystem_info( char * );
960 extern int get_irq_list(char *);
961 extern int get_dma_list(char *);
962 extern int get_cpuinfo(char *);
963 extern int get_pci_list(char*);
964 extern int get_md_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 CONFIG_APM
1027 case PROC_APM:
1028 return apm_proc(page);
1029 #endif
1030 #ifdef __SMP_PROF__
1031 case PROC_SMP_PROF:
1032 return get_smp_prof_list(page);
1033 #endif
1034 case PROC_CMDLINE:
1035 return get_cmdline(page);
1036
1037 case PROC_MTAB:
1038 return get_filesystem_info( page );
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 };