From 0ae8dceaebe3659ee0c3352c08125f403e77ebca Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 28 Sep 1999 22:25:29 +0000 Subject: Merge with 2.3.10. --- fs/proc/fd.c | 7 +++---- fs/proc/inode.c | 24 ++++++++++++++++++++++-- fs/proc/link.c | 7 +++++++ fs/proc/root.c | 48 ++++++++++++++++++++++++++++++------------------ 4 files changed, 62 insertions(+), 24 deletions(-) (limited to 'fs/proc') 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(); } } -- cgit v1.2.3