This source file includes following definitions.
- read_core
- get_loadavg
- get_kstat
- get_uptime
- get_meminfo
- get_version
- get_task
- get_phys_addr
- get_array
- get_env
- get_arg
- get_wchan
- get_stat
- get_statm
- get_maps
- array_read
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <linux/types.h>
19 #include <linux/errno.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
22 #include <linux/kernel_stat.h>
23 #include <linux/tty.h>
24 #include <linux/user.h>
25 #include <linux/a.out.h>
26 #include <linux/string.h>
27 #include <linux/mman.h>
28
29 #include <asm/segment.h>
30 #include <asm/io.h>
31
32 #define LOAD_INT(x) ((x) >> FSHIFT)
33 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
34
35 #ifdef CONFIG_DEBUG_MALLOC
36 int get_malloc(char * buffer);
37 #endif
38
39 static int read_core(struct inode * inode, struct file * file,char * buf, int count)
40 {
41 unsigned long p = file->f_pos;
42 int read;
43 int count1;
44 char * pnt;
45 struct user dump;
46
47 memset(&dump, 0, sizeof(struct user));
48 dump.magic = CMAGIC;
49 dump.u_dsize = high_memory >> 12;
50
51 if (count < 0)
52 return -EINVAL;
53 if (p >= high_memory + PAGE_SIZE)
54 return 0;
55 if (count > high_memory + PAGE_SIZE - p)
56 count = high_memory + PAGE_SIZE - p;
57 read = 0;
58
59 if (p < sizeof(struct user) && count > 0) {
60 count1 = count;
61 if (p + count1 > sizeof(struct user))
62 count1 = sizeof(struct user)-p;
63 pnt = (char *) &dump + p;
64 memcpy_tofs(buf,(void *) pnt, count1);
65 buf += count1;
66 p += count1;
67 count -= count1;
68 read += count1;
69 }
70
71 while (p < 2*PAGE_SIZE && count > 0) {
72 put_fs_byte(0,buf);
73 buf++;
74 p++;
75 count--;
76 read++;
77 }
78 memcpy_tofs(buf,(void *) (p - PAGE_SIZE),count);
79 read += count;
80 file->f_pos += read;
81 return read;
82 }
83
84 static int get_loadavg(char * buffer)
85 {
86 int a, b, c;
87
88 a = avenrun[0] + (FIXED_1/200);
89 b = avenrun[1] + (FIXED_1/200);
90 c = avenrun[2] + (FIXED_1/200);
91 return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n",
92 LOAD_INT(a), LOAD_FRAC(a),
93 LOAD_INT(b), LOAD_FRAC(b),
94 LOAD_INT(c), LOAD_FRAC(c));
95 }
96
97 static int get_kstat(char * buffer)
98 {
99 int i, len;
100 unsigned sum = 0;
101
102 for (i = 0 ; i < 16 ; i++)
103 sum += kstat.interrupts[i];
104 len = sprintf(buffer,
105 "cpu %u %u %u %lu\n"
106 "disk %u %u %u %u\n"
107 "page %u %u\n"
108 "swap %u %u\n"
109 "intr %u",
110 kstat.cpu_user,
111 kstat.cpu_nice,
112 kstat.cpu_system,
113 jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
114 kstat.dk_drive[0],
115 kstat.dk_drive[1],
116 kstat.dk_drive[2],
117 kstat.dk_drive[3],
118 kstat.pgpgin,
119 kstat.pgpgout,
120 kstat.pswpin,
121 kstat.pswpout,
122 sum);
123 for (i = 0 ; i < 16 ; i++)
124 len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
125 len += sprintf(buffer + len,
126 "\nctxt %u\n"
127 "btime %lu\n",
128 kstat.context_swtch,
129 xtime.tv_sec - jiffies / HZ);
130 return len;
131 }
132
133
134 static int get_uptime(char * buffer)
135 {
136 unsigned long uptime;
137 unsigned long idle;
138
139 uptime = jiffies;
140 idle = task[0]->utime + task[0]->stime;
141 return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
142 uptime / HZ,
143 uptime % HZ,
144 idle / HZ,
145 idle % HZ);
146 }
147
148 static int get_meminfo(char * buffer)
149 {
150 struct sysinfo i;
151
152 si_meminfo(&i);
153 si_swapinfo(&i);
154 return sprintf(buffer, " total: used: free: shared: buffers:\n"
155 "Mem: %8lu %8lu %8lu %8lu %8lu\n"
156 "Swap: %8lu %8lu %8lu\n",
157 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
158 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
159 }
160
161 static int get_version(char * buffer)
162 {
163 extern char *linux_banner;
164
165 strcpy(buffer, linux_banner);
166 return strlen(buffer);
167 }
168
169 static struct task_struct ** get_task(pid_t pid)
170 {
171 struct task_struct ** p;
172
173 p = task;
174 while (++p < task+NR_TASKS) {
175 if (*p && (*p)->pid == pid)
176 return p;
177 }
178 return NULL;
179 }
180
181 static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
182 {
183 unsigned long page;
184
185 if (!p || !*p || ptr >= TASK_SIZE)
186 return 0;
187 page = *PAGE_DIR_OFFSET((*p)->tss.cr3,ptr);
188 if (!(page & PAGE_PRESENT))
189 return 0;
190 page &= PAGE_MASK;
191 page += PAGE_PTR(ptr);
192 page = *(unsigned long *) page;
193 if (!(page & PAGE_PRESENT))
194 return 0;
195 page &= PAGE_MASK;
196 page += ptr & ~PAGE_MASK;
197 return page;
198 }
199
200 static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
201 {
202 unsigned long addr;
203 int size = 0, result = 0;
204 char c;
205
206 if (start >= end)
207 return result;
208 for (;;) {
209 addr = get_phys_addr(p, start);
210 if (!addr)
211 goto ready;
212 do {
213 c = *(char *) addr;
214 if (!c)
215 result = size;
216 if (size < PAGE_SIZE)
217 buffer[size++] = c;
218 else
219 goto ready;
220 addr++;
221 start++;
222 if (!c && start >= end)
223 goto ready;
224 } while (addr & ~PAGE_MASK);
225 }
226 ready:
227
228 while (result>0 && buffer[result-1]==' ')
229 result--;
230 return result;
231 }
232
233 static int get_env(int pid, char * buffer)
234 {
235 struct task_struct ** p = get_task(pid);
236
237 if (!p || !*p)
238 return 0;
239 return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer);
240 }
241
242 static int get_arg(int pid, char * buffer)
243 {
244 struct task_struct ** p = get_task(pid);
245
246 if (!p || !*p)
247 return 0;
248 return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer);
249 }
250
251 static unsigned long get_wchan(struct task_struct *p)
252 {
253 unsigned long ebp, eip;
254 unsigned long stack_page;
255 int count = 0;
256
257 if (!p || p == current || p->state == TASK_RUNNING)
258 return 0;
259 stack_page = p->kernel_stack_page;
260 if (!stack_page)
261 return 0;
262 ebp = p->tss.ebp;
263 do {
264 if (ebp < stack_page || ebp >= 4092+stack_page)
265 return 0;
266 eip = *(unsigned long *) (ebp+4);
267 if ((void *)eip != sleep_on &&
268 (void *)eip != interruptible_sleep_on)
269 return eip;
270 ebp = *(unsigned long *) ebp;
271 } while (count++ < 16);
272 return 0;
273 }
274
275 #define KSTK_EIP(stack) (((unsigned long *)stack)[1019])
276 #define KSTK_ESP(stack) (((unsigned long *)stack)[1022])
277
278 static int get_stat(int pid, char * buffer)
279 {
280 struct task_struct ** p = get_task(pid);
281 unsigned long sigignore=0, sigcatch=0, bit=1, wchan;
282 unsigned long vsize, eip, esp;
283 int i,tty_pgrp;
284 char state;
285
286 if (!p || !*p)
287 return 0;
288 if ((*p)->state < 0 || (*p)->state > 5)
289 state = '.';
290 else
291 state = "RSDZTD"[(*p)->state];
292 eip = esp = 0;
293 vsize = (*p)->kernel_stack_page;
294 if (vsize) {
295 eip = KSTK_EIP(vsize);
296 esp = KSTK_ESP(vsize);
297 vsize = (*p)->mm->brk - (*p)->mm->start_code + PAGE_SIZE-1;
298 if (esp)
299 vsize += TASK_SIZE - esp;
300 }
301 wchan = get_wchan(*p);
302 for(i=0; i<32; ++i) {
303 switch((int) (*p)->sigaction[i].sa_handler) {
304 case 1: sigignore |= bit; break;
305 case 0: break;
306 default: sigcatch |= bit;
307 } bit <<= 1;
308 }
309 if ((*p)->tty)
310 tty_pgrp = (*p)->tty->pgrp;
311 else
312 tty_pgrp = -1;
313 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
314 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %u %lu %lu %lu %lu %lu %lu \
315 %lu %lu %lu %lu\n",
316 pid,
317 (*p)->comm,
318 state,
319 (*p)->p_pptr->pid,
320 (*p)->pgrp,
321 (*p)->session,
322 (*p)->tty ? (*p)->tty->device : 0,
323 tty_pgrp,
324 (*p)->flags,
325 (*p)->mm->min_flt,
326 (*p)->mm->cmin_flt,
327 (*p)->mm->maj_flt,
328 (*p)->mm->cmaj_flt,
329 (*p)->utime,
330 (*p)->stime,
331 (*p)->cutime,
332 (*p)->cstime,
333 (*p)->counter,
334
335 (*p)->priority,
336
337 (*p)->timeout,
338 (*p)->it_real_value,
339 (*p)->start_time,
340 vsize,
341 (*p)->mm->rss,
342 (*p)->rlim[RLIMIT_RSS].rlim_cur,
343 (*p)->mm->start_code,
344 (*p)->mm->end_code,
345 (*p)->mm->start_stack,
346 esp,
347 eip,
348 (*p)->signal,
349 (*p)->blocked,
350 sigignore,
351 sigcatch,
352 wchan);
353 }
354
355 static int get_statm(int pid, char * buffer)
356 {
357 struct task_struct ** p = get_task(pid);
358 int i, tpag;
359 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
360 unsigned long ptbl, *buf, *pte, *pagedir, map_nr;
361
362 if (!p || !*p)
363 return 0;
364 tpag = (*p)->mm->end_code / PAGE_SIZE;
365 if ((*p)->state != TASK_ZOMBIE) {
366 pagedir = (unsigned long *) (*p)->tss.cr3;
367 for (i = 0; i < 0x300; ++i) {
368 if ((ptbl = pagedir[i]) == 0) {
369 tpag -= PTRS_PER_PAGE;
370 continue;
371 }
372 buf = (unsigned long *)(ptbl & PAGE_MASK);
373 for (pte = buf; pte < (buf + PTRS_PER_PAGE); ++pte) {
374 if (*pte != 0) {
375 ++size;
376 if (*pte & 1) {
377 ++resident;
378 if (tpag > 0)
379 ++trs;
380 else
381 ++drs;
382 if (i >= 15 && i < 0x2f0) {
383 ++lrs;
384 if (*pte & 0x40)
385 ++dt;
386 else
387 --drs;
388 }
389 map_nr = MAP_NR(*pte);
390 if (map_nr < (high_memory / PAGE_SIZE) && mem_map[map_nr] > 1)
391 ++share;
392 }
393 }
394 --tpag;
395 }
396 }
397 }
398 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
399 size, resident, share, trs, lrs, drs, dt);
400 }
401
402 static int get_maps(int pid, char *buf)
403 {
404 int sz = 0;
405 struct task_struct **p = get_task(pid);
406 struct vm_area_struct *map;
407
408 if (!p || !*p)
409 return 0;
410
411 for(map = (*p)->mm->mmap; map != NULL; map = map->vm_next) {
412 char str[7], *cp = str;
413 int prot = map->vm_page_prot;
414 int perms, flags;
415 int end = sz + 80;
416 dev_t dev;
417 unsigned long ino;
418
419
420
421
422
423
424
425 flags = perms = 0;
426
427 if ((prot & PAGE_READONLY) == PAGE_READONLY)
428 perms |= PROT_READ | PROT_EXEC;
429 if (prot & (PAGE_COW|PAGE_RW)) {
430 perms |= PROT_WRITE | PROT_READ;
431 flags = prot & PAGE_COW ? MAP_PRIVATE : MAP_SHARED;
432 }
433
434 *cp++ = perms & PROT_READ ? 'r' : '-';
435 *cp++ = perms & PROT_WRITE ? 'w' : '-';
436 *cp++ = perms & PROT_EXEC ? 'x' : '-';
437 *cp++ = flags & MAP_SHARED ? 's' : '-';
438 *cp++ = flags & MAP_PRIVATE ? 'p' : '-';
439 *cp++ = 0;
440
441 if (end >= PAGE_SIZE) {
442 sprintf(buf+sz, "...\n");
443 break;
444 }
445
446 if (map->vm_inode != NULL) {
447 dev = map->vm_inode->i_dev;
448 ino = map->vm_inode->i_ino;
449 } else {
450 dev = 0;
451 ino = 0;
452 }
453
454 sz += sprintf(buf+sz, "%08lx-%08lx %s %08lx %02x:%02x %lu\n",
455 map->vm_start, map->vm_end, str, map->vm_offset,
456 MAJOR(dev),MINOR(dev), ino);
457 if (sz > end) {
458 printk("get_maps: end(%d) < sz(%d)\n", end, sz);
459 break;
460 }
461 }
462
463 return sz;
464 }
465
466 extern int get_module_list(char *);
467 extern int get_device_list(char *);
468 extern int get_filesystem_list(char *);
469 extern int get_ksyms_list(char *);
470
471 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
472 {
473 char * page;
474 int length;
475 int end;
476 unsigned int type, pid;
477
478 if (count < 0)
479 return -EINVAL;
480 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
481 return -ENOMEM;
482 type = inode->i_ino;
483 pid = type >> 16;
484 type &= 0x0000ffff;
485 switch (type) {
486 case 2:
487 length = get_loadavg(page);
488 break;
489 case 3:
490 length = get_uptime(page);
491 break;
492 case 4:
493 length = get_meminfo(page);
494 break;
495 case 6:
496 length = get_version(page);
497 break;
498 case 9:
499 length = get_env(pid, page);
500 break;
501 case 10:
502 length = get_arg(pid, page);
503 break;
504 case 11:
505 length = get_stat(pid, page);
506 break;
507 case 12:
508 length = get_statm(pid, page);
509 break;
510 #ifdef CONFIG_DEBUG_MALLOC
511 case 13:
512 length = get_malloc(page);
513 break;
514 #endif
515 case 14:
516 free_page((unsigned long) page);
517 return read_core(inode, file, buf, count);
518 case 15:
519 length = get_maps(pid, page);
520 break;
521 case 16:
522 length = get_module_list(page);
523 break;
524 case 17:
525 length = get_kstat(page);
526 break;
527 case 18:
528 length = get_device_list(page);
529 break;
530 case 19:
531 length = get_filesystem_list(page);
532 break;
533 case 20:
534 length = get_ksyms_list(page);
535 break;
536 default:
537 free_page((unsigned long) page);
538 return -EBADF;
539 }
540 if (file->f_pos >= length) {
541 free_page((unsigned long) page);
542 return 0;
543 }
544 if (count + file->f_pos > length)
545 count = length - file->f_pos;
546 end = count + file->f_pos;
547 memcpy_tofs(buf, page + file->f_pos, count);
548 free_page((unsigned long) page);
549 file->f_pos = end;
550 return count;
551 }
552
553 static struct file_operations proc_array_operations = {
554 NULL,
555 array_read,
556 NULL,
557 NULL,
558 NULL,
559 NULL,
560 NULL,
561 NULL,
562 NULL,
563 NULL
564 };
565
566 struct inode_operations proc_array_inode_operations = {
567 &proc_array_operations,
568 NULL,
569 NULL,
570 NULL,
571 NULL,
572 NULL,
573 NULL,
574 NULL,
575 NULL,
576 NULL,
577 NULL,
578 NULL,
579 NULL,
580 NULL,
581 NULL
582 };