patch-2.3.27 linux/fs/proc/array.c
Next file: linux/fs/proc/base.c
Previous file: linux/fs/proc/Makefile
Back to the patch index
Back to the overall index
- Lines: 925
- Date:
Tue Nov 9 19:39:07 1999
- Orig file:
v2.3.26/linux/fs/proc/array.c
- Orig date:
Sun Nov 7 16:37:34 1999
diff -u --recursive --new-file v2.3.26/linux/fs/proc/array.c linux/fs/proc/array.c
@@ -46,6 +46,10 @@
*
* Gerhard Wichert : added BIGMEM support
* Siemens AG <Gerhard.Wichert@pdb.siemens.de>
+ *
+ * Al Viro & Jeff Garzik : moved most of the thing into base.c and
+ * : proc_misc.c. The rest may eventually go into
+ * : base.c too.
*/
#include <linux/types.h>
@@ -70,401 +74,7 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
-
-
-static int open_kcore(struct inode * inode, struct file * filp)
-{
- return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
-}
-
-extern ssize_t read_kcore(struct file *, char *, size_t, loff_t *);
-
-static struct file_operations proc_kcore_operations = {
- NULL, /* lseek */
- read_kcore,
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- open_kcore
-};
-
-struct inode_operations proc_kcore_inode_operations = {
- &proc_kcore_operations,
-};
-
-/*
- * This function accesses profiling information. The returned data is
- * binary: the sampling step and the actual contents of the profile
- * buffer. Use of the program readprofile is recommended in order to
- * get meaningful info out of these data.
- */
-static ssize_t read_profile(struct file *file, char *buf,
- size_t count, loff_t *ppos)
-{
- unsigned long p = *ppos;
- ssize_t read;
- char * pnt;
- unsigned int sample_step = 1 << prof_shift;
-
- if (p >= (prof_len+1)*sizeof(unsigned int))
- return 0;
- if (count > (prof_len+1)*sizeof(unsigned int) - p)
- count = (prof_len+1)*sizeof(unsigned int) - p;
- read = 0;
-
- while (p < sizeof(unsigned int) && count > 0) {
- put_user(*((char *)(&sample_step)+p),buf);
- buf++; p++; count--; read++;
- }
- pnt = (char *)prof_buffer + p - sizeof(unsigned int);
- copy_to_user(buf,(void *)pnt,count);
- read += count;
- *ppos += read;
- return read;
-}
-
-/*
- * Writing to /proc/profile resets the counters
- *
- * Writing a 'profiling multiplier' value into it also re-sets the profiling
- * interrupt frequency, on architectures that support this.
- */
-static ssize_t write_profile(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
-#ifdef __SMP__
- extern int setup_profiling_timer (unsigned int multiplier);
-
- if (count==sizeof(int)) {
- unsigned int multiplier;
-
- if (copy_from_user(&multiplier, buf, sizeof(int)))
- return -EFAULT;
-
- if (setup_profiling_timer(multiplier))
- return -EINVAL;
- }
-#endif
-
- memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
- return count;
-}
-
-static struct file_operations proc_profile_operations = {
- NULL, /* lseek */
- read_profile,
- write_profile,
-};
-
-struct inode_operations proc_profile_inode_operations = {
- &proc_profile_operations,
-};
-
-static struct page * get_phys_addr(struct mm_struct * mm, unsigned long ptr)
-{
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t pte;
-
- if (ptr >= TASK_SIZE)
- return 0;
- pgd = pgd_offset(mm,ptr);
- if (pgd_none(*pgd))
- return 0;
- if (pgd_bad(*pgd)) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- return 0;
- }
- pmd = pmd_offset(pgd,ptr);
- if (pmd_none(*pmd))
- return 0;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- return 0;
- }
- pte = *pte_offset(pmd,ptr);
- if (!pte_present(pte))
- return 0;
- return pte_page(pte);
-}
-
-static int get_array(struct mm_struct *mm, unsigned long start, unsigned long end, char * buffer)
-{
- struct page *page;
- unsigned long kaddr;
- int size = 0, result = 0;
- char c;
-
- if (start >= end)
- return result;
- for (;;) {
- page = get_phys_addr(mm, start);
- if (!page)
- return result;
- kaddr = kmap(page, KM_READ) + (start & ~PAGE_MASK);
- do {
- c = *(char *) kaddr;
- if (!c)
- result = size;
- if (size < PAGE_SIZE)
- buffer[size++] = c;
- else {
- kunmap(kaddr, KM_READ);
- return result;
- }
- kaddr++;
- start++;
- if (!c && start >= end) {
- kunmap(kaddr, KM_READ);
- return result;
- }
- } while (kaddr & ~PAGE_MASK);
- kunmap(kaddr, KM_READ);
- }
- return result;
-}
-
-static struct mm_struct *get_mm(int pid)
-{
- struct task_struct *p;
- struct mm_struct *mm = NULL;
-
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- if (p)
- mm = p->mm;
- if (mm)
- atomic_inc(&mm->mm_users);
- read_unlock(&tasklist_lock);
- return mm;
-}
-
-
-static int get_env(int pid, char * buffer)
-{
- struct mm_struct *mm = get_mm(pid);
- int res = 0;
- if (mm) {
- res = get_array(mm, mm->env_start, mm->env_end, buffer);
- mmput(mm);
- }
- return res;
-}
-
-static int get_arg(int pid, char * buffer)
-{
- struct mm_struct *mm = get_mm(pid);
- int res = 0;
- if (mm) {
- res = get_array(mm, mm->arg_start, mm->arg_end, buffer);
- mmput(mm);
- }
- return res;
-}
-
-/*
- * These bracket the sleeping functions..
- */
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-#define first_sched ((unsigned long) scheduling_functions_start_here)
-#define last_sched ((unsigned long) scheduling_functions_end_here)
-
-static unsigned long get_wchan(struct task_struct *p)
-{
- if (!p || p == current || p->state == TASK_RUNNING)
- return 0;
-#if defined(__i386__)
- {
- unsigned long ebp, esp, eip;
- unsigned long stack_page;
- int count = 0;
-
- stack_page = (unsigned long)p;
- esp = p->thread.esp;
- if (!stack_page || esp < stack_page || esp > 8188+stack_page)
- return 0;
- /* include/asm-i386/system.h:switch_to() pushes ebp last. */
- ebp = *(unsigned long *) esp;
- do {
- if (ebp < stack_page || ebp > 8184+stack_page)
- return 0;
- eip = *(unsigned long *) (ebp+4);
- if (eip < first_sched || eip >= last_sched)
- return eip;
- ebp = *(unsigned long *) ebp;
- } while (count++ < 16);
- }
-#elif defined(__alpha__)
- /*
- * This one depends on the frame size of schedule(). Do a
- * "disass schedule" in gdb to find the frame size. Also, the
- * code assumes that sleep_on() follows immediately after
- * interruptible_sleep_on() and that add_timer() follows
- * immediately after interruptible_sleep(). Ugly, isn't it?
- * Maybe adding a wchan field to task_struct would be better,
- * after all...
- */
- {
- unsigned long schedule_frame;
- unsigned long pc;
-
- pc = thread_saved_pc(&p->thread);
- if (pc >= first_sched && pc < last_sched) {
- schedule_frame = ((unsigned long *)p->thread.ksp)[6];
- return ((unsigned long *)schedule_frame)[12];
- }
- return pc;
- }
-#elif defined(__mips__)
- /*
- * The same comment as on the Alpha applies here, too ...
- */
- {
- unsigned long schedule_frame;
- unsigned long pc;
-
- pc = thread_saved_pc(&p->tss);
- if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
- schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16];
- return (unsigned long)((unsigned long *)schedule_frame)[11];
- }
- return pc;
- }
-#elif defined(__mc68000__)
- {
- unsigned long fp, pc;
- unsigned long stack_page;
- int count = 0;
-
- stack_page = (unsigned long)p;
- fp = ((struct switch_stack *)p->thread.ksp)->a6;
- do {
- if (fp < stack_page+sizeof(struct task_struct) ||
- fp >= 8184+stack_page)
- return 0;
- pc = ((unsigned long *)fp)[1];
- /* FIXME: This depends on the order of these functions. */
- if (pc < first_sched || pc >= last_sched)
- return pc;
- fp = *(unsigned long *) fp;
- } while (count++ < 16);
- }
-#elif defined(__powerpc__)
- {
- unsigned long ip, sp;
- unsigned long stack_page = (unsigned long) p;
- int count = 0;
-
- sp = p->thread.ksp;
- do {
- sp = *(unsigned long *)sp;
- if (sp < stack_page || sp >= stack_page + 8188)
- return 0;
- if (count > 0) {
- ip = *(unsigned long *)(sp + 4);
- if (ip < first_sched || ip >= last_sched)
- return ip;
- }
- } while (count++ < 16);
- }
-#elif defined(__arm__)
- {
- unsigned long fp, lr;
- unsigned long stack_page;
- int count = 0;
-
- stack_page = 4096 + (unsigned long)p;
- fp = get_css_fp(&p->thread);
- do {
- if (fp < stack_page || fp > 4092+stack_page)
- return 0;
- lr = pc_pointer (((unsigned long *)fp)[-1]);
- if (lr < first_sched || lr > last_sched)
- return lr;
- fp = *(unsigned long *) (fp - 12);
- } while (count ++ < 16);
- }
-#elif defined (__sparc__)
- {
- unsigned long pc, fp, bias = 0;
- unsigned long task_base = (unsigned long) p;
- struct reg_window *rw;
- int count = 0;
-
-#ifdef __sparc_v9__
- bias = STACK_BIAS;
-#endif
- fp = p->thread.ksp + bias;
- do {
- /* Bogus frame pointer? */
- if (fp < (task_base + sizeof(struct task_struct)) ||
- fp >= (task_base + (2 * PAGE_SIZE)))
- break;
- rw = (struct reg_window *) fp;
- pc = rw->ins[7];
- if (pc < first_sched || pc >= last_sched)
- return pc;
- fp = rw->ins[6] + bias;
- } while (++count < 16);
- }
-#endif
-
- return 0;
-}
-
-#if defined(__i386__)
-# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-#elif defined(__alpha__)
- /*
- * See arch/alpha/kernel/ptrace.c for details.
- */
-# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
- + (long)&((struct pt_regs *)0)->reg)
-# define KSTK_EIP(tsk) \
- (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
-# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
-#elif defined(__arm__)
-# ifdef CONFIG_CPU_26
-# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
-# else
-# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1021])
-# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-# endif
-#elif defined(__mc68000__)
-#define KSTK_EIP(tsk) \
- ({ \
- unsigned long eip = 0; \
- if ((tsk)->thread.esp0 > PAGE_SIZE && \
- MAP_NR((tsk)->thread.esp0) < max_mapnr) \
- eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
- eip; })
-#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
-#elif defined(__powerpc__)
-#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip)
-#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1])
-#elif defined (__sparc_v9__)
-# define KSTK_EIP(tsk) ((tsk)->thread.kregs->tpc)
-# define KSTK_ESP(tsk) ((tsk)->thread.kregs->u_regs[UREG_FP])
-#elif defined(__sparc__)
-# define KSTK_EIP(tsk) ((tsk)->thread.kregs->pc)
-# define KSTK_ESP(tsk) ((tsk)->thread.kregs->u_regs[UREG_FP])
-#elif defined(__mips__)
-# define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg \
- - sizeof(struct pt_regs))
-#define KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32)
-# define KSTK_EIP(tsk) (*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(cp0_epc)))
-# define KSTK_ESP(tsk) (*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(regs[29])))
-#elif defined(__sh__)
-# define KSTK_EIP(tsk) ((tsk)->thread.pc)
-# define KSTK_ESP(tsk) ((tsk)->thread.sp)
-#endif
+#include <asm/processor.h>
/* Gcc optimizes away "strlen(x)" for constant x */
#define ADDBUF(buffer, string) \
@@ -654,36 +264,27 @@
}
-static int get_status(int pid, char * buffer)
+/* task is locked, so we are safe here */
+
+int proc_pid_status(struct task_struct *task, char * buffer)
{
char * orig = buffer;
- struct task_struct *tsk;
- struct mm_struct *mm = NULL;
+ struct mm_struct *mm = task->mm;
- read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
- if (tsk)
- mm = tsk->mm;
- if (mm)
- atomic_inc(&mm->mm_users);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */
- if (!tsk)
- return 0;
- buffer = task_name(tsk, buffer);
- buffer = task_state(tsk, buffer);
+ buffer = task_name(task, buffer);
+ buffer = task_state(task, buffer);
if (mm)
buffer = task_mem(mm, buffer);
- buffer = task_sig(tsk, buffer);
- buffer = task_cap(tsk, buffer);
- if (mm)
- mmput(mm);
+ buffer = task_sig(task, buffer);
+ buffer = task_cap(task, buffer);
return buffer - orig;
}
-static int get_stat(int pid, char * buffer)
+/* task is locked, so we are safe here */
+
+int proc_pid_stat(struct task_struct *task, char * buffer)
{
- struct task_struct *tsk;
- struct mm_struct *mm = NULL;
+ struct mm_struct *mm = task->mm;
unsigned long vsize, eip, esp, wchan;
long priority, nice;
int tty_pgrp;
@@ -691,16 +292,7 @@
char state;
int res;
- read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
- if (tsk)
- mm = tsk->mm;
- if (mm)
- atomic_inc(&mm->mm_users);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */
- if (!tsk)
- return 0;
- state = *get_task_state(tsk);
+ state = *get_task_state(task);
vsize = eip = esp = 0;
if (mm) {
struct vm_area_struct *vma;
@@ -710,55 +302,55 @@
vsize += vma->vm_end - vma->vm_start;
vma = vma->vm_next;
}
- eip = KSTK_EIP(tsk);
- esp = KSTK_ESP(tsk);
+ eip = KSTK_EIP(task);
+ esp = KSTK_ESP(task);
up(&mm->mmap_sem);
}
- wchan = get_wchan(tsk);
+ wchan = get_wchan(task);
- collect_sigign_sigcatch(tsk, &sigign, &sigcatch);
+ collect_sigign_sigcatch(task, &sigign, &sigcatch);
- if (tsk->tty)
- tty_pgrp = tsk->tty->pgrp;
+ if (task->tty)
+ tty_pgrp = task->tty->pgrp;
else
tty_pgrp = -1;
/* scale priority and nice values from timeslices to -20..20 */
/* to make it look like a "normal" Unix priority/nice value */
- priority = tsk->counter;
+ priority = task->counter;
priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
- nice = tsk->priority;
+ nice = task->priority;
nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
res = 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 %lu %lu %lu %d %d\n",
- pid,
- tsk->comm,
+ task->pid,
+ task->comm,
state,
- tsk->p_pptr->pid,
- tsk->pgrp,
- tsk->session,
- tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
+ task->p_pptr->pid,
+ task->pgrp,
+ task->session,
+ task->tty ? kdev_t_to_nr(task->tty->device) : 0,
tty_pgrp,
- tsk->flags,
- tsk->min_flt,
- tsk->cmin_flt,
- tsk->maj_flt,
- tsk->cmaj_flt,
- tsk->times.tms_utime,
- tsk->times.tms_stime,
- tsk->times.tms_cutime,
- tsk->times.tms_cstime,
+ task->flags,
+ task->min_flt,
+ task->cmin_flt,
+ task->maj_flt,
+ task->cmaj_flt,
+ task->times.tms_utime,
+ task->times.tms_stime,
+ task->times.tms_cutime,
+ task->times.tms_cstime,
priority,
nice,
0UL /* removed */,
- tsk->it_real_value,
- tsk->start_time,
+ task->it_real_value,
+ task->start_time,
vsize,
mm ? mm->rss : 0, /* you might want to shift this left 3 */
- tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
+ task->rlim ? task->rlim[RLIMIT_RSS].rlim_cur : 0,
mm ? mm->start_code : 0,
mm ? mm->end_code : 0,
mm ? mm->start_stack : 0,
@@ -768,17 +360,15 @@
* It must be decimal for Linux 2.0 compatibility.
* Use /proc/#/status for real-time signals.
*/
- tsk->signal .sig[0] & 0x7fffffffUL,
- tsk->blocked.sig[0] & 0x7fffffffUL,
+ task->signal .sig[0] & 0x7fffffffUL,
+ task->blocked.sig[0] & 0x7fffffffUL,
sigign .sig[0] & 0x7fffffffUL,
sigcatch .sig[0] & 0x7fffffffUL,
wchan,
- tsk->nswap,
- tsk->cnswap,
- tsk->exit_signal,
- tsk->processor);
- if (mm)
- mmput(mm);
+ task->nswap,
+ task->cnswap,
+ task->exit_signal,
+ task->processor);
return res;
}
@@ -813,9 +403,9 @@
++*pages;
if (pte_dirty(page))
++*dirty;
- if (MAP_NR(pte_page(page)) >= max_mapnr)
+ if (pte_pagenr(page) >= max_mapnr)
continue;
- if (page_count(mem_map + MAP_NR(pte_page(page))) > 1)
+ if (page_count(pte_page(page)) > 1)
++*shared;
} while (address < end);
}
@@ -855,9 +445,9 @@
}
}
-static int get_statm(int pid, char * buffer)
+int proc_pid_statm(struct task_struct *task, char * buffer)
{
- struct mm_struct *mm = get_mm(pid);
+ struct mm_struct *mm = task->mm;
int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
if (mm) {
@@ -884,7 +474,6 @@
vma = vma->vm_next;
}
up(&mm->mmap_sem);
- mmput(mm);
}
return sprintf(buffer,"%d %d %d %d %d %d %d\n",
size, resident, share, trs, lrs, drs, dt);
@@ -923,10 +512,10 @@
#define MAPS_LINE_MAX MAPS_LINE_MAX8
-static ssize_t read_maps (int pid, struct file * file, char * buf,
+ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char * buf,
size_t count, loff_t *ppos)
{
- struct task_struct *p;
+ struct mm_struct *mm = task->mm;
struct vm_area_struct * map, * next;
char * destptr = buf, * buffer;
loff_t lineno;
@@ -942,25 +531,19 @@
if (!buffer)
goto out;
- retval = -EINVAL;
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */
- if (!p)
- goto freepage_out;
-
- if (!p->mm || count == 0)
+ if (!mm || count == 0)
goto getlen_out;
/* Check whether the mmaps could change if we sleep */
- volatile_task = (p != current || atomic_read(&p->mm->mm_users) > 1);
+ volatile_task = (task != current || atomic_read(&mm->mm_users) > 1);
/* decode f_pos */
lineno = *ppos >> MAPS_LINE_SHIFT;
column = *ppos & (MAPS_LINE_LENGTH-1);
/* quickly go to line lineno */
- for (map = p->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
+ down(&mm->mmap_sem);
+ for (map = mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
continue;
for ( ; map ; map = next ) {
@@ -1019,7 +602,9 @@
i = len-column;
if (i > count)
i = count;
+ up(&mm->mmap_sem);
copy_to_user(destptr, line+column, i); /* may have slept */
+ down(&mm->mmap_sem);
destptr += i;
count -= i;
column += i;
@@ -1038,246 +623,34 @@
if (volatile_task)
break;
}
+ up(&mm->mmap_sem);
/* encode f_pos */
*ppos = (lineno << MAPS_LINE_SHIFT) + column;
getlen_out:
retval = destptr - buf;
-
-freepage_out:
free_page((unsigned long)buffer);
out:
return retval;
}
#ifdef __SMP__
-static int get_pidcpu(int pid, char * buffer)
+int proc_pid_cpu(struct task_struct *task, char * buffer)
{
- struct task_struct * tsk = current ;
int i, len;
- read_lock(&tasklist_lock);
- if (pid != tsk->pid)
- tsk = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */
-
- if (tsk == NULL)
- return 0;
-
len = sprintf(buffer,
"cpu %lu %lu\n",
- tsk->times.tms_utime,
- tsk->times.tms_stime);
+ task->times.tms_utime,
+ task->times.tms_stime);
for (i = 0 ; i < smp_num_cpus; i++)
len += sprintf(buffer + len, "cpu%d %lu %lu\n",
i,
- tsk->per_cpu_utime[cpu_logical_map(i)],
- tsk->per_cpu_stime[cpu_logical_map(i)]);
+ task->per_cpu_utime[cpu_logical_map(i)],
+ task->per_cpu_stime[cpu_logical_map(i)]);
return len;
}
#endif
-
-static int process_unauthorized(int type, int pid)
-{
- struct task_struct *p;
- uid_t euid=0; /* Save the euid keep the lock short */
- int ok = 0;
-
- read_lock(&tasklist_lock);
-
- /*
- * Grab the lock, find the task, save the uid and
- * check it has an mm still (ie its not dead)
- */
-
- p = find_task_by_pid(pid);
- if (p) {
- euid=p->euid;
- ok = p->dumpable;
- if(!cap_issubset(p->cap_permitted, current->cap_permitted))
- ok=0;
- }
-
- read_unlock(&tasklist_lock);
-
- if (!p)
- return 1;
-
- switch(type) {
- case PROC_PID_STATUS:
- case PROC_PID_STATM:
- case PROC_PID_STAT:
- case PROC_PID_MAPS:
- case PROC_PID_CMDLINE:
- case PROC_PID_CPU:
- return 0;
- }
- if(capable(CAP_DAC_OVERRIDE) || (current->fsuid == euid && ok))
- return 0;
- return 1;
-}
-
-
-static inline int get_process_array(char * page, int pid, int type)
-{
- switch (type) {
- case PROC_PID_STATUS:
- return get_status(pid, page);
- case PROC_PID_ENVIRON:
- return get_env(pid, page);
- case PROC_PID_CMDLINE:
- return get_arg(pid, page);
- case PROC_PID_STAT:
- return get_stat(pid, page);
- case PROC_PID_STATM:
- return get_statm(pid, page);
-#ifdef __SMP__
- case PROC_PID_CPU:
- return get_pidcpu(pid, page);
-#endif
- }
- return -EBADF;
-}
-
-#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */
-
-static ssize_t array_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- struct inode * inode = file->f_dentry->d_inode;
- unsigned long page;
- char *start;
- ssize_t length;
- ssize_t end;
- unsigned int type, pid;
- struct proc_dir_entry *dp;
-
- if (count > PROC_BLOCK_SIZE)
- count = PROC_BLOCK_SIZE;
- if (!(page = __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- type = inode->i_ino;
- pid = type >> 16;
- type &= 0x0000ffff;
- start = NULL;
- dp = (struct proc_dir_entry *) inode->u.generic_ip;
-
- if (!pid) { /* can't happen */
- free_page(page);
- return -EBADF;
- }
-
- if (process_unauthorized(type, pid)) {
- free_page(page);
- return -EIO;
- }
-
- length = get_process_array((char *) page, pid, type);
- if (length < 0) {
- free_page(page);
- return length;
- }
- /* Static 4kB (or whatever) block capacity */
- if (*ppos >= length) {
- free_page(page);
- return 0;
- }
- if (count + *ppos > length)
- count = length - *ppos;
- end = count + *ppos;
- copy_to_user(buf, (char *) page + *ppos, count);
- *ppos = end;
- free_page(page);
- return count;
-}
-
-static struct file_operations proc_array_operations = {
- NULL, /* array_lseek */
- array_read,
- NULL, /* array_write */
- NULL, /* array_readdir */
- NULL, /* array_poll */
- NULL, /* array_ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
-};
-
-struct inode_operations proc_array_inode_operations = {
- &proc_array_operations, /* default base directory file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static ssize_t arraylong_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- struct inode * inode = file->f_dentry->d_inode;
- unsigned int pid = inode->i_ino >> 16;
- unsigned int type = inode->i_ino & 0x0000ffff;
-
- switch (type) {
- case PROC_PID_MAPS:
- return read_maps(pid, file, buf, count, ppos);
- }
- return -EINVAL;
-}
-
-static struct file_operations proc_arraylong_operations = {
- NULL, /* array_lseek */
- arraylong_read,
- NULL, /* array_write */
- NULL, /* array_readdir */
- NULL, /* array_poll */
- NULL, /* array_ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
-};
-
-struct inode_operations proc_arraylong_inode_operations = {
- &proc_arraylong_operations, /* default base directory file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)