patch-2.3.99-pre4 linux/fs/open.c

Next file: linux/fs/partitions/Config.in
Previous file: linux/fs/ntfs/fs.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre3/linux/fs/open.c linux/fs/open.c
@@ -141,11 +141,8 @@
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = -ENOENT;
-	if (!(dentry = file->f_dentry))
-		goto out_putf;
-	if (!(inode = dentry->d_inode))
-		goto out_putf;
+	dentry = file->f_dentry;
+	inode = dentry->d_inode;
 	error = -EACCES;
 	if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
 		goto out_putf;
@@ -330,35 +327,41 @@
 	return res;
 }
 
+/* MOUNT_REWRITE: pass &mnt to lookup_dentry */
 asmlinkage long sys_chdir(const char * filename)
 {
 	int error;
-	struct inode *inode;
 	struct dentry *dentry, *tmp;
+	struct vfsmount *mnt = NULL, *tmp_mnt;
+	char *name;
 
 	lock_kernel();
 	
-	dentry = namei(filename);
+	name = getname(filename);
+	error = PTR_ERR(name);
+	if (IS_ERR(name))
+		goto out;
+
+	dentry = lookup_dentry(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW | LOOKUP_DIRECTORY);
+	putname(name);
 	error = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
 		goto out;
 
-	inode = dentry->d_inode;
-
-	error = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
-		goto dput_and_out;
-
-	error = permission(inode,MAY_EXEC);
+	error = permission(dentry->d_inode,MAY_EXEC);
 	if (error)
 		goto dput_and_out;
 
 	/* exchange dentries */
 	tmp = current->fs->pwd;
+	tmp_mnt = current->fs->pwdmnt;
 	current->fs->pwd = dentry;
+	current->fs->pwdmnt = mnt;
 	dentry = tmp;
+	mnt = tmp_mnt;
 
 dput_and_out:
+	mntput(mnt);
 	dput(dentry);
 out:
 	unlock_kernel();
@@ -370,6 +373,7 @@
 	struct file *file;
 	struct dentry *dentry;
 	struct inode *inode;
+	struct vfsmount *mnt;
 	int error;
 
 	error = -EBADF;
@@ -377,11 +381,9 @@
 	if (!file)
 		goto out;
 
-	error = -ENOENT;
-	if (!(dentry = file->f_dentry))
-		goto out_putf;
-	if (!(inode = dentry->d_inode))
-		goto out_putf;
+	dentry = file->f_dentry;
+	mnt = file->f_vfsmnt;
+	inode = dentry->d_inode;
 
 	error = -ENOTDIR;
 	if (!S_ISDIR(inode->i_mode))
@@ -391,7 +393,10 @@
 	error = permission(inode, MAY_EXEC);
 	if (!error) {
 		struct dentry *tmp = current->fs->pwd;
+		struct vfsmount *tmp_mnt = current->fs->pwdmnt;
 		current->fs->pwd = dget(dentry);
+		current->fs->pwdmnt = mntget(mnt);
+		mntput(tmp_mnt);
 		dput(tmp);
 	}
 	unlock_kernel();
@@ -401,26 +406,28 @@
 	return error;
 }
 
+/* MOUNT_REWRITE: pass &mnt to lookup_dentry */
 asmlinkage long sys_chroot(const char * filename)
 {
 	int error;
-	struct inode *inode;
 	struct dentry *dentry, *tmp;
+	struct vfsmount *mnt = NULL, *tmp_mnt;
+	char *name;
 
 	lock_kernel();
 	
-	dentry = namei(filename);
+	name = getname(filename);
+	error = PTR_ERR(name);
+	if (IS_ERR(name))
+		goto out;
+
+	dentry = lookup_dentry(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW | LOOKUP_DIRECTORY);
+	putname(name);
 	error = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
 		goto out;
 
-	inode = dentry->d_inode;
-
-	error = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
-		goto dput_and_out;
-
-	error = permission(inode,MAY_EXEC);
+	error = permission(dentry->d_inode,MAY_EXEC);
 	if (error)
 		goto dput_and_out;
 
@@ -430,11 +437,15 @@
 
 	/* exchange dentries */
 	tmp = current->fs->root;
+	tmp_mnt = current->fs->rootmnt;
 	current->fs->root = dentry;
+	current->fs->rootmnt = mnt;
 	dentry = tmp;
+	mnt = tmp_mnt;
 	error = 0;
 
 dput_and_out:
+	mntput(mnt);
 	dput(dentry);
 out:
 	unlock_kernel();
@@ -453,11 +464,8 @@
 	if (!file)
 		goto out;
 
-	err = -ENOENT;
-	if (!(dentry = file->f_dentry))
-		goto out_putf;
-	if (!(inode = dentry->d_inode))
-		goto out_putf;
+	dentry = file->f_dentry;
+	inode = dentry->d_inode;
 
 	err = -EROFS;
 	if (IS_RDONLY(inode))
@@ -612,20 +620,16 @@
 
 asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
 {
-	struct dentry * dentry;
 	struct file * file;
 	int error = -EBADF;
 
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = -ENOENT;
 	lock_kernel();
-	if ((dentry = file->f_dentry) != NULL)
-		error = chown_common(dentry, user, group);
+	error = chown_common(file->f_dentry, user, group);
 	unlock_kernel();
 	fput(file);
-
 out:
 	return error;
 }
@@ -644,26 +648,25 @@
  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  * used by symlinks.
  */
-struct file *filp_open(const char * filename, int flags, int mode, struct dentry * base)
+struct file *filp_open(const char * filename, int flags, int mode)
 {
-	struct dentry * dentry;
-	int flag,error;
+	int namei_flags, error;
+	struct nameidata nd;
 
-	flag = flags;
-	if ((flag+1) & O_ACCMODE)
-		flag++;
-	if (flag & O_TRUNC)
-		flag |= 2;
+	namei_flags = flags;
+	if ((namei_flags+1) & O_ACCMODE)
+		namei_flags++;
+	if (namei_flags & O_TRUNC)
+		namei_flags |= 2;
 
-	dentry = __open_namei(filename, flag, mode, base);
-	error = PTR_ERR(dentry);
-	if (!IS_ERR(dentry))
-		return dentry_open(dentry, flags);
+	error = open_namei(filename, namei_flags, mode, &nd);
+	if (!error)
+		return dentry_open(nd.dentry, nd.mnt, flags);
 
 	return ERR_PTR(error);
 }
 
-struct file *dentry_open(struct dentry *dentry, int flags)
+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
 {
 	struct file * f;
 	struct inode *inode;
@@ -679,15 +682,14 @@
 	if (f->f_mode & FMODE_WRITE) {
 		error = get_write_access(inode);
 		if (error)
-			goto cleanup_dentry;
+			goto cleanup_file;
 	}
 
 	f->f_dentry = dentry;
+	f->f_vfsmnt = mnt;
 	f->f_pos = 0;
 	f->f_reada = 0;
-	f->f_op = NULL;
-	if (inode->i_op)
-		f->f_op = inode->i_fop;
+	f->f_op = inode->i_fop;
 	if (inode->i_sb)
 		file_move(f, &inode->i_sb->s_files);
 	if (f->f_op && f->f_op->open) {
@@ -703,9 +705,12 @@
 	if (f->f_mode & FMODE_WRITE)
 		put_write_access(inode);
 	f->f_dentry = NULL;
+	f->f_vfsmnt = NULL;
+cleanup_file:
+	put_filp(f);
 cleanup_dentry:
 	dput(dentry);
-	put_filp(f);
+	mntput(mnt);
 	return ERR_PTR(error);
 }
 
@@ -795,7 +800,7 @@
 		if (fd >= 0) {
 			struct file * f;
 			lock_kernel();
-			f = filp_open(tmp, flags, mode, NULL);
+			f = filp_open(tmp, flags, mode);
 			unlock_kernel();
 			error = PTR_ERR(f);
 			if (IS_ERR(f))
@@ -833,7 +838,6 @@
 int filp_close(struct file *filp, fl_owner_t id)
 {
 	int retval;
-	struct dentry *dentry = filp->f_dentry;
 
 	if (!file_count(filp)) {
 		printk("VFS: Close: file count is 0\n");
@@ -842,8 +846,7 @@
 	retval = 0;
 	if (filp->f_op && filp->f_op->flush)
 		retval = filp->f_op->flush(filp);
-	if (dentry->d_inode)
-		locks_remove_posix(filp, id);
+	locks_remove_posix(filp, id);
 	fput(filp);
 	return retval;
 }

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