[RFC] Allow open intents to return a fully initialized file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following patch is to allow filesystems that support the lookup with
open intents optimization to return a fully initialized file pointer.

The main use for this is stuff like NFSv4 that does lookup + sets up
open state in a single atomic RPC call, and that wishes to cache the
state information in the struct file. Currently, the filesystem has to
save that state information, then hunt round for it in the open
file_operation (something which is race prone, and doesn't allow one to
clean up the mess if the VFS aborts the open before calling down to the
filesystem again).

The NFSv4 code that makes use of this patch may be found on

  http://client.linux-nfs.org/Linux-2.6.x/2.6.12-rc1/

Comments appreciated.

Cheers,
  Trond


----
VFS: Allow the filesystem to return a full file pointer on open intent

 Signed-off-by: Trond Myklebust <[email protected]>
---
 fs/exec.c             |   12 ++++++------
 fs/namei.c            |   19 ++++++++++++++++---
 fs/open.c             |   14 +++++++++++++-
 include/linux/namei.h |   10 ++++++++++
 4 files changed, 45 insertions(+), 10 deletions(-)

Index: linux-2.6.12-rc1/fs/namei.c
===================================================================
--- linux-2.6.12-rc1.orig/fs/namei.c
+++ linux-2.6.12-rc1/fs/namei.c
@@ -28,6 +28,7 @@
 #include <linux/syscalls.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
+#include <linux/file.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
@@ -318,6 +319,19 @@ void path_release_on_umount(struct namei
 }
 
 /*
+ * Open intents have to release any file pointer that was allocated
+ * but not used by the VFS.
+ */
+void path_release_open_intent(struct nameidata *nd)
+{
+	if ((nd->flags & LOOKUP_OPEN) && nd->intent.open.file != NULL) {
+		fput(nd->intent.open.file);
+		nd->intent.open.file = NULL;
+	}
+	path_release(nd);
+}
+
+/*
  * Internal lookup() using the new generic dcache.
  * SMP-safe
  */
@@ -1406,8 +1420,7 @@ int open_namei(const char * pathname, in
 		acc_mode |= MAY_APPEND;
 
 	/* Fill in the open() intent data */
-	nd->intent.open.flags = flag;
-	nd->intent.open.create_mode = mode;
+	nd_init_open_intent(nd, flag, mode);
 
 	/*
 	 * The simplest case - just a plain lookup.
@@ -1498,7 +1511,7 @@ ok:
 exit_dput:
 	dput(dentry);
 exit:
-	path_release(nd);
+	path_release_open_intent(nd);
 	return error;
 
 do_link:
Index: linux-2.6.12-rc1/fs/exec.c
===================================================================
--- linux-2.6.12-rc1.orig/fs/exec.c
+++ linux-2.6.12-rc1/fs/exec.c
@@ -123,7 +123,7 @@ asmlinkage long sys_uselib(const char __
 	struct nameidata nd;
 	int error;
 
-	nd.intent.open.flags = FMODE_READ;
+	nd_init_open_intent(&nd, FMODE_READ, 0);
 	error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
 	if (error)
 		goto out;
@@ -136,7 +136,7 @@ asmlinkage long sys_uselib(const char __
 	if (error)
 		goto exit;
 
-	file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+	file = nd_open_file(&nd, O_RDONLY);
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
 		goto out;
@@ -164,7 +164,7 @@ asmlinkage long sys_uselib(const char __
 out:
   	return error;
 exit:
-	path_release(&nd);
+	path_release_open_intent(&nd);
 	goto out;
 }
 
@@ -491,7 +491,7 @@ struct file *open_exec(const char *name)
 	int err;
 	struct file *file;
 
-	nd.intent.open.flags = FMODE_READ;
+	nd_init_open_intent(&nd, FMODE_READ, 0);
 	err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
 	file = ERR_PTR(err);
 
@@ -505,7 +505,7 @@ struct file *open_exec(const char *name)
 				err = -EACCES;
 			file = ERR_PTR(err);
 			if (!err) {
-				file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+				file = nd_open_file(&nd, O_RDONLY);
 				if (!IS_ERR(file)) {
 					err = deny_write_access(file);
 					if (err) {
@@ -517,7 +517,7 @@ out:
 				return file;
 			}
 		}
-		path_release(&nd);
+		path_release_open_intent(&nd);
 	}
 	goto out;
 }
Index: linux-2.6.12-rc1/include/linux/namei.h
===================================================================
--- linux-2.6.12-rc1.orig/include/linux/namei.h
+++ linux-2.6.12-rc1/include/linux/namei.h
@@ -8,6 +8,7 @@ struct vfsmount;
 struct open_intent {
 	int	flags;
 	int	create_mode;
+	struct file *file;
 };
 
 enum { MAX_NESTED_LINKS = 5 };
@@ -64,6 +65,15 @@ extern int FASTCALL(path_walk(const char
 extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
 extern void path_release(struct nameidata *);
 extern void path_release_on_umount(struct nameidata *);
+extern void path_release_open_intent(struct nameidata *);
+
+extern struct file *nd_open_file(struct nameidata *nd, int flags);
+static inline void nd_init_open_intent(struct nameidata *nd, int flags, int mode)
+{
+	nd->intent.open.flags = flags;
+	nd->intent.open.create_mode = mode;
+	nd->intent.open.file = NULL;
+}
 
 extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
 extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
Index: linux-2.6.12-rc1/fs/open.c
===================================================================
--- linux-2.6.12-rc1.orig/fs/open.c
+++ linux-2.6.12-rc1/fs/open.c
@@ -763,13 +763,25 @@ struct file *filp_open(const char * file
 
 	error = open_namei(filename, namei_flags, mode, &nd);
 	if (!error)
-		return dentry_open(nd.dentry, nd.mnt, flags);
+		return nd_open_file(&nd, flags);
 
 	return ERR_PTR(error);
 }
 
 EXPORT_SYMBOL(filp_open);
 
+struct file *nd_open_file(struct nameidata *nd, int flags)
+{
+	struct file *filp;
+
+	if ((nd->flags & LOOKUP_OPEN) && nd->intent.open.file != NULL) {
+		filp = nd->intent.open.file;
+		path_release(nd);
+	} else
+		filp = dentry_open(nd->dentry, nd->mnt, flags);
+	return filp;
+}
+
 struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
 {
 	struct file * f;

-- 
Trond Myklebust <[email protected]>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux