summaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
commit0ae8dceaebe3659ee0c3352c08125f403e77ebca (patch)
tree5085c389f09da78182b899d19fe1068b619a69dd /fs/proc
parent273767781288c35c9d679e908672b9996cda4c34 (diff)
Merge with 2.3.10.
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/fd.c7
-rw-r--r--fs/proc/inode.c24
-rw-r--r--fs/proc/link.c7
-rw-r--r--fs/proc/root.c48
4 files changed, 62 insertions, 24 deletions
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index a900d01bf..195ca41b8 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -104,7 +104,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
read_lock(&tasklist_lock);
file = NULL;
p = find_task_by_pid(pid);
- if (p)
+ if (p && p->files)
file = fcheck_task(p, fd);
read_unlock(&tasklist_lock);
@@ -114,7 +114,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
* is NULL
*/
- if (!file || !file->f_dentry)
+ if (!file)
goto out;
ino = (pid << 16) + PROC_PID_FD_DIR + fd;
@@ -161,10 +161,9 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++)
{
- struct file * file = fcheck_task(p, fd);
unsigned int i,j;
- if (!file || !file->f_dentry)
+ if (!fcheck_task(p, fd))
continue;
j = NUMBUF;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 970e63a96..a5596e4ee 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -87,13 +87,26 @@ static void proc_delete_inode(struct inode *inode)
}
}
+struct super_block *proc_super_blocks = NULL;
+
+static void proc_put_super(struct super_block *sb)
+{
+ struct super_block **p = &proc_super_blocks;
+ while (*p != sb) {
+ if (!*p) /* should never happen */
+ return;
+ p = (struct super_block **)&(*p)->u.generic_sbp;
+ }
+ *p = (struct super_block *)(*p)->u.generic_sbp;
+}
+
static struct super_operations proc_sops = {
proc_read_inode,
proc_write_inode,
proc_put_inode,
proc_delete_inode, /* delete_inode(struct inode *) */
NULL,
- NULL,
+ proc_put_super,
NULL,
proc_statfs,
NULL
@@ -323,6 +336,8 @@ struct super_block *proc_read_super(struct super_block *s,void *data,
if (!s->s_root)
goto out_no_root;
parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
+ s->u.generic_sbp = (void*) proc_super_blocks;
+ proc_super_blocks = s;
unlock_super(s);
return s;
@@ -385,9 +400,12 @@ void proc_read_inode(struct inode * inode)
if (ino & PROC_PID_FD_DIR) {
struct file * file;
ino &= 0x7fff;
+ if (!p->files) /* can we ever get here if that's the case? */
+ goto out_unlock;
+ read_lock(&p->files->file_lock);
file = fcheck_task(p, ino);
if (!file)
- goto out_unlock;
+ goto out_unlock2;
inode->i_op = &proc_link_inode_operations;
inode->i_size = 64;
@@ -396,6 +414,8 @@ void proc_read_inode(struct inode * inode)
inode->i_mode |= S_IRUSR | S_IXUSR;
if (file->f_mode & 2)
inode->i_mode |= S_IWUSR | S_IXUSR;
+out_unlock2:
+ read_unlock(&p->files->file_lock);
}
out_unlock:
/* Defer unlocking until we're done with the task */
diff --git a/fs/proc/link.c b/fs/proc/link.c
index 647dc339f..6f5c63ec3 100644
--- a/fs/proc/link.c
+++ b/fs/proc/link.c
@@ -119,10 +119,14 @@ static struct dentry * proc_follow_link(struct dentry *dentry,
if (ino & PROC_PID_FD_DIR) {
struct file * file;
ino &= 0x7fff;
+ if (!p->files) /* shouldn't happen here */
+ goto out_unlock;
+ read_lock(&p->files->file_lock);
file = fcheck_task(p, ino);
if (!file || !file->f_dentry)
goto out_unlock;
result = file->f_dentry;
+ read_unlock(&p->files->file_lock);
goto out_dget;
}
}
@@ -146,6 +150,9 @@ static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
int len;
+ if(tmp==NULL)
+ return -ENOMEM;
+
/* Check for special dentries.. */
pattern = NULL;
inode = dentry->d_inode;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index d08860c26..df3c0b049 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -365,24 +365,36 @@ int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
*/
static void proc_kill_inodes(int ino)
{
- struct file *filp;
-
- /* inuse_filps is protected by the single kernel lock */
- for (filp = inuse_filps; filp; filp = filp->f_next) {
- 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;
+ 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();
}
}