--- /dev/null
+From b0c34c08a36aafbbb2240d384935343feefb68f3 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Thu, 30 Aug 2012 16:13:49 +0200
+Subject: [PATCH 01/13] vfs: add i_op->dentry_open()
+Patch-mainline: not yet
+
+Add a new inode operation i_op->dentry_open(). This is for stacked filesystems
+that want to return a struct file from a different filesystem.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+---
+ Documentation/filesystems/Locking | 2 ++
+ Documentation/filesystems/vfs.txt | 7 +++++++
+ fs/namei.c | 9 ++++++---
+ fs/open.c | 23 +++++++++++++++++++++--
+ include/linux/fs.h | 2 ++
+ 5 files changed, 38 insertions(+), 5 deletions(-)
+
+Index: linux-3.6-rc7-master/Documentation/filesystems/Locking
+===================================================================
+--- linux-3.6-rc7-master.orig/Documentation/filesystems/Locking 2012-09-28 13:36:40.000000000 +0200
++++ linux-3.6-rc7-master/Documentation/filesystems/Locking 2012-09-28 13:36:47.000000000 +0200
+@@ -64,6 +64,7 @@ d_manage: no no yes (ref-walk) maybe
+ int (*atomic_open)(struct inode *, struct dentry *,
+ struct file *, unsigned open_flag,
+ umode_t create_mode, int *opened);
++ int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
+
+ locking rules:
+ all may block
+@@ -92,6 +93,7 @@ removexattr: yes
+ fiemap: no
+ update_time: no
+ atomic_open: yes
++dentry_open: no
+
+ Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
+ victim.
+Index: linux-3.6-rc7-master/Documentation/filesystems/vfs.txt
+===================================================================
+--- linux-3.6-rc7-master.orig/Documentation/filesystems/vfs.txt 2012-09-28 13:36:40.000000000 +0200
++++ linux-3.6-rc7-master/Documentation/filesystems/vfs.txt 2012-09-28 13:36:47.000000000 +0200
+@@ -363,6 +363,7 @@ struct inode_operations {
+ int (*atomic_open)(struct inode *, struct dentry *,
+ struct file *, unsigned open_flag,
+ umode_t create_mode, int *opened);
++ int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
+ };
+
+ Again, all methods are called without any locks being held, unless
+@@ -692,6 +693,12 @@ struct address_space_operations {
+ but instead uses bmap to find out where the blocks in the file
+ are and uses those addresses directly.
+
++ dentry_open: this is an alternative to f_op->open(), the difference is that
++ this method may open a file not necessarily originating from the same
++ filesystem as the one i_op->open() was called on. It may be
++ useful for stacking filesystems which want to allow native I/O directly
++ on underlying files.
++
+
+ invalidatepage: If a page has PagePrivate set, then invalidatepage
+ will be called when part or all of the page is to be removed
+Index: linux-3.6-rc7-master/fs/namei.c
+===================================================================
+--- linux-3.6-rc7-master.orig/fs/namei.c 2012-09-28 13:36:40.000000000 +0200
++++ linux-3.6-rc7-master/fs/namei.c 2012-09-28 13:36:47.000000000 +0200
+@@ -2870,9 +2870,12 @@ static int do_last(struct nameidata *nd,
+ error = may_open(&nd->path, acc_mode, open_flag);
+ if (error)
+ goto out;
+- file->f_path.mnt = nd->path.mnt;
+- error = finish_open(file, nd->path.dentry, NULL, opened);
+- if (error) {
++
++ BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
++ error = vfs_open(&nd->path, file, current_cred());
++ if (!error) {
++ *opened |= FILE_OPENED;
++ } else {
+ if (error == -EOPENSTALE)
+ goto stale_open;
+ goto out;
+Index: linux-3.6-rc7-master/fs/open.c
+===================================================================
+--- linux-3.6-rc7-master.orig/fs/open.c 2012-09-28 13:36:40.000000000 +0200
++++ linux-3.6-rc7-master/fs/open.c 2012-09-28 13:36:47.000000000 +0200
+@@ -787,8 +787,7 @@ struct file *dentry_open(const struct pa
+ return ERR_PTR(error);
+
+ f->f_flags = flags;
+- f->f_path = *path;
+- error = do_dentry_open(f, NULL, cred);
++ error = vfs_open(path, f, cred);
+ if (!error) {
+ error = open_check_o_direct(f);
+ if (error) {
+@@ -803,6 +802,26 @@ struct file *dentry_open(const struct pa
+ }
+ EXPORT_SYMBOL(dentry_open);
+
++/**
++ * vfs_open - open the file at the given path
++ * @path: path to open
++ * @filp: newly allocated file with f_flag initialized
++ * @cred: credentials to use
++ */
++int vfs_open(const struct path *path, struct file *filp,
++ const struct cred *cred)
++{
++ struct inode *inode = path->dentry->d_inode;
++
++ if (inode->i_op->dentry_open)
++ return inode->i_op->dentry_open(path->dentry, filp, cred);
++ else {
++ filp->f_path = *path;
++ return do_dentry_open(filp, NULL, cred);
++ }
++}
++EXPORT_SYMBOL(vfs_open);
++
+ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
+ {
+ int lookup_flags = 0;
+Index: linux-3.6-rc7-master/include/linux/fs.h
+===================================================================
+--- linux-3.6-rc7-master.orig/include/linux/fs.h 2012-09-28 13:36:40.000000000 +0200
++++ linux-3.6-rc7-master/include/linux/fs.h 2012-09-28 13:36:47.000000000 +0200
+@@ -1843,6 +1843,7 @@ struct inode_operations {
+ int (*atomic_open)(struct inode *, struct dentry *,
+ struct file *, unsigned open_flag,
+ umode_t create_mode, int *opened);
++ int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
+ } ____cacheline_aligned;
+
+ struct seq_file;
+@@ -2211,6 +2212,7 @@ extern long do_sys_open(int dfd, const c
+ extern struct file *filp_open(const char *, int, umode_t);
+ extern struct file *file_open_root(struct dentry *, struct vfsmount *,
+ const char *, int);
++extern int vfs_open(const struct path *, struct file *, const struct cred *);
+ extern struct file * dentry_open(const struct path *, int, const struct cred *);
+ extern int filp_close(struct file *, fl_owner_t id);
+