summaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
commit53b3988d474435254a3b053a68bb24ce9e439295 (patch)
treef8da8e40f01f4ad02bbd76b8c9920749b118235f /fs/proc
parentb0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff)
Merge with 2.3.99-pre9.
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c70
-rw-r--r--fs/proc/generic.c11
-rw-r--r--fs/proc/kcore.c17
-rw-r--r--fs/proc/proc_devtree.c1
-rw-r--r--fs/proc/root.c29
5 files changed, 77 insertions, 51 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 2e83c6a4e..d513987d8 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -22,6 +22,7 @@
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/file.h>
+#include <linux/string.h>
/*
* For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -651,6 +652,11 @@ static int pid_fd_revalidate(struct dentry * dentry, int flags)
return 0;
}
+/*
+ * Exceptional case: normally we are not allowed to unhash a busy
+ * directory. In this case, however, we can do it - no aliasing problems
+ * due to the way we treat inodes.
+ */
static int pid_base_revalidate(struct dentry * dentry, int flags)
{
if (dentry->d_inode->u.proc_i.task->p_pptr)
@@ -659,9 +665,9 @@ static int pid_base_revalidate(struct dentry * dentry, int flags)
return 0;
}
-static void pid_delete_dentry(struct dentry * dentry)
+static int pid_delete_dentry(struct dentry * dentry)
{
- d_drop(dentry);
+ return 1;
}
static struct dentry_operations pid_fd_dentry_operations =
@@ -861,6 +867,28 @@ static struct inode_operations proc_base_inode_operations = {
lookup: proc_base_lookup,
};
+/*
+ * /proc/self:
+ */
+static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ char tmp[30];
+ sprintf(tmp, "%d", current->pid);
+ return vfs_readlink(dentry,buffer,buflen,tmp);
+}
+
+static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ char tmp[30];
+ sprintf(tmp, "%d", current->pid);
+ return vfs_follow_link(nd,tmp);
+}
+
+static struct inode_operations proc_self_inode_operations = {
+ readlink: proc_self_readlink,
+ follow_link: proc_self_follow_link,
+};
+
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
{
unsigned int pid, c;
@@ -872,6 +900,23 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
pid = 0;
name = dentry->d_name.name;
len = dentry->d_name.len;
+ if (len == 4 && !memcmp(name, "self", 4)) {
+ inode = get_empty_inode();
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+ inode->i_sb = dir->i_sb;
+ inode->i_dev = dir->i_sb->s_dev;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ inode->i_ino = fake_ino(0, PROC_PID_INO);
+ inode->u.proc_i.file = NULL;
+ inode->u.proc_i.task = NULL;
+ inode->i_mode = S_IFLNK|S_IRWXUGO;
+ inode->i_uid = inode->i_gid = 0;
+ inode->i_size = 64;
+ inode->i_op = &proc_self_inode_operations;
+ d_add(dentry, inode);
+ return NULL;
+ }
while (len-- > 0) {
c = *name - '0';
name++;
@@ -916,7 +961,8 @@ void proc_pid_delete_inode(struct inode *inode)
{
if (inode->u.proc_i.file)
fput(inode->u.proc_i.file);
- free_task_struct(inode->u.proc_i.task);
+ if (inode->u.proc_i.task)
+ free_task_struct(inode->u.proc_i.task);
}
#define PROC_NUMBUF 10
@@ -932,7 +978,7 @@ static int get_pid_list(int index, unsigned int *pids)
struct task_struct *p;
int nr_pids = 0;
- index -= FIRST_PROCESS_ENTRY;
+ index--;
read_lock(&tasklist_lock);
for_each_task(p) {
int pid = p->pid;
@@ -953,9 +999,17 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
unsigned int pid_array[PROC_MAXPIDS];
char buf[PROC_NUMBUF];
- unsigned int nr = filp->f_pos;
+ unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
unsigned int nr_pids, i;
+ if (!nr) {
+ ino_t ino = fake_ino(0,PROC_PID_INO);
+ if (filldir(dirent, "self", 4, filp->f_pos, ino) < 0)
+ return 0;
+ filp->f_pos++;
+ nr++;
+ }
+
nr_pids = get_pid_list(nr, pid_array);
for (i = 0; i < nr_pids; i++) {
@@ -963,11 +1017,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
ino_t ino = fake_ino(pid,PROC_PID_INO);
unsigned long j = PROC_NUMBUF;
- do {
- j--;
- buf[j] = '0' + (pid % 10);
- pid /= 10;
- } while (pid);
+ do buf[--j] = '0' + (pid % 10); while (pid/=10);
if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0)
break;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 31e43fab9..1585657a2 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -140,9 +140,13 @@ proc_file_lseek(struct file * file, loff_t offset, int orig)
{
switch (orig) {
case 0:
+ if (offset < 0)
+ return -EINVAL;
file->f_pos = offset;
return(file->f_pos);
case 1:
+ if (offset + file->f_pos < 0)
+ return -EINVAL;
file->f_pos += offset;
return(file->f_pos);
case 2:
@@ -218,10 +222,9 @@ static struct inode_operations proc_link_inode_operations = {
* smarter: we could keep a "volatile" flag in the
* inode to indicate which ones to keep.
*/
-static void
-proc_delete_dentry(struct dentry * dentry)
+static int proc_delete_dentry(struct dentry * dentry)
{
- d_drop(dentry);
+ return 1;
}
static struct dentry_operations proc_dentry_operations =
@@ -340,7 +343,7 @@ static struct inode_operations proc_dir_inode_operations = {
lookup: proc_lookup,
};
-int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
+static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
int i;
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 13ec76b02..01db469da 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -315,13 +315,12 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t
size_t elf_buflen;
int num_vma;
- /* XXX we need to somehow lock vmlist between here
- * and after elf_kcore_store_hdr() returns.
- * For now assume that num_vma does not change (TA)
- */
+ read_lock(&vmlist_lock);
proc_root_kcore->size = size = get_kcore_size(&num_vma, &elf_buflen);
- if (buflen == 0 || *fpos >= size)
+ if (buflen == 0 || *fpos >= size) {
+ read_unlock(&vmlist_lock);
return 0;
+ }
/* trim buflen to not go beyond EOF */
if (buflen > size - *fpos)
@@ -335,10 +334,13 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t
if (buflen < tsz)
tsz = buflen;
elf_buf = kmalloc(elf_buflen, GFP_ATOMIC);
- if (!elf_buf)
+ if (!elf_buf) {
+ read_unlock(&vmlist_lock);
return -ENOMEM;
+ }
memset(elf_buf, 0, elf_buflen);
elf_kcore_store_hdr(elf_buf, num_vma, elf_buflen);
+ read_unlock(&vmlist_lock);
if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
kfree(elf_buf);
return -EFAULT;
@@ -352,7 +354,8 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t
/* leave now if filled buffer already */
if (buflen == 0)
return acc;
- }
+ } else
+ read_unlock(&vmlist_lock);
/* where page 0 not mapped, write zeros into buffer */
#if defined (__i386__) || defined (__mc68000__)
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 88d41c3c2..c64166f78 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -112,7 +112,6 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
al = proc_symlink(at, de, ent->name);
if (al == 0)
break;
- proc_register(de, al);
*lastp = al;
lastp = &al->next;
}
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 8088d064d..075a5843d 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -22,38 +22,9 @@ struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
struct proc_dir_entry *proc_sys_root;
#endif
-/*
- * /proc/self:
- */
-static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- char tmp[30];
- sprintf(tmp, "%d", current->pid);
- return vfs_readlink(dentry,buffer,buflen,tmp);
-}
-
-static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- char tmp[30];
- sprintf(tmp, "%d", current->pid);
- return vfs_follow_link(nd,tmp);
-}
-
-static struct inode_operations proc_self_inode_operations = {
- readlink: proc_self_readlink,
- follow_link: proc_self_follow_link
-};
-
-static struct proc_dir_entry proc_root_self = {
- 0, 4, "self",
- S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
- 64, &proc_self_inode_operations,
-};
-
void __init proc_root_init(void)
{
proc_misc_init();
- proc_register(&proc_root, &proc_root_self);
proc_net = proc_mkdir("net", 0);
#ifdef CONFIG_SYSVIPC
proc_mkdir("sysvipc", 0);