aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-10-23 18:14:35 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-10-23 18:14:35 -0400
commit4aa7c6346be395bdf776f82bbb2e3e2bc60bdd2b (patch)
treea2135754a04370e7fcf7b867b0f4fbeaa58b3521
parentf114040e3ea6e07372334ade75d1ee0775c355e1 (diff)
vfs: add i_op->dentry_open()
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>
-rw-r--r--Documentation/filesystems/Locking2
-rw-r--r--Documentation/filesystems/vfs.txt7
-rw-r--r--fs/namei.c9
-rw-r--r--fs/open.c23
-rw-r--r--include/linux/fs.h4
5 files changed, 40 insertions, 5 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 94d93b1f8b53..b30753cbf431 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -67,6 +67,7 @@ prototypes:
67 struct file *, unsigned open_flag, 67 struct file *, unsigned open_flag,
68 umode_t create_mode, int *opened); 68 umode_t create_mode, int *opened);
69 int (*tmpfile) (struct inode *, struct dentry *, umode_t); 69 int (*tmpfile) (struct inode *, struct dentry *, umode_t);
70 int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
70 71
71locking rules: 72locking rules:
72 all may block 73 all may block
@@ -96,6 +97,7 @@ fiemap: no
96update_time: no 97update_time: no
97atomic_open: yes 98atomic_open: yes
98tmpfile: no 99tmpfile: no
100dentry_open: no
99 101
100 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on 102 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
101victim. 103victim.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index fceff7c00a3c..20bf204426ca 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -364,6 +364,7 @@ struct inode_operations {
364 int (*atomic_open)(struct inode *, struct dentry *, struct file *, 364 int (*atomic_open)(struct inode *, struct dentry *, struct file *,
365 unsigned open_flag, umode_t create_mode, int *opened); 365 unsigned open_flag, umode_t create_mode, int *opened);
366 int (*tmpfile) (struct inode *, struct dentry *, umode_t); 366 int (*tmpfile) (struct inode *, struct dentry *, umode_t);
367 int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
367}; 368};
368 369
369Again, all methods are called without any locks being held, unless 370Again, all methods are called without any locks being held, unless
@@ -696,6 +697,12 @@ struct address_space_operations {
696 but instead uses bmap to find out where the blocks in the file 697 but instead uses bmap to find out where the blocks in the file
697 are and uses those addresses directly. 698 are and uses those addresses directly.
698 699
700 dentry_open: *WARNING: probably going away soon, do not use!* This is an
701 alternative to f_op->open(), the difference is that this method may open
702 a file not necessarily originating from the same filesystem as the one
703 i_op->open() was called on. It may be useful for stacking filesystems
704 which want to allow native I/O directly on underlying files.
705
699 706
700 invalidatepage: If a page has PagePrivate set, then invalidatepage 707 invalidatepage: If a page has PagePrivate set, then invalidatepage
701 will be called when part or all of the page is to be removed 708 will be called when part or all of the page is to be removed
diff --git a/fs/namei.c b/fs/namei.c
index 43927d14db67..75306b3c9526 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3064,9 +3064,12 @@ finish_open_created:
3064 error = may_open(&nd->path, acc_mode, open_flag); 3064 error = may_open(&nd->path, acc_mode, open_flag);
3065 if (error) 3065 if (error)
3066 goto out; 3066 goto out;
3067 file->f_path.mnt = nd->path.mnt; 3067
3068 error = finish_open(file, nd->path.dentry, NULL, opened); 3068 BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
3069 if (error) { 3069 error = vfs_open(&nd->path, file, current_cred());
3070 if (!error) {
3071 *opened |= FILE_OPENED;
3072 } else {
3070 if (error == -EOPENSTALE) 3073 if (error == -EOPENSTALE)
3071 goto stale_open; 3074 goto stale_open;
3072 goto out; 3075 goto out;
diff --git a/fs/open.c b/fs/open.c
index d6fd3acde134..de92c13b58be 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -823,8 +823,7 @@ struct file *dentry_open(const struct path *path, int flags,
823 f = get_empty_filp(); 823 f = get_empty_filp();
824 if (!IS_ERR(f)) { 824 if (!IS_ERR(f)) {
825 f->f_flags = flags; 825 f->f_flags = flags;
826 f->f_path = *path; 826 error = vfs_open(path, f, cred);
827 error = do_dentry_open(f, NULL, cred);
828 if (!error) { 827 if (!error) {
829 /* from now on we need fput() to dispose of f */ 828 /* from now on we need fput() to dispose of f */
830 error = open_check_o_direct(f); 829 error = open_check_o_direct(f);
@@ -841,6 +840,26 @@ struct file *dentry_open(const struct path *path, int flags,
841} 840}
842EXPORT_SYMBOL(dentry_open); 841EXPORT_SYMBOL(dentry_open);
843 842
843/**
844 * vfs_open - open the file at the given path
845 * @path: path to open
846 * @filp: newly allocated file with f_flag initialized
847 * @cred: credentials to use
848 */
849int vfs_open(const struct path *path, struct file *filp,
850 const struct cred *cred)
851{
852 struct inode *inode = path->dentry->d_inode;
853
854 if (inode->i_op->dentry_open)
855 return inode->i_op->dentry_open(path->dentry, filp, cred);
856 else {
857 filp->f_path = *path;
858 return do_dentry_open(filp, NULL, cred);
859 }
860}
861EXPORT_SYMBOL(vfs_open);
862
844static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op) 863static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
845{ 864{
846 int lookup_flags = 0; 865 int lookup_flags = 0;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a957d4366c24..5cf7f6759679 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1528,6 +1528,9 @@ struct inode_operations {
1528 umode_t create_mode, int *opened); 1528 umode_t create_mode, int *opened);
1529 int (*tmpfile) (struct inode *, struct dentry *, umode_t); 1529 int (*tmpfile) (struct inode *, struct dentry *, umode_t);
1530 int (*set_acl)(struct inode *, struct posix_acl *, int); 1530 int (*set_acl)(struct inode *, struct posix_acl *, int);
1531
1532 /* WARNING: probably going away soon, do not use! */
1533 int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
1531} ____cacheline_aligned; 1534} ____cacheline_aligned;
1532 1535
1533ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, 1536ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
@@ -2040,6 +2043,7 @@ extern struct file *file_open_name(struct filename *, int, umode_t);
2040extern struct file *filp_open(const char *, int, umode_t); 2043extern struct file *filp_open(const char *, int, umode_t);
2041extern struct file *file_open_root(struct dentry *, struct vfsmount *, 2044extern struct file *file_open_root(struct dentry *, struct vfsmount *,
2042 const char *, int); 2045 const char *, int);
2046extern int vfs_open(const struct path *, struct file *, const struct cred *);
2043extern struct file * dentry_open(const struct path *, int, const struct cred *); 2047extern struct file * dentry_open(const struct path *, int, const struct cred *);
2044extern int filp_close(struct file *, fl_owner_t id); 2048extern int filp_close(struct file *, fl_owner_t id);
2045 2049