summaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/proc
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/Makefile2
-rw-r--r--fs/proc/array.c1
-rw-r--r--fs/proc/base.c21
-rw-r--r--fs/proc/generic.c387
-rw-r--r--fs/proc/inode-alloc.txt1
-rw-r--r--fs/proc/inode.c87
-rw-r--r--fs/proc/kcore.c74
-rw-r--r--fs/proc/kmsg.c19
-rw-r--r--fs/proc/omirr.c19
-rw-r--r--fs/proc/openprom-dev.c46
-rw-r--r--fs/proc/openpromfs.c208
-rw-r--r--fs/proc/proc_devtree.c97
-rw-r--r--fs/proc/proc_misc.c18
-rw-r--r--fs/proc/proc_tty.c20
-rw-r--r--fs/proc/procfs_syms.c12
-rw-r--r--fs/proc/root.c563
16 files changed, 652 insertions, 923 deletions
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 8ff6cd522..e8bb4774f 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -18,9 +18,11 @@ M_OBJS :=
ifeq ($(CONFIG_SUN_OPENPROMFS),y)
O_OBJS += openpromfs.o
+OX_OBJS := openprom-dev.o
else
ifeq ($(CONFIG_SUN_OPENPROMFS),m)
M_OBJS += openpromfs.o
+ OX_OBJS := openprom-dev.o
endif
endif
diff --git a/fs/proc/array.c b/fs/proc/array.c
index eebb1f470..4ae097ca2 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -62,7 +62,6 @@
#include <linux/mman.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
-#include <linux/config.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 866bb50d4..eac10cbd4 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -104,9 +104,12 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
{
struct mm_struct *mm = task->mm;
int res = 0;
- if (mm)
- res = access_process_vm(task, mm->env_start, buffer,
- mm->env_end - mm->env_start, 0);
+ if (mm) {
+ int len = mm->env_end - mm->env_start;
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ res = access_process_vm(task, mm->env_start, buffer, len, 0);
+ }
return res;
}
@@ -116,9 +119,12 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
struct mm_struct *mm = task->mm;
int res = 0;
- if (mm)
- res = access_process_vm(task, mm->arg_start, buffer,
- mm->arg_end - mm->arg_start, 0);
+ if (mm) {
+ int len = mm->arg_end - mm->arg_start;
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ res = access_process_vm(task, mm->arg_start, buffer, len, 0);
+ }
return res;
}
@@ -363,10 +369,8 @@ static struct inode_operations proc_mem_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
proc_permission, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -788,7 +792,6 @@ static struct inode_operations proc_fd_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
proc_permission, /* permission */
};
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 5ef59004c..5f43c691e 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -16,8 +16,6 @@
#include <linux/stat.h>
#include <asm/bitops.h>
-extern struct inode_operations proc_dyna_dir_inode_operations;
-
static ssize_t proc_file_read(struct file * file, char * buf,
size_t nbytes, loff_t *ppos);
static ssize_t proc_file_write(struct file * file, const char * buffer,
@@ -37,37 +35,10 @@ static struct file_operations proc_file_operations = {
proc_file_lseek, /* lseek */
proc_file_read, /* read */
proc_file_write, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
};
-struct inode_operations proc_file_inode_operations = {
+static struct inode_operations proc_file_inode_operations = {
&proc_file_operations, /* default proc file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
#ifndef MIN
@@ -101,12 +72,8 @@ proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
/*
* Handle backwards compatibility with the old net
* routines.
- *
- * XXX What gives with the file->f_flags & O_ACCMODE
- * test? Seems stupid to me....
*/
- n = dp->get_info(page, &start, *ppos, count,
- (file->f_flags & O_ACCMODE) == O_RDWR);
+ n = dp->get_info(page, &start, *ppos, count);
if (n < count)
eof = 1;
} else if (dp->read_proc) {
@@ -114,7 +81,7 @@ proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
count, &eof, dp->data);
} else
break;
-
+
if (!start) {
/*
* For proc files that are less than 4k
@@ -221,6 +188,321 @@ static int xlate_proc_name(const char *name,
return 0;
}
+static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
+
+static int make_inode_number(void)
+{
+ int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
+ if (i<0 || i>=PROC_NDYNAMIC)
+ return -1;
+ set_bit(i, (void *) proc_alloc_map);
+ return PROC_DYNAMIC_FIRST + i;
+}
+
+static int proc_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
+ return vfs_readlink(dentry, buffer, buflen, s);
+}
+
+static struct dentry *proc_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags)
+{
+ char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
+ return vfs_follow_link(dentry, base, flags, s);
+}
+
+static struct inode_operations proc_link_inode_operations = {
+ readlink: proc_readlink,
+ follow_link: proc_follow_link
+};
+
+/*
+ * As some entries in /proc are volatile, we want to
+ * get rid of unused dentries. This could be made
+ * smarter: we could keep a "volatile" flag in the
+ * inode to indicate which ones to keep.
+ */
+static void
+proc_delete_dentry(struct dentry * dentry)
+{
+ d_drop(dentry);
+}
+
+static struct dentry_operations proc_dentry_operations =
+{
+ NULL, /* revalidate */
+ NULL, /* d_hash */
+ NULL, /* d_compare */
+ proc_delete_dentry /* d_delete(struct dentry *) */
+};
+
+/*
+ * Don't create negative dentries here, return -ENOENT by hand
+ * instead.
+ */
+struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
+{
+ struct inode *inode;
+ struct proc_dir_entry * de;
+ int error;
+
+ error = -ENOENT;
+ inode = NULL;
+ de = (struct proc_dir_entry *) dir->u.generic_ip;
+ if (de) {
+ for (de = de->subdir; de ; de = de->next) {
+ if (!de || !de->low_ino)
+ continue;
+ if (de->namelen != dentry->d_name.len)
+ continue;
+ if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
+ int ino = de->low_ino;
+ error = -EINVAL;
+ inode = proc_get_inode(dir->i_sb, ino, de);
+ break;
+ }
+ }
+ }
+
+ if (inode) {
+ dentry->d_op = &proc_dentry_operations;
+ d_add(dentry, inode);
+ return NULL;
+ }
+ return ERR_PTR(error);
+}
+
+/*
+ * This returns non-zero if at EOF, so that the /proc
+ * root directory can use this and check if it should
+ * continue with the <pid> entries..
+ *
+ * Note that the VFS-layer doesn't care about the return
+ * value of the readdir() call, as long as it's non-negative
+ * for success..
+ */
+int proc_readdir(struct file * filp,
+ void * dirent, filldir_t filldir)
+{
+ struct proc_dir_entry * de;
+ unsigned int ino;
+ int i;
+ struct inode *inode = filp->f_dentry->d_inode;
+
+ ino = inode->i_ino;
+ de = (struct proc_dir_entry *) inode->u.generic_ip;
+ if (!de)
+ return -EINVAL;
+ i = filp->f_pos;
+ switch (i) {
+ case 0:
+ if (filldir(dirent, ".", 1, i, ino) < 0)
+ return 0;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ case 1:
+ if (filldir(dirent, "..", 2, i,
+ filp->f_dentry->d_parent->d_inode->i_ino
+ ) < 0)
+ return 0;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ default:
+ de = de->subdir;
+ i -= 2;
+ for (;;) {
+ if (!de)
+ return 1;
+ if (!i)
+ break;
+ de = de->next;
+ i--;
+ }
+
+ do {
+ if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
+ return 0;
+ filp->f_pos++;
+ de = de->next;
+ } while (de);
+ }
+ return 1;
+}
+
+/*
+ * These are the generic /proc directory operations. They
+ * use the in-memory "struct proc_dir_entry" tree to parse
+ * the /proc directory.
+ */
+static struct file_operations proc_dir_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ proc_readdir, /* readdir */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+struct inode_operations proc_dir_inode_operations = {
+ &proc_dir_operations, /* default net directory file-ops */
+ NULL, /* create */
+ proc_lookup, /* lookup */
+};
+
+int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
+{
+ int i;
+
+ i = make_inode_number();
+ if (i < 0)
+ return -EAGAIN;
+ dp->low_ino = i;
+ dp->next = dir->subdir;
+ dp->parent = dir;
+ dir->subdir = dp;
+ if (S_ISDIR(dp->mode)) {
+ 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 (S_ISREG(dp->mode)) {
+ if (dp->ops == NULL)
+ dp->ops = &proc_file_inode_operations;
+ }
+ return 0;
+}
+
+/*
+ * Kill an inode that got unregistered..
+ */
+static void proc_kill_inodes(struct proc_dir_entry *de)
+{
+ struct list_head *p;
+ struct super_block *sb;
+
+ /*
+ * Actually it's a partial revoke(). We have to go through all
+ * copies of procfs. proc_super_blocks is protected by the big
+ * lock for the time being.
+ */
+ for (sb = proc_super_blocks;
+ sb;
+ sb = (struct super_block*)sb->u.generic_sbp) {
+ file_list_lock();
+ for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
+ struct file * filp = list_entry(p, struct file, f_list);
+ struct dentry * dentry;
+ struct inode * inode;
+
+ dentry = filp->f_dentry;
+ if (!dentry)
+ continue;
+ if (dentry->d_op != &proc_dentry_operations)
+ continue;
+ inode = dentry->d_inode;
+ if (!inode)
+ continue;
+ if (inode->u.generic_ip != de)
+ continue;
+ filp->f_op = NULL;
+ }
+ file_list_unlock();
+ }
+}
+
+struct proc_dir_entry *proc_symlink(const char *name,
+ struct proc_dir_entry *parent, char *dest)
+{
+ struct proc_dir_entry *ent = NULL;
+ const char *fn = name;
+ int len;
+
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
+ len = strlen(fn);
+
+ ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
+ if (!ent)
+ goto out;
+ memset(ent, 0, sizeof(struct proc_dir_entry));
+ memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
+ ent->name = ((char *) ent) + sizeof(*ent);
+ ent->namelen = len;
+ ent->nlink = 1;
+ ent->mode = S_IFLNK|S_IRUGO|S_IWUGO|S_IXUGO;
+ ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
+ if (!ent->data) {
+ kfree(ent);
+ goto out;
+ }
+ strcpy((char*)ent->data,dest);
+
+ proc_register(parent, ent);
+
+out:
+ return ent;
+}
+
+struct proc_dir_entry *proc_mknod(const char *name, mode_t mode,
+ struct proc_dir_entry *parent, kdev_t rdev)
+{
+ struct proc_dir_entry *ent = NULL;
+ const char *fn = name;
+ int len;
+
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
+ len = strlen(fn);
+
+ ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
+ if (!ent)
+ goto out;
+ memset(ent, 0, sizeof(struct proc_dir_entry));
+ memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
+ ent->name = ((char *) ent) + sizeof(*ent);
+ ent->namelen = len;
+ ent->nlink = 1;
+ ent->mode = mode;
+ ent->rdev = rdev;
+
+ proc_register(parent, ent);
+
+out:
+ return ent;
+}
+
+struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
+{
+ struct proc_dir_entry *ent = NULL;
+ const char *fn = name;
+ int len;
+
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
+ len = strlen(fn);
+
+ ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
+ if (!ent)
+ goto out;
+ memset(ent, 0, sizeof(struct proc_dir_entry));
+ memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
+ ent->name = ((char *) ent) + sizeof(*ent);
+ ent->namelen = len;
+ ent->ops = &proc_dir_inode_operations;
+ ent->nlink = 2;
+ ent->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+
+ proc_register(parent, ent);
+
+out:
+ return ent;
+}
+
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent)
{
@@ -243,7 +525,7 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
if (S_ISDIR(mode)) {
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO | S_IXUGO;
- ent->ops = &proc_dyna_dir_inode_operations;
+ ent->ops = &proc_dir_inode_operations;
ent->nlink = 2;
} else {
if ((mode & S_IFMT) == 0)
@@ -260,14 +542,16 @@ out:
return ent;
}
-extern void free_proc_entry(struct proc_dir_entry *);
void free_proc_entry(struct proc_dir_entry *de)
{
int ino = de->low_ino;
- if (ino >= PROC_DYNAMIC_FIRST &&
- ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
- kfree(de);
+ if (ino < PROC_DYNAMIC_FIRST &&
+ ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
+ return;
+ if (S_ISLNK(de->mode) && de->data)
+ kfree(de->data);
+ kfree(de);
}
/*
@@ -276,6 +560,7 @@ void free_proc_entry(struct proc_dir_entry *de)
*/
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
{
+ struct proc_dir_entry **p;
struct proc_dir_entry *de;
const char *fn = name;
int len;
@@ -283,14 +568,17 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
goto out;
len = strlen(fn);
-
- for (de = parent->subdir; de ; de = de->next) {
- if (proc_match(len, fn, de))
- break;
- }
-
- if (de) {
- proc_unregister(parent, de->low_ino);
+ for (p = &parent->subdir; *p; p=&(*p)->next ) {
+ if (!proc_match(len, fn, *p))
+ continue;
+ de = *p;
+ *p = de->next;
+ de->next = NULL;
+ if (S_ISDIR(de->mode))
+ parent->nlink--;
+ clear_bit(de->low_ino-PROC_DYNAMIC_FIRST,
+ (void *) proc_alloc_map);
+ proc_kill_inodes(de);
de->nlink = 0;
de->deleted = 1;
if (!de->count)
@@ -299,6 +587,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
printk("remove_proc_entry: %s/%s busy, count=%d\n",
parent->name, de->name, de->count);
}
+ break;
}
out:
return;
diff --git a/fs/proc/inode-alloc.txt b/fs/proc/inode-alloc.txt
index 4af79966c..fbcfa4e40 100644
--- a/fs/proc/inode-alloc.txt
+++ b/fs/proc/inode-alloc.txt
@@ -5,7 +5,6 @@ Current inode allocations in the proc-fs (hex-numbers):
001 root-ino
00001000-00001fff dynamic entries
- 00002000-00002fff openprom entries
0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff
80000000-ffffffff unused
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 8842cc253..607a7d7e9 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -13,7 +13,7 @@
#include <linux/file.h>
#include <linux/locks.h>
#include <linux/limits.h>
-#include <linux/config.h>
+#define __NO_VERSION__
#include <linux/module.h>
#include <asm/system.h>
@@ -51,10 +51,6 @@ void de_put(struct proc_dir_entry *de)
static void proc_put_inode(struct inode *inode)
{
-#ifdef CONFIG_SUN_OPENPROMFS_MODULE
- if (PROC_INODE_OPENPROM(inode) && proc_openprom_use)
- (*proc_openprom_use)(inode, 0);
-#endif
/*
* Kill off unused inodes ... VFS will unhash and
* delete the inode if we set i_nlink to zero.
@@ -74,9 +70,6 @@ static void proc_delete_inode(struct inode *inode)
proc_pid_delete_inode(inode);
return;
}
- if (PROC_INODE_OPENPROM(inode))
- return;
-
if (de) {
if (de->owner)
__MOD_DEC_USE_COUNT(de->owner);
@@ -97,6 +90,30 @@ static void proc_put_super(struct super_block *sb)
*p = (struct super_block *)(*p)->u.generic_sbp;
}
+static void proc_write_inode(struct inode * inode)
+{
+}
+
+static void proc_read_inode(struct inode * inode)
+{
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+}
+
+static int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+ struct statfs tmp;
+
+ tmp.f_type = PROC_SUPER_MAGIC;
+ tmp.f_bsize = PAGE_SIZE/sizeof(long);
+ tmp.f_blocks = 0;
+ tmp.f_bfree = 0;
+ tmp.f_bavail = 0;
+ tmp.f_files = 0;
+ tmp.f_ffree = 0;
+ tmp.f_namelen = NAME_MAX;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
static struct super_operations proc_sops = {
proc_read_inode,
proc_write_inode,
@@ -158,11 +175,6 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count);
if (!inode)
goto out_fail;
-#ifdef CONFIG_SUN_OPENPROMFS_MODULE
- if (PROC_INODE_OPENPROM(inode) && proc_openprom_use)
- (*proc_openprom_use)(inode, 1);
-#endif
-
inode->u.generic_ip = (void *) de;
if (de) {
if (de->mode) {
@@ -172,26 +184,16 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count);
}
if (de->size)
inode->i_size = de->size;
- if (de->ops)
- inode->i_op = de->ops;
if (de->nlink)
inode->i_nlink = de->nlink;
if (de->owner)
__MOD_INC_USE_COUNT(de->owner);
+ if (S_ISBLK(de->mode)||S_ISCHR(de->mode)||S_ISFIFO(de->mode))
+ init_special_inode(inode,de->mode,kdev_t_to_nr(de->rdev));
+ else if (de->ops)
+ inode->i_op = de->ops;
}
- /*
- * Fixup the root inode's nlink value
- */
- if (inode->i_ino == PROC_ROOT_INO) {
- struct task_struct *p;
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (p->pid)
- inode->i_nlink++;
- }
- read_unlock(&tasklist_lock);
- }
out:
return inode;
@@ -204,6 +206,7 @@ struct super_block *proc_read_super(struct super_block *s,void *data,
int silent)
{
struct inode * root_inode;
+ struct task_struct *p;
lock_super(s);
s->s_blocksize = 1024;
@@ -213,6 +216,12 @@ struct super_block *proc_read_super(struct super_block *s,void *data,
root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
if (!root_inode)
goto out_no_root;
+ /*
+ * Fixup the root inode's nlink value
+ */
+ read_lock(&tasklist_lock);
+ for_each_task(p) if (p->pid) root_inode->i_nlink++;
+ read_unlock(&tasklist_lock);
s->s_root = d_alloc_root(root_inode);
if (!s->s_root)
goto out_no_root;
@@ -229,27 +238,3 @@ out_no_root:
unlock_super(s);
return NULL;
}
-
-int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
-{
- struct statfs tmp;
-
- tmp.f_type = PROC_SUPER_MAGIC;
- tmp.f_bsize = PAGE_SIZE/sizeof(long);
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
-}
-
-void proc_read_inode(struct inode * inode)
-{
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-}
-
-void proc_write_inode(struct inode * inode)
-{
-}
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index ec2a92db3..28635ff14 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -3,9 +3,9 @@
*
* Modelled on fs/exec.c:aout_core_dump()
* Jeremy Fitzhardinge <jeremy@sw.oz.au>
- * Implemented by David Howells <David.Howells@nexor.co.uk>
+ * ELF version written by David Howells <David.Howells@nexor.co.uk>
* Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@sco.com>
- * Support to dump vmalloc'd data structures (ELF only), Tigran Aivazian <tigran@sco.com>
+ * Support to dump vmalloc'd areas (ELF only), Tigran Aivazian <tigran@sco.com>
*/
#include <linux/config.h>
@@ -16,7 +16,6 @@
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
#include <asm/uaccess.h>
@@ -43,8 +42,7 @@ struct inode_operations proc_kcore_inode_operations = {
};
#ifdef CONFIG_KCORE_AOUT
-static ssize_t read_kcore(struct file * file, char * buf,
- size_t count, loff_t *ppos)
+static ssize_t read_kcore(struct file *file, char *buf, size_t count, loff_t *ppos)
{
unsigned long long p = *ppos, memsize;
ssize_t read;
@@ -79,7 +77,8 @@ static ssize_t read_kcore(struct file * file, char * buf,
if (p + count1 > sizeof(struct user))
count1 = sizeof(struct user)-p;
pnt = (char *) &dump + p;
- copy_to_user(buf,(void *) pnt, count1);
+ if (copy_to_user(buf,(void *) pnt, count1))
+ return -EFAULT;
buf += count1;
p += count1;
count -= count1;
@@ -90,14 +89,16 @@ static ssize_t read_kcore(struct file * file, char * buf,
count1 = PAGE_SIZE + FIRST_MAPPED - p;
if (count1 > count)
count1 = count;
- clear_user(buf, count1);
+ if (clear_user(buf, count1))
+ return -EFAULT;
buf += count1;
p += count1;
count -= count1;
read += count1;
}
if (count > 0) {
- copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count);
+ if (copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count))
+ return -EFAULT;
read += count;
}
*ppos += read;
@@ -130,6 +131,8 @@ static size_t get_kcore_size(int *num_vma, int *elf_buflen)
}
for (m=vmlist; m; m=m->next) {
+ if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
+ continue;
try = (size_t)m->addr + m->size;
if (try > size)
size = try;
@@ -189,7 +192,7 @@ static char *storenote(struct memelfnote *men, char *bufp)
* store an ELF coredump header in the supplied buffer
* num_vma is the number of elements in vmlist
*/
-static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
+static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff)
{
struct elf_prstatus prstatus; /* NT_PRSTATUS */
struct elf_prpsinfo prpsinfo; /* NT_PRPSINFO */
@@ -235,28 +238,33 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
nhdr->p_flags = 0;
nhdr->p_align = 0;
- /* setup ELF PT_LOAD program header */
+ /* setup ELF PT_LOAD program header for the
+ * virtual range 0xc0000000 -> high_memory */
phdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
- phdr->p_offset = elf_buflen;
+ phdr->p_offset = dataoff;
phdr->p_vaddr = PAGE_OFFSET;
phdr->p_paddr = __pa(PAGE_OFFSET);
phdr->p_filesz = phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET);
phdr->p_align = PAGE_SIZE;
+ /* setup ELF PT_LOAD program header for every vmalloc'd area */
for (m=vmlist; m; m=m->next) {
+ if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
+ continue;
+
phdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
- phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + elf_buflen;
+ phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + dataoff;
phdr->p_vaddr = (size_t)m->addr;
- phdr->p_paddr = __pa(m);
+ phdr->p_paddr = __pa(m->addr);
phdr->p_filesz = phdr->p_memsz = m->size;
phdr->p_align = PAGE_SIZE;
}
@@ -310,13 +318,12 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
/*
* read from the ELF header and then kernel memory
*/
-static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
- loff_t *fpos)
+static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos)
{
ssize_t acc = 0;
size_t size, tsz;
- char * elf_buffer;
- int elf_buflen = 0, num_vma = 0;
+ size_t elf_buflen;
+ int num_vma;
/* XXX we need to somehow lock vmlist between here
* and after elf_kcore_store_hdr() returns.
@@ -332,16 +339,21 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
/* construct an ELF core header if we'll need some of it */
if (*fpos < elf_buflen) {
+ char * elf_buf;
+
tsz = elf_buflen - *fpos;
if (buflen < tsz)
tsz = buflen;
- elf_buffer = kmalloc(elf_buflen, GFP_KERNEL);
- if (!elf_buffer)
+ elf_buf = kmalloc(elf_buflen, GFP_ATOMIC);
+ if (!elf_buf)
return -ENOMEM;
- memset(elf_buffer, 0, elf_buflen);
- elf_kcore_store_hdr(elf_buffer, num_vma, elf_buflen);
- copy_to_user(buffer, elf_buffer, tsz);
- kfree(elf_buffer);
+ memset(elf_buf, 0, elf_buflen);
+ elf_kcore_store_hdr(elf_buf, num_vma, elf_buflen);
+ if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
+ kfree(elf_buf);
+ return -EFAULT;
+ }
+ kfree(elf_buf);
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
@@ -349,7 +361,7 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
/* leave now if filled buffer already */
if (buflen == 0)
- return tsz;
+ return acc;
}
/* where page 0 not mapped, write zeros into buffer */
@@ -361,7 +373,8 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
tsz = buflen;
/* write zeros to buffer */
- clear_user(buffer, tsz);
+ if (clear_user(buffer, tsz))
+ return -EFAULT;
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
@@ -372,17 +385,12 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
return tsz;
}
#endif
-
/* fill the remainder of the buffer from kernel VM space */
-#if defined (__i386__) || defined (__mc68000__)
- copy_to_user(buffer, __va(*fpos - PAGE_SIZE), buflen);
-#else
- copy_to_user(buffer, __va(*fpos), buflen);
-#endif
+ if (copy_to_user(buffer, __va(*fpos - elf_buflen), buflen))
+ return -EFAULT;
+
acc += buflen;
*fpos += buflen;
-
return acc;
-
}
#endif /* CONFIG_KCORE_AOUT */
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index bfe6c8c2e..b9344ba55 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -61,23 +61,4 @@ static struct file_operations proc_kmsg_operations = {
struct inode_operations proc_kmsg_inode_operations = {
&proc_kmsg_operations, /* default base directory file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
diff --git a/fs/proc/omirr.c b/fs/proc/omirr.c
index f738827a7..f205dd753 100644
--- a/fs/proc/omirr.c
+++ b/fs/proc/omirr.c
@@ -278,23 +278,4 @@ static struct file_operations omirr_operations = {
struct inode_operations proc_omirr_inode_operations = {
&omirr_operations,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
diff --git a/fs/proc/openprom-dev.c b/fs/proc/openprom-dev.c
new file mode 100644
index 000000000..79ef8d549
--- /dev/null
+++ b/fs/proc/openprom-dev.c
@@ -0,0 +1,46 @@
+/*
+ * linux/fs/proc/openprom-dev.c
+ *
+ * handling of devices attached to openpromfs.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+struct openpromfs_dev *openprom_devices = NULL;
+static ino_t openpromdev_ino = PROC_OPENPROMD_FIRST;
+
+int proc_openprom_regdev(struct openpromfs_dev *d)
+{
+ if (openpromdev_ino == PROC_OPENPROMD_FIRST + PROC_NOPENPROMD)
+ return -1;
+ d->next = openprom_devices;
+ d->inode = openpromdev_ino++;
+ openprom_devices = d;
+ return 0;
+}
+
+int proc_openprom_unregdev(struct openpromfs_dev *d)
+{
+ if (d == openprom_devices) {
+ openprom_devices = d->next;
+ } else if (!openprom_devices)
+ return -1;
+ else {
+ struct openpromfs_dev *p;
+
+ for (p = openprom_devices; p->next != d && p->next; p = p->next);
+ if (!p->next) return -1;
+ p->next = d->next;
+ }
+ return 0;
+}
+
+#if defined(CONFIG_SUN_OPENPROMFS_MODULE)
+EXPORT_SYMBOL(openprom_devices);
+#endif
diff --git a/fs/proc/openpromfs.c b/fs/proc/openpromfs.c
index c9553ea24..55f290664 100644
--- a/fs/proc/openpromfs.c
+++ b/fs/proc/openpromfs.c
@@ -50,8 +50,7 @@ static u16 options = 0xffff;
static u16 aliases = 0xffff;
static int aliases_nodes = 0;
static char *alias_names [ALIASES_NNODES];
-static struct inode_operations *proc_openprom_iops = 0;
-static struct openpromfs_dev **devices;
+extern struct openpromfs_dev *openprom_devices;
#define NODE(ino) nodes[ino - PROC_OPENPROM_FIRST]
#define NODE2INO(node) (node + PROC_OPENPROM_FIRST)
@@ -566,25 +565,6 @@ static struct file_operations openpromfs_prop_ops = {
static struct inode_operations openpromfs_prop_inode_ops = {
&openpromfs_prop_ops, /* default property file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
static struct file_operations openpromfs_nodenum_ops = {
@@ -603,25 +583,6 @@ static struct file_operations openpromfs_nodenum_ops = {
static struct inode_operations openpromfs_nodenum_inode_ops = {
&openpromfs_nodenum_ops,/* default .node file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
static struct file_operations openprom_alias_operations = {
@@ -654,13 +615,13 @@ static struct inode_operations openprom_alias_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
+extern struct inode_operations openprom_inode_operations;
+
static int lookup_children(u16 n, const char * name, int len)
{
int ret;
@@ -772,7 +733,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
}
}
if (!ino) {
- for (d = *devices; d; d = d->next)
+ for (d = openprom_devices; d; d = d->next)
if ((d->node == n) && (strlen (d->name) == len)
&& !strncmp (d->name, name, len)) {
ino = d->inode;
@@ -787,7 +748,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
else
return ERR_PTR(-ENOENT);
}
- inode = proc_get_inode (dir->i_sb, ino, 0);
+ inode = iget (dir->i_sb, ino, 0);
if (!inode)
return ERR_PTR(-EINVAL);
switch (type) {
@@ -797,7 +758,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
inode->i_mode |= S_IWUSR;
inode->i_op = &openprom_alias_inode_operations;
} else
- inode->i_op = proc_openprom_iops;
+ inode->i_op = &openprom_inode_operations;
inode->i_nlink = 2;
break;
case OPFSL_NODENUM:
@@ -825,11 +786,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
(((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));
break;
case OPFSL_DEVICE:
- inode->i_mode = d->mode;
- inode->i_op = &chrdev_inode_operations;
- inode->i_nlink = 1;
- inode->i_rdev = d->rdev;
- break;
+ init_special_inode(d->mode, kdev_to_nr(d->rdev));
}
inode->i_gid = 0;
@@ -914,7 +871,7 @@ static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filld
}
}
}
- for (d = *devices; d; d = d->next) {
+ for (d = openprom_devices; d; d = d->next) {
if (d->node == n) {
if (i) i--;
else {
@@ -947,9 +904,8 @@ static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode
strncpy (p, dentry->d_name.name, dentry->d_name.len);
p [dentry->d_name.len] = 0;
alias_names [aliases_nodes++] = p;
- inode = proc_get_inode (dir->i_sb,
- NODEP2INO(NODE(dir->i_ino).first_prop)
- + aliases_nodes, 0);
+ inode = iget (dir->i_sb,
+ NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes);
if (!inode)
return -EINVAL;
inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;
@@ -1090,25 +1046,6 @@ void openpromfs_use (struct inode *inode, int inc)
{
static int root_fresh = 1;
static int dec_first = 1;
-#ifdef OPENPROM_DEBUGGING
- static int usec = 0;
-
- if (inc) {
- if (inode->i_count == 1)
- usec++;
- else if (root_fresh && inode->i_ino == PROC_OPENPROM_FIRST) {
- root_fresh = 0;
- usec++;
- }
- } else {
- if (inode->i_ino == PROC_OPENPROM_FIRST)
- root_fresh = 0;
- if (!dec_first)
- usec--;
- }
- printk ("openpromfs_use: %d %d %d %d\n",
- inode->i_ino, inc, usec, inode->i_count);
-#else
if (inc) {
if (inode->i_count == 1)
MOD_INC_USE_COUNT;
@@ -1122,7 +1059,6 @@ void openpromfs_use (struct inode *inode, int inc)
if (!dec_first)
MOD_DEC_USE_COUNT;
}
-#endif
dec_first = 0;
}
@@ -1130,39 +1066,131 @@ void openpromfs_use (struct inode *inode, int inc)
#define openpromfs_use 0
#endif
-#ifndef MODULE
-#define RET(x)
-void __init openpromfs_init (void)
-#else
+static struct file_operations openprom_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ openpromfs_readdir, /* readdir */
+};
-EXPORT_NO_SYMBOLS;
+static struct inode_operations openprom_inode_operations = {
+ &openprom_operations,/* default net directory file-ops */
+ NULL, /* create */
+ openpromfs_lookup, /* lookup */
+};
-#define RET(x) -x
-int init_module (void)
-#endif
+static void openprom_read_inode(struct inode * inode)
+{
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ if (inode->i_ino == PROC_OPENPROM) {
+ inode->i_op = &openprom_inode_operations;
+ }
+}
+
+static void openprom_put_super(struct super_block *sb)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+static int openprom_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+ struct statfs tmp;
+
+ tmp.f_type = PROC_SUPER_MAGIC; /* FIXME */
+ tmp.f_bsize = PAGE_SIZE/sizeof(long); /* ??? */
+ tmp.f_blocks = 0;
+ tmp.f_bfree = 0;
+ tmp.f_bavail = 0;
+ tmp.f_files = 0;
+ tmp.f_ffree = 0;
+ tmp.f_namelen = NAME_MAX;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static struct super_operations openprom_sops = {
+ openprom_read_inode,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ openprom_put_super,
+ NULL,
+ openprom_statfs,
+ NULL
+};
+
+struct super_block *openprom_read_super(struct super_block *s,void *data,
+ int silent)
+{
+ struct inode * root_inode;
+
+ MOD_INC_USE_COUNT;
+ lock_super(s);
+ s->s_blocksize = 1024;
+ s->s_blocksize_bits = 10;
+ s->s_magic = PROC_SUPER_MAGIC; /* FIXME */
+ s->s_op = &openprom_sops;
+ root_inode = iget(s, PROC_OPENPROM);
+ if (!root_inode)
+ goto out_no_root;
+ s->s_root = d_alloc_root(root_inode);
+ if (!s->s_root)
+ goto out_no_root;
+ unlock_super(s);
+ return s;
+
+out_no_root:
+ printk("proc_read_super: get root inode failed\n");
+ iput(root_inode);
+ s->s_dev = 0;
+ unlock_super(s);
+ return NULL;
+}
+
+static struct file_system_type openprom_fs_type = {
+ "openprom",
+ 0,
+ openprom_read_super,
+ NULL
+};
+
+static int init_openprom_fs(void)
{
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);
+ return -EIO;
}
if (get_nodes (0xffff, prom_root_node) == 0xffff) {
printk (KERN_WARNING "/proc/openprom: couldn't setup tree\n");
- return RET(EIO);
+ return -EIO;
}
nodes[last_node].first_prop = first_prop;
- proc_openprom_iops = proc_openprom_register (openpromfs_readdir,
- openpromfs_lookup,
- openpromfs_use,
- &devices);
- return RET(0);
+ return register_filesystem(&openprom_fs_type);
+}
+
+#ifdef MODULE
+
+EXPORT_NO_SYMBOLS;
+
+int init_module (void)
+{
+ return init_openprom_fs();
+}
+
+#else
+
+void __init openpromfs_init (void)
+{
+ init_openprom_fs();
}
+#endif
#ifdef MODULE
void cleanup_module (void)
{
int i;
- proc_openprom_deregister ();
+ unregister_filesystem(&openprom_fs_type);
free_pages ((unsigned long)nodes, alloced);
for (i = 0; i < aliases_nodes; i++)
if (alias_names [i])
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index c06a802ce..1b4b7f23b 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -41,62 +41,6 @@ static int property_read_proc(char *page, char **start, off_t off,
* and "@10" to it.
*/
-static int devtree_readlink(struct dentry *, char *, int);
-static struct dentry *devtree_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-struct inode_operations devtree_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- devtree_readlink, /* readlink */
- devtree_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static struct dentry *devtree_follow_link(struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- struct proc_dir_entry * de;
- char *link;
-
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- link = (char *) de->data;
- return lookup_dentry(link, base, follow);
-}
-
-static int devtree_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct proc_dir_entry * de;
- char *link;
- int linklen;
-
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- link = (char *) de->data;
- linklen = strlen(link);
- if (linklen > buflen)
- linklen = buflen;
- if (copy_to_user(buffer, link, linklen))
- return -EFAULT;
- return linklen;
-}
-
/*
* Process a node, adding entries for its children and its properties.
*/
@@ -115,18 +59,11 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
- ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ ent = create_proc_read_entry(de, 0, pp->name,
+ property_read_proc, pp);
if (ent == 0)
break;
- memset(ent, 0, sizeof(struct proc_dir_entry));
- ent->name = pp->name;
- ent->namelen = strlen(pp->name);
- ent->mode = S_IFREG | S_IRUGO;
- ent->nlink = 1;
- ent->data = pp;
- ent->read_proc = property_read_proc;
ent->size = pp->length;
- proc_register(de, ent);
*lastp = ent;
lastp = &ent->next;
}
@@ -140,15 +77,9 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
l = strlen(p);
if (l > 2 && p[l-2] == '@' && p[l-1] == '0')
l -= 2;
- ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ ent = proc_mkdir(de, p);
if (ent == 0)
break;
- memset(ent, 0, sizeof(struct proc_dir_entry));
- ent->name = p;
- ent->namelen = l;
- ent->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- ent->nlink = 2;
- proc_register(de, ent);
*lastp = ent;
lastp = &ent->next;
add_node(child, ent);
@@ -168,18 +99,9 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
if (sib->name && strcmp(sib->name, child->name) == 0)
break;
if (sib == child && strncmp(p, child->name, l) != 0) {
- al = kmalloc(sizeof(struct proc_dir_entry),
- GFP_KERNEL);
+ al = proc_symlink(de, child->name, ent->name);
if (al == 0)
break;
- memset(al, 0, sizeof(struct proc_dir_entry));
- al->name = child->name;
- al->namelen = strlen(child->name);
- al->mode = S_IFLNK | S_IRUGO | S_IXUGO;
- al->nlink = 1;
- al->data = (void *) ent->name;
- al->ops = &devtree_symlink_inode_operations;
- proc_register(de, al);
*lastp = al;
lastp = &al->next;
}
@@ -187,16 +109,9 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
/*
* Add another directory with the @address part as its name.
*/
- al = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ al = proc_symlink(de, at, ent->name);
if (al == 0)
break;
- memset(al, 0, sizeof(struct proc_dir_entry));
- al->name = at;
- al->namelen = strlen(at);
- al->mode = S_IFLNK | S_IRUGO | S_IXUGO;
- al->nlink = 1;
- al->data = (void *) ent->name;
- al->ops = &devtree_symlink_inode_operations;
proc_register(de, al);
*lastp = al;
lastp = &al->next;
@@ -213,7 +128,7 @@ void proc_device_tree_init(void)
struct device_node *root;
if ( !have_of )
return;
- proc_device_tree = create_proc_entry("device-tree", S_IFDIR, 0);
+ proc_device_tree = proc_mkdir("device-tree", 0);
if (proc_device_tree == 0)
return;
root = find_path_device("/");
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 97f74a028..00b09e6a7 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -60,7 +60,6 @@ extern int get_filesystem_info(char *);
extern int get_exec_domain_list(char *);
extern int get_irq_list(char *);
extern int get_dma_list(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_SGI_DS1286
@@ -453,20 +452,6 @@ static int cmdline_read_proc(char *page, char **start, off_t off,
return len;
}
-#ifdef CONFIG_RTC
-static int rtc_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len = get_rtc_status(page);
- if (len <= off+count) *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
- return len;
-}
-#endif
-
#ifdef CONFIG_SGI_DS1286
static int ds1286_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
@@ -665,9 +650,6 @@ void proc_misc_init(void)
{"dma", dma_read_proc},
{"ioports", ioports_read_proc},
{"cmdline", cmdline_read_proc},
-#ifdef CONFIG_RTC
- {"rtc", rtc_read_proc},
-#endif
#ifdef CONFIG_SGI_DS1286
{"rtc", ds1286_read_proc},
#endif
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 4b4ca41b8..e241c938e 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -161,10 +161,9 @@ void proc_tty_unregister_driver(struct tty_driver *driver)
if (!ent)
return;
- proc_unregister(proc_tty_driver, ent->low_ino);
+ remove_proc_entry(driver->driver_name, proc_tty_driver);
driver->proc_entry = 0;
- kfree(ent);
}
/*
@@ -172,18 +171,11 @@ void proc_tty_unregister_driver(struct tty_driver *driver)
*/
void __init proc_tty_init(void)
{
- struct proc_dir_entry *ent;
-
- ent = create_proc_entry("tty", S_IFDIR, 0);
- if (!ent)
+ if (!proc_mkdir("tty", 0))
return;
- proc_tty_ldisc = create_proc_entry("tty/ldisc", S_IFDIR, 0);
- proc_tty_driver = create_proc_entry("tty/driver", S_IFDIR, 0);
+ proc_tty_ldisc = proc_mkdir("tty/ldisc", 0);
+ proc_tty_driver = proc_mkdir("tty/driver", 0);
- ent = create_proc_entry("tty/ldiscs", 0, 0);
- ent->read_proc = tty_ldiscs_read_proc;
-
- ent = create_proc_entry("tty/drivers", 0, 0);
- ent->read_proc = tty_drivers_read_proc;
+ create_proc_read_entry("tty/ldiscs", 0, 0, tty_ldiscs_read_proc,NULL);
+ create_proc_read_entry("tty/drivers", 0, 0, tty_drivers_read_proc,NULL);
}
-
diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c
index fa2ee362e..7c986d615 100644
--- a/fs/proc/procfs_syms.c
+++ b/fs/proc/procfs_syms.c
@@ -8,22 +8,16 @@ extern struct proc_dir_entry *proc_sys_root;
#ifdef CONFIG_SYSCTL
EXPORT_SYMBOL(proc_sys_root);
#endif
-EXPORT_SYMBOL(proc_register);
-EXPORT_SYMBOL(proc_unregister);
+EXPORT_SYMBOL(proc_symlink);
+EXPORT_SYMBOL(proc_mknod);
+EXPORT_SYMBOL(proc_mkdir);
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(proc_dir_inode_operations);
EXPORT_SYMBOL(proc_net);
EXPORT_SYMBOL(proc_bus);
-#if defined(CONFIG_SUN_OPENPROMFS_MODULE)
-EXPORT_SYMBOL(proc_openprom_register);
-EXPORT_SYMBOL(proc_openprom_deregister);
-#endif
-
static struct file_system_type proc_fs_type = {
"proc",
0 /* FS_NO_DCACHE doesn't work correctly */,
diff --git a/fs/proc/root.c b/fs/proc/root.c
index b87b0fb4f..83a0d7619 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -15,383 +15,21 @@
#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
-
-static int proc_root_readdir(struct file *, void *, filldir_t);
-static struct dentry *proc_root_lookup(struct inode *,struct dentry *);
-static int proc_unlink(struct inode *, struct dentry *);
-
-static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
-
-/*
- * These are the generic /proc directory operations. They
- * use the in-memory "struct proc_dir_entry" tree to parse
- * the /proc directory.
- */
-static struct file_operations proc_dir_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- proc_readdir, /* readdir */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_dir_inode_operations = {
- &proc_dir_operations, /* default net directory file-ops */
- NULL, /* create */
- proc_lookup, /* lookup */
-};
-
-/*
- * /proc dynamic directories now support unlinking
- */
-struct inode_operations proc_dyna_dir_inode_operations = {
- &proc_dir_operations, /* default proc dir ops */
- NULL, /* create */
- proc_lookup, /* lookup */
- NULL, /* link */
- proc_unlink, /* unlink(struct inode *, struct dentry *) */
-};
-
-/*
- * The root /proc directory is special, as it has the
- * <pid> directories. Thus we don't use the generic
- * directory handling functions for that..
- */
-static struct file_operations proc_root_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- proc_root_readdir, /* readdir */
-};
-
-/*
- * proc root can do almost nothing..
- */
-static struct inode_operations proc_root_inode_operations = {
- &proc_root_operations, /* default base directory file-ops */
- NULL, /* create */
- proc_root_lookup, /* lookup */
-};
-
-/*
- * This is the root "inode" in the /proc tree..
- */
-struct proc_dir_entry proc_root = {
- PROC_ROOT_INO, 5, "/proc",
- S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
- 0, &proc_root_inode_operations,
- NULL, NULL,
- NULL,
- &proc_root, NULL
-};
struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
-#ifdef CONFIG_MCA
-struct proc_dir_entry *proc_mca;
-#endif
-
#ifdef CONFIG_SYSCTL
struct proc_dir_entry *proc_sys_root;
#endif
-#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
-
-static int (*proc_openprom_defreaddir_ptr)(struct file *, void *, filldir_t);
-static struct dentry * (*proc_openprom_deflookup_ptr)(struct inode *, struct dentry *);
-void (*proc_openprom_use)(struct inode *, int) = 0;
-static struct openpromfs_dev *proc_openprom_devices = NULL;
-static ino_t proc_openpromdev_ino = PROC_OPENPROMD_FIRST;
-
-struct inode_operations *
-proc_openprom_register(int (*readdir)(struct file *, void *, filldir_t),
- struct dentry * (*lookup)(struct inode *, struct dentry *),
- void (*use)(struct inode *, int),
- struct openpromfs_dev ***devices)
-{
- proc_openprom_defreaddir_ptr = (proc_openprom_inode_operations.default_file_ops)->readdir;
- proc_openprom_deflookup_ptr = proc_openprom_inode_operations.lookup;
- (proc_openprom_inode_operations.default_file_ops)->readdir = readdir;
- proc_openprom_inode_operations.lookup = lookup;
- proc_openprom_use = use;
- *devices = &proc_openprom_devices;
- return &proc_openprom_inode_operations;
-}
-
-int proc_openprom_regdev(struct openpromfs_dev *d)
-{
- if (proc_openpromdev_ino == PROC_OPENPROMD_FIRST + PROC_NOPENPROMD)
- return -1;
- d->next = proc_openprom_devices;
- d->inode = proc_openpromdev_ino++;
- proc_openprom_devices = d;
- return 0;
-}
-
-int proc_openprom_unregdev(struct openpromfs_dev *d)
-{
- if (d == proc_openprom_devices) {
- proc_openprom_devices = d->next;
- } else if (!proc_openprom_devices)
- return -1;
- else {
- struct openpromfs_dev *p;
-
- for (p = proc_openprom_devices; p->next != d && p->next; p = p->next);
- if (!p->next) return -1;
- p->next = d->next;
- }
- return 0;
-}
-
-#ifdef CONFIG_SUN_OPENPROMFS_MODULE
-void
-proc_openprom_deregister(void)
-{
- (proc_openprom_inode_operations.default_file_ops)->readdir = proc_openprom_defreaddir_ptr;
- proc_openprom_inode_operations.lookup = proc_openprom_deflookup_ptr;
- proc_openprom_use = 0;
-}
-#endif
-
-#if defined(CONFIG_SUN_OPENPROMFS_MODULE) && defined(CONFIG_KMOD)
-static int
-proc_openprom_defreaddir(struct file * filp, void * dirent, filldir_t filldir)
-{
- request_module("openpromfs");
- if ((proc_openprom_inode_operations.default_file_ops)->readdir !=
- proc_openprom_defreaddir)
- return (proc_openprom_inode_operations.default_file_ops)->readdir
- (filp, dirent, filldir);
- return -EINVAL;
-}
-#define OPENPROM_DEFREADDIR proc_openprom_defreaddir
-
-static struct dentry *
-proc_openprom_deflookup(struct inode * dir, struct dentry *dentry)
-{
- request_module("openpromfs");
- if (proc_openprom_inode_operations.lookup !=
- proc_openprom_deflookup)
- return proc_openprom_inode_operations.lookup
- (dir, dentry);
- return ERR_PTR(-ENOENT);
-}
-#define OPENPROM_DEFLOOKUP proc_openprom_deflookup
-#else
-#define OPENPROM_DEFREADDIR NULL
-#define OPENPROM_DEFLOOKUP NULL
-#endif
-
-static struct file_operations proc_openprom_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- OPENPROM_DEFREADDIR, /* readdir */
-};
-
-struct inode_operations proc_openprom_inode_operations = {
- &proc_openprom_operations,/* default net directory file-ops */
- NULL, /* create */
- OPENPROM_DEFLOOKUP, /* lookup */
-};
-
-struct proc_dir_entry proc_openprom = {
- PROC_OPENPROM, 8, "openprom",
- S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
- 0, &proc_openprom_inode_operations,
- NULL, NULL,
- NULL,
- &proc_root, NULL
-};
-
-extern void openpromfs_init (void);
-#endif /* CONFIG_SUN_OPENPROMFS */
-
-static int make_inode_number(void)
-{
- int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
- if (i<0 || i>=PROC_NDYNAMIC)
- return -1;
- set_bit(i, (void *) proc_alloc_map);
- return PROC_DYNAMIC_FIRST + i;
-}
-
-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, unsigned int follow)
-{
- 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, follow);
- free_page((unsigned long) page);
- return d;
-}
-
-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, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
-{
- int i;
-
- if (dp->low_ino == 0) {
- i = make_inode_number();
- if (i < 0)
- return -EAGAIN;
- dp->low_ino = i;
- }
- dp->next = dir->subdir;
- dp->parent = dir;
- dir->subdir = dp;
- if (S_ISDIR(dp->mode)) {
- 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;
- }
- return 0;
-}
-
-/*
- * Kill an inode that got unregistered..
- */
-static void proc_kill_inodes(int ino)
-{
- struct list_head *p;
- struct super_block *sb;
-
- /*
- * Actually it's a partial revoke(). We have to go through all
- * copies of procfs. proc_super_blocks is protected by the big
- * lock for the time being.
- */
- for (sb = proc_super_blocks;
- sb;
- sb = (struct super_block*)sb->u.generic_sbp) {
- file_list_lock();
- for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
- struct file * filp = list_entry(p, struct file, f_list);
- struct dentry * dentry;
- struct inode * inode;
-
- dentry = filp->f_dentry;
- if (!dentry)
- continue;
- if (dentry->d_op != &proc_dentry_operations)
- continue;
- inode = dentry->d_inode;
- if (!inode)
- continue;
- if (inode->i_ino != ino)
- continue;
- filp->f_op = NULL;
- }
- file_list_unlock();
- }
-}
-
-int proc_unregister(struct proc_dir_entry * dir, int ino)
-{
- struct proc_dir_entry **p = &dir->subdir, *dp;
-
- while ((dp = *p) != NULL) {
- if (dp->low_ino == ino) {
- *p = dp->next;
- dp->next = NULL;
- if (S_ISDIR(dp->mode))
- dir->nlink--;
- if (ino >= PROC_DYNAMIC_FIRST &&
- ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
- clear_bit(ino-PROC_DYNAMIC_FIRST,
- (void *) proc_alloc_map);
- proc_kill_inodes(ino);
- return 0;
- }
- p = &dp->next;
- }
- return -EINVAL;
-}
-
/*
* /proc/self:
*/
static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- int len;
char tmp[30];
-
- len = sprintf(tmp, "%d", current->pid);
- if (buflen < len)
- len = buflen;
- copy_to_user(buffer, tmp, len);
- return len;
+ sprintf(tmp, "%d", current->pid);
+ return vfs_readlink(dentry,buffer,buflen,tmp);
}
static struct dentry * proc_self_follow_link(struct dentry *dentry,
@@ -399,32 +37,13 @@ static struct dentry * proc_self_follow_link(struct dentry *dentry,
unsigned int follow)
{
char tmp[30];
-
sprintf(tmp, "%d", current->pid);
- return lookup_dentry(tmp, base, follow);
+ return vfs_follow_link(dentry,base,follow,tmp);
}
static struct inode_operations proc_self_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_self_readlink, /* readlink */
- proc_self_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: proc_self_readlink,
+ follow_link: proc_self_follow_link
};
static struct proc_dir_entry proc_root_self = {
@@ -435,7 +54,7 @@ static struct proc_dir_entry proc_root_self = {
#ifdef __powerpc__
static struct proc_dir_entry proc_root_ppc_htab = {
0, 8, "ppc_htab",
- S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0,
+ S_IFREG | S_IRUGO|S_IWUSR, 1, 0, 0,
0, &proc_ppc_htab_inode_operations,
};
#endif
@@ -444,23 +63,21 @@ void __init proc_root_init(void)
{
proc_misc_init();
proc_register(&proc_root, &proc_root_self);
- proc_net = create_proc_entry("net", S_IFDIR, 0);
+ proc_net = proc_mkdir("net", 0);
#ifdef CONFIG_SYSVIPC
- create_proc_entry("sysvipc", S_IFDIR, 0);
+ proc_mkdir("sysvipc", 0);
#endif
#ifdef CONFIG_SYSCTL
- proc_sys_root = create_proc_entry("sys", S_IFDIR, 0);
+ proc_sys_root = proc_mkdir("sys", 0);
#endif
-#ifdef CONFIG_MCA
- proc_mca = create_proc_entry("mca", S_IFDIR, 0);
-#endif
- proc_root_fs = create_proc_entry("fs", S_IFDIR, 0);
- proc_root_driver = create_proc_entry("driver", S_IFDIR, 0);
+ proc_root_fs = proc_mkdir("fs", 0);
+ proc_root_driver = proc_mkdir("driver", 0);
#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
#ifdef CONFIG_SUN_OPENPROMFS
openpromfs_init ();
#endif
- proc_register(&proc_root, &proc_openprom);
+ /* just give it a mountpoint */
+ proc_mkdir("openprom", 0);
#endif
proc_tty_init();
#ifdef __powerpc__
@@ -469,63 +86,7 @@ void __init proc_root_init(void)
#ifdef CONFIG_PROC_DEVICETREE
proc_device_tree_init();
#endif
- proc_bus = create_proc_entry("bus", S_IFDIR, 0);
-}
-
-/*
- * As some entries in /proc are volatile, we want to
- * get rid of unused dentries. This could be made
- * smarter: we could keep a "volatile" flag in the
- * inode to indicate which ones to keep.
- */
-static void
-proc_delete_dentry(struct dentry * dentry)
-{
- d_drop(dentry);
-}
-
-struct dentry_operations proc_dentry_operations =
-{
- NULL, /* revalidate */
- NULL, /* d_hash */
- NULL, /* d_compare */
- proc_delete_dentry /* d_delete(struct dentry *) */
-};
-
-/*
- * Don't create negative dentries here, return -ENOENT by hand
- * instead.
- */
-struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
-{
- struct inode *inode;
- struct proc_dir_entry * de;
- int error;
-
- error = -ENOENT;
- inode = NULL;
- de = (struct proc_dir_entry *) dir->u.generic_ip;
- if (de) {
- for (de = de->subdir; de ; de = de->next) {
- if (!de || !de->low_ino)
- continue;
- if (de->namelen != dentry->d_name.len)
- continue;
- if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
- int ino = de->low_ino;
- error = -EINVAL;
- inode = proc_get_inode(dir->i_sb, ino, de);
- break;
- }
- }
- }
-
- if (inode) {
- dentry->d_op = &proc_dentry_operations;
- d_add(dentry, inode);
- return NULL;
- }
- return ERR_PTR(error);
+ proc_bus = proc_mkdir("bus", 0);
}
static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry)
@@ -564,63 +125,6 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
return proc_pid_lookup(dir, dentry);
}
-/*
- * This returns non-zero if at EOF, so that the /proc
- * root directory can use this and check if it should
- * continue with the <pid> entries..
- *
- * Note that the VFS-layer doesn't care about the return
- * value of the readdir() call, as long as it's non-negative
- * for success..
- */
-int proc_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
-{
- struct proc_dir_entry * de;
- unsigned int ino;
- int i;
- struct inode *inode = filp->f_dentry->d_inode;
-
- ino = inode->i_ino;
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- if (!de)
- return -EINVAL;
- i = filp->f_pos;
- switch (i) {
- case 0:
- if (filldir(dirent, ".", 1, i, ino) < 0)
- return 0;
- i++;
- filp->f_pos++;
- /* fall through */
- case 1:
- if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
- return 0;
- i++;
- filp->f_pos++;
- /* fall through */
- default:
- de = de->subdir;
- i -= 2;
- for (;;) {
- if (!de)
- return 1;
- if (!i)
- break;
- de = de->next;
- i--;
- }
-
- do {
- if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
- return 0;
- filp->f_pos++;
- de = de->next;
- } while (de);
- }
- return 1;
-}
-
static int proc_root_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
@@ -636,14 +140,35 @@ static int proc_root_readdir(struct file * filp,
return proc_pid_readdir(filp, dirent, filldir);
}
-static int proc_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct proc_dir_entry * dp = dir->u.generic_ip;
+/*
+ * The root /proc directory is special, as it has the
+ * <pid> directories. Thus we don't use the generic
+ * directory handling functions for that..
+ */
+static struct file_operations proc_root_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ proc_root_readdir, /* readdir */
+};
-printk("proc_file_unlink: deleting %s/%s\n", dp->name, dentry->d_name.name);
+/*
+ * proc root can do almost nothing..
+ */
+static struct inode_operations proc_root_inode_operations = {
+ &proc_root_operations, /* default base directory file-ops */
+ NULL, /* create */
+ proc_root_lookup, /* lookup */
+};
- remove_proc_entry(dentry->d_name.name, dp);
- dentry->d_inode->i_nlink = 0;
- d_delete(dentry);
- return 0;
-}
+/*
+ * This is the root "inode" in the /proc tree..
+ */
+struct proc_dir_entry proc_root = {
+ PROC_ROOT_INO, 5, "/proc",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+ 0, &proc_root_inode_operations,
+ NULL, NULL,
+ NULL,
+ &proc_root, NULL
+};