summaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
commit27cfca1ec98e91261b1a5355d10a8996464b63af (patch)
tree8e895a53e372fa682b4c0a585b9377d67ed70d0e /fs/proc
parent6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff)
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too o Upgrade to 2.1.89. Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/.cvsignore1
-rw-r--r--fs/proc/array.c165
-rw-r--r--fs/proc/base.c22
-rw-r--r--fs/proc/generic.c2
-rw-r--r--fs/proc/kmsg.c2
-rw-r--r--fs/proc/link.c70
-rw-r--r--fs/proc/openpromfs.c4
-rw-r--r--fs/proc/proc_devtree.c8
-rw-r--r--fs/proc/root.c112
9 files changed, 282 insertions, 104 deletions
diff --git a/fs/proc/.cvsignore b/fs/proc/.cvsignore
index 4671378ae..857dd22e9 100644
--- a/fs/proc/.cvsignore
+++ b/fs/proc/.cvsignore
@@ -1 +1,2 @@
.depend
+.*.flags
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 88d10d2bc..5364cea14 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -28,6 +28,13 @@
*
* 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
+ * 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>
*/
#include <linux/types.h>
@@ -221,7 +228,34 @@ static int get_kstat(char * buffer)
ticks = jiffies * smp_num_cpus;
for (i = 0 ; i < NR_IRQS ; i++)
- sum += kstat.interrupts[i];
+ sum += kstat_irqs(i);
+
+#ifdef __SMP__
+ len = sprintf(buffer,
+ "cpu %u %u %u %lu\n",
+ kstat.cpu_user,
+ kstat.cpu_nice,
+ kstat.cpu_system,
+ jiffies*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)] \
+ + kstat.per_cpu_nice[cpu_logical_map(i)] \
+ + kstat.per_cpu_system[cpu_logical_map(i)]));
+ len += sprintf(buffer + len,
+ "disk %u %u %u %u\n"
+ "disk_rio %u %u %u %u\n"
+ "disk_wio %u %u %u %u\n"
+ "disk_rblk %u %u %u %u\n"
+ "disk_wblk %u %u %u %u\n"
+ "page %u %u\n"
+ "swap %u %u\n"
+ "intr %u",
+#else
len = sprintf(buffer,
"cpu %u %u %u %lu\n"
"disk %u %u %u %u\n"
@@ -236,6 +270,7 @@ static int get_kstat(char * buffer)
kstat.cpu_nice,
kstat.cpu_system,
ticks - (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],
kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
@@ -252,7 +287,7 @@ static int get_kstat(char * buffer)
kstat.pswpout,
sum);
for (i = 0 ; i < NR_IRQS ; i++)
- len += sprintf(buffer + len, " %u", kstat.interrupts[i]);
+ len += sprintf(buffer + len, " %u", kstat_irqs(i));
len += sprintf(buffer + len,
"\nctxt %u\n"
"btime %lu\n"
@@ -427,6 +462,14 @@ static int get_arg(int pid, char * buffer)
return get_array(p, p->mm->arg_start, p->mm->arg_end, buffer);
}
+/*
+ * 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)
@@ -445,8 +488,7 @@ static unsigned long get_wchan(struct task_struct *p)
if (ebp < stack_page || ebp >= 4092+stack_page)
return 0;
eip = *(unsigned long *) (ebp+4);
- if (eip < (unsigned long) interruptible_sleep_on
- || eip >= (unsigned long) add_timer)
+ if (eip < first_sched || eip >= last_sched)
return eip;
ebp = *(unsigned long *) ebp;
} while (count++ < 16);
@@ -466,7 +508,7 @@ static unsigned long get_wchan(struct task_struct *p)
unsigned long pc;
pc = thread_saved_pc(&p->tss);
- if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
+ if (pc >= first_sched && pc < last_sched) {
schedule_frame = ((unsigned long *)p->tss.ksp)[6];
return ((unsigned long *)schedule_frame)[12];
}
@@ -503,10 +545,7 @@ static unsigned long get_wchan(struct task_struct *p)
return 0;
pc = ((unsigned long *)fp)[1];
/* FIXME: This depends on the order of these functions. */
- if ((pc < (unsigned long) __down
- || pc >= (unsigned long) add_timer)
- && (pc < (unsigned long) schedule
- || pc >= (unsigned long) sys_pause))
+ if (pc < first_sched || pc >= last_sched)
return pc;
fp = *(unsigned long *) fp;
} while (count++ < 16);
@@ -592,30 +631,47 @@ static inline char * task_name(struct task_struct *p, char * buf)
return buf+1;
}
-static inline char * task_state(struct task_struct *p, char *buffer)
+/*
+ * The task state array is a strange "bitmap" of
+ * reasons to sleep. Thus "running" is zero, and
+ * you can test for combinations of others with
+ * simple bit tests.
+ */
+static const char *task_state_array[] = {
+ "R (running)", /* 0 */
+ "S (sleeping)", /* 1 */
+ "D (disk sleep)", /* 2 */
+ "Z (zombie)", /* 4 */
+ "T (stopped)", /* 8 */
+ "W (paging)" /* 16 */
+};
+
+static inline const char * get_task_state(struct task_struct *tsk)
{
-#define NR_STATES (sizeof(states)/sizeof(const char *))
- unsigned int n = p->state;
- static const char * states[] = {
- "R (running)",
- "S (sleeping)",
- "D (disk sleep)",
- "Z (zombie)",
- "T (stopped)",
- "W (paging)",
- ". Huh?"
- };
-
- if (n >= NR_STATES)
- n = NR_STATES-1;
+ unsigned int state = tsk->state & (TASK_RUNNING |
+ TASK_INTERRUPTIBLE |
+ TASK_UNINTERRUPTIBLE |
+ TASK_ZOMBIE |
+ TASK_STOPPED |
+ TASK_SWAPPING);
+ const char **p = &task_state_array[0];
+
+ while (state) {
+ p++;
+ state >>= 1;
+ }
+ return *p;
+}
+static inline char * task_state(struct task_struct *p, char *buffer)
+{
buffer += sprintf(buffer,
"State:\t%s\n"
"Pid:\t%d\n"
"PPid:\t%d\n"
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
- states[n],
+ 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);
@@ -633,7 +689,7 @@ static inline char * task_mem(struct task_struct *p, char *buffer)
for (vma = mm->mmap; vma; vma = vma->vm_next) {
unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
- if (!vma->vm_dentry) {
+ if (!vma->vm_file) {
data += len;
if (vma->vm_flags & VM_GROWSDOWN)
stack += len;
@@ -751,10 +807,7 @@ static int get_stat(int pid, char * buffer)
if (!tsk)
return 0;
- if (tsk->state < 0 || tsk->state > 5)
- state = '.';
- else
- state = "RSDZTW"[tsk->state];
+ state = *get_task_state(tsk);
vsize = eip = esp = 0;
if (tsk->mm && tsk->mm != &init_mm) {
struct vm_area_struct *vma = tsk->mm->mmap;
@@ -1031,10 +1084,10 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
dev = 0;
ino = 0;
- if (map->vm_dentry != NULL) {
- dev = map->vm_dentry->d_inode->i_dev;
- ino = map->vm_dentry->d_inode->i_ino;
- line = d_path(map->vm_dentry, buffer, PAGE_SIZE);
+ if (map->vm_file != NULL) {
+ dev = map->vm_file->f_dentry->d_inode->i_dev;
+ ino = map->vm_file->f_dentry->d_inode->i_ino;
+ line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE);
buffer[PAGE_SIZE-1] = '\n';
line -= maxlen;
if(line < buffer)
@@ -1047,7 +1100,7 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
map->vm_start, map->vm_end, str, map->vm_offset,
kdevname(dev), ino);
- if(map->vm_dentry) {
+ if(map->vm_file) {
for(i = len; i < maxlen; i++)
line[i] = ' ';
len = buffer + PAGE_SIZE - line;
@@ -1094,6 +1147,33 @@ out:
return retval;
}
+#ifdef __SMP__
+static int get_pidcpu(int pid, char * buffer)
+{
+ struct task_struct * tsk = current ;
+ int i, len;
+
+ if (pid != tsk->pid)
+ tsk = find_task_by_pid(pid);
+
+ if (tsk == NULL)
+ return 0;
+
+ len = sprintf(buffer,
+ "cpu %lu %lu\n",
+ tsk->times.tms_utime,
+ tsk->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)]);
+
+ return len;
+}
+#endif
+
#ifdef CONFIG_MODULES
extern int get_module_list(char *);
extern int get_ksyms_list(char *, char **, off_t, int);
@@ -1104,14 +1184,11 @@ extern int get_filesystem_info( char * );
extern int get_irq_list(char *);
extern int get_dma_list(char *);
extern int get_cpuinfo(char *);
-extern int get_pci_list(char*);
+extern int get_pci_list(char *);
extern int get_md_status (char *);
extern int get_rtc_status (char *);
extern int get_locks_status (char *, char **, off_t, int);
extern int get_swaparea_info (char *);
-#ifdef __SMP_PROF__
-extern int get_smp_prof_list(char *);
-#endif
#ifdef CONFIG_ZORRO
extern int zorro_get_list(char *);
#endif
@@ -1132,7 +1209,7 @@ static long get_root_array(char * page, int type, char **start,
case PROC_MEMINFO:
return get_meminfo(page);
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_OLD_PROC
case PROC_PCI:
return get_pci_list(page);
#endif
@@ -1180,10 +1257,6 @@ static long get_root_array(char * page, int type, char **start,
case PROC_MD:
return get_md_status(page);
#endif
-#ifdef __SMP_PROF__
- case PROC_SMP_PROF:
- return get_smp_prof_list(page);
-#endif
case PROC_CMDLINE:
return get_cmdline(page);
@@ -1223,6 +1296,10 @@ static int get_process_array(char * page, int pid, int type)
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;
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ac6704e4b..dc182682a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -158,6 +158,15 @@ static struct proc_dir_entry proc_pid_ringbuf = {
};
#endif
+#ifdef __SMP__
+static struct proc_dir_entry proc_pid_cpu = {
+ PROC_PID_CPU, 3, "cpu",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations,
+ NULL, proc_pid_fill_inode,
+};
+#endif
+
void proc_base_init(void)
{
#if CONFIG_AP1000
@@ -174,4 +183,17 @@ void proc_base_init(void)
proc_register(&proc_pid, &proc_pid_stat);
proc_register(&proc_pid, &proc_pid_statm);
proc_register(&proc_pid, &proc_pid_maps);
+#ifdef __SMP__
+ proc_register(&proc_pid, &proc_pid_cpu);
+#endif
};
+
+
+
+
+
+
+
+
+
+
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index a467af4df..a38481c85 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -298,8 +298,6 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
}
if (de) {
-printk("remove_proc_entry: parent nlink=%d, file nlink=%d\n",
-parent->nlink, de->nlink);
proc_unregister(parent, de->low_ino);
de->nlink = 0;
de->deleted = 1;
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 42346a895..e21c0cd1c 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -38,7 +38,7 @@ static ssize_t kmsg_read(struct file * file, char * buf,
static unsigned int kmsg_poll(struct file *file, poll_table * wait)
{
- poll_wait(&log_wait, wait);
+ poll_wait(file, &log_wait, wait);
if (log_size)
return POLLIN | POLLRDNORM;
return 0;
diff --git a/fs/proc/link.c b/fs/proc/link.c
index 0c189dcc3..66a01e1af 100644
--- a/fs/proc/link.c
+++ b/fs/proc/link.c
@@ -15,8 +15,8 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
-static int proc_readlink(struct inode *, char *, int);
-static struct dentry * proc_follow_link(struct inode *, struct dentry *);
+static int proc_readlink(struct dentry *, char *, int);
+static struct dentry * proc_follow_link(struct dentry *, struct dentry *);
/*
* PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke
@@ -60,8 +60,10 @@ struct inode_operations proc_link_inode_operations = {
NULL /* permission */
};
-static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base)
+static struct dentry * proc_follow_link(struct dentry *dentry,
+ struct dentry *base)
{
+ struct inode *inode = dentry->d_inode;
struct task_struct *p;
struct dentry * result;
int ino, pid;
@@ -73,7 +75,7 @@ static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base
error = permission(inode, MAY_EXEC);
result = ERR_PTR(error);
if (error)
- return result;
+ goto out;
ino = inode->i_ino;
pid = ino >> 16;
@@ -82,7 +84,7 @@ static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base
p = find_task_by_pid(pid);
result = ERR_PTR(-ENOENT);
if (!p)
- return result;
+ goto out;
switch (ino) {
case PROC_PID_CWD:
@@ -103,8 +105,8 @@ static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base
break;
vma = p->mm->mmap;
while (vma) {
- if (vma->vm_flags & VM_EXECUTABLE)
- return dget(vma->vm_dentry);
+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
+ return dget(vma->vm_file->f_dentry);
vma = vma->vm_next;
}
@@ -126,30 +128,56 @@ static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base
break;
}
}
+out:
return result;
}
-static int proc_readlink(struct inode * inode, char * buffer, int buflen)
+/*
+ * This pretty-prints the pathname of a dentry,
+ * clarifying sockets etc.
+ */
+static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
+{
+ struct inode * inode;
+ char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
+ int len;
+
+ /* Check for special dentries.. */
+ pattern = NULL;
+ inode = dentry->d_inode;
+ if (inode && dentry->d_parent == dentry) {
+ if (S_ISSOCK(inode->i_mode))
+ pattern = "socket:[%lu]";
+ if (S_ISFIFO(inode->i_mode))
+ pattern = "pipe:[%lu]";
+ }
+
+ if (pattern) {
+ len = sprintf(tmp, pattern, inode->i_ino);
+ path = tmp;
+ } else {
+ path = d_path(dentry, tmp, PAGE_SIZE);
+ len = tmp + PAGE_SIZE - path;
+ }
+
+ if (len < buflen)
+ buflen = len;
+ dput(dentry);
+ copy_to_user(buffer, path, buflen);
+ free_page((unsigned long)tmp);
+ return buflen;
+}
+
+static int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
{
int error;
- struct dentry * dentry = proc_follow_link(inode, NULL);
+ dentry = proc_follow_link(dentry, NULL);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = -ENOENT;
if (dentry) {
- char * tmp = (char*)__get_free_page(GFP_KERNEL), *path;
- int len;
-
- path = d_path(dentry, tmp, PAGE_SIZE);
- len = tmp + PAGE_SIZE - path;
-
- if (len < buflen)
- buflen = len;
- dput(dentry);
- copy_to_user(buffer, path, buflen);
- free_page((unsigned long)tmp);
- error = buflen;
+ error = do_proc_readlink(dentry, buffer, buflen);
}
}
return error;
diff --git a/fs/proc/openpromfs.c b/fs/proc/openpromfs.c
index 485049b69..aaf53006f 100644
--- a/fs/proc/openpromfs.c
+++ b/fs/proc/openpromfs.c
@@ -901,7 +901,7 @@ static int check_space (u16 n)
unsigned long pages;
if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) {
- pages = __get_free_pages (GFP_KERNEL, alloced + 1, 0);
+ pages = __get_free_pages (GFP_KERNEL, alloced + 1);
if (!pages)
return -1;
@@ -1048,7 +1048,7 @@ int init_module (void)
if (!romvec->pv_romvers)
return RET(ENODEV);
#endif
- nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0, 0);
+ nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
if (!nodes) {
printk (KERN_WARNING "/proc/openprom: can't get free page\n");
return RET(EIO);
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 8c5a1bc3a..6fdccf974 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -65,24 +65,24 @@ struct inode_operations devtree_symlink_inode_operations = {
NULL /* smap */
};
-static struct dentry *devtree_follow_link(struct inode *inode,
+static struct dentry *devtree_follow_link(struct dentry *dentry,
struct dentry *base)
{
struct proc_dir_entry * de;
char *link;
- de = (struct proc_dir_entry *) inode->u.generic_ip;
+ de = (struct proc_dir_entry *) dentry->inode->u.generic_ip;
link = (char *) de->data;
return lookup_dentry(link, base, 1);
}
-static int devtree_readlink(struct inode *inode, char *buffer, int buflen)
+static int devtree_readlink(struct dentry *dentry, char *buffer, int buflen)
{
struct proc_dir_entry * de;
char *link;
int linklen;
- de = (struct proc_dir_entry *) inode->u.generic_ip;
+ de = (struct proc_dir_entry *) dentry->inode->u.generic_ip;
link = (char *) de->data;
linklen = strlen(link);
if (linklen > buflen)
diff --git a/fs/proc/root.c b/fs/proc/root.c
index c72c06483..3e344bd09 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -50,6 +50,9 @@ static struct file_operations proc_dir_operations = {
NULL /* can't fsync */
};
+int proc_readlink(struct dentry * dentry, char * buffer, int buflen);
+struct dentry * proc_follow_link(struct dentry *dentry, struct dentry *base);
+
/*
* proc directories can do almost nothing..
*/
@@ -149,7 +152,7 @@ struct proc_dir_entry proc_root = {
&proc_root, NULL
};
-struct proc_dir_entry *proc_net, *proc_scsi;
+struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus;
#ifdef CONFIG_MCA
struct proc_dir_entry proc_mca = {
@@ -332,15 +335,13 @@ int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
if (dp->ops == NULL)
dp->ops = &proc_dir_inode_operations;
dir->nlink++;
+ } else if (S_ISLNK(dp->mode)) {
+ if (dp->ops == NULL)
+ dp->ops = &proc_link_inode_operations;
} else {
if (dp->ops == NULL)
dp->ops = &proc_file_inode_operations;
}
- /*
- * kludge until we fixup the md device driver
- */
- if (dp->low_ino == PROC_MD)
- dp->ops = &proc_array_inode_operations;
return 0;
}
@@ -368,7 +369,7 @@ int proc_unregister(struct proc_dir_entry * dir, int ino)
/*
* /proc/self:
*/
-static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
+static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
{
int len;
char tmp[30];
@@ -380,15 +381,59 @@ static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
return len;
}
-static struct dentry * proc_self_follow_link(struct inode *inode, struct dentry *base)
+static struct dentry * proc_self_follow_link(struct dentry *dentry,
+ struct dentry *base)
{
- int len;
char tmp[30];
- len = sprintf(tmp, "%d", current->pid);
+ sprintf(tmp, "%d", current->pid);
return lookup_dentry(tmp, base, 1);
}
+int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
+{
+ struct inode *inode = dentry->d_inode;
+ struct proc_dir_entry * de;
+ char *page;
+ int len = 0;
+
+ de = (struct proc_dir_entry *) inode->u.generic_ip;
+ if (!de)
+ return -ENOENT;
+ if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (de->readlink_proc)
+ len = de->readlink_proc(de, page);
+
+ if (len > buflen)
+ len = buflen;
+
+ copy_to_user(buffer, page, len);
+ free_page((unsigned long) page);
+ return len;
+}
+
+struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base)
+{
+ struct inode *inode = dentry->d_inode;
+ struct proc_dir_entry * de;
+ char *page;
+ struct dentry *d;
+ int len = 0;
+
+ de = (struct proc_dir_entry *) inode->u.generic_ip;
+ if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+ return NULL;
+
+ if (de->readlink_proc)
+ len = de->readlink_proc(de, page);
+
+ d = lookup_dentry(page, base, 1);
+ free_page((unsigned long) page);
+ return d;
+}
+
static struct inode_operations proc_self_inode_operations = {
NULL, /* no file-ops */
NULL, /* create */
@@ -409,6 +454,26 @@ static struct inode_operations proc_self_inode_operations = {
NULL /* permission */
};
+static struct inode_operations proc_link_inode_operations = {
+ NULL, /* no file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ proc_readlink, /* readlink */
+ proc_follow_link, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
+
static struct proc_dir_entry proc_root_loadavg = {
PROC_LOADAVG, 7, "loadavg",
S_IFREG | S_IRUGO, 1, 0, 0,
@@ -434,7 +499,7 @@ static struct proc_dir_entry proc_root_version = {
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_OLD_PROC
static struct proc_dir_entry proc_root_pci = {
PROC_PCI, 3, "pci",
S_IFREG | S_IRUGO, 1, 0, 0,
@@ -504,13 +569,6 @@ static struct proc_dir_entry proc_root_interrupts = {
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
-#ifdef __SMP_PROF__
-static struct proc_dir_entry proc_root_smp = {
- PROC_SMP_PROF, 3,"smp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_array_inode_operations
-};
-#endif
static struct proc_dir_entry proc_root_filesystems = {
PROC_FILESYSTEMS, 11,"filesystems",
S_IFREG | S_IRUGO, 1, 0, 0,
@@ -563,13 +621,6 @@ static struct proc_dir_entry proc_root_slab = {
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
-#ifdef CONFIG_OMIRR
-static struct proc_dir_entry proc_root_omirr = {
- PROC_OMIRR, 5, "omirr",
- S_IFREG | S_IRUSR, 1, 0, 0,
- 0, &proc_omirr_inode_operations
-};
-#endif
#ifdef __powerpc__
static struct proc_dir_entry proc_root_ppc_htab = {
PROC_PPC_HTAB, 8, "ppc_htab",
@@ -578,7 +629,6 @@ static struct proc_dir_entry proc_root_ppc_htab = {
NULL, NULL, /* get_info, fill_inode */
NULL, /* next */
NULL, NULL /* parent, subdir */
-
};
#endif
@@ -590,7 +640,7 @@ 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_PCI
+#ifdef CONFIG_PCI_OLD_PROC
proc_register(&proc_root, &proc_root_pci);
#endif
#ifdef CONFIG_ZORRO
@@ -620,9 +670,6 @@ void proc_root_init(void)
proc_register(&proc_root, &proc_root_stat);
proc_register(&proc_root, &proc_root_devices);
proc_register(&proc_root, &proc_root_interrupts);
-#ifdef __SMP_PROF__
- proc_register(&proc_root, &proc_root_smp);
-#endif
proc_register(&proc_root, &proc_root_filesystems);
proc_register(&proc_root, &proc_root_dma);
proc_register(&proc_root, &proc_root_ioports);
@@ -658,6 +705,11 @@ void proc_root_init(void)
#ifdef CONFIG_PROC_DEVICETREE
proc_device_tree_init();
#endif
+
+ proc_bus = create_proc_entry("bus", S_IFDIR, 0);
+#ifdef CONFIG_PCI
+ proc_bus_pci_init();
+#endif
}
/*