root/fs/proc/array.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_loadavg
  2. get_uptime
  3. get_meminfo
  4. get_task
  5. get_phys_addr
  6. get_long
  7. get_char
  8. get_array
  9. get_env
  10. get_arg
  11. get_stat
  12. array_read

   1 /*
   2  *  linux/fs/proc/array.c
   3  *
   4  *  Copyright (C) 1992  by Linus Torvalds
   5  *  based on ideas by Darren Senn
   6  */
   7 
   8 #include <linux/types.h>
   9 #include <linux/errno.h>
  10 #include <linux/sched.h>
  11 #include <linux/kernel.h>
  12 
  13 #include <asm/segment.h>
  14 #include <asm/io.h>
  15 
  16 static int get_loadavg(char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
  17 {
  18         return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n",
  19                 avenrun[0] >> FSHIFT,
  20                 (FIXED_1/2 + (avenrun[0] & (FIXED_1-1))*100) >> FSHIFT,
  21                 avenrun[1] >> FSHIFT,
  22                 (FIXED_1/2 + (avenrun[1] & (FIXED_1-1))*100) >> FSHIFT,
  23                 avenrun[2] >> FSHIFT,
  24                 (FIXED_1/2 + (avenrun[2] & (FIXED_1-1))*100) >> FSHIFT);
  25 }
  26 
  27 static int get_uptime(char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
  28 {
  29         return sprintf(buffer,"%d\n",(jiffies+jiffies_offset)/HZ);
  30 }
  31 
  32 static int get_meminfo(char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         struct sysinfo i;
  35 
  36         si_meminfo(&i);
  37         si_swapinfo(&i);
  38         return sprintf(buffer, "        total:   used:    free:   shared:  buffers:\n"
  39                 "Mem:  %8d %8d %8d %8d %8d\n"
  40                 "Swap: %8d %8d %8d\n",
  41                 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
  42                 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
  43 }
  44 
  45 static struct task_struct ** get_task(pid_t pid)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47         struct task_struct ** p;
  48 
  49         p = task;
  50         while (++p < task+NR_TASKS) {
  51                 if (*p && (*p)->pid == pid)
  52                         return p;
  53         }
  54         return NULL;
  55 }
  56 
  57 static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         unsigned long page;
  60 
  61         if (!p || !*p || ptr >= TASK_SIZE)
  62                 return 0;
  63         page = (*p)->tss.cr3;
  64         page += (ptr >> 20) & 0xffc;
  65         page = *(unsigned long *) page;
  66         if (!(page & 1))
  67                 return 0;
  68         page &= 0xfffff000;
  69         page += (ptr >> 10) & 0xffc;
  70         page = *(unsigned long *) page;
  71         if (!(page & 1))
  72                 return 0;
  73         page &= 0xfffff000;
  74         page += ptr & 0xfff;
  75         return page;
  76 }
  77 
  78 static unsigned long get_long(struct task_struct ** p, unsigned long ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         unsigned long addr;
  81 
  82         if (ptr & 3)
  83                 return 0;
  84         addr = get_phys_addr(p,ptr);
  85         if (!addr)
  86                 return 0;
  87         return *(unsigned long *) addr;
  88 }
  89 
  90 static int get_char(struct task_struct ** p, unsigned long ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         unsigned long addr;
  93 
  94         addr = get_phys_addr(p,ptr);
  95         if (!addr)
  96                 return -1;
  97         return *(unsigned char *) addr;
  98 }
  99 
 100 static int get_array(struct task_struct ** p, unsigned long ptr, char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         unsigned long tmp;
 103         int size = 0, result = 0;
 104         unsigned long array;
 105         char c;
 106 
 107         array = get_long(p,ptr);
 108         if (!ptr)
 109                 return 0;
 110         for (;;) {
 111                 tmp = get_long(p,array);
 112                 if (!tmp)
 113                         return result;
 114                 array += 4;
 115                 while ((c = get_char(p,tmp++)) > 0) {
 116                         if (size < PAGE_SIZE)
 117                                 buffer[size++] = c;
 118                         else
 119                                 return result;
 120                 }
 121                 if (c < 0)
 122                         return result;
 123                 result = size;
 124                 if (size < PAGE_SIZE)
 125                         buffer[size++] = '\0';
 126         }
 127 }
 128 
 129 static int get_env(int pid, char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         struct task_struct ** p = get_task(pid);
 132 
 133         if (!p || !*p)
 134                 return 0;
 135         return get_array(p, (*p)->start_stack+8, buffer);
 136 }
 137 
 138 static int get_arg(int pid, char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140         struct task_struct ** p = get_task(pid);
 141 
 142         if (!p || !*p)
 143                 return 0;
 144         return get_array(p, (*p)->start_stack+4, buffer);
 145 }
 146 
 147 static int get_stat(int pid, char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 148 {
 149         struct task_struct ** p = get_task(pid);
 150         char state;
 151 
 152         if (!p || !*p)
 153                 return 0;
 154         if ((*p)->state < 0)
 155                 state = '.';
 156         else
 157                 state = "RSDZTD"[(*p)->state];
 158         return sprintf(buffer,"%d (%s) %c %d %d %d %d\n",
 159                 pid,
 160                 (*p)->comm,
 161                 state,
 162                 (*p)->p_pptr->pid,
 163                 (*p)->pgrp,
 164                 (*p)->session,
 165                 (*p)->tty);
 166 }
 167 
 168 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 169 {
 170         char * page;
 171         int length;
 172         int end;
 173         int type, pid;
 174 
 175         if (count < 0)
 176                 return -EINVAL;
 177         page = (char *) get_free_page(GFP_KERNEL);
 178         *page = 0;
 179         if (!page)
 180                 return -ENOMEM;
 181         type = inode->i_ino;
 182         pid = type >> 16;
 183         type &= 0x0000ffff;
 184         switch (type) {
 185                 case 2:
 186                         length = get_loadavg(page);
 187                         break;
 188                 case 3:
 189                         length = get_uptime(page);
 190                         break;
 191                 case 4:
 192                         length = get_meminfo(page);
 193                         break;
 194                 case 9:
 195                         length = get_env(pid, page);
 196                         break;
 197                 case 10:
 198                         length = get_arg(pid, page);
 199                         break;
 200                 case 11:
 201                         length = get_stat(pid, page);
 202                         break;
 203                 default:
 204                         return -EBADF;
 205         }
 206         if (file->f_pos >= length)
 207                 return 0;
 208         if (count + file->f_pos > length)
 209                 count = length - file->f_pos;
 210         end = count + file->f_pos;
 211         memcpy_tofs(buf, page + file->f_pos, count);
 212         free_page((unsigned long) page);
 213         file->f_pos = end;
 214         return count;
 215 }
 216 
 217 static struct file_operations proc_array_operations = {
 218         NULL,           /* array_lseek */
 219         array_read,
 220         NULL,           /* array_write */
 221         NULL,           /* array_readdir */
 222         NULL,           /* array_select */
 223         NULL,           /* array_ioctl */
 224         NULL,           /* mmap */
 225         NULL,           /* no special open code */
 226         NULL            /* no special release code */
 227 };
 228 
 229 struct inode_operations proc_array_inode_operations = {
 230         &proc_array_operations, /* default base directory file-ops */
 231         NULL,                   /* create */
 232         NULL,                   /* lookup */
 233         NULL,                   /* link */
 234         NULL,                   /* unlink */
 235         NULL,                   /* symlink */
 236         NULL,                   /* mkdir */
 237         NULL,                   /* rmdir */
 238         NULL,                   /* mknod */
 239         NULL,                   /* rename */
 240         NULL,                   /* readlink */
 241         NULL,                   /* follow_link */
 242         NULL,                   /* bmap */
 243         NULL                    /* truncate */
 244 };

/* [previous][next][first][last][top][bottom][index][help] */