summaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
commitd6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch)
treee2be02f33984c48ec019c654051d27964e42c441 /fs/proc
parent609d1e803baf519487233b765eb487f9ec227a18 (diff)
Merge with 2.3.19.
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c295
-rw-r--r--fs/proc/base.c2
-rw-r--r--fs/proc/fd.c13
-rw-r--r--fs/proc/link.c74
-rw-r--r--fs/proc/mem.c5
-rw-r--r--fs/proc/openpromfs.c8
-rw-r--r--fs/proc/proc_tty.c2
-rw-r--r--fs/proc/root.c46
8 files changed, 271 insertions, 174 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index f108511fb..e2775ae0d 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -42,6 +42,10 @@
* Alan Cox : security fixes.
* <Alan.Cox@linux.org>
*
+ * Al Viro : safe handling of mm_struct
+ *
+ * Gerhard Wichert : added BIGMEM support
+ * Siemens AG <Gerhard.Wichert@pdb.siemens.de>
*/
#include <linux/types.h>
@@ -76,6 +80,11 @@ int get_malloc(char * buffer);
#endif
+static int open_kcore(struct inode * inode, struct file * filp)
+{
+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
static ssize_t read_core(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
@@ -93,6 +102,9 @@ static ssize_t read_core(struct file * file, char * buf,
memset(&dump, 0, sizeof(struct user));
dump.magic = CMAGIC;
dump.u_dsize = max_mapnr;
+#if defined (__i386__)
+ dump.start_code = PAGE_OFFSET;
+#endif
#ifdef __alpha__
dump.start_data = PAGE_OFFSET;
#endif
@@ -137,6 +149,12 @@ static ssize_t read_core(struct file * file, char * buf,
static struct file_operations proc_kcore_operations = {
NULL, /* lseek */
read_core,
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ open_kcore
};
struct inode_operations proc_kcore_inode_operations = {
@@ -223,7 +241,7 @@ static int get_loadavg(char * buffer)
LOAD_INT(a), LOAD_FRAC(a),
LOAD_INT(b), LOAD_FRAC(b),
LOAD_INT(c), LOAD_FRAC(c),
- nr_running, nr_tasks, last_pid);
+ nr_running, nr_threads, last_pid);
}
static int get_kstat(char * buffer)
@@ -231,9 +249,8 @@ static int get_kstat(char * buffer)
int i, len;
unsigned sum = 0;
extern unsigned long total_forks;
- unsigned long ticks;
+ unsigned long jif = HZ_TO_STD(jiffies);
- ticks = HZ_TO_STD(jiffies) * smp_num_cpus;
for (i = 0 ; i < NR_IRQS ; i++)
sum += kstat_irqs(i);
@@ -243,14 +260,14 @@ static int get_kstat(char * buffer)
kstat.cpu_user,
kstat.cpu_nice,
kstat.cpu_system,
- jiffies*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
+ jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
for (i = 0 ; i < smp_num_cpus; i++)
len += sprintf(buffer + len, "cpu%d %u %u %u %lu\n",
i,
kstat.per_cpu_user[cpu_logical_map(i)],
kstat.per_cpu_nice[cpu_logical_map(i)],
kstat.per_cpu_system[cpu_logical_map(i)],
- jiffies - ( kstat.per_cpu_user[cpu_logical_map(i)] \
+ jif - ( kstat.per_cpu_user[cpu_logical_map(i)] \
+ kstat.per_cpu_nice[cpu_logical_map(i)] \
+ kstat.per_cpu_system[cpu_logical_map(i)]));
len += sprintf(buffer + len,
@@ -276,7 +293,7 @@ static int get_kstat(char * buffer)
HZ_TO_STD(kstat.cpu_user),
HZ_TO_STD(kstat.cpu_nice),
HZ_TO_STD(kstat.cpu_system),
- ticks - HZ_TO_STD(kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
+ jif*smp_num_cpus - HZ_TO_STD(kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
#endif
kstat.dk_drive[0], kstat.dk_drive[1],
kstat.dk_drive[2], kstat.dk_drive[3],
@@ -300,7 +317,7 @@ static int get_kstat(char * buffer)
"btime %lu\n"
"processes %lu\n",
kstat.context_swtch,
- xtime.tv_sec - jiffies / HZ,
+ xtime.tv_sec - jif / HZ,
total_forks);
return len;
}
@@ -312,7 +329,7 @@ static int get_uptime(char * buffer)
unsigned long idle;
uptime = jiffies;
- idle = task[0]->times.tms_utime + task[0]->times.tms_stime;
+ idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
that would overflow about every five days at HZ == 100.
@@ -348,7 +365,7 @@ static int get_meminfo(char * buffer)
len = sprintf(buffer, " total: used: free: shared: buffers: cached:\n"
"Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n"
"Swap: %8lu %8lu %8lu\n",
- i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, atomic_read(&page_cache_size)*PAGE_SIZE,
+ i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, (unsigned long) atomic_read(&page_cache_size)*PAGE_SIZE,
i.totalswap, i.totalswap-i.freeswap, i.freeswap);
/*
* Tagged format, for easy grepping and expansion. The above will go away
@@ -360,6 +377,8 @@ static int get_meminfo(char * buffer)
"MemShared: %8lu kB\n"
"Buffers: %8lu kB\n"
"Cached: %8u kB\n"
+ "BigTotal: %8lu kB\n"
+ "BigFree: %8lu kB\n"
"SwapTotal: %8lu kB\n"
"SwapFree: %8lu kB\n",
i.totalram >> 10,
@@ -367,6 +386,8 @@ static int get_meminfo(char * buffer)
i.sharedram >> 10,
i.bufferram >> 10,
atomic_read(&page_cache_size) << (PAGE_SHIFT - 10),
+ i.totalbig >> 10,
+ i.freebig >> 10,
i.totalswap >> 10,
i.freeswap >> 10);
}
@@ -386,21 +407,15 @@ static int get_cmdline(char * buffer)
return sprintf(buffer, "%s\n", saved_command_line);
}
-static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
+static unsigned long get_phys_addr(struct mm_struct * mm, unsigned long ptr)
{
pgd_t *page_dir;
pmd_t *page_middle;
pte_t pte;
- if (!p || !p->mm || ptr >= TASK_SIZE)
+ if (ptr >= TASK_SIZE)
return 0;
- /* Check for NULL pgd .. shouldn't happen! */
- if (!p->mm->pgd) {
- printk("get_phys_addr: pid %d has NULL pgd!\n", p->pid);
- return 0;
- }
-
- page_dir = pgd_offset(p->mm,ptr);
+ page_dir = pgd_offset(mm,ptr);
if (pgd_none(*page_dir))
return 0;
if (pgd_bad(*page_dir)) {
@@ -422,7 +437,9 @@ static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
return pte_page(pte) + (ptr & ~PAGE_MASK);
}
-static int get_array(struct task_struct *p, unsigned long start, unsigned long end, char * buffer)
+#include <linux/bigmem.h>
+
+static int get_array(struct mm_struct *mm, unsigned long start, unsigned long end, char * buffer)
{
unsigned long addr;
int size = 0, result = 0;
@@ -431,49 +448,68 @@ static int get_array(struct task_struct *p, unsigned long start, unsigned long e
if (start >= end)
return result;
for (;;) {
- addr = get_phys_addr(p, start);
+ addr = get_phys_addr(mm, start);
if (!addr)
return result;
+ addr = kmap(addr, KM_READ);
do {
c = *(char *) addr;
if (!c)
result = size;
if (size < PAGE_SIZE)
buffer[size++] = c;
- else
+ else {
+ kunmap(addr, KM_READ);
return result;
+ }
addr++;
start++;
- if (!c && start >= end)
+ if (!c && start >= end) {
+ kunmap(addr, KM_READ);
return result;
+ }
} while (addr & ~PAGE_MASK);
+ kunmap(addr, KM_READ);
}
return result;
}
-static int get_env(int pid, char * buffer)
+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);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */
+ if (p)
+ mm = p->mm;
+ if (mm)
+ atomic_inc(&mm->mm_users);
+ read_unlock(&tasklist_lock);
+ return mm;
+}
- if (!p || !p->mm)
- return 0;
- return get_array(p, p->mm->env_start, p->mm->env_end, buffer);
+
+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 task_struct *p;
-
- 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 || !p->mm)
- return 0;
- return get_array(p, p->mm->arg_start, p->mm->arg_end, 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;
}
/*
@@ -495,13 +531,13 @@ static unsigned long get_wchan(struct task_struct *p)
int count = 0;
stack_page = (unsigned long)p;
- esp = p->tss.esp;
- if (!stack_page || esp < stack_page || esp >= 8188+stack_page)
+ 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 >= 8188+stack_page)
+ if (ebp < stack_page || ebp > 8184+stack_page)
return 0;
eip = *(unsigned long *) (ebp+4);
if (eip < first_sched || eip >= last_sched)
@@ -523,9 +559,9 @@ static unsigned long get_wchan(struct task_struct *p)
unsigned long schedule_frame;
unsigned long pc;
- pc = thread_saved_pc(&p->tss);
+ pc = thread_saved_pc(&p->thread);
if (pc >= first_sched && pc < last_sched) {
- schedule_frame = ((unsigned long *)p->tss.ksp)[6];
+ schedule_frame = ((unsigned long *)p->thread.ksp)[6];
return ((unsigned long *)schedule_frame)[12];
}
return pc;
@@ -538,9 +574,9 @@ static unsigned long get_wchan(struct task_struct *p)
unsigned long schedule_frame;
unsigned long pc;
- pc = thread_saved_pc(&p->tss);
+ pc = thread_saved_pc(&p->thread);
if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
- schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16];
+ schedule_frame = ((unsigned long *)(long)p->thread.reg30)[16];
return (unsigned long)((unsigned long *)schedule_frame)[11];
}
return pc;
@@ -552,7 +588,7 @@ static unsigned long get_wchan(struct task_struct *p)
int count = 0;
stack_page = (unsigned long)p;
- fp = ((struct switch_stack *)p->tss.ksp)->a6;
+ fp = ((struct switch_stack *)p->thread.ksp)->a6;
do {
if (fp < stack_page+sizeof(struct task_struct) ||
fp >= 8184+stack_page)
@@ -570,7 +606,7 @@ static unsigned long get_wchan(struct task_struct *p)
unsigned long stack_page = (unsigned long) p;
int count = 0;
- sp = p->tss.ksp;
+ sp = p->thread.ksp;
do {
sp = *(unsigned long *)sp;
if (sp < stack_page || sp >= stack_page + 8188)
@@ -609,7 +645,7 @@ static unsigned long get_wchan(struct task_struct *p)
#ifdef __sparc_v9__
bias = STACK_BIAS;
#endif
- fp = p->tss.ksp + bias;
+ fp = p->thread.ksp + bias;
do {
/* Bogus frame pointer? */
if (fp < (task_base + sizeof(struct task_struct)) ||
@@ -638,7 +674,7 @@ static unsigned long get_wchan(struct task_struct *p)
+ (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)->tss.usp)
+# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
#elif defined(__arm__)
# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
@@ -646,26 +682,29 @@ static unsigned long get_wchan(struct task_struct *p)
#define KSTK_EIP(tsk) \
({ \
unsigned long eip = 0; \
- if ((tsk)->tss.esp0 > PAGE_SIZE && \
- MAP_NR((tsk)->tss.esp0) < max_mapnr) \
- eip = ((struct pt_regs *) (tsk)->tss.esp0)->pc; \
+ 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)->tss.usp)
+#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
#elif defined(__powerpc__)
-#define KSTK_EIP(tsk) ((tsk)->tss.regs->nip)
-#define KSTK_ESP(tsk) ((tsk)->tss.regs->gpr[1])
+#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)->tss.kregs->tpc)
-# define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP])
+# 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)->tss.kregs->pc)
-# define KSTK_ESP(tsk) ((tsk)->tss.kregs->u_regs[UREG_FP])
+# 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
/* Gcc optimizes away "strlen(x)" for constant x */
@@ -747,11 +786,13 @@ static inline char * task_state(struct task_struct *p, char *buffer)
"PPid:\t%d\n"
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n"
+ "FDSize:\t%d\n"
"Groups:\t",
get_task_state(p),
p->pid, p->p_pptr->pid,
p->uid, p->euid, p->suid, p->fsuid,
- p->gid, p->egid, p->sgid, p->fsgid);
+ p->gid, p->egid, p->sgid, p->fsgid,
+ p->files ? p->files->max_fds : 0);
for (g = 0; g < p->ngroups; g++)
buffer += sprintf(buffer, "%d ", p->groups[g]);
@@ -760,46 +801,44 @@ static inline char * task_state(struct task_struct *p, char *buffer)
return buffer;
}
-static inline char * task_mem(struct task_struct *p, char *buffer)
+static inline char * task_mem(struct mm_struct *mm, char *buffer)
{
- struct mm_struct * mm = p->mm;
-
- if (mm && mm != &init_mm) {
- struct vm_area_struct * vma = mm->mmap;
- unsigned long data = 0, stack = 0;
- unsigned long exec = 0, lib = 0;
-
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
- if (!vma->vm_file) {
- data += len;
- if (vma->vm_flags & VM_GROWSDOWN)
- stack += len;
- continue;
- }
- if (vma->vm_flags & VM_WRITE)
+ struct vm_area_struct * vma;
+ unsigned long data = 0, stack = 0;
+ unsigned long exec = 0, lib = 0;
+
+ down(&mm->mmap_sem);
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
+ if (!vma->vm_file) {
+ data += len;
+ if (vma->vm_flags & VM_GROWSDOWN)
+ stack += len;
+ continue;
+ }
+ if (vma->vm_flags & VM_WRITE)
+ continue;
+ if (vma->vm_flags & VM_EXEC) {
+ exec += len;
+ if (vma->vm_flags & VM_EXECUTABLE)
continue;
- if (vma->vm_flags & VM_EXEC) {
- exec += len;
- if (vma->vm_flags & VM_EXECUTABLE)
- continue;
- lib += len;
- }
- }
- buffer += sprintf(buffer,
- "VmSize:\t%8lu kB\n"
- "VmLck:\t%8lu kB\n"
- "VmRSS:\t%8lu kB\n"
- "VmData:\t%8lu kB\n"
- "VmStk:\t%8lu kB\n"
- "VmExe:\t%8lu kB\n"
- "VmLib:\t%8lu kB\n",
- mm->total_vm << (PAGE_SHIFT-10),
- mm->locked_vm << (PAGE_SHIFT-10),
- mm->rss << (PAGE_SHIFT-10),
- data - stack, stack,
- exec - lib, lib);
+ lib += len;
+ }
}
+ buffer += sprintf(buffer,
+ "VmSize:\t%8lu kB\n"
+ "VmLck:\t%8lu kB\n"
+ "VmRSS:\t%8lu kB\n"
+ "VmData:\t%8lu kB\n"
+ "VmStk:\t%8lu kB\n"
+ "VmExe:\t%8lu kB\n"
+ "VmLib:\t%8lu kB\n",
+ mm->total_vm << (PAGE_SHIFT-10),
+ mm->locked_vm << (PAGE_SHIFT-10),
+ mm->rss << (PAGE_SHIFT-10),
+ data - stack, stack,
+ exec - lib, lib);
+ up(&mm->mmap_sem);
return buffer;
}
@@ -860,44 +899,61 @@ static int get_status(int pid, char * buffer)
{
char * orig = buffer;
struct task_struct *tsk;
+ struct mm_struct *mm = NULL;
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_mem(tsk, buffer);
+ if (mm)
+ buffer = task_mem(mm, buffer);
buffer = task_sig(tsk, buffer);
buffer = task_cap(tsk, buffer);
+ if (mm)
+ mmput(mm);
return buffer - orig;
}
static int get_stat(int pid, char * buffer)
{
struct task_struct *tsk;
+ struct mm_struct *mm = NULL;
unsigned long vsize, eip, esp, wchan;
long priority, nice;
int tty_pgrp;
sigset_t sigign, sigcatch;
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);
vsize = eip = esp = 0;
- if (tsk->mm && tsk->mm != &init_mm) {
- struct vm_area_struct *vma = tsk->mm->mmap;
+ if (mm) {
+ struct vm_area_struct *vma;
+ down(&mm->mmap_sem);
+ vma = mm->mmap;
while (vma) {
vsize += vma->vm_end - vma->vm_start;
vma = vma->vm_next;
}
eip = KSTK_EIP(tsk);
esp = KSTK_ESP(tsk);
+ up(&mm->mmap_sem);
}
wchan = get_wchan(tsk);
@@ -916,7 +972,7 @@ static int get_stat(int pid, char * buffer)
nice = tsk->priority;
nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
- return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
+ 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,
@@ -942,11 +998,11 @@ static int get_stat(int pid, char * buffer)
tsk->it_real_value,
tsk->start_time,
vsize,
- tsk->mm ? tsk->mm->rss : 0, /* you might want to shift this left 3 */
+ mm ? mm->rss : 0, /* you might want to shift this left 3 */
tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
- tsk->mm ? tsk->mm->start_code : 0,
- tsk->mm ? tsk->mm->end_code : 0,
- tsk->mm ? tsk->mm->start_stack : 0,
+ mm ? mm->start_code : 0,
+ mm ? mm->end_code : 0,
+ mm ? mm->start_stack : 0,
esp,
eip,
/* The signal information here is obsolete.
@@ -962,6 +1018,9 @@ static int get_stat(int pid, char * buffer)
tsk->cnswap,
tsk->exit_signal,
tsk->processor);
+ if (mm)
+ mmput(mm);
+ return res;
}
static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
@@ -1039,19 +1098,15 @@ static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long en
static int get_statm(int pid, char * buffer)
{
- struct task_struct *tsk;
+ struct mm_struct *mm = get_mm(pid);
int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
- read_lock(&tasklist_lock);
- tsk = find_task_by_pid(pid);
- read_unlock(&tasklist_lock); /* FIXME!! This should be done after the last use */
- if (!tsk)
- return 0;
- if (tsk->mm && tsk->mm != &init_mm) {
- struct vm_area_struct * vma = tsk->mm->mmap;
-
+ if (mm) {
+ struct vm_area_struct * vma;
+ down(&mm->mmap_sem);
+ vma = mm->mmap;
while (vma) {
- pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
+ pgd_t *pgd = pgd_offset(mm, vma->vm_start);
int pages = 0, shared = 0, dirty = 0, total = 0;
statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
@@ -1069,6 +1124,8 @@ static int get_statm(int pid, char * buffer)
drs += pages;
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);
@@ -1133,11 +1190,11 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
if (!p)
goto freepage_out;
- if (!p->mm || p->mm == &init_mm || count == 0)
+ if (!p->mm || count == 0)
goto getlen_out;
/* Check whether the mmaps could change if we sleep */
- volatile_task = (p != current || atomic_read(&p->mm->count) > 1);
+ volatile_task = (p != current || atomic_read(&p->mm->mm_users) > 1);
/* decode f_pos */
lineno = *ppos >> MAPS_LINE_SHIFT;
@@ -1296,7 +1353,7 @@ static long get_root_array(char * page, int type, char **start,
case PROC_MEMINFO:
return get_meminfo(page);
-#ifdef CONFIG_PCI_OLD_PROC
+#ifdef CONFIG_PCI
case PROC_PCI:
return get_pci_list(page);
#endif
@@ -1404,8 +1461,6 @@ static int process_unauthorized(int type, int pid)
ok = p->dumpable;
if(!cap_issubset(p->cap_permitted, current->cap_permitted))
ok=0;
- if(!p->mm) /* Scooby scooby doo where are you ? */
- p=NULL;
}
read_unlock(&tasklist_lock);
@@ -1413,8 +1468,7 @@ static int process_unauthorized(int type, int pid)
if (!p)
return 1;
- switch(type)
- {
+ switch(type) {
case PROC_PID_STATUS:
case PROC_PID_STATM:
case PROC_PID_STAT:
@@ -1481,8 +1535,7 @@ static ssize_t array_read(struct file * file, char * buf,
start = NULL;
dp = (struct proc_dir_entry *) inode->u.generic_ip;
- if (pid && process_unauthorized(type, pid))
- {
+ if (pid && process_unauthorized(type, pid)) {
free_page(page);
return -EIO;
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 118e94956..f0a0febf8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -178,7 +178,7 @@ static struct proc_dir_entry proc_pid_cpu = {
};
#endif
-__initfunc(void proc_base_init(void))
+void __init proc_base_init(void)
{
#if CONFIG_AP1000
proc_register(&proc_pid, &proc_pid_ringbuf);
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 195ca41b8..1862f6f5f 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -90,6 +90,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
fd = 0;
len = dentry->d_name.len;
name = dentry->d_name.name;
+ if (len > 1 && *name == '0') goto out;
while (len-- > 0) {
c = *name - '0';
name++;
@@ -133,7 +134,7 @@ out:
static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct task_struct * p, **tarrayp;
+ struct task_struct *p, *tmp;
unsigned int fd, pid, ino;
int retval;
char buf[NUMBUF];
@@ -157,7 +158,6 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
p = find_task_by_pid(pid);
if (!p)
goto out_unlock;
- tarrayp = p->tarray_ptr;
for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++)
{
@@ -182,8 +182,13 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
goto out;
read_lock(&tasklist_lock);
- /* filldir() might have slept, so we must re-validate "p" */
- if (p != *tarrayp || p->pid != pid)
+ /*
+ * filldir() might have slept, so we must
+ * re-validate "p". This is fast enough due
+ * to the pidhash
+ */
+ tmp = find_task_by_pid(pid);
+ if (p != tmp)
break;
}
out_unlock:
diff --git a/fs/proc/link.c b/fs/proc/link.c
index 6f5c63ec3..69d435600 100644
--- a/fs/proc/link.c
+++ b/fs/proc/link.c
@@ -82,60 +82,70 @@ static struct dentry * proc_follow_link(struct dentry *dentry,
ino &= 0x0000ffff;
result = ERR_PTR(-ENOENT);
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- if (!p)
- goto out_unlock;
switch (ino) {
case PROC_PID_CWD:
- if (!p->fs || !p->fs->pwd)
- goto out_unlock;
- result = p->fs->pwd;
- goto out_dget;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p && p->fs && p->fs->pwd)
+ result = dget(p->fs->pwd);
+ read_unlock(&tasklist_lock);
+ break;
case PROC_PID_ROOT:
- if (!p->fs || !p->fs->root)
- goto out_unlock;
- result = p->fs->root;
- goto out_dget;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p && p->fs && p->fs->root)
+ result = dget(p->fs->root);
+ read_unlock(&tasklist_lock);
+ break;
case PROC_PID_EXE: {
+ struct mm_struct *mm = NULL;
struct vm_area_struct * vma;
- if (!p->mm)
- goto out_unlock;
- vma = p->mm->mmap;
+ 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);
+ if (!mm)
+ break;
+ down(&mm->mmap_sem);
+ vma = mm->mmap;
while (vma) {
if ((vma->vm_flags & VM_EXECUTABLE) &&
vma->vm_file) {
- result = vma->vm_file->f_dentry;
- goto out_dget;
+ result = dget(vma->vm_file->f_dentry);
+ break;
}
vma = vma->vm_next;
}
- goto out_unlock;
+ up(&mm->mmap_sem);
+ mmput(mm);
+ break;
}
default:
if (ino & PROC_PID_FD_DIR) {
struct file * file;
+ struct files_struct *files = NULL;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p)
+ files = p->files;
+ read_unlock(&tasklist_lock);
+ if (!files)
+ break;
ino &= 0x7fff;
- if (!p->files) /* shouldn't happen here */
- goto out_unlock;
- read_lock(&p->files->file_lock);
- file = fcheck_task(p, ino);
- if (!file || !file->f_dentry)
- goto out_unlock;
- result = file->f_dentry;
+ read_lock(&files->file_lock);
+ /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+ if (ino < files->max_fds &&
+ (file = files->fd[ino]) && file->f_dentry)
+ result = dget(file->f_dentry);
read_unlock(&p->files->file_lock);
- goto out_dget;
}
}
-out_dget:
- result = dget(result);
-
-out_unlock:
- read_unlock(&tasklist_lock);
-
out:
return result;
}
diff --git a/fs/proc/mem.c b/fs/proc/mem.c
index 4d599c77b..f9fcb0970 100644
--- a/fs/proc/mem.c
+++ b/fs/proc/mem.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
+#include <linux/bigmem.h>
#include <asm/page.h>
#include <asm/uaccess.h>
@@ -120,7 +121,9 @@ static ssize_t mem_read(struct file * file, char * buf,
i = PAGE_SIZE-(addr & ~PAGE_MASK);
if (i > scount)
i = scount;
+ page = (char *) kmap((unsigned long) page, KM_READ);
copy_to_user(tmp, page, i);
+ kunmap((unsigned long) page, KM_READ);
addr += i;
tmp += i;
scount -= i;
@@ -177,7 +180,9 @@ static ssize_t mem_write(struct file * file, char * buf,
i = PAGE_SIZE-(addr & ~PAGE_MASK);
if (i > count)
i = count;
+ page = (unsigned long) kmap((unsigned long) page, KM_WRITE);
copy_from_user(page, tmp, i);
+ kunmap((unsigned long) page, KM_WRITE);
addr += i;
tmp += i;
count -= i;
diff --git a/fs/proc/openpromfs.c b/fs/proc/openpromfs.c
index 72bb194cf..c9553ea24 100644
--- a/fs/proc/openpromfs.c
+++ b/fs/proc/openpromfs.c
@@ -1,4 +1,4 @@
-/* $Id: openpromfs.c,v 1.33 1999/04/28 11:57:33 davem Exp $
+/* $Id: openpromfs.c,v 1.36 1999/08/31 07:01:03 davem Exp $
* openpromfs.c: /proc/openprom handling routines
*
* Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -990,7 +990,7 @@ static int openpromfs_unlink (struct inode *dir, struct dentry *dentry)
/* {{{ init section */
#ifndef MODULE
-__initfunc(static int check_space (u16 n))
+static int __init check_space (u16 n)
#else
static int check_space (u16 n)
#endif
@@ -1014,7 +1014,7 @@ static int check_space (u16 n)
}
#ifndef MODULE
-__initfunc(static u16 get_nodes (u16 parent, u32 node))
+static u16 __init get_nodes (u16 parent, u32 node)
#else
static u16 get_nodes (u16 parent, u32 node)
#endif
@@ -1132,7 +1132,7 @@ void openpromfs_use (struct inode *inode, int inc)
#ifndef MODULE
#define RET(x)
-__initfunc(void openpromfs_init (void))
+void __init openpromfs_init (void)
#else
EXPORT_NO_SYMBOLS;
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 5ba245615..4b4ca41b8 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -170,7 +170,7 @@ void proc_tty_unregister_driver(struct tty_driver *driver)
/*
* Called by proc_root_init() to initialize the /proc/tty subtree
*/
-__initfunc(void proc_tty_init(void))
+void __init proc_tty_init(void)
{
struct proc_dir_entry *ent;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index df3c0b049..65ef929e7 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -641,6 +641,14 @@ struct proc_dir_entry proc_root_fs = {
NULL,
NULL, NULL
};
+struct proc_dir_entry proc_root_driver = {
+ PROC_DRIVER, 6, "driver",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+ 0, &proc_dir_inode_operations,
+ NULL, NULL,
+ NULL,
+ NULL, NULL
+};
static struct proc_dir_entry proc_root_dma = {
PROC_DMA, 3, "dma",
S_IFREG | S_IRUGO, 1, 0, 0,
@@ -651,8 +659,8 @@ static struct proc_dir_entry proc_root_ioports = {
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
-static struct proc_dir_entry proc_root_memory = {
- PROC_MEMORY, 6, "memory",
+static struct proc_dir_entry proc_root_iomem = {
+ PROC_MEMORY, 5, "iomem",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
@@ -711,7 +719,7 @@ static struct proc_dir_entry proc_root_ppc_htab = {
};
#endif
-__initfunc(void proc_root_init(void))
+void __init proc_root_init(void)
{
proc_base_init();
proc_register(&proc_root, &proc_root_loadavg);
@@ -745,13 +753,14 @@ __initfunc(void proc_root_init(void))
#endif
proc_register(&proc_root, &proc_root_stat);
proc_register(&proc_root, &proc_root_devices);
+ proc_register(&proc_root, &proc_root_driver);
proc_register(&proc_root, &proc_root_partitions);
proc_register(&proc_root, &proc_root_interrupts);
proc_register(&proc_root, &proc_root_filesystems);
proc_register(&proc_root, &proc_root_fs);
proc_register(&proc_root, &proc_root_dma);
proc_register(&proc_root, &proc_root_ioports);
- proc_register(&proc_root, &proc_root_memory);
+ proc_register(&proc_root, &proc_root_iomem);
proc_register(&proc_root, &proc_root_cmdline);
#ifdef CONFIG_RTC
proc_register(&proc_root, &proc_root_rtc);
@@ -859,14 +868,29 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
int len;
if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */
- dir->i_nlink = proc_root.nlink;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (p->pid)
- dir->i_nlink++;
+ extern unsigned long total_forks;
+ static int last_timestamp = 0;
+
+ /*
+ * this one can be a serious 'ps' performance problem if
+ * there are many threads running - thus we do 'lazy'
+ * link-recalculation - we change it only if the number
+ * of threads has increased.
+ */
+ if (total_forks != last_timestamp) {
+ int nlink = proc_root.nlink;
+
+ read_lock(&tasklist_lock);
+ last_timestamp = total_forks;
+ for_each_task(p)
+ nlink++;
+ read_unlock(&tasklist_lock);
+ /*
+ * subtract the # of idle threads which
+ * do not show up in /proc:
+ */
+ dir->i_nlink = nlink - smp_num_cpus;
}
- read_unlock(&tasklist_lock);
}
if (!proc_lookup(dir, dentry))