summaryrefslogtreecommitdiffstats
path: root/fs/proc/root.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/root.c')
-rw-r--r--fs/proc/root.c563
1 files changed, 44 insertions, 519 deletions
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
+};