diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/Makefile | 6 | ||||
-rw-r--r-- | fs/proc/array.c | 89 | ||||
-rw-r--r-- | fs/proc/base.c | 13 | ||||
-rw-r--r-- | fs/proc/fd.c | 13 | ||||
-rw-r--r-- | fs/proc/generic.c | 28 | ||||
-rw-r--r-- | fs/proc/inode-alloc.txt | 50 | ||||
-rw-r--r-- | fs/proc/inode.c | 5 | ||||
-rw-r--r-- | fs/proc/link.c | 5 | ||||
-rw-r--r-- | fs/proc/net.c | 2 | ||||
-rw-r--r-- | fs/proc/proc_tty.c | 5 | ||||
-rw-r--r-- | fs/proc/procfs_syms.c | 4 | ||||
-rw-r--r-- | fs/proc/root.c | 121 |
12 files changed, 228 insertions, 113 deletions
diff --git a/fs/proc/Makefile b/fs/proc/Makefile index d01072a4b..cd488e328 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile @@ -1,11 +1,11 @@ # -# Makefile for the linux proc-filesystem routines. +# Makefile for the Linux proc filesystem routines. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). +# unless it's something special (not a .c file). # -# Note 2! The CFLAGS definitions are now in the main makefile... +# Note 2! The CFLAGS definitions are now in the main makefile. O_TARGET := proc.o O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \ diff --git a/fs/proc/array.c b/fs/proc/array.c index 7376c30f5..cde538846 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -29,12 +29,14 @@ * Yves Arrouye : remove removal of trailing spaces in get_array. * <Yves.Arrouye@marin.fdn.fr> - * Jerome Forissier : added per-cpu time information to /proc/stat + * Jerome Forissier : added per-CPU time information to /proc/stat * and /proc/<pid>/cpu extension * <forissier@isia.cma.fr> * - Incorporation and non-SMP safe operation * of forissier patch in 2.1.78 by * Hans Marcus <crowbar@concepts.nl> + * + * aeb@cwi.nl : /proc/partitions */ #include <linux/types.h> @@ -559,6 +561,23 @@ static unsigned long get_wchan(struct task_struct *p) } #elif defined(__powerpc__) return (p->tss.wchan); +#elif defined (CONFIG_ARM) + { + unsigned long fp, lr; + unsigned long stack_page; + int count = 0; + + stack_page = 4096 + (unsigned long)p; + fp = get_css_fp (&p->tss); + 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); + } #endif return 0; @@ -576,6 +595,9 @@ static unsigned long get_wchan(struct task_struct *p) # define KSTK_EIP(tsk) \ (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk))) # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp) +#elif defined(CONFIG_ARM) +# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) +# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020]) #elif defined(__mc68000__) #define KSTK_EIP(tsk) \ ({ \ @@ -729,21 +751,6 @@ static inline char * task_mem(struct task_struct *p, char *buffer) return buffer; } -char * render_sigset_t(sigset_t *set, char *buffer) -{ - int i = _NSIG, x; - do { - i -= 4, x = 0; - if (sigismember(set, i+1)) x |= 1; - if (sigismember(set, i+2)) x |= 2; - if (sigismember(set, i+3)) x |= 4; - if (sigismember(set, i+4)) x |= 8; - *buffer++ = (x < 10 ? '0' : 'a' - 10) + x; - } while (i >= 4); - *buffer = 0; - return buffer; -} - static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign, sigset_t *catch) { @@ -779,7 +786,7 @@ static inline char * task_sig(struct task_struct *p, char *buffer) buffer += sprintf(buffer, "SigIgn:\t"); buffer = render_sigset_t(&ign, buffer); *buffer++ = '\n'; - buffer += sprintf(buffer, "SigCat:\t"); + buffer += sprintf(buffer, "SigCgt:\t"); /* Linux 2.0 uses "SigCgt" */ buffer = render_sigset_t(&catch, buffer); *buffer++ = '\n'; @@ -822,10 +829,6 @@ static int get_stat(int pid, char * buffer) long priority, nice; int tty_pgrp; sigset_t sigign, sigcatch; - char signal_str[sizeof(sigset_t)*2+1]; - char blocked_str[sizeof(sigset_t)*2+1]; - char sigign_str[sizeof(sigset_t)*2+1]; - char sigcatch_str[sizeof(sigset_t)*2+1]; char state; read_lock(&tasklist_lock); @@ -848,10 +851,6 @@ static int get_stat(int pid, char * buffer) wchan = get_wchan(tsk); collect_sigign_sigcatch(tsk, &sigign, &sigcatch); - render_sigset_t(&tsk->signal, signal_str); - render_sigset_t(&tsk->blocked, blocked_str); - render_sigset_t(&sigign, sigign_str); - render_sigset_t(&sigcatch, sigcatch_str); if (tsk->tty) tty_pgrp = tsk->tty->pgrp; @@ -859,7 +858,7 @@ static int get_stat(int pid, char * buffer) tty_pgrp = -1; /* 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 = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY; nice = tsk->priority; @@ -867,7 +866,7 @@ static int get_stat(int pid, char * buffer) 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 %s %s %s %s %lu %lu %lu\n", +%lu %lu %lu %lu %lu %lu %lu %lu\n", pid, tsk->comm, state, @@ -898,10 +897,14 @@ static int get_stat(int pid, char * buffer) tsk->mm ? tsk->mm->start_stack : 0, esp, eip, - signal_str, - blocked_str, - sigign_str, - sigcatch_str, + /* The signal information here is obsolete. + * 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, + sigign .sig[0] & 0x7fffffffUL, + sigcatch .sig[0] & 0x7fffffffUL, wchan, tsk->nswap, tsk->cnswap); @@ -982,7 +985,7 @@ 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 = find_task_by_pid(pid); + struct task_struct *tsk; int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0; read_lock(&tasklist_lock); @@ -1080,7 +1083,7 @@ static ssize_t read_maps (int pid, struct file * file, char * buf, goto getlen_out; /* Check whether the mmaps could change if we sleep */ - volatile_task = (p != current || p->mm->count > 1); + volatile_task = (p != current || atomic_read(&p->mm->count) > 1); /* decode f_pos */ lineno = *ppos >> MAPS_LINE_SHIFT; @@ -1212,6 +1215,7 @@ extern int get_module_list(char *); extern int get_ksyms_list(char *, char **, off_t, int); #endif extern int get_device_list(char *); +extern int get_partition_list(char *); extern int get_filesystem_list(char *); extern int get_filesystem_info( char * ); extern int get_irq_list(char *); @@ -1222,12 +1226,8 @@ extern int get_md_status (char *); extern int get_rtc_status (char *); extern int get_locks_status (char *, char **, off_t, int); extern int get_swaparea_info (char *); -#ifdef CONFIG_ZORRO -extern int zorro_get_list(char *); -#endif -#if defined (CONFIG_AMIGA) || defined (CONFIG_ATARI) extern int get_hardware_list(char *); -#endif +extern int get_stram_list(char *); static long get_root_array(char * page, int type, char **start, off_t offset, unsigned long length) @@ -1275,6 +1275,9 @@ static long get_root_array(char * page, int type, char **start, case PROC_DEVICES: return get_device_list(page); + case PROC_PARTITIONS: + return get_partition_list(page); + case PROC_INTERRUPTS: return get_irq_list(page); @@ -1308,14 +1311,14 @@ static long get_root_array(char * page, int type, char **start, #endif case PROC_LOCKS: return get_locks_status(page, start, offset, length); -#ifdef CONFIG_ZORRO - case PROC_ZORRO: - return zorro_get_list(page); -#endif -#if defined (CONFIG_AMIGA) || defined (CONFIG_ATARI) +#ifdef CONFIG_PROC_HARDWARE case PROC_HARDWARE: return get_hardware_list(page); #endif +#ifdef CONFIG_STRAM_PROC + case PROC_STRAM: + return get_stram_list(page); +#endif } return -EBADF; } diff --git a/fs/proc/base.c b/fs/proc/base.c index e535276bb..edfe8b758 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -13,6 +13,7 @@ #include <linux/sched.h> #include <linux/proc_fs.h> #include <linux/stat.h> +#include <linux/init.h> static struct file_operations proc_base_operations = { NULL, /* lseek - default */ @@ -62,10 +63,14 @@ static void proc_pid_fill_inode(struct inode * inode, int fill) read_lock(&tasklist_lock); if (fill && (p = find_task_by_pid(pid)) != NULL) { + uid_t uid = 0; + gid_t gid = 0; if (p->dumpable || ino == PROC_PID_INO) { - inode->i_uid = p->euid; - inode->i_gid = p->gid; + uid = p->euid; + gid = p->egid; } + inode->i_uid = uid; + inode->i_gid = gid; } read_unlock(&tasklist_lock); } @@ -116,7 +121,7 @@ static struct proc_dir_entry proc_pid_exe = { }; static struct proc_dir_entry proc_pid_fd = { PROC_PID_FD, 2, "fd", - S_IFDIR | S_IRUSR | S_IXUSR, 1, 0, 0, + S_IFDIR | S_IRUSR | S_IXUSR, 2, 0, 0, 0, &proc_fd_inode_operations, NULL, proc_pid_fill_inode, }; @@ -169,7 +174,7 @@ static struct proc_dir_entry proc_pid_cpu = { }; #endif -void proc_base_init(void) +__initfunc(void 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 04da4f412..57f99bfd7 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -4,6 +4,10 @@ * Copyright (C) 1991, 1992 Linus Torvalds * * proc fd directory handling functions + * + * 01-May-98 Edgar Toernig <froese@gmx.de> + * Added support for more than 256 fds. + * Limit raised to 32768. */ #include <linux/errno.h> @@ -91,7 +95,7 @@ static int proc_lookupfd(struct inode * dir, struct dentry * dentry) goto out; fd *= 10; fd += c; - if (fd & 0xffff0000) + if (fd & 0xffff8000) goto out; } @@ -111,8 +115,7 @@ static int proc_lookupfd(struct inode * dir, struct dentry * dentry) if (!file || !file->f_dentry) goto out; - /* N.B. What happens if fd > 255?? */ - ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd; + ino = (pid << 16) + PROC_PID_FD_DIR + fd; inode = proc_get_inode(dir->i_sb, ino, NULL); if (inode) { d_add(dentry, inode); @@ -144,7 +147,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) goto out; for (fd = filp->f_pos; fd < 2; fd++, filp->f_pos++) { - unsigned long ino = inode->i_ino; + ino = inode->i_ino; if (fd) ino = (ino & 0xffff0000) | PROC_PID_INO; if (filldir(dirent, "..", fd+1, fd, ino) < 0) @@ -176,7 +179,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) /* Drop the task lock, as the filldir function may block */ read_unlock(&tasklist_lock); - ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd; + ino = (pid << 16) + PROC_PID_FD_DIR + fd; if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0) goto out; diff --git a/fs/proc/generic.c b/fs/proc/generic.c index a38481c85..a9b00f1f5 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -154,14 +154,19 @@ proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) break; } - n -= copy_to_user(buf, start, n); /* BUG ??? */ + /* This is a hack to allow mangling of file pos independent + * of actual bytes read. Simply place the data at page, + * return the bytes, and set `start' to the desired offset + * as an unsigned int. - Paul.Russell@rustcorp.com.au + */ + n -= copy_to_user(buf, start < page ? page : start, n); if (n == 0) { if (retval == 0) retval = -EFAULT; break; } - - *ppos += n; /* Move down the file */ + + *ppos += start < page ? (long)start : n; /* Move down the file */ nbytes -= n; buf += n; retval += n; @@ -255,13 +260,16 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, ent->name = ((char *) ent) + sizeof(*ent); ent->namelen = len; - if (mode == S_IFDIR) { + if (S_ISDIR(mode)) { + if ((mode & S_IALLUGO) == 0) mode |= S_IRUGO | S_IXUGO; ent->ops = &proc_dyna_dir_inode_operations; ent->nlink = 2; - } - else if (mode == 0) { - mode = S_IFREG | S_IRUGO; + } else { + if ((mode & S_IFMT) == 0) + mode |= S_IFREG; + if ((mode & S_IALLUGO) == 0) + mode |= S_IRUGO; ent->nlink = 1; } ent->mode = mode; @@ -275,7 +283,11 @@ out: extern void free_proc_entry(struct proc_dir_entry *); void free_proc_entry(struct proc_dir_entry *de) { - kfree(de); + int ino = de->low_ino; + + if (ino >= PROC_DYNAMIC_FIRST && + ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC) + kfree(de); } /* diff --git a/fs/proc/inode-alloc.txt b/fs/proc/inode-alloc.txt new file mode 100644 index 000000000..440d3baf8 --- /dev/null +++ b/fs/proc/inode-alloc.txt @@ -0,0 +1,50 @@ +Inode allocations in the proc-fs (hex-numbers): + + 00000000 reserved + 00000001-00000fff static entries + 001 root-ino + 002 load-avg + 003 uptime + ... + 080 net/* + ... + 100 scsi/* + ... + xxx mca/* + ... + yyy bus/* + ... + fff end + + 00001000-00001fff dynamic entries + + 00002000-00002fff openprom entries + + 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff + 0000 unused + 0001 unused + 0002 pid + 0003 pid/status + ... + 0008 pid/fd + ... + 00xx-00ff unused + 01xx pid/fd/* for fd 0-ff + ... + 01ff end + 0200-ffff unused + + 80000000-ffffffff unused + + + +New allocation: + + 00000000-0000ffff unchanged + + 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff + 0000-00ff unchanged + 0100-7fff unused + 8000-ffff pid/fd/* for fd 0-7fff + + 80000000-ffffffff unchanged diff --git a/fs/proc/inode.c b/fs/proc/inode.c index b4ca1094c..44c4916f8 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -382,10 +382,9 @@ void proc_read_inode(struct inode * inode) inode->i_uid = p->euid; inode->i_gid = p->egid; } - switch (ino >> 8) { + if (ino & PROC_PID_FD_DIR) { struct file * file; - case PROC_PID_FD_DIR: - ino &= 0xff; + ino &= 0x7fff; file = fcheck_task(p, ino); if (!file) goto out_unlock; diff --git a/fs/proc/link.c b/fs/proc/link.c index 28bb81a93..05ab85030 100644 --- a/fs/proc/link.c +++ b/fs/proc/link.c @@ -111,10 +111,9 @@ static struct dentry * proc_follow_link(struct dentry *dentry, goto out_unlock; } default: - switch (ino >> 8) { + if (ino & PROC_PID_FD_DIR) { struct file * file; - case PROC_PID_FD_DIR: - ino &= 0xff; + ino &= 0x7fff; file = fcheck_task(p, ino); if (!file || !file->f_dentry) goto out_unlock; diff --git a/fs/proc/net.c b/fs/proc/net.c index 257487569..408c8e0d4 100644 --- a/fs/proc/net.c +++ b/fs/proc/net.c @@ -20,7 +20,7 @@ * Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de) * /proc/net/snmp. * Alan Cox (gw4pts@gw4pts.ampr.org) 1/95 - * Added Appletalk slots + * Added AppleTalk slots * * proc net directory handling functions */ diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index 9523ff9f0..5ba245615 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c @@ -6,6 +6,7 @@ #include <asm/uaccess.h> +#include <linux/init.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/proc_fs.h> @@ -79,7 +80,7 @@ static int tty_drivers_read_proc(char *page, char **start, off_t off, break; } len += sprintf(page+len, "%-20s /dev/%-8s %3d %7s %s\n", - p->driver_name ? p->driver_name : "", + p->driver_name ? p->driver_name : "unknown", p->name, p->major, range, type); if (len+begin > off+count) break; @@ -169,7 +170,7 @@ void proc_tty_unregister_driver(struct tty_driver *driver) /* * Called by proc_root_init() to initialize the /proc/tty subtree */ -void proc_tty_init(void) +__initfunc(void proc_tty_init(void)) { struct proc_dir_entry *ent; diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c index d3077ea79..6a6ef687e 100644 --- a/fs/proc/procfs_syms.c +++ b/fs/proc/procfs_syms.c @@ -11,17 +11,21 @@ extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, off_t offset, int length, int inout); extern struct inode_operations proc_scsi_inode_operations; +extern struct proc_dir_entry proc_sys_root; +EXPORT_SYMBOL(proc_sys_root); EXPORT_SYMBOL(proc_register); EXPORT_SYMBOL(proc_unregister); EXPORT_SYMBOL(create_proc_entry); EXPORT_SYMBOL(remove_proc_entry); EXPORT_SYMBOL(proc_root); +EXPORT_SYMBOL(proc_root_fs); EXPORT_SYMBOL(proc_get_inode); EXPORT_SYMBOL(in_group_p); EXPORT_SYMBOL(proc_dir_inode_operations); EXPORT_SYMBOL(proc_net_inode_operations); EXPORT_SYMBOL(proc_net); +EXPORT_SYMBOL(proc_bus); /* * This is required so that if we load scsi later, that the diff --git a/fs/proc/root.c b/fs/proc/root.c index afc440fc0..999783ee5 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -13,10 +13,14 @@ #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/config.h> +#include <linux/init.h> #include <asm/bitops.h> #ifdef CONFIG_KMOD #include <linux/kmod.h> #endif +#ifdef CONFIG_ZORRO +#include <linux/zorro.h> +#endif /* * Offset of the first process in the /proc root directory.. @@ -498,25 +502,25 @@ static struct proc_dir_entry proc_root_version = { S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; -#ifdef CONFIG_ZORRO -static struct proc_dir_entry proc_root_zorro = { - PROC_ZORRO, 5, "zorro", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations -}; -#endif static struct proc_dir_entry proc_root_cpuinfo = { PROC_CPUINFO, 7, "cpuinfo", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; -#if defined (CONFIG_AMIGA) || defined (CONFIG_ATARI) +#if defined (CONFIG_PROC_HARDWARE) static struct proc_dir_entry proc_root_hardware = { PROC_HARDWARE, 8, "hardware", S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; #endif +#ifdef CONFIG_STRAM_PROC +static struct proc_dir_entry proc_root_stram = { + PROC_STRAM, 5, "stram", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations +}; +#endif static struct proc_dir_entry proc_root_self = { PROC_SELF, 4, "self", S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0, @@ -556,6 +560,11 @@ static struct proc_dir_entry proc_root_devices = { S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; +static struct proc_dir_entry proc_root_partitions = { + PROC_PARTITIONS, 10, "partitions", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations +}; static struct proc_dir_entry proc_root_interrupts = { PROC_INTERRUPTS, 10,"interrupts", S_IFREG | S_IRUGO, 1, 0, 0, @@ -566,6 +575,14 @@ static struct proc_dir_entry proc_root_filesystems = { S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; +struct proc_dir_entry proc_root_fs = { + PROC_FS, 2, "fs", + 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, @@ -631,7 +648,7 @@ static struct proc_dir_entry proc_root_ppc_htab = { }; #endif -void proc_root_init(void) +__initfunc(void proc_root_init(void)) { proc_base_init(); proc_register(&proc_root, &proc_root_loadavg); @@ -639,9 +656,6 @@ void proc_root_init(void) proc_register(&proc_root, &proc_root_meminfo); proc_register(&proc_root, &proc_root_kmsg); proc_register(&proc_root, &proc_root_version); -#ifdef CONFIG_ZORRO - proc_register(&proc_root, &proc_root_zorro); -#endif proc_register(&proc_root, &proc_root_cpuinfo); proc_register(&proc_root, &proc_root_self); proc_net = create_proc_entry("net", S_IFDIR, 0); @@ -665,8 +679,10 @@ 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_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_cmdline); @@ -687,14 +703,17 @@ void proc_root_init(void) #endif proc_register(&proc_root, &proc_openprom); #endif -#if defined (CONFIG_AMIGA) || defined (CONFIG_ATARI) +#ifdef CONFIG_PROC_HARDWARE proc_register(&proc_root, &proc_root_hardware); #endif +#ifdef CONFIG_STRAM_PROC + proc_register(&proc_root, &proc_root_stram); +#endif proc_register(&proc_root, &proc_root_slab); if (prof_shift) { proc_register(&proc_root, &proc_root_profile); - proc_root_profile.size = (1+prof_len) * sizeof(unsigned long); + proc_root_profile.size = (1+prof_len) * sizeof(unsigned int); } proc_tty_init(); @@ -810,16 +829,14 @@ static int proc_root_lookup(struct inode * dir, struct dentry * dentry) } read_lock(&tasklist_lock); p = find_task_by_pid(pid); + read_unlock(&tasklist_lock); inode = NULL; if (pid && p) { unsigned long ino = (pid << 16) + PROC_PID_INO; inode = proc_get_inode(dir->i_sb, ino, &proc_pid); - if (!inode) { - read_unlock(&tasklist_lock); + if (!inode) return -EINVAL; - } } - read_unlock(&tasklist_lock); dentry->d_op = &proc_dentry_operations; d_add(dentry, inode); @@ -886,46 +903,68 @@ int proc_readdir(struct file * filp, return 1; } -#define NUMBUF 10 +#define PROC_NUMBUF 10 +#define PROC_MAXPIDS 20 + +/* + * Get a few pid's to return for filldir - we need to hold the + * tasklist lock while doing this, and we must release it before + * we actually do the filldir itself, so we use a temp buffer.. + */ +static int get_pid_list(unsigned int index, unsigned int *pids) +{ + struct task_struct *p; + int nr = FIRST_PROCESS_ENTRY; + int nr_pids = 0; + + read_lock(&tasklist_lock); + for_each_task(p) { + int pid; + if (nr++ < index) + continue; + pid = p->pid; + if (!pid) + continue; + pids[nr_pids] = pid; + nr_pids++; + if (nr_pids >= PROC_MAXPIDS) + break; + } + read_unlock(&tasklist_lock); + return nr_pids; +} static int proc_root_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct task_struct *p; - char buf[NUMBUF]; + unsigned int pid_array[PROC_MAXPIDS]; + char buf[PROC_NUMBUF]; unsigned int nr = filp->f_pos; + unsigned int nr_pids, i; if (nr < FIRST_PROCESS_ENTRY) { int error = proc_readdir(filp, dirent, filldir); if (error <= 0) return error; - filp->f_pos = FIRST_PROCESS_ENTRY; + filp->f_pos = nr = FIRST_PROCESS_ENTRY; } - nr = FIRST_PROCESS_ENTRY; - read_lock(&tasklist_lock); - for_each_task(p) { - unsigned int pid; + nr_pids = get_pid_list(nr, pid_array); - if(nr++ < filp->f_pos) - continue; + for (i = 0; i < nr_pids; i++) { + int pid = pid_array[i]; + unsigned long j = PROC_NUMBUF; - if((pid = p->pid) != 0) { - unsigned long j = NUMBUF, i = pid; + do { + j--; + buf[j] = '0' + (pid % 10); + pid /= 10; + } while (pid); - do { - j--; - buf[j] = '0' + (i % 10); - i /= 10; - } while (i); - - if (filldir(dirent, buf+j, NUMBUF-j, - filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) - break; - } + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) + break; filp->f_pos++; } - read_unlock(&tasklist_lock); return 0; } |