patch-2.3.99-pre4 linux/fs/proc/base.c

Next file: linux/fs/proc/generic.c
Previous file: linux/fs/proc/array.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre3/linux/fs/proc/base.c linux/fs/proc/base.c
@@ -38,22 +38,28 @@
 int proc_pid_statm(struct task_struct*,char*);
 int proc_pid_cpu(struct task_struct*,char*);
 
-static struct dentry *proc_fd_link(struct inode *inode)
+/* MOUNT_REWRITE: make all files have non-NULL ->f_vfsmnt (pipefs, sockfs) */
+static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-	if (inode->u.proc_i.file)
-		return dget(inode->u.proc_i.file->f_dentry);
-	return NULL;
+	if (inode->u.proc_i.file) {
+		if (inode->u.proc_i.file->f_vfsmnt) {
+			*mnt = mntget(inode->u.proc_i.file->f_vfsmnt);
+		}
+		*dentry = dget(inode->u.proc_i.file->f_dentry);
+		return 0;
+	}
+	return -ENOENT;
 }
 
-static struct dentry *proc_exe_link(struct inode *inode)
+static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
 	struct mm_struct * mm;
 	struct vm_area_struct * vma;
-	struct dentry *result = NULL;
+	int result = -ENOENT;
 	struct task_struct *task = inode->u.proc_i.task;
 
 	if (!task_lock(task))
-		return NULL;
+		return result;
 	mm = task->mm;
 	if (!mm)
 		goto out;
@@ -62,7 +68,9 @@
 	while (vma) {
 		if ((vma->vm_flags & VM_EXECUTABLE) && 
 		    vma->vm_file) {
-			result = dget(vma->vm_file->f_dentry);
+			*mnt = mntget(vma->vm_file->f_vfsmnt);
+			*dentry = dget(vma->vm_file->f_dentry);
+			result = 0;
 			break;
 		}
 		vma = vma->vm_next;
@@ -73,25 +81,31 @@
 	return result;
 }
 
-static struct dentry *proc_cwd_link(struct inode *inode)
+static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-	struct dentry *result = NULL;
+	int result = -ENOENT;
 	if (task_lock(inode->u.proc_i.task)) {
 		struct fs_struct *fs = inode->u.proc_i.task->fs;
-		if (fs)
-			result = dget(fs->pwd);
+		if (fs) {
+			*mnt = mntget(fs->pwdmnt);
+			*dentry = dget(fs->pwd);
+			result = 0;
+		}
 		task_unlock(inode->u.proc_i.task);
 	}
 	return result;
 }
 
-static struct dentry *proc_root_link(struct inode *inode)
+static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-	struct dentry *result = NULL;
+	int result = -ENOENT;
 	if (task_lock(inode->u.proc_i.task)) {
 		struct fs_struct *fs = inode->u.proc_i.task->fs;
-		if (fs)
-			result = dget(fs->root);
+		if (fs) {
+			*mnt = mntget(fs->rootmnt);
+			*dentry = dget(fs->root);
+			result = 0;
+		}
 		task_unlock(inode->u.proc_i.task);
 	}
 	return result;
@@ -160,16 +174,18 @@
 {
 	struct dentry *de, *base, *root;
 	struct super_block *our_sb, *sb, *below;
+	struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
 
 	if (standard_permission(inode, mask) != 0)
 		return -EACCES;
 
 	base = current->fs->root;
-	de = root = proc_root_link(inode); /* Ewww... */
-
-	if (!de)
+	our_vfsmnt = current->fs->rootmnt;
+	if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
 		return -ENOENT;
 
+	de = root;
+	mnt = vfsmnt;
 	our_sb = base->d_inode->i_sb;
 	sb = de->d_inode->i_sb;
 	while (sb != our_sb) {
@@ -184,9 +200,11 @@
 		goto out;
 
 	dput(root);
+	mntput(mnt);
 	return 0;
 out:
 	dput(root);
+	mntput(mnt);
 	return -EACCES;
 }
 
@@ -345,30 +363,26 @@
 	permission:	proc_permission,
 };
 
-static struct dentry * proc_pid_follow_link(struct dentry *dentry,
-					struct dentry *base,
-					unsigned int follow)
+static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
-	struct dentry * result;
 	int error;
 
 	/* We don't need a base pointer in the /proc filesystem */
-	dput(base);
+	dput(nd->dentry);
+	mntput(nd->mnt);
 
 	error = proc_permission(inode, MAY_EXEC);
-	result = ERR_PTR(error);
 	if (error)
 		goto out;
 
-	result = inode->u.proc_i.op.proc_get_link(inode);
+	error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
 out:
-	if (!result)
-		result = ERR_PTR(-ENOENT);
-	return result;
+	return error;
 }
 
-static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
+static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt,
+			    char * buffer, int buflen)
 {
 	struct inode * inode;
 	char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
@@ -391,7 +405,7 @@
 		len = sprintf(tmp, pattern, inode->i_ino);
 		path = tmp;
 	} else {
-		path = d_path(dentry, tmp, PAGE_SIZE);
+		path = d_path(dentry, mnt, tmp, PAGE_SIZE);
 		len = tmp + PAGE_SIZE - 1 - path;
 	}
 
@@ -406,22 +420,19 @@
 {
 	int error;
 	struct inode *inode = dentry->d_inode;
+	struct vfsmount *mnt;
 
 	error = proc_permission(inode, MAY_EXEC);
 	if (error)
 		goto out;
 
-	dentry = inode->u.proc_i.op.proc_get_link(inode);
-	error = -ENOENT;
-	if (!dentry)
-		goto out;
-
-	error = PTR_ERR(dentry);
-	if (IS_ERR(dentry))
+	error = inode->u.proc_i.op.proc_get_link(inode, &dentry, &mnt);
+	if (error)
 		goto out;
 
-	error = do_proc_readlink(dentry, buffer, buflen);
+	error = do_proc_readlink(dentry, mnt, buffer, buflen);
 	dput(dentry);
+	mntput(mnt);
 out:
 	return error;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)