From d6434e1042f3b0a6dfe1b1f615af369486f9b1fa Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 9 Oct 1999 00:00:47 +0000 Subject: Merge with 2.3.19. --- fs/proc/array.c | 295 ++++++++++++++++++++++++++++++--------------------- fs/proc/base.c | 2 +- fs/proc/fd.c | 13 ++- fs/proc/link.c | 74 +++++++------ fs/proc/mem.c | 5 + fs/proc/openpromfs.c | 8 +- fs/proc/proc_tty.c | 2 +- fs/proc/root.c | 46 ++++++-- 8 files changed, 271 insertions(+), 174 deletions(-) (limited to 'fs/proc') 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. * * + * Al Viro : safe handling of mm_struct + * + * Gerhard Wichert : added BIGMEM support + * Siemens AG */ #include @@ -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 + +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 #include #include +#include #include #include @@ -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)) -- cgit v1.2.3