mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	procfs: switch /proc/self away from proc_dir_entry
Just have it pinned in dcache all along and let procfs ->kill_sb() drop it before kill_anon_super(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									0ecc833bac
								
							
						
					
					
						commit
						021ada7dff
					
				
					 6 changed files with 56 additions and 12 deletions
				
			
		|  | @ -2794,7 +2794,7 @@ static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter ite | ||||||
| 	return iter; | 	return iter; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define TGID_OFFSET (FIRST_PROCESS_ENTRY) | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1) | ||||||
| 
 | 
 | ||||||
| static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | ||||||
| 	struct tgid_iter iter) | 	struct tgid_iter iter) | ||||||
|  | @ -2817,13 +2817,21 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||||||
| 	struct tgid_iter iter; | 	struct tgid_iter iter; | ||||||
| 	struct pid_namespace *ns; | 	struct pid_namespace *ns; | ||||||
| 	filldir_t __filldir; | 	filldir_t __filldir; | ||||||
|  | 	loff_t pos = filp->f_pos; | ||||||
| 
 | 
 | ||||||
| 	if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) | 	if (pos >= PID_MAX_LIMIT + TGID_OFFSET) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	ns = filp->f_dentry->d_sb->s_fs_info; | 	if (pos == TGID_OFFSET - 1) { | ||||||
|  | 		if (proc_fill_cache(filp, dirent, filldir, "self", 4, | ||||||
|  | 					NULL, NULL, NULL) < 0) | ||||||
|  | 			goto out; | ||||||
|  | 		iter.tgid = 0; | ||||||
|  | 	} else { | ||||||
|  | 		iter.tgid = pos - TGID_OFFSET; | ||||||
|  | 	} | ||||||
| 	iter.task = NULL; | 	iter.task = NULL; | ||||||
| 	iter.tgid = filp->f_pos - TGID_OFFSET; | 	ns = filp->f_dentry->d_sb->s_fs_info; | ||||||
| 	for (iter = next_tgid(ns, iter); | 	for (iter = next_tgid(ns, iter); | ||||||
| 	     iter.task; | 	     iter.task; | ||||||
| 	     iter.tgid += 1, iter = next_tgid(ns, iter)) { | 	     iter.tgid += 1, iter = next_tgid(ns, iter)) { | ||||||
|  |  | ||||||
|  | @ -506,5 +506,5 @@ int proc_fill_super(struct super_block *s) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return proc_setup_self(s); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -205,3 +205,4 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr); | ||||||
| extern const struct inode_operations proc_ns_dir_inode_operations; | extern const struct inode_operations proc_ns_dir_inode_operations; | ||||||
| extern const struct file_operations proc_ns_dir_operations; | extern const struct file_operations proc_ns_dir_operations; | ||||||
| 
 | 
 | ||||||
|  | extern int proc_setup_self(struct super_block *); | ||||||
|  |  | ||||||
|  | @ -137,6 +137,8 @@ static void proc_kill_sb(struct super_block *sb) | ||||||
| 	struct pid_namespace *ns; | 	struct pid_namespace *ns; | ||||||
| 
 | 
 | ||||||
| 	ns = (struct pid_namespace *)sb->s_fs_info; | 	ns = (struct pid_namespace *)sb->s_fs_info; | ||||||
|  | 	if (ns->proc_self) | ||||||
|  | 		dput(ns->proc_self); | ||||||
| 	kill_anon_super(sb); | 	kill_anon_super(sb); | ||||||
| 	put_pid_ns(ns); | 	put_pid_ns(ns); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include <linux/proc_fs.h> |  | ||||||
| #include <linux/sched.h> | #include <linux/sched.h> | ||||||
| #include <linux/namei.h> | #include <linux/namei.h> | ||||||
|  | #include <linux/pid_namespace.h> | ||||||
|  | #include "internal.h" | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * /proc/self: |  * /proc/self: | ||||||
|  | @ -48,12 +49,43 @@ static const struct inode_operations proc_self_inode_operations = { | ||||||
| 	.put_link	= proc_self_put_link, | 	.put_link	= proc_self_put_link, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static unsigned self_inum; | ||||||
|  | 
 | ||||||
|  | int proc_setup_self(struct super_block *s) | ||||||
|  | { | ||||||
|  | 	struct inode *root_inode = s->s_root->d_inode; | ||||||
|  | 	struct pid_namespace *ns = s->s_fs_info; | ||||||
|  | 	struct dentry *self; | ||||||
|  | 	 | ||||||
|  | 	mutex_lock(&root_inode->i_mutex); | ||||||
|  | 	self = d_alloc_name(s->s_root, "self"); | ||||||
|  | 	if (self) { | ||||||
|  | 		struct inode *inode = new_inode_pseudo(s); | ||||||
|  | 		if (inode) { | ||||||
|  | 			inode->i_ino = self_inum; | ||||||
|  | 			inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||||||
|  | 			inode->i_mode = S_IFLNK | S_IRWXUGO; | ||||||
|  | 			inode->i_uid = GLOBAL_ROOT_UID; | ||||||
|  | 			inode->i_gid = GLOBAL_ROOT_GID; | ||||||
|  | 			inode->i_op = &proc_self_inode_operations; | ||||||
|  | 			d_add(self, inode); | ||||||
|  | 		} else { | ||||||
|  | 			dput(self); | ||||||
|  | 			self = ERR_PTR(-ENOMEM); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		self = ERR_PTR(-ENOMEM); | ||||||
|  | 	} | ||||||
|  | 	mutex_unlock(&root_inode->i_mutex); | ||||||
|  | 	if (IS_ERR(self)) { | ||||||
|  | 		pr_err("proc_fill_super: can't allocate /proc/self\n"); | ||||||
|  | 		return PTR_ERR(self); | ||||||
|  | 	} | ||||||
|  | 	ns->proc_self = self; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void __init proc_self_init(void) | void __init proc_self_init(void) | ||||||
| { | { | ||||||
| 	struct proc_dir_entry *proc_self_symlink; | 	proc_alloc_inum(&self_inum); | ||||||
| 	umode_t mode; |  | ||||||
| 
 |  | ||||||
| 	mode = S_IFLNK | S_IRWXUGO; |  | ||||||
| 	proc_self_symlink = proc_create("self", mode, NULL, NULL ); |  | ||||||
| 	proc_self_symlink->proc_iops = &proc_self_inode_operations; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ struct pid_namespace { | ||||||
| 	struct pid_namespace *parent; | 	struct pid_namespace *parent; | ||||||
| #ifdef CONFIG_PROC_FS | #ifdef CONFIG_PROC_FS | ||||||
| 	struct vfsmount *proc_mnt; | 	struct vfsmount *proc_mnt; | ||||||
|  | 	struct dentry *proc_self; | ||||||
| #endif | #endif | ||||||
| #ifdef CONFIG_BSD_PROCESS_ACCT | #ifdef CONFIG_BSD_PROCESS_ACCT | ||||||
| 	struct bsd_acct_struct *bacct; | 	struct bsd_acct_struct *bacct; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Al Viro
						Al Viro