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)->env_start, (*p)->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)->arg_start, (*p)->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)->brk - (*p)->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 tty_pgrp = (*p)->tty;
310 if (tty_pgrp > 0 && tty_table[tty_pgrp])
311 tty_pgrp = tty_table[tty_pgrp]->pgrp;
312 else
313 tty_pgrp = -1;
314 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
315 %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %u %u %lu %lu %lu %lu %lu %lu \
316 %lu %lu %lu %lu\n",
317 pid,
318 (*p)->comm,
319 state,
320 (*p)->p_pptr->pid,
321 (*p)->pgrp,
322 (*p)->session,
323 (*p)->tty,
324 tty_pgrp,
325 (*p)->flags,
326 (*p)->min_flt,
327 (*p)->cmin_flt,
328 (*p)->maj_flt,
329 (*p)->cmaj_flt,
330 (*p)->utime,
331 (*p)->stime,
332 (*p)->cutime,
333 (*p)->cstime,
334 (*p)->counter,
335
336 (*p)->priority,
337
338 (*p)->timeout,
339 (*p)->it_real_value,
340 (*p)->start_time,
341 vsize,
342 (*p)->rss,
343 (*p)->rlim[RLIMIT_RSS].rlim_cur,
344 (*p)->start_code,
345 (*p)->end_code,
346 (*p)->start_stack,
347 esp,
348 eip,
349 (*p)->signal,
350 (*p)->blocked,
351 sigignore,
352 sigcatch,
353 wchan);
354 }
355
356 static int get_statm(int pid, char * buffer)
357 {
358 struct task_struct ** p = get_task(pid);
359 int i, tpag;
360 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
361 unsigned long ptbl, *buf, *pte, *pagedir, map_nr;
362
363 if (!p || !*p)
364 return 0;
365 tpag = (*p)->end_code / PAGE_SIZE;
366 if ((*p)->state != TASK_ZOMBIE) {
367 pagedir = (unsigned long *) (*p)->tss.cr3;
368 for (i = 0; i < 0x300; ++i) {
369 if ((ptbl = pagedir[i]) == 0) {
370 tpag -= PTRS_PER_PAGE;
371 continue;
372 }
373 buf = (unsigned long *)(ptbl & PAGE_MASK);
374 for (pte = buf; pte < (buf + PTRS_PER_PAGE); ++pte) {
375 if (*pte != 0) {
376 ++size;
377 if (*pte & 1) {
378 ++resident;
379 if (tpag > 0)
380 ++trs;
381 else
382 ++drs;
383 if (i >= 15 && i < 0x2f0) {
384 ++lrs;
385 if (*pte & 0x40)
386 ++dt;
387 else
388 --drs;
389 }
390 map_nr = MAP_NR(*pte);
391 if (map_nr < (high_memory / PAGE_SIZE) && mem_map[map_nr] > 1)
392 ++share;
393 }
394 }
395 --tpag;
396 }
397 }
398 }
399 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
400 size, resident, share, trs, lrs, drs, dt);
401 }
402
403 static int get_maps(int pid, char *buf)
404 {
405 int sz = 0;
406 struct task_struct **p = get_task(pid);
407 struct vm_area_struct *map;
408
409 if (!p || !*p)
410 return 0;
411
412 for(map = (*p)->mmap; map != NULL; map = map->vm_next) {
413 char str[7], *cp = str;
414 int prot = map->vm_page_prot;
415 int perms, flags;
416 int end = sz + 80;
417 dev_t dev;
418 unsigned long ino;
419
420
421
422
423
424
425
426 flags = perms = 0;
427
428 if ((prot & PAGE_READONLY) == PAGE_READONLY)
429 perms |= PROT_READ | PROT_EXEC;
430 if (prot & (PAGE_COW|PAGE_RW)) {
431 perms |= PROT_WRITE | PROT_READ;
432 flags = prot & PAGE_COW ? MAP_PRIVATE : MAP_SHARED;
433 }
434
435 *cp++ = perms & PROT_READ ? 'r' : '-';
436 *cp++ = perms & PROT_WRITE ? 'w' : '-';
437 *cp++ = perms & PROT_EXEC ? 'x' : '-';
438 *cp++ = flags & MAP_SHARED ? 's' : '-';
439 *cp++ = flags & MAP_PRIVATE ? 'p' : '-';
440 *cp++ = 0;
441
442 if (end >= PAGE_SIZE) {
443 sprintf(buf+sz, "...\n");
444 break;
445 }
446
447 if (map->vm_inode != NULL) {
448 dev = map->vm_inode->i_dev;
449 ino = map->vm_inode->i_ino;
450 } else {
451 dev = 0;
452 ino = 0;
453 }
454
455 sz += sprintf(buf+sz, "%08lx-%08lx %s %08lx %02x:%02x %lu\n",
456 map->vm_start, map->vm_end, str, map->vm_offset,
457 MAJOR(dev),MINOR(dev), ino);
458 if (sz > end) {
459 printk("get_maps: end(%d) < sz(%d)\n", end, sz);
460 break;
461 }
462 }
463
464 return sz;
465 }
466
467 extern int get_module_list(char *);
468 extern int get_device_list(char *);
469
470 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
471 {
472 char * page;
473 int length;
474 int end;
475 unsigned int type, pid;
476
477 if (count < 0)
478 return -EINVAL;
479 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
480 return -ENOMEM;
481 type = inode->i_ino;
482 pid = type >> 16;
483 type &= 0x0000ffff;
484 switch (type) {
485 case 2:
486 length = get_loadavg(page);
487 break;
488 case 3:
489 length = get_uptime(page);
490 break;
491 case 4:
492 length = get_meminfo(page);
493 break;
494 case 6:
495 length = get_version(page);
496 break;
497 case 9:
498 length = get_env(pid, page);
499 break;
500 case 10:
501 length = get_arg(pid, page);
502 break;
503 case 11:
504 length = get_stat(pid, page);
505 break;
506 case 12:
507 length = get_statm(pid, page);
508 break;
509 #ifdef CONFIG_DEBUG_MALLOC
510 case 13:
511 length = get_malloc(page);
512 break;
513 #endif
514 case 14:
515 free_page((unsigned long) page);
516 return read_core(inode, file, buf, count);
517 case 15:
518 length = get_maps(pid, page);
519 break;
520 case 16:
521 length = get_module_list(page);
522 break;
523 case 17:
524 length = get_kstat(page);
525 break;
526 case 18:
527 length = get_device_list(page);
528 break;
529 default:
530 free_page((unsigned long) page);
531 return -EBADF;
532 }
533 if (file->f_pos >= length) {
534 free_page((unsigned long) page);
535 return 0;
536 }
537 if (count + file->f_pos > length)
538 count = length - file->f_pos;
539 end = count + file->f_pos;
540 memcpy_tofs(buf, page + file->f_pos, count);
541 free_page((unsigned long) page);
542 file->f_pos = end;
543 return count;
544 }
545
546 static struct file_operations proc_array_operations = {
547 NULL,
548 array_read,
549 NULL,
550 NULL,
551 NULL,
552 NULL,
553 NULL,
554 NULL,
555 NULL,
556 NULL
557 };
558
559 struct inode_operations proc_array_inode_operations = {
560 &proc_array_operations,
561 NULL,
562 NULL,
563 NULL,
564 NULL,
565 NULL,
566 NULL,
567 NULL,
568 NULL,
569 NULL,
570 NULL,
571 NULL,
572 NULL,
573 NULL,
574 NULL
575 };