OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [proc/] [array.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 *  linux/fs/proc/array.c
 *  linux/fs/proc/array.c
 *
 *
 *  Copyright (C) 1992  by Linus Torvalds
 *  Copyright (C) 1992  by Linus Torvalds
 *  based on ideas by Darren Senn
 *  based on ideas by Darren Senn
 *
 *
 * Fixes:
 * Fixes:
 * Michael. K. Johnson: stat,statm extensions.
 * Michael. K. Johnson: stat,statm extensions.
 *                      <johnsonm@stolaf.edu>
 *                      <johnsonm@stolaf.edu>
 *
 *
 * Pauline Middelink :  Made cmdline,envline only break at '\0's, to
 * Pauline Middelink :  Made cmdline,envline only break at '\0's, to
 *                      make sure SET_PROCTITLE works. Also removed
 *                      make sure SET_PROCTITLE works. Also removed
 *                      bad '!' which forced address recalculation for
 *                      bad '!' which forced address recalculation for
 *                      EVERY character on the current page.
 *                      EVERY character on the current page.
 *                      <middelin@polyware.iaf.nl>
 *                      <middelin@polyware.iaf.nl>
 *
 *
 * Danny ter Haar    :  added cpuinfo
 * Danny ter Haar    :  added cpuinfo
 *                      <dth@cistron.nl>
 *                      <dth@cistron.nl>
 *
 *
 * Alessandro Rubini :  profile extension.
 * Alessandro Rubini :  profile extension.
 *                      <rubini@ipvvis.unipv.it>
 *                      <rubini@ipvvis.unipv.it>
 *
 *
 * Jeff Tranter      :  added BogoMips field to cpuinfo
 * Jeff Tranter      :  added BogoMips field to cpuinfo
 *                      <Jeff_Tranter@Mitel.COM>
 *                      <Jeff_Tranter@Mitel.COM>
 *
 *
 * Bruno Haible      :  remove 4K limit for the maps file
 * Bruno Haible      :  remove 4K limit for the maps file
 * <haible@ma2s2.mathematik.uni-karlsruhe.de>
 * <haible@ma2s2.mathematik.uni-karlsruhe.de>
 *
 *
 * Yves Arrouye      :  remove removal of trailing spaces in get_array.
 * Yves Arrouye      :  remove removal of trailing spaces in get_array.
 *                      <Yves.Arrouye@marin.fdn.fr>
 *                      <Yves.Arrouye@marin.fdn.fr>
 *
 *
 * Alan Cox          :  security fixes. <Alan.Cox@linux.org>
 * Alan Cox          :  security fixes. <Alan.Cox@linux.org>
 */
 */
 
 
/*
/*
 * uClinux revisions for NO_MM
 * uClinux revisions for NO_MM
 * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
 * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
 *                     The Silver Hammer Group, Ltd.
 *                     The Silver Hammer Group, Ltd.
 */
 */
 
 
#include <linux/types.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/kernel_stat.h>
#include <linux/kernel_stat.h>
#include <linux/tty.h>
#include <linux/tty.h>
#include <linux/user.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/a.out.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/mman.h>
#include <linux/mman.h>
#include <linux/proc_fs.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
#include <linux/ioport.h>
#include <linux/config.h>
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/swap.h>
 
 
#include <asm/segment.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/io.h>
 
 
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
 
 
#ifdef CONFIG_DEBUG_MALLOC
#ifdef CONFIG_DEBUG_MALLOC
int get_malloc(char * buffer);
int get_malloc(char * buffer);
#endif
#endif
 
 
extern unsigned long get_wchan(struct task_struct *);
extern unsigned long get_wchan(struct task_struct *);
 
 
static int read_core(struct inode * inode, struct file * file,char * buf, int count)
static int read_core(struct inode * inode, struct file * file,char * buf, int count)
{
{
        unsigned long p = file->f_pos, memsize;
        unsigned long p = file->f_pos, memsize;
        int read;
        int read;
        int count1;
        int count1;
        char * pnt;
        char * pnt;
        struct user dump;
        struct user dump;
#ifdef __i386__
#ifdef __i386__
#       define FIRST_MAPPED     PAGE_SIZE       /* we don't have page 0 mapped on x86.. */
#       define FIRST_MAPPED     PAGE_SIZE       /* we don't have page 0 mapped on x86.. */
#else
#else
#       define FIRST_MAPPED     0
#       define FIRST_MAPPED     0
#endif
#endif
 
 
        memset(&dump, 0, sizeof(struct user));
        memset(&dump, 0, sizeof(struct user));
        dump.magic = CMAGIC;
        dump.magic = CMAGIC;
        dump.u_dsize = MAP_NR(high_memory);
        dump.u_dsize = MAP_NR(high_memory);
#ifdef __alpha__
#ifdef __alpha__
        dump.start_data = PAGE_OFFSET;
        dump.start_data = PAGE_OFFSET;
#endif
#endif
 
 
        if (count < 0)
        if (count < 0)
                return -EINVAL;
                return -EINVAL;
        memsize = MAP_NR(high_memory + PAGE_SIZE) << PAGE_SHIFT;
        memsize = MAP_NR(high_memory + PAGE_SIZE) << PAGE_SHIFT;
        if (p >= memsize)
        if (p >= memsize)
                return 0;
                return 0;
        if (count > memsize - p)
        if (count > memsize - p)
                count = memsize - p;
                count = memsize - p;
        read = 0;
        read = 0;
 
 
        if (p < sizeof(struct user) && count > 0) {
        if (p < sizeof(struct user) && count > 0) {
                count1 = count;
                count1 = count;
                if (p + count1 > sizeof(struct user))
                if (p + count1 > sizeof(struct user))
                        count1 = sizeof(struct user)-p;
                        count1 = sizeof(struct user)-p;
                pnt = (char *) &dump + p;
                pnt = (char *) &dump + p;
                memcpy_tofs(buf,(void *) pnt, count1);
                memcpy_tofs(buf,(void *) pnt, count1);
                buf += count1;
                buf += count1;
                p += count1;
                p += count1;
                count -= count1;
                count -= count1;
                read += count1;
                read += count1;
        }
        }
 
 
        while (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) {
        while (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) {
                put_user(0,buf);
                put_user(0,buf);
                buf++;
                buf++;
                p++;
                p++;
                count--;
                count--;
                read++;
                read++;
        }
        }
        memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count);
        memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count);
        read += count;
        read += count;
        file->f_pos += read;
        file->f_pos += read;
        return read;
        return read;
}
}
 
 
static struct file_operations proc_kcore_operations = {
static struct file_operations proc_kcore_operations = {
        NULL,           /* lseek */
        NULL,           /* lseek */
        read_core,
        read_core,
};
};
 
 
struct inode_operations proc_kcore_inode_operations = {
struct inode_operations proc_kcore_inode_operations = {
        &proc_kcore_operations,
        &proc_kcore_operations,
};
};
 
 
 
 
/*
/*
 * This function accesses profiling information. The returned data is
 * This function accesses profiling information. The returned data is
 * binary: the sampling step and the actual contents of the profile
 * binary: the sampling step and the actual contents of the profile
 * buffer. Use of the program readprofile is recommended in order to
 * buffer. Use of the program readprofile is recommended in order to
 * get meaningful info out of these data.
 * get meaningful info out of these data.
 */
 */
static int read_profile(struct inode *inode, struct file *file, char *buf, int count)
static int read_profile(struct inode *inode, struct file *file, char *buf, int count)
{
{
        unsigned long p = file->f_pos;
        unsigned long p = file->f_pos;
        int read;
        int read;
        char * pnt;
        char * pnt;
        unsigned int sample_step = 1 << prof_shift;
        unsigned int sample_step = 1 << prof_shift;
 
 
        if (count < 0)
        if (count < 0)
                return -EINVAL;
                return -EINVAL;
        if (p >= (prof_len+1)*sizeof(unsigned int))
        if (p >= (prof_len+1)*sizeof(unsigned int))
                return 0;
                return 0;
        if (count > (prof_len+1)*sizeof(unsigned int) - p)
        if (count > (prof_len+1)*sizeof(unsigned int) - p)
                count = (prof_len+1)*sizeof(unsigned int) - p;
                count = (prof_len+1)*sizeof(unsigned int) - p;
        read = 0;
        read = 0;
 
 
        while (p < sizeof(unsigned int) && count > 0) {
        while (p < sizeof(unsigned int) && count > 0) {
                put_user(*((char *)(&sample_step)+p),buf);
                put_user(*((char *)(&sample_step)+p),buf);
                buf++; p++; count--; read++;
                buf++; p++; count--; read++;
        }
        }
        pnt = (char *)prof_buffer + p - sizeof(unsigned int);
        pnt = (char *)prof_buffer + p - sizeof(unsigned int);
        memcpy_tofs(buf,(void *)pnt,count);
        memcpy_tofs(buf,(void *)pnt,count);
        read += count;
        read += count;
        file->f_pos += read;
        file->f_pos += read;
        return read;
        return read;
}
}
 
 
/* Writing to /proc/profile resets the counters */
/* Writing to /proc/profile resets the counters */
static int write_profile(struct inode * inode, struct file * file, const char * buf, int count)
static int write_profile(struct inode * inode, struct file * file, const char * buf, int count)
{
{
    int i=prof_len;
    int i=prof_len;
 
 
    while (i--)
    while (i--)
            prof_buffer[i]=0UL;
            prof_buffer[i]=0UL;
    return count;
    return count;
}
}
 
 
static struct file_operations proc_profile_operations = {
static struct file_operations proc_profile_operations = {
        NULL,           /* lseek */
        NULL,           /* lseek */
        read_profile,
        read_profile,
        write_profile,
        write_profile,
};
};
 
 
struct inode_operations proc_profile_inode_operations = {
struct inode_operations proc_profile_inode_operations = {
        &proc_profile_operations,
        &proc_profile_operations,
};
};
 
 
 
 
static int get_loadavg(char * buffer)
static int get_loadavg(char * buffer)
{
{
        int a, b, c;
        int a, b, c;
 
 
        a = avenrun[0] + (FIXED_1/200);
        a = avenrun[0] + (FIXED_1/200);
        b = avenrun[1] + (FIXED_1/200);
        b = avenrun[1] + (FIXED_1/200);
        c = avenrun[2] + (FIXED_1/200);
        c = avenrun[2] + (FIXED_1/200);
        return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
        return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
                LOAD_INT(a), LOAD_FRAC(a),
                LOAD_INT(a), LOAD_FRAC(a),
                LOAD_INT(b), LOAD_FRAC(b),
                LOAD_INT(b), LOAD_FRAC(b),
                LOAD_INT(c), LOAD_FRAC(c),
                LOAD_INT(c), LOAD_FRAC(c),
                nr_running, nr_tasks, last_pid);
                nr_running, nr_tasks, last_pid);
}
}
 
 
static int get_kstat(char * buffer)
static int get_kstat(char * buffer)
{
{
        int i, len;
        int i, len;
        unsigned sum = 0;
        unsigned sum = 0;
        extern unsigned long total_forks;
        extern unsigned long total_forks;
 
 
        for (i = 0 ; i < NR_IRQS ; i++)
        for (i = 0 ; i < NR_IRQS ; i++)
                sum += kstat.interrupts[i];
                sum += kstat.interrupts[i];
        len = sprintf(buffer,
        len = sprintf(buffer,
                "cpu  %u %u %u %lu\n"
                "cpu  %u %u %u %lu\n"
                "disk %u %u %u %u\n"
                "disk %u %u %u %u\n"
                "disk_rio %u %u %u %u\n"
                "disk_rio %u %u %u %u\n"
                "disk_wio %u %u %u %u\n"
                "disk_wio %u %u %u %u\n"
                "disk_rblk %u %u %u %u\n"
                "disk_rblk %u %u %u %u\n"
                "disk_wblk %u %u %u %u\n"
                "disk_wblk %u %u %u %u\n"
                "page %u %u\n"
                "page %u %u\n"
                "swap %u %u\n"
                "swap %u %u\n"
                "intr %u",
                "intr %u",
                kstat.cpu_user,
                kstat.cpu_user,
                kstat.cpu_nice,
                kstat.cpu_nice,
                kstat.cpu_system,
                kstat.cpu_system,
                jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
                jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
                kstat.dk_drive[0], kstat.dk_drive[1],
                kstat.dk_drive[0], kstat.dk_drive[1],
                kstat.dk_drive[2], kstat.dk_drive[3],
                kstat.dk_drive[2], kstat.dk_drive[3],
                kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
                kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
                kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
                kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
                kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
                kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
                kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
                kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
                kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
                kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
                kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
                kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
                kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
                kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
                kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
                kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
                kstat.pgpgin,
                kstat.pgpgin,
                kstat.pgpgout,
                kstat.pgpgout,
                kstat.pswpin,
                kstat.pswpin,
                kstat.pswpout,
                kstat.pswpout,
                sum);
                sum);
        for (i = 0 ; i < NR_IRQS ; i++)
        for (i = 0 ; i < NR_IRQS ; i++)
                len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
                len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
        len += sprintf(buffer + len,
        len += sprintf(buffer + len,
                "\nctxt %u\n"
                "\nctxt %u\n"
                "btime %lu\n"
                "btime %lu\n"
                "processes %lu\n",
                "processes %lu\n",
                kstat.context_swtch,
                kstat.context_swtch,
                xtime.tv_sec - jiffies / HZ,
                xtime.tv_sec - jiffies / HZ,
                total_forks);
                total_forks);
        return len;
        return len;
}
}
 
 
 
 
static int get_uptime(char * buffer)
static int get_uptime(char * buffer)
{
{
        unsigned long uptime;
        unsigned long uptime;
        unsigned long idle;
        unsigned long idle;
 
 
        uptime = jiffies;
        uptime = jiffies;
        idle = task[0]->utime + task[0]->stime;
        idle = task[0]->utime + task[0]->stime;
 
 
        /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
        /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
           that would overflow about every five days at HZ == 100.
           that would overflow about every five days at HZ == 100.
           Therefore the identity a = (a / b) * b + a % b is used so that it is
           Therefore the identity a = (a / b) * b + a % b is used so that it is
           calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
           calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
           The part in front of the '+' always evaluates as 0 (mod 100). All divisions
           The part in front of the '+' always evaluates as 0 (mod 100). All divisions
           in the above formulas are truncating. For HZ being a power of 10, the
           in the above formulas are truncating. For HZ being a power of 10, the
           calculations simplify to the version in the #else part (if the printf
           calculations simplify to the version in the #else part (if the printf
           format is adapted to the same number of digits as zeroes in HZ.
           format is adapted to the same number of digits as zeroes in HZ.
         */
         */
#if HZ!=100
#if HZ!=100
        return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
        return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
                uptime / HZ,
                uptime / HZ,
                (((uptime % HZ) * 100) / HZ) % 100,
                (((uptime % HZ) * 100) / HZ) % 100,
                idle / HZ,
                idle / HZ,
                (((idle % HZ) * 100) / HZ) % 100);
                (((idle % HZ) * 100) / HZ) % 100);
#else
#else
        return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
        return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
                uptime / HZ,
                uptime / HZ,
                uptime % HZ,
                uptime % HZ,
                idle / HZ,
                idle / HZ,
                idle % HZ);
                idle % HZ);
#endif
#endif
}
}
 
 
static int get_meminfo(char * buffer)
static int get_meminfo(char * buffer)
{
{
        struct sysinfo i;
        struct sysinfo i;
        int len;
        int len;
 
 
        si_meminfo(&i);
        si_meminfo(&i);
        si_swapinfo(&i);
        si_swapinfo(&i);
        len = sprintf(buffer, "        total:    used:    free:  shared: buffers:  cached:\n"
        len = sprintf(buffer, "        total:    used:    free:  shared: buffers:  cached:\n"
                "Mem:  %8lu %8lu %8lu %8lu %8lu %8lu\n"
                "Mem:  %8lu %8lu %8lu %8lu %8lu %8lu\n"
                "Swap: %8lu %8lu %8lu\n",
                "Swap: %8lu %8lu %8lu\n",
                i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE,
                i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE,
                i.totalswap, i.totalswap-i.freeswap, i.freeswap);
                i.totalswap, i.totalswap-i.freeswap, i.freeswap);
        /*
        /*
         * Tagged format, for easy grepping and expansion. The above will go away
         * Tagged format, for easy grepping and expansion. The above will go away
         * eventually, once the tools have been updated.
         * eventually, once the tools have been updated.
         */
         */
        return len + sprintf(buffer+len,
        return len + sprintf(buffer+len,
                "MemTotal:  %8lu kB\n"
                "MemTotal:  %8lu kB\n"
                "MemFree:   %8lu kB\n"
                "MemFree:   %8lu kB\n"
                "MemShared: %8lu kB\n"
                "MemShared: %8lu kB\n"
                "Buffers:   %8lu kB\n"
                "Buffers:   %8lu kB\n"
                "Cached:    %8lu kB\n"
                "Cached:    %8lu kB\n"
                "SwapTotal: %8lu kB\n"
                "SwapTotal: %8lu kB\n"
                "SwapFree:  %8lu kB\n",
                "SwapFree:  %8lu kB\n",
                i.totalram >> 10,
                i.totalram >> 10,
                i.freeram >> 10,
                i.freeram >> 10,
                i.sharedram >> 10,
                i.sharedram >> 10,
                i.bufferram >> 10,
                i.bufferram >> 10,
                page_cache_size << (PAGE_SHIFT - 10),
                page_cache_size << (PAGE_SHIFT - 10),
                i.totalswap >> 10,
                i.totalswap >> 10,
                i.freeswap >> 10);
                i.freeswap >> 10);
}
}
 
 
static int get_version(char * buffer)
static int get_version(char * buffer)
{
{
        extern const char *linux_banner;
        extern const char *linux_banner;
 
 
        strcpy(buffer, linux_banner);
        strcpy(buffer, linux_banner);
        return strlen(buffer);
        return strlen(buffer);
}
}
 
 
static int get_cmdline(char * buffer)
static int get_cmdline(char * buffer)
{
{
        extern char saved_command_line[];
        extern char saved_command_line[];
 
 
        return sprintf(buffer, "%s\n", saved_command_line);
        return sprintf(buffer, "%s\n", saved_command_line);
}
}
 
 
static struct task_struct ** get_task(pid_t pid)
static struct task_struct ** get_task(pid_t pid)
{
{
        struct task_struct ** p;
        struct task_struct ** p;
 
 
        p = task;
        p = task;
        while (++p < task+NR_TASKS) {
        while (++p < task+NR_TASKS) {
                if (*p && (*p)->pid == pid)
                if (*p && (*p)->pid == pid)
                        return p;
                        return p;
        }
        }
        return NULL;
        return NULL;
}
}
 
 
static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
{
{
#ifndef NO_MM
#ifndef NO_MM
        pgd_t *page_dir;
        pgd_t *page_dir;
        pmd_t *page_middle;
        pmd_t *page_middle;
        pte_t pte;
        pte_t pte;
 
 
        if (!p || !p->mm || ptr >= TASK_SIZE)
        if (!p || !p->mm || ptr >= TASK_SIZE)
                return 0;
                return 0;
        page_dir = pgd_offset(p->mm,ptr);
        page_dir = pgd_offset(p->mm,ptr);
        if (pgd_none(*page_dir))
        if (pgd_none(*page_dir))
                return 0;
                return 0;
        if (pgd_bad(*page_dir)) {
        if (pgd_bad(*page_dir)) {
                printk("bad page directory entry %08lx\n", pgd_val(*page_dir));
                printk("bad page directory entry %08lx\n", pgd_val(*page_dir));
                pgd_clear(page_dir);
                pgd_clear(page_dir);
                return 0;
                return 0;
        }
        }
        page_middle = pmd_offset(page_dir,ptr);
        page_middle = pmd_offset(page_dir,ptr);
        if (pmd_none(*page_middle))
        if (pmd_none(*page_middle))
                return 0;
                return 0;
        if (pmd_bad(*page_middle)) {
        if (pmd_bad(*page_middle)) {
                printk("bad page middle entry %08lx\n", pmd_val(*page_middle));
                printk("bad page middle entry %08lx\n", pmd_val(*page_middle));
                pmd_clear(page_middle);
                pmd_clear(page_middle);
                return 0;
                return 0;
        }
        }
        pte = *pte_offset(page_middle,ptr);
        pte = *pte_offset(page_middle,ptr);
        if (!pte_present(pte))
        if (!pte_present(pte))
                return 0;
                return 0;
        return pte_page(pte) + (ptr & ~PAGE_MASK);
        return pte_page(pte) + (ptr & ~PAGE_MASK);
#else /* NO_MM */
#else /* NO_MM */
        return ptr;
        return ptr;
#endif /* NO_MM */
#endif /* NO_MM */
}
}
 
 
static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
{
{
        unsigned long addr;
        unsigned long addr;
        int size = 0, result = 0;
        int size = 0, result = 0;
        char c;
        char c;
 
 
        if (start >= end)
        if (start >= end)
                return result;
                return result;
        for (;;) {
        for (;;) {
                addr = get_phys_addr(*p, start);
                addr = get_phys_addr(*p, start);
                if (!addr)
                if (!addr)
                        return result;
                        return result;
                do {
                do {
                        c = *(char *) addr;
                        c = *(char *) addr;
                        if (!c)
                        if (!c)
                                result = size;
                                result = size;
                        if (size < PAGE_SIZE)
                        if (size < PAGE_SIZE)
                                buffer[size++] = c;
                                buffer[size++] = c;
                        else
                        else
                                return result;
                                return result;
                        addr++;
                        addr++;
                        start++;
                        start++;
                        if (!c && start >= end)
                        if (!c && start >= end)
                                return result;
                                return result;
                } while (addr & ~PAGE_MASK);
                } while (addr & ~PAGE_MASK);
        }
        }
        return result;
        return result;
}
}
 
 
static int get_env(int pid, char * buffer)
static int get_env(int pid, char * buffer)
{
{
        struct task_struct ** p = get_task(pid);
        struct task_struct ** p = get_task(pid);
 
 
        if (!p || !*p || !(*p)->mm)
        if (!p || !*p || !(*p)->mm)
                return 0;
                return 0;
        return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer);
        return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer);
}
}
 
 
static int get_arg(int pid, char * buffer)
static int get_arg(int pid, char * buffer)
{
{
        struct task_struct ** p = get_task(pid);
        struct task_struct ** p = get_task(pid);
 
 
        if (!p || !*p || !(*p)->mm)
        if (!p || !*p || !(*p)->mm)
                return 0;
                return 0;
        return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer);
        return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer);
}
}
 
 
#if defined(__i386__)
#if defined(__i386__)
# define KSTK_EIP(tsk)  (((unsigned long *)tsk->kernel_stack_page)[1019])
# define KSTK_EIP(tsk)  (((unsigned long *)tsk->kernel_stack_page)[1019])
# define KSTK_ESP(tsk)  (((unsigned long *)tsk->kernel_stack_page)[1022])
# define KSTK_ESP(tsk)  (((unsigned long *)tsk->kernel_stack_page)[1022])
#elif defined(__alpha__)
#elif defined(__alpha__)
  /*
  /*
   * See arch/alpha/kernel/ptrace.c for details.
   * See arch/alpha/kernel/ptrace.c for details.
   */
   */
# define PT_REG(reg)            (PAGE_SIZE - sizeof(struct pt_regs)     \
# define PT_REG(reg)            (PAGE_SIZE - sizeof(struct pt_regs)     \
                                 + (long)&((struct pt_regs *)0)->reg)
                                 + (long)&((struct pt_regs *)0)->reg)
# define KSTK_EIP(tsk)  (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_EIP(tsk)  (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_ESP(tsk)  ((tsk) == current ? rdusp() : (tsk)->tss.usp)
# define KSTK_ESP(tsk)  ((tsk) == current ? rdusp() : (tsk)->tss.usp)
#elif defined(__sparc__)
#elif defined(__sparc__)
# define PT_REG(reg)            (PAGE_SIZE - sizeof(struct pt_regs)     \
# define PT_REG(reg)            (PAGE_SIZE - sizeof(struct pt_regs)     \
                                 + (long)&((struct pt_regs *)0)->reg)
                                 + (long)&((struct pt_regs *)0)->reg)
# define KSTK_EIP(tsk)  (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_EIP(tsk)  (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
# define KSTK_ESP(tsk)  (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(u_regs[UREG_FP])))
# define KSTK_ESP(tsk)  (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(u_regs[UREG_FP])))
#endif
#endif
 
 
/* Gcc optimizes away "strlen(x)" for constant x */
/* Gcc optimizes away "strlen(x)" for constant x */
#define ADDBUF(buffer, string) \
#define ADDBUF(buffer, string) \
do { memcpy(buffer, string, strlen(string)); \
do { memcpy(buffer, string, strlen(string)); \
     buffer += strlen(string); } while (0)
     buffer += strlen(string); } while (0)
 
 
static inline char * task_name(struct task_struct *p, char * buf)
static inline char * task_name(struct task_struct *p, char * buf)
{
{
        int i;
        int i;
        char * name;
        char * name;
 
 
        ADDBUF(buf, "Name:\t");
        ADDBUF(buf, "Name:\t");
        name = p->comm;
        name = p->comm;
        i = sizeof(p->comm);
        i = sizeof(p->comm);
        do {
        do {
                unsigned char c = *name;
                unsigned char c = *name;
                name++;
                name++;
                i--;
                i--;
                *buf = c;
                *buf = c;
                if (!c)
                if (!c)
                        break;
                        break;
                if (c == '\\') {
                if (c == '\\') {
                        buf[1] = c;
                        buf[1] = c;
                        buf += 2;
                        buf += 2;
                        continue;
                        continue;
                }
                }
                if (c == '\n') {
                if (c == '\n') {
                        buf[0] = '\\';
                        buf[0] = '\\';
                        buf[1] = 'n';
                        buf[1] = 'n';
                        buf += 2;
                        buf += 2;
                        continue;
                        continue;
                }
                }
                buf++;
                buf++;
        } while (i);
        } while (i);
        *buf = '\n';
        *buf = '\n';
        return buf+1;
        return buf+1;
}
}
 
 
static inline char * task_state(struct task_struct *p, char *buffer)
static inline char * task_state(struct task_struct *p, char *buffer)
{
{
#define NR_STATES (sizeof(states)/sizeof(const char *))
#define NR_STATES (sizeof(states)/sizeof(const char *))
        unsigned int n = p->state;
        unsigned int n = p->state;
        static const char * states[] = {
        static const char * states[] = {
                "R (running)",
                "R (running)",
                "S (sleeping)",
                "S (sleeping)",
                "D (disk sleep)",
                "D (disk sleep)",
                "Z (zombie)",
                "Z (zombie)",
                "T (stopped)",
                "T (stopped)",
                "W (paging)",
                "W (paging)",
                ". Huh?"
                ". Huh?"
        };
        };
 
 
        if (n >= NR_STATES)
        if (n >= NR_STATES)
                n = NR_STATES-1;
                n = NR_STATES-1;
 
 
        buffer += sprintf(buffer,
        buffer += sprintf(buffer,
                "State:\t%s\n"
                "State:\t%s\n"
                "Pid:\t%d\n"
                "Pid:\t%d\n"
                "PPid:\t%d\n"
                "PPid:\t%d\n"
                "Uid:\t%d\t%d\t%d\t%d\n"
                "Uid:\t%d\t%d\t%d\t%d\n"
                "Gid:\t%d\t%d\t%d\t%d\n",
                "Gid:\t%d\t%d\t%d\t%d\n",
                states[n],
                states[n],
                p->pid, p->p_pptr->pid,
                p->pid, p->p_pptr->pid,
                p->uid, p->euid, p->suid, p->fsuid,
                p->uid, p->euid, p->suid, p->fsuid,
                p->gid, p->egid, p->sgid, p->fsgid);
                p->gid, p->egid, p->sgid, p->fsgid);
        return buffer;
        return buffer;
}
}
 
 
static inline char * task_mem(struct task_struct *p, char *buffer)
static inline char * task_mem(struct task_struct *p, char *buffer)
{
{
#ifndef NO_MM
#ifndef NO_MM
        struct mm_struct * mm = p->mm;
        struct mm_struct * mm = p->mm;
 
 
        if (mm && mm != &init_mm) {
        if (mm && mm != &init_mm) {
                struct vm_area_struct * vma = mm->mmap;
                struct vm_area_struct * vma = mm->mmap;
                unsigned long data = 0, stack = 0;
                unsigned long data = 0, stack = 0;
                unsigned long exec = 0, lib = 0;
                unsigned long exec = 0, lib = 0;
 
 
                for (vma = mm->mmap; vma; vma = vma->vm_next) {
                for (vma = mm->mmap; vma; vma = vma->vm_next) {
                        unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
                        unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
                        if (!vma->vm_inode) {
                        if (!vma->vm_inode) {
                                data += len;
                                data += len;
                                if (vma->vm_flags & VM_GROWSDOWN)
                                if (vma->vm_flags & VM_GROWSDOWN)
                                        stack += len;
                                        stack += len;
                                continue;
                                continue;
                        }
                        }
                        if (vma->vm_flags & VM_WRITE)
                        if (vma->vm_flags & VM_WRITE)
                                continue;
                                continue;
                        if (vma->vm_flags & VM_EXEC) {
                        if (vma->vm_flags & VM_EXEC) {
                                exec += len;
                                exec += len;
                                if (vma->vm_flags & VM_EXECUTABLE)
                                if (vma->vm_flags & VM_EXECUTABLE)
                                        continue;
                                        continue;
                                lib += len;
                                lib += len;
                        }
                        }
                }
                }
                buffer += sprintf(buffer,
                buffer += sprintf(buffer,
                        "VmSize:\t%8lu kB\n"
                        "VmSize:\t%8lu kB\n"
                        "VmLck:\t%8lu kB\n"
                        "VmLck:\t%8lu kB\n"
                        "VmRSS:\t%8lu kB\n"
                        "VmRSS:\t%8lu kB\n"
                        "VmData:\t%8lu kB\n"
                        "VmData:\t%8lu kB\n"
                        "VmStk:\t%8lu kB\n"
                        "VmStk:\t%8lu kB\n"
                        "VmExe:\t%8lu kB\n"
                        "VmExe:\t%8lu kB\n"
                        "VmLib:\t%8lu kB\n",
                        "VmLib:\t%8lu kB\n",
                        mm->total_vm << (PAGE_SHIFT-10),
                        mm->total_vm << (PAGE_SHIFT-10),
                        mm->locked_vm << (PAGE_SHIFT-10),
                        mm->locked_vm << (PAGE_SHIFT-10),
                        mm->rss << (PAGE_SHIFT-10),
                        mm->rss << (PAGE_SHIFT-10),
                        data - stack, stack,
                        data - stack, stack,
                        exec - lib, lib);
                        exec - lib, lib);
        }
        }
#else /* NO_MM */
#else /* NO_MM */
        unsigned long bytes = 0, sbytes = 0;
        unsigned long bytes = 0, sbytes = 0;
        struct mm_tblock_struct * tblock;
        struct mm_tblock_struct * tblock;
 
 
        /* Logic: we've got two memory sums for each process, "shared", and
        /* Logic: we've got two memory sums for each process, "shared", and
         * "non-shared". Shared memory may get counted more then once, for
         * "non-shared". Shared memory may get counted more then once, for
         * each process that owns it. Non-shared memory is counted
         * each process that owns it. Non-shared memory is counted
         * accurately.
         * accurately.
         *
         *
         *      -- Kenneth Albanowski
         *      -- Kenneth Albanowski
         */
         */
 
 
        for(tblock = &p->mm->tblock;tblock;tblock=tblock->next) {
        for(tblock = &p->mm->tblock;tblock;tblock=tblock->next) {
 
 
                if (tblock->rblock) {
                if (tblock->rblock) {
 
 
                        bytes += ksize(tblock);
                        bytes += ksize(tblock);
 
 
                        if ((p->mm->count > 1) || (tblock->rblock->refcount > 1)) {
                        if ((p->mm->count > 1) || (tblock->rblock->refcount > 1)) {
                                sbytes += ksize(tblock->rblock->kblock);
                                sbytes += ksize(tblock->rblock->kblock);
                                sbytes += ksize(tblock->rblock) ;
                                sbytes += ksize(tblock->rblock) ;
                        } else {
                        } else {
                                bytes += ksize(tblock->rblock->kblock);
                                bytes += ksize(tblock->rblock->kblock);
                                bytes += ksize(tblock->rblock) ;
                                bytes += ksize(tblock->rblock) ;
                        }
                        }
 
 
                }
                }
 
 
 
 
        }
        }
 
 
        ((p->mm->count > 1) ? sbytes : bytes) += ksize(p->mm);
        ((p->mm->count > 1) ? sbytes : bytes) += ksize(p->mm);
        ((p->fs->count > 1) ? sbytes : bytes) += ksize(p->fs);
        ((p->fs->count > 1) ? sbytes : bytes) += ksize(p->fs);
        ((p->files->count > 1) ? sbytes : bytes) += ksize(p->files);
        ((p->files->count > 1) ? sbytes : bytes) += ksize(p->files);
        ((p->sig->count > 1) ? sbytes : bytes) += ksize(p->sig);
        ((p->sig->count > 1) ? sbytes : bytes) += ksize(p->sig);
        bytes += ksize(p);
        bytes += ksize(p);
 
 
        bytes += PAGE_SIZE; /* Kernel stack */
        bytes += PAGE_SIZE; /* Kernel stack */
 
 
        buffer += sprintf(buffer,
        buffer += sprintf(buffer,
                "Mem:\t%8lu bytes\n"
                "Mem:\t%8lu bytes\n"
                "Shared:\t%8lu bytes\n",
                "Shared:\t%8lu bytes\n",
                bytes,
                bytes,
                sbytes);
                sbytes);
#endif /* NO_MM */
#endif /* NO_MM */
        return buffer;
        return buffer;
}
}
 
 
static inline char * task_sig(struct task_struct *p, char *buffer)
static inline char * task_sig(struct task_struct *p, char *buffer)
{
{
        buffer += sprintf(buffer,
        buffer += sprintf(buffer,
                "SigPnd:\t%08lx\n"
                "SigPnd:\t%08lx\n"
                "SigBlk:\t%08lx\n",
                "SigBlk:\t%08lx\n",
                p->signal, p->blocked);
                p->signal, p->blocked);
        if (p->sig) {
        if (p->sig) {
                struct sigaction * action = p->sig->action;
                struct sigaction * action = p->sig->action;
                unsigned long sig_ign = 0, sig_caught = 0;
                unsigned long sig_ign = 0, sig_caught = 0;
                unsigned long bit = 1;
                unsigned long bit = 1;
                int i;
                int i;
 
 
                for (i = 0; i < 32; i++) {
                for (i = 0; i < 32; i++) {
                        switch((unsigned long) action->sa_handler) {
                        switch((unsigned long) action->sa_handler) {
                                case 0:
                                case 0:
                                        break;
                                        break;
                                case 1:
                                case 1:
                                        sig_ign |= bit;
                                        sig_ign |= bit;
                                        break;
                                        break;
                                default:
                                default:
                                        sig_caught |= bit;
                                        sig_caught |= bit;
                        }
                        }
                        bit <<= 1;
                        bit <<= 1;
                        action++;
                        action++;
                }
                }
 
 
                buffer += sprintf(buffer,
                buffer += sprintf(buffer,
                        "SigIgn:\t%08lx\n"
                        "SigIgn:\t%08lx\n"
                        "SigCgt:\t%08lx\n",
                        "SigCgt:\t%08lx\n",
                        sig_ign, sig_caught);
                        sig_ign, sig_caught);
        }
        }
        return buffer;
        return buffer;
}
}
 
 
static int get_status(int pid, char * buffer)
static int get_status(int pid, char * buffer)
{
{
        char * orig = buffer;
        char * orig = buffer;
        struct task_struct ** p = get_task(pid), *tsk;
        struct task_struct ** p = get_task(pid), *tsk;
 
 
        if (!p || (tsk = *p) == NULL)
        if (!p || (tsk = *p) == NULL)
                return 0;
                return 0;
        buffer = task_name(tsk, buffer);
        buffer = task_name(tsk, buffer);
        buffer = task_state(tsk, buffer);
        buffer = task_state(tsk, buffer);
        buffer = task_mem(tsk, buffer);
        buffer = task_mem(tsk, buffer);
        buffer = task_sig(tsk, buffer);
        buffer = task_sig(tsk, buffer);
        return buffer - orig;
        return buffer - orig;
}
}
 
 
static int get_stat(int pid, char * buffer)
static int get_stat(int pid, char * buffer)
{
{
        struct task_struct ** p = get_task(pid), *tsk;
        struct task_struct ** p = get_task(pid), *tsk;
        unsigned long sigignore=0, sigcatch=0, wchan;
        unsigned long sigignore=0, sigcatch=0, wchan;
        unsigned long vsize, eip, esp;
        unsigned long vsize, eip, esp;
        long priority, nice;
        long priority, nice;
        int i,tty_pgrp;
        int i,tty_pgrp;
        char state;
        char state;
 
 
        if (!p || (tsk = *p) == NULL)
        if (!p || (tsk = *p) == NULL)
                return 0;
                return 0;
        if (tsk->state < 0 || tsk->state > 5)
        if (tsk->state < 0 || tsk->state > 5)
                state = '.';
                state = '.';
        else
        else
                state = "RSDZTW"[tsk->state];
                state = "RSDZTW"[tsk->state];
        vsize = eip = esp = 0;
        vsize = eip = esp = 0;
        if (tsk->mm && tsk->mm != &init_mm) {
        if (tsk->mm && tsk->mm != &init_mm) {
#ifndef NO_MM
#ifndef NO_MM
                struct vm_area_struct *vma = tsk->mm->mmap;
                struct vm_area_struct *vma = tsk->mm->mmap;
                while (vma) {
                while (vma) {
                        vsize += vma->vm_end - vma->vm_start;
                        vsize += vma->vm_end - vma->vm_start;
                        vma = vma->vm_next;
                        vma = vma->vm_next;
                }
                }
                if (tsk->kernel_stack_page) {
                if (tsk->kernel_stack_page) {
                        eip = KSTK_EIP(tsk);
                        eip = KSTK_EIP(tsk);
                        esp = KSTK_ESP(tsk);
                        esp = KSTK_ESP(tsk);
                }
                }
#endif /* !NO_MM */
#endif /* !NO_MM */
        }
        }
        wchan = get_wchan(tsk);
        wchan = get_wchan(tsk);
        if (tsk->sig) {
        if (tsk->sig) {
                unsigned long bit = 1;
                unsigned long bit = 1;
                for(i=0; i<32; ++i) {
                for(i=0; i<32; ++i) {
                        switch((unsigned long) tsk->sig->action[i].sa_handler) {
                        switch((unsigned long) tsk->sig->action[i].sa_handler) {
                                case 0:
                                case 0:
                                        break;
                                        break;
                                case 1:
                                case 1:
                                        sigignore |= bit;
                                        sigignore |= bit;
                                        break;
                                        break;
                                default:
                                default:
                                        sigcatch |= bit;
                                        sigcatch |= bit;
                        }
                        }
                        bit <<= 1;
                        bit <<= 1;
                }
                }
        }
        }
        if (tsk->tty)
        if (tsk->tty)
                tty_pgrp = tsk->tty->pgrp;
                tty_pgrp = tsk->tty->pgrp;
        else
        else
                tty_pgrp = -1;
                tty_pgrp = -1;
 
 
        /* scale priority and nice values from timeslices to -20..20 */
        /* scale priority and nice values from timeslices to -20..20 */
        /* to make it look like a "normal" unix priority/nice value  */
        /* to make it look like a "normal" unix priority/nice value  */
        priority = tsk->counter;
        priority = tsk->counter;
        priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
        priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
        nice = tsk->priority;
        nice = tsk->priority;
        nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
        nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
 
 
        return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
        return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu\n",
%lu %lu %lu %lu %lu %lu %lu %lu\n",
                pid,
                pid,
                tsk->comm,
                tsk->comm,
                state,
                state,
                tsk->p_pptr->pid,
                tsk->p_pptr->pid,
                tsk->pgrp,
                tsk->pgrp,
                tsk->session,
                tsk->session,
                tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
                tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
                tty_pgrp,
                tty_pgrp,
                tsk->flags,
                tsk->flags,
                tsk->min_flt,
                tsk->min_flt,
                tsk->cmin_flt,
                tsk->cmin_flt,
                tsk->maj_flt,
                tsk->maj_flt,
                tsk->cmaj_flt,
                tsk->cmaj_flt,
                tsk->utime,
                tsk->utime,
                tsk->stime,
                tsk->stime,
                tsk->cutime,
                tsk->cutime,
                tsk->cstime,
                tsk->cstime,
                priority,
                priority,
                nice,
                nice,
                tsk->timeout,
                tsk->timeout,
                tsk->it_real_value,
                tsk->it_real_value,
                tsk->start_time,
                tsk->start_time,
                vsize,
                vsize,
                tsk->mm ? tsk->mm->rss : 0, /* you might want to shift this left 3 */
                tsk->mm ? tsk->mm->rss : 0, /* you might want to shift this left 3 */
                tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
                tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
                tsk->mm ? tsk->mm->start_code : 0,
                tsk->mm ? tsk->mm->start_code : 0,
                tsk->mm ? tsk->mm->end_code : 0,
                tsk->mm ? tsk->mm->end_code : 0,
                tsk->mm ? tsk->mm->start_stack : 0,
                tsk->mm ? tsk->mm->start_stack : 0,
                esp,
                esp,
                eip,
                eip,
                tsk->signal,
                tsk->signal,
                tsk->blocked,
                tsk->blocked,
                sigignore,
                sigignore,
                sigcatch,
                sigcatch,
                wchan,
                wchan,
                tsk->nswap,
                tsk->nswap,
                tsk->cnswap);
                tsk->cnswap);
}
}
 
 
#ifndef NO_MM
#ifndef NO_MM
static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
        int * pages, int * shared, int * dirty, int * total)
        int * pages, int * shared, int * dirty, int * total)
{
{
        pte_t * pte;
        pte_t * pte;
        unsigned long end;
        unsigned long end;
 
 
        if (pmd_none(*pmd))
        if (pmd_none(*pmd))
                return;
                return;
        if (pmd_bad(*pmd)) {
        if (pmd_bad(*pmd)) {
                printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
                printk("statm_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
                pmd_clear(pmd);
                pmd_clear(pmd);
                return;
                return;
        }
        }
        pte = pte_offset(pmd, address);
        pte = pte_offset(pmd, address);
        address &= ~PMD_MASK;
        address &= ~PMD_MASK;
        end = address + size;
        end = address + size;
        if (end > PMD_SIZE)
        if (end > PMD_SIZE)
                end = PMD_SIZE;
                end = PMD_SIZE;
        do {
        do {
                pte_t page = *pte;
                pte_t page = *pte;
 
 
                address += PAGE_SIZE;
                address += PAGE_SIZE;
                pte++;
                pte++;
                if (pte_none(page))
                if (pte_none(page))
                        continue;
                        continue;
                ++*total;
                ++*total;
                if (!pte_present(page))
                if (!pte_present(page))
                        continue;
                        continue;
                ++*pages;
                ++*pages;
                if (pte_dirty(page))
                if (pte_dirty(page))
                        ++*dirty;
                        ++*dirty;
                if (pte_page(page) >= high_memory)
                if (pte_page(page) >= high_memory)
                        continue;
                        continue;
                if (mem_map[MAP_NR(pte_page(page))].count > 1)
                if (mem_map[MAP_NR(pte_page(page))].count > 1)
                        ++*shared;
                        ++*shared;
        } while (address < end);
        } while (address < end);
}
}
 
 
static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
static inline void statm_pmd_range(pgd_t * pgd, unsigned long address, unsigned long size,
        int * pages, int * shared, int * dirty, int * total)
        int * pages, int * shared, int * dirty, int * total)
{
{
        pmd_t * pmd;
        pmd_t * pmd;
        unsigned long end;
        unsigned long end;
 
 
        if (pgd_none(*pgd))
        if (pgd_none(*pgd))
                return;
                return;
        if (pgd_bad(*pgd)) {
        if (pgd_bad(*pgd)) {
                printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
                printk("statm_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
                pgd_clear(pgd);
                pgd_clear(pgd);
                return;
                return;
        }
        }
        pmd = pmd_offset(pgd, address);
        pmd = pmd_offset(pgd, address);
        address &= ~PGDIR_MASK;
        address &= ~PGDIR_MASK;
        end = address + size;
        end = address + size;
        if (end > PGDIR_SIZE)
        if (end > PGDIR_SIZE)
                end = PGDIR_SIZE;
                end = PGDIR_SIZE;
        do {
        do {
                statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
                statm_pte_range(pmd, address, end - address, pages, shared, dirty, total);
                address = (address + PMD_SIZE) & PMD_MASK;
                address = (address + PMD_SIZE) & PMD_MASK;
                pmd++;
                pmd++;
        } while (address < end);
        } while (address < end);
}
}
 
 
static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long end,
        int * pages, int * shared, int * dirty, int * total)
        int * pages, int * shared, int * dirty, int * total)
{
{
        while (address < end) {
        while (address < end) {
                statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
                statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
                address = (address + PGDIR_SIZE) & PGDIR_MASK;
                address = (address + PGDIR_SIZE) & PGDIR_MASK;
                pgd++;
                pgd++;
        }
        }
}
}
 
 
static int get_statm(int pid, char * buffer)
static int get_statm(int pid, char * buffer)
{
{
        struct task_struct ** p = get_task(pid), *tsk;
        struct task_struct ** p = get_task(pid), *tsk;
        int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
        int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
 
 
        if (!p || (tsk = *p) == NULL)
        if (!p || (tsk = *p) == NULL)
                return 0;
                return 0;
        if (tsk->mm && tsk->mm != &init_mm) {
        if (tsk->mm && tsk->mm != &init_mm) {
                struct vm_area_struct * vma = tsk->mm->mmap;
                struct vm_area_struct * vma = tsk->mm->mmap;
 
 
                while (vma) {
                while (vma) {
                        pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
                        pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
                        int pages = 0, shared = 0, dirty = 0, total = 0;
                        int pages = 0, shared = 0, dirty = 0, total = 0;
 
 
                        statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
                        statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
                        resident += pages;
                        resident += pages;
                        share += shared;
                        share += shared;
                        dt += dirty;
                        dt += dirty;
                        size += total;
                        size += total;
                        if (vma->vm_flags & VM_EXECUTABLE)
                        if (vma->vm_flags & VM_EXECUTABLE)
                                trs += pages;   /* text */
                                trs += pages;   /* text */
                        else if (vma->vm_flags & VM_GROWSDOWN)
                        else if (vma->vm_flags & VM_GROWSDOWN)
                                drs += pages;   /* stack */
                                drs += pages;   /* stack */
                        else if (vma->vm_end > 0x60000000)
                        else if (vma->vm_end > 0x60000000)
                                lrs += pages;   /* library */
                                lrs += pages;   /* library */
                        else
                        else
                                drs += pages;
                                drs += pages;
                        vma = vma->vm_next;
                        vma = vma->vm_next;
                }
                }
        }
        }
        return sprintf(buffer,"%d %d %d %d %d %d %d\n",
        return sprintf(buffer,"%d %d %d %d %d %d %d\n",
                       size, resident, share, trs, lrs, drs, dt);
                       size, resident, share, trs, lrs, drs, dt);
}
}
 
 
/*
/*
 * The way we support synthetic files > 4K
 * The way we support synthetic files > 4K
 * - without storing their contents in some buffer and
 * - without storing their contents in some buffer and
 * - without walking through the entire synthetic file until we reach the
 * - without walking through the entire synthetic file until we reach the
 *   position of the requested data
 *   position of the requested data
 * is to cleverly encode the current position in the file's f_pos field.
 * is to cleverly encode the current position in the file's f_pos field.
 * There is no requirement that a read() call which returns `count' bytes
 * There is no requirement that a read() call which returns `count' bytes
 * of data increases f_pos by exactly `count'.
 * of data increases f_pos by exactly `count'.
 *
 *
 * This idea is Linus' one. Bruno implemented it.
 * This idea is Linus' one. Bruno implemented it.
 */
 */
 
 
/*
/*
 * For the /proc/<pid>/maps file, we use fixed length records, each containing
 * For the /proc/<pid>/maps file, we use fixed length records, each containing
 * a single line.
 * a single line.
 */
 */
#define MAPS_LINE_LENGTH        1024
#define MAPS_LINE_LENGTH        1024
#define MAPS_LINE_SHIFT         10
#define MAPS_LINE_SHIFT         10
/*
/*
 * f_pos = (number of the vma in the task->mm->mmap list) * MAPS_LINE_LENGTH
 * f_pos = (number of the vma in the task->mm->mmap list) * MAPS_LINE_LENGTH
 *         + (index into the line)
 *         + (index into the line)
 */
 */
/* for systems with sizeof(void*) == 4: */
/* for systems with sizeof(void*) == 4: */
#define MAPS_LINE_FORMAT4         "%08lx-%08lx %s %08lx %s %lu\n"
#define MAPS_LINE_FORMAT4         "%08lx-%08lx %s %08lx %s %lu\n"
#define MAPS_LINE_MAX4  49 /* sum of 8  1  8  1 4 1 8 1 5 1 10 1 */
#define MAPS_LINE_MAX4  49 /* sum of 8  1  8  1 4 1 8 1 5 1 10 1 */
 
 
/* for systems with sizeof(void*) == 8: */
/* for systems with sizeof(void*) == 8: */
#define MAPS_LINE_FORMAT8         "%016lx-%016lx %s %016lx %s %lu\n"
#define MAPS_LINE_FORMAT8         "%016lx-%016lx %s %016lx %s %lu\n"
#define MAPS_LINE_MAX8  73 /* sum of 16  1  16  1 4 1 16 1 5 1 10 1 */
#define MAPS_LINE_MAX8  73 /* sum of 16  1  16  1 4 1 16 1 5 1 10 1 */
 
 
#define MAPS_LINE_MAX   MAPS_LINE_MAX8
#define MAPS_LINE_MAX   MAPS_LINE_MAX8
 
 
 
 
static int read_maps (int pid, struct file * file, char * buf, int count)
static int read_maps (int pid, struct file * file, char * buf, int count)
{
{
        struct task_struct ** p = get_task(pid);
        struct task_struct ** p = get_task(pid);
        char * destptr;
        char * destptr;
        loff_t lineno;
        loff_t lineno;
        int column;
        int column;
        struct vm_area_struct * map;
        struct vm_area_struct * map;
        int i;
        int i;
 
 
        if (!p || !*p)
        if (!p || !*p)
                return -EINVAL;
                return -EINVAL;
 
 
        if (!(*p)->mm || (*p)->mm == &init_mm || count == 0)
        if (!(*p)->mm || (*p)->mm == &init_mm || count == 0)
                return 0;
                return 0;
 
 
        /* decode f_pos */
        /* decode f_pos */
        lineno = file->f_pos >> MAPS_LINE_SHIFT;
        lineno = file->f_pos >> MAPS_LINE_SHIFT;
        column = file->f_pos & (MAPS_LINE_LENGTH-1);
        column = file->f_pos & (MAPS_LINE_LENGTH-1);
 
 
        /* quickly go to line lineno */
        /* quickly go to line lineno */
        for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
        for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
                continue;
                continue;
 
 
        destptr = buf;
        destptr = buf;
 
 
        for ( ; map ; ) {
        for ( ; map ; ) {
                /* produce the next line */
                /* produce the next line */
                char line[MAPS_LINE_MAX+1];
                char line[MAPS_LINE_MAX+1];
                char str[5], *cp = str;
                char str[5], *cp = str;
                int flags;
                int flags;
                kdev_t dev;
                kdev_t dev;
                unsigned long ino;
                unsigned long ino;
                int len;
                int len;
 
 
                flags = map->vm_flags;
                flags = map->vm_flags;
 
 
                *cp++ = flags & VM_READ ? 'r' : '-';
                *cp++ = flags & VM_READ ? 'r' : '-';
                *cp++ = flags & VM_WRITE ? 'w' : '-';
                *cp++ = flags & VM_WRITE ? 'w' : '-';
                *cp++ = flags & VM_EXEC ? 'x' : '-';
                *cp++ = flags & VM_EXEC ? 'x' : '-';
                *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
                *cp++ = flags & VM_MAYSHARE ? 's' : 'p';
                *cp++ = 0;
                *cp++ = 0;
 
 
                if (map->vm_inode != NULL) {
                if (map->vm_inode != NULL) {
                        dev = map->vm_inode->i_dev;
                        dev = map->vm_inode->i_dev;
                        ino = map->vm_inode->i_ino;
                        ino = map->vm_inode->i_ino;
                } else {
                } else {
                        dev = 0;
                        dev = 0;
                        ino = 0;
                        ino = 0;
                }
                }
 
 
                len = sprintf(line,
                len = sprintf(line,
                              sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8,
                              sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8,
                              map->vm_start, map->vm_end, str, map->vm_offset,
                              map->vm_start, map->vm_end, str, map->vm_offset,
                              kdevname(dev), ino);
                              kdevname(dev), ino);
 
 
                if (column >= len) {
                if (column >= len) {
                        column = 0; /* continue with next line at column 0 */
                        column = 0; /* continue with next line at column 0 */
                        lineno++;
                        lineno++;
                        map = map->vm_next;
                        map = map->vm_next;
                        continue;
                        continue;
                }
                }
 
 
                i = len-column;
                i = len-column;
                if (i > count)
                if (i > count)
                        i = count;
                        i = count;
                memcpy_tofs(destptr, line+column, i);
                memcpy_tofs(destptr, line+column, i);
                destptr += i; count -= i;
                destptr += i; count -= i;
                column += i;
                column += i;
                if (column >= len) {
                if (column >= len) {
                        column = 0; /* next time: next line at column 0 */
                        column = 0; /* next time: next line at column 0 */
                        lineno++;
                        lineno++;
                        map = map->vm_next;
                        map = map->vm_next;
                }
                }
 
 
                /* done? */
                /* done? */
                if (count == 0)
                if (count == 0)
                        break;
                        break;
 
 
                /* By writing to user space, we might have slept.
                /* By writing to user space, we might have slept.
                 * Stop the loop, to avoid a race condition.
                 * Stop the loop, to avoid a race condition.
                 */
                 */
                if (*p != current)
                if (*p != current)
                        break;
                        break;
        }
        }
 
 
        /* encode f_pos */
        /* encode f_pos */
        file->f_pos = (lineno << MAPS_LINE_SHIFT) + column;
        file->f_pos = (lineno << MAPS_LINE_SHIFT) + column;
 
 
        return destptr-buf;
        return destptr-buf;
}
}
#endif /* !NO_MM */
#endif /* !NO_MM */
 
 
#ifdef CONFIG_MODULES
#ifdef CONFIG_MODULES
extern int get_module_list(char *);
extern int get_module_list(char *);
extern int get_ksyms_list(char *, char **, off_t, int);
extern int get_ksyms_list(char *, char **, off_t, int);
#endif
#endif
extern int get_device_list(char *);
extern int get_device_list(char *);
extern int get_filesystem_list(char *);
extern int get_filesystem_list(char *);
extern int get_filesystem_info( char * );
extern int get_filesystem_info( char * );
extern int get_irq_list(char *);
extern int get_irq_list(char *);
extern int get_serialinfo(char *);
extern int get_serialinfo(char *);
extern int get_dma_list(char *);
extern int get_dma_list(char *);
extern int get_cpuinfo(char *);
extern int get_cpuinfo(char *);
extern int get_pci_list(char*);
extern int get_pci_list(char*);
extern int get_md_status (char *);
extern int get_md_status (char *);
extern int get_rtc_status (char *);
extern int get_rtc_status (char *);
extern int get_locks_status (char *, char **, off_t, int);
extern int get_locks_status (char *, char **, off_t, int);
#ifdef __SMP_PROF__
#ifdef __SMP_PROF__
extern int get_smp_prof_list(char *);
extern int get_smp_prof_list(char *);
#endif
#endif
 
 
static int get_root_array(char * page, int type, char **start, off_t offset, int length)
static int get_root_array(char * page, int type, char **start, off_t offset, int length)
{
{
        switch (type) {
        switch (type) {
                case PROC_LOADAVG:
                case PROC_LOADAVG:
                        return get_loadavg(page);
                        return get_loadavg(page);
 
 
                case PROC_UPTIME:
                case PROC_UPTIME:
                        return get_uptime(page);
                        return get_uptime(page);
 
 
                case PROC_MEMINFO:
                case PROC_MEMINFO:
                        return get_meminfo(page);
                        return get_meminfo(page);
 
 
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
                case PROC_PCI:
                case PROC_PCI:
                        return get_pci_list(page);
                        return get_pci_list(page);
#endif
#endif
 
 
                case PROC_CPUINFO:
                case PROC_CPUINFO:
                        return get_cpuinfo(page);
                        return get_cpuinfo(page);
 
 
                case PROC_VERSION:
                case PROC_VERSION:
                        return get_version(page);
                        return get_version(page);
 
 
#ifdef CONFIG_DEBUG_MALLOC
#ifdef CONFIG_DEBUG_MALLOC
                case PROC_MALLOC:
                case PROC_MALLOC:
                        return get_malloc(page);
                        return get_malloc(page);
#endif
#endif
 
 
#ifdef CONFIG_MODULES
#ifdef CONFIG_MODULES
                case PROC_MODULES:
                case PROC_MODULES:
                        return get_module_list(page);
                        return get_module_list(page);
 
 
                case PROC_KSYMS:
                case PROC_KSYMS:
                        return get_ksyms_list(page, start, offset, length);
                        return get_ksyms_list(page, start, offset, length);
#endif
#endif
 
 
                case PROC_STAT:
                case PROC_STAT:
                        return get_kstat(page);
                        return get_kstat(page);
 
 
                case PROC_DEVICES:
                case PROC_DEVICES:
                        return get_device_list(page);
                        return get_device_list(page);
 
 
                case PROC_INTERRUPTS:
                case PROC_INTERRUPTS:
                        return get_irq_list(page);
                        return get_irq_list(page);
 
 
                case PROC_SERIAL:
                case PROC_SERIAL:
                        return get_serialinfo(page);
                        return get_serialinfo(page);
 
 
                case PROC_FILESYSTEMS:
                case PROC_FILESYSTEMS:
                        return get_filesystem_list(page);
                        return get_filesystem_list(page);
 
 
                case PROC_DMA:
                case PROC_DMA:
                        return get_dma_list(page);
                        return get_dma_list(page);
 
 
                case PROC_IOPORTS:
                case PROC_IOPORTS:
                        return get_ioport_list(page);
                        return get_ioport_list(page);
#ifdef CONFIG_BLK_DEV_MD
#ifdef CONFIG_BLK_DEV_MD
                case PROC_MD:
                case PROC_MD:
                        return get_md_status(page);
                        return get_md_status(page);
#endif
#endif
#ifdef __SMP_PROF__
#ifdef __SMP_PROF__
                case PROC_SMP_PROF:
                case PROC_SMP_PROF:
                        return get_smp_prof_list(page);
                        return get_smp_prof_list(page);
#endif
#endif
                case PROC_CMDLINE:
                case PROC_CMDLINE:
                        return get_cmdline(page);
                        return get_cmdline(page);
 
 
                case PROC_MTAB:
                case PROC_MTAB:
                       return get_filesystem_info( page );
                       return get_filesystem_info( page );
#ifdef CONFIG_RTC
#ifdef CONFIG_RTC
                case PROC_RTC:
                case PROC_RTC:
                        return get_rtc_status(page);
                        return get_rtc_status(page);
#endif
#endif
                case PROC_LOCKS:
                case PROC_LOCKS:
                        return get_locks_status(page, start, offset, length);
                        return get_locks_status(page, start, offset, length);
        }
        }
        return -EBADF;
        return -EBADF;
}
}
 
 
static int process_unauthorized(int type, int pid)
static int process_unauthorized(int type, int pid)
{
{
        struct task_struct ** p = get_task(pid);
        struct task_struct ** p = get_task(pid);
 
 
        if (!p || !*p || !(*p)->mm)
        if (!p || !*p || !(*p)->mm)
                return 1;
                return 1;
 
 
        switch(type)
        switch(type)
        {
        {
                case PROC_PID_STATUS:
                case PROC_PID_STATUS:
                case PROC_PID_STAT:
                case PROC_PID_STAT:
                case PROC_PID_CMDLINE:
                case PROC_PID_CMDLINE:
#ifndef NO_MM
#ifndef NO_MM
                case PROC_PID_STATM:
                case PROC_PID_STATM:
                case PROC_PID_MAPS:
                case PROC_PID_MAPS:
#endif
#endif
                        return 0;
                        return 0;
        }
        }
        if(suser() || current->fsuid == (*p)->euid)
        if(suser() || current->fsuid == (*p)->euid)
                return 0;
                return 0;
        return 1;
        return 1;
}
}
 
 
 
 
static int get_process_array(char * page, int pid, int type)
static int get_process_array(char * page, int pid, int type)
{
{
        switch (type) {
        switch (type) {
                case PROC_PID_STATUS:
                case PROC_PID_STATUS:
                        return get_status(pid, page);
                        return get_status(pid, page);
                case PROC_PID_ENVIRON:
                case PROC_PID_ENVIRON:
                        return get_env(pid, page);
                        return get_env(pid, page);
                case PROC_PID_CMDLINE:
                case PROC_PID_CMDLINE:
                        return get_arg(pid, page);
                        return get_arg(pid, page);
                case PROC_PID_STAT:
                case PROC_PID_STAT:
                        return get_stat(pid, page);
                        return get_stat(pid, page);
#ifndef NO_MM
#ifndef NO_MM
                case PROC_PID_STATM:
                case PROC_PID_STATM:
                        return get_statm(pid, page);
                        return get_statm(pid, page);
#endif /* !NO_MM */
#endif /* !NO_MM */
        }
        }
        return -EBADF;
        return -EBADF;
}
}
 
 
 
 
static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
{
{
        if (pid)
        if (pid)
                return get_process_array(page, pid, type);
                return get_process_array(page, pid, type);
        return get_root_array(page, type, start, offset, length);
        return get_root_array(page, type, start, offset, length);
}
}
 
 
#define PROC_BLOCK_SIZE (3*1024)                /* 4K page size but our output routines use some slack for overruns */
#define PROC_BLOCK_SIZE (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 
 
static int array_read(struct inode * inode, struct file * file,char * buf, int count)
static int array_read(struct inode * inode, struct file * file,char * buf, int count)
{
{
        unsigned long page;
        unsigned long page;
        char *start;
        char *start;
        int length;
        int length;
        int end;
        int end;
        unsigned int type, pid;
        unsigned int type, pid;
        struct proc_dir_entry *dp;
        struct proc_dir_entry *dp;
 
 
        if (count < 0)
        if (count < 0)
                return -EINVAL;
                return -EINVAL;
        if (count > PROC_BLOCK_SIZE)
        if (count > PROC_BLOCK_SIZE)
                count = PROC_BLOCK_SIZE;
                count = PROC_BLOCK_SIZE;
        if (!(page = __get_free_page(GFP_KERNEL)))
        if (!(page = __get_free_page(GFP_KERNEL)))
                return -ENOMEM;
                return -ENOMEM;
        type = inode->i_ino;
        type = inode->i_ino;
        pid = type >> 16;
        pid = type >> 16;
        type &= 0x0000ffff;
        type &= 0x0000ffff;
        start = NULL;
        start = NULL;
        dp = (struct proc_dir_entry *) inode->u.generic_ip;
        dp = (struct proc_dir_entry *) inode->u.generic_ip;
 
 
        if (pid && process_unauthorized(type, pid))
        if (pid && process_unauthorized(type, pid))
        {
        {
                free_page(page);
                free_page(page);
                return -EIO;
                return -EIO;
        }
        }
 
 
        if (dp->get_info)
        if (dp->get_info)
                length = dp->get_info((char *)page, &start, file->f_pos,
                length = dp->get_info((char *)page, &start, file->f_pos,
                                      count, 0);
                                      count, 0);
        else
        else
                length = fill_array((char *) page, pid, type,
                length = fill_array((char *) page, pid, type,
                                    &start, file->f_pos, count);
                                    &start, file->f_pos, count);
        if (length < 0) {
        if (length < 0) {
                free_page(page);
                free_page(page);
                return length;
                return length;
        }
        }
        if (start != NULL) {
        if (start != NULL) {
                /* We have had block-adjusting processing! */
                /* We have had block-adjusting processing! */
                memcpy_tofs(buf, start, length);
                memcpy_tofs(buf, start, length);
                file->f_pos += length;
                file->f_pos += length;
                count = length;
                count = length;
        } else {
        } else {
                /* Static 4kB (or whatever) block capacity */
                /* Static 4kB (or whatever) block capacity */
                if (file->f_pos >= length) {
                if (file->f_pos >= length) {
                        free_page(page);
                        free_page(page);
                        return 0;
                        return 0;
                }
                }
                if (count + file->f_pos > length)
                if (count + file->f_pos > length)
                        count = length - file->f_pos;
                        count = length - file->f_pos;
                end = count + file->f_pos;
                end = count + file->f_pos;
                memcpy_tofs(buf, (char *) page + file->f_pos, count);
                memcpy_tofs(buf, (char *) page + file->f_pos, count);
                file->f_pos = end;
                file->f_pos = end;
        }
        }
        free_page(page);
        free_page(page);
        return count;
        return count;
}
}
 
 
static struct file_operations proc_array_operations = {
static struct file_operations proc_array_operations = {
        NULL,           /* array_lseek */
        NULL,           /* array_lseek */
        array_read,
        array_read,
        NULL,           /* array_write */
        NULL,           /* array_write */
        NULL,           /* array_readdir */
        NULL,           /* array_readdir */
        NULL,           /* array_select */
        NULL,           /* array_select */
        NULL,           /* array_ioctl */
        NULL,           /* array_ioctl */
        NULL,           /* mmap */
        NULL,           /* mmap */
        NULL,           /* no special open code */
        NULL,           /* no special open code */
        NULL,           /* no special release code */
        NULL,           /* no special release code */
        NULL            /* can't fsync */
        NULL            /* can't fsync */
};
};
 
 
struct inode_operations proc_array_inode_operations = {
struct inode_operations proc_array_inode_operations = {
        &proc_array_operations, /* default base directory file-ops */
        &proc_array_operations, /* default base directory file-ops */
        NULL,                   /* create */
        NULL,                   /* create */
        NULL,                   /* lookup */
        NULL,                   /* lookup */
        NULL,                   /* link */
        NULL,                   /* link */
        NULL,                   /* unlink */
        NULL,                   /* unlink */
        NULL,                   /* symlink */
        NULL,                   /* symlink */
        NULL,                   /* mkdir */
        NULL,                   /* mkdir */
        NULL,                   /* rmdir */
        NULL,                   /* rmdir */
        NULL,                   /* mknod */
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
        NULL,                   /* follow_link */
        NULL,                   /* readpage */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
        NULL,                   /* bmap */
        NULL,                   /* truncate */
        NULL,                   /* truncate */
        NULL                    /* permission */
        NULL                    /* permission */
};
};
 
 
static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
{
{
#ifndef NO_MM
#ifndef NO_MM
        unsigned int pid = inode->i_ino >> 16;
        unsigned int pid = inode->i_ino >> 16;
        unsigned int type = inode->i_ino & 0x0000ffff;
        unsigned int type = inode->i_ino & 0x0000ffff;
 
 
        if (count < 0)
        if (count < 0)
                return -EINVAL;
                return -EINVAL;
 
 
        switch (type) {
        switch (type) {
                case PROC_PID_MAPS:
                case PROC_PID_MAPS:
                        return read_maps(pid, file, buf, count);
                        return read_maps(pid, file, buf, count);
        }
        }
#endif /* !NO_MM */
#endif /* !NO_MM */
        return -EINVAL;
        return -EINVAL;
}
}
 
 
static struct file_operations proc_arraylong_operations = {
static struct file_operations proc_arraylong_operations = {
        NULL,           /* array_lseek */
        NULL,           /* array_lseek */
        arraylong_read,
        arraylong_read,
        NULL,           /* array_write */
        NULL,           /* array_write */
        NULL,           /* array_readdir */
        NULL,           /* array_readdir */
        NULL,           /* array_select */
        NULL,           /* array_select */
        NULL,           /* array_ioctl */
        NULL,           /* array_ioctl */
        NULL,           /* mmap */
        NULL,           /* mmap */
        NULL,           /* no special open code */
        NULL,           /* no special open code */
        NULL,           /* no special release code */
        NULL,           /* no special release code */
        NULL            /* can't fsync */
        NULL            /* can't fsync */
};
};
 
 
struct inode_operations proc_arraylong_inode_operations = {
struct inode_operations proc_arraylong_inode_operations = {
        &proc_arraylong_operations,     /* default base directory file-ops */
        &proc_arraylong_operations,     /* default base directory file-ops */
        NULL,                   /* create */
        NULL,                   /* create */
        NULL,                   /* lookup */
        NULL,                   /* lookup */
        NULL,                   /* link */
        NULL,                   /* link */
        NULL,                   /* unlink */
        NULL,                   /* unlink */
        NULL,                   /* symlink */
        NULL,                   /* symlink */
        NULL,                   /* mkdir */
        NULL,                   /* mkdir */
        NULL,                   /* rmdir */
        NULL,                   /* rmdir */
        NULL,                   /* mknod */
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
        NULL,                   /* follow_link */
        NULL,                   /* readpage */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
        NULL,                   /* bmap */
        NULL,                   /* truncate */
        NULL,                   /* truncate */
        NULL                    /* permission */
        NULL                    /* permission */
};
};
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.