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 flags;
414 int end = sz + 80;
415 dev_t dev;
416 unsigned long ino;
417
418 flags = map->vm_flags;
419
420 *cp++ = flags & VM_READ ? 'r' : '-';
421 *cp++ = flags & VM_WRITE ? 'w' : '-';
422 *cp++ = flags & VM_EXEC ? 'x' : '-';
423 *cp++ = flags & VM_SHARED ? 's' : 'p';
424 *cp++ = 0;
425
426 if (end >= PAGE_SIZE) {
427 sprintf(buf+sz, "...\n");
428 break;
429 }
430
431 if (map->vm_inode != NULL) {
432 dev = map->vm_inode->i_dev;
433 ino = map->vm_inode->i_ino;
434 } else {
435 dev = 0;
436 ino = 0;
437 }
438
439 sz += sprintf(buf+sz, "%08lx-%08lx %s %08lx %02x:%02x %lu\n",
440 map->vm_start, map->vm_end, str, map->vm_offset,
441 MAJOR(dev),MINOR(dev), ino);
442 if (sz > end) {
443 printk("get_maps: end(%d) < sz(%d)\n", end, sz);
444 break;
445 }
446 }
447
448 return sz;
449 }
450
451 extern int get_module_list(char *);
452 extern int get_device_list(char *);
453 extern int get_filesystem_list(char *);
454 extern int get_ksyms_list(char *);
455
456 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
457 {
458 char * page;
459 int length;
460 int end;
461 unsigned int type, pid;
462
463 if (count < 0)
464 return -EINVAL;
465 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
466 return -ENOMEM;
467 type = inode->i_ino;
468 pid = type >> 16;
469 type &= 0x0000ffff;
470 switch (type) {
471 case 2:
472 length = get_loadavg(page);
473 break;
474 case 3:
475 length = get_uptime(page);
476 break;
477 case 4:
478 length = get_meminfo(page);
479 break;
480 case 6:
481 length = get_version(page);
482 break;
483 case 9:
484 length = get_env(pid, page);
485 break;
486 case 10:
487 length = get_arg(pid, page);
488 break;
489 case 11:
490 length = get_stat(pid, page);
491 break;
492 case 12:
493 length = get_statm(pid, page);
494 break;
495 #ifdef CONFIG_DEBUG_MALLOC
496 case 13:
497 length = get_malloc(page);
498 break;
499 #endif
500 case 14:
501 free_page((unsigned long) page);
502 return read_core(inode, file, buf, count);
503 case 15:
504 length = get_maps(pid, page);
505 break;
506 case 16:
507 length = get_module_list(page);
508 break;
509 case 17:
510 length = get_kstat(page);
511 break;
512 case 18:
513 length = get_device_list(page);
514 break;
515 case 19:
516 length = get_filesystem_list(page);
517 break;
518 case 20:
519 length = get_ksyms_list(page);
520 break;
521 default:
522 free_page((unsigned long) page);
523 return -EBADF;
524 }
525 if (file->f_pos >= length) {
526 free_page((unsigned long) page);
527 return 0;
528 }
529 if (count + file->f_pos > length)
530 count = length - file->f_pos;
531 end = count + file->f_pos;
532 memcpy_tofs(buf, page + file->f_pos, count);
533 free_page((unsigned long) page);
534 file->f_pos = end;
535 return count;
536 }
537
538 static struct file_operations proc_array_operations = {
539 NULL,
540 array_read,
541 NULL,
542 NULL,
543 NULL,
544 NULL,
545 NULL,
546 NULL,
547 NULL,
548 NULL
549 };
550
551 struct inode_operations proc_array_inode_operations = {
552 &proc_array_operations,
553 NULL,
554 NULL,
555 NULL,
556 NULL,
557 NULL,
558 NULL,
559 NULL,
560 NULL,
561 NULL,
562 NULL,
563 NULL,
564 NULL,
565 NULL,
566 NULL
567 };