Commit 4aa7c634 authored by Miklos Szeredi's avatar Miklos Szeredi

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: default avatarMiklos Szeredi <mszeredi@suse.cz>
parent f114040e
...@@ -67,6 +67,7 @@ prototypes: ...@@ -67,6 +67,7 @@ prototypes:
struct file *, unsigned open_flag, struct file *, unsigned open_flag,
umode_t create_mode, int *opened); umode_t create_mode, int *opened);
int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*tmpfile) (struct inode *, struct dentry *, umode_t);
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
locking rules: locking rules:
all may block all may block
...@@ -96,6 +97,7 @@ fiemap: no ...@@ -96,6 +97,7 @@ fiemap: no
update_time: no update_time: no
atomic_open: yes atomic_open: yes
tmpfile: no tmpfile: no
dentry_open: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim. victim.
......
...@@ -364,6 +364,7 @@ struct inode_operations { ...@@ -364,6 +364,7 @@ struct inode_operations {
int (*atomic_open)(struct inode *, struct dentry *, struct file *, int (*atomic_open)(struct inode *, struct dentry *, struct file *,
unsigned open_flag, umode_t create_mode, int *opened); unsigned open_flag, umode_t create_mode, int *opened);
int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*tmpfile) (struct inode *, struct dentry *, umode_t);
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
}; };
Again, all methods are called without any locks being held, unless Again, all methods are called without any locks being held, unless
...@@ -696,6 +697,12 @@ struct address_space_operations { ...@@ -696,6 +697,12 @@ struct address_space_operations {
but instead uses bmap to find out where the blocks in the file but instead uses bmap to find out where the blocks in the file
are and uses those addresses directly. are and uses those addresses directly.
dentry_open: *WARNING: probably going away soon, do not use!* 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 invalidatepage: If a page has PagePrivate set, then invalidatepage
will be called when part or all of the page is to be removed will be called when part or all of the page is to be removed
......
...@@ -3064,9 +3064,12 @@ static int do_last(struct nameidata *nd, struct path *path, ...@@ -3064,9 +3064,12 @@ static int do_last(struct nameidata *nd, struct path *path,
error = may_open(&nd->path, acc_mode, open_flag); error = may_open(&nd->path, acc_mode, open_flag);
if (error) if (error)
goto out; goto out;
file->f_path.mnt = nd->path.mnt;
error = finish_open(file, nd->path.dentry, NULL, opened); BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
if (error) { error = vfs_open(&nd->path, file, current_cred());
if (!error) {
*opened |= FILE_OPENED;
} else {
if (error == -EOPENSTALE) if (error == -EOPENSTALE)
goto stale_open; goto stale_open;
goto out; goto out;
......
...@@ -823,8 +823,7 @@ struct file *dentry_open(const struct path *path, int flags, ...@@ -823,8 +823,7 @@ struct file *dentry_open(const struct path *path, int flags,
f = get_empty_filp(); f = get_empty_filp();
if (!IS_ERR(f)) { if (!IS_ERR(f)) {
f->f_flags = flags; f->f_flags = flags;
f->f_path = *path; error = vfs_open(path, f, cred);
error = do_dentry_open(f, NULL, cred);
if (!error) { if (!error) {
/* from now on we need fput() to dispose of f */ /* from now on we need fput() to dispose of f */
error = open_check_o_direct(f); error = open_check_o_direct(f);
...@@ -841,6 +840,26 @@ struct file *dentry_open(const struct path *path, int flags, ...@@ -841,6 +840,26 @@ struct file *dentry_open(const struct path *path, int flags,
} }
EXPORT_SYMBOL(dentry_open); 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) static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
{ {
int lookup_flags = 0; int lookup_flags = 0;
......
...@@ -1528,6 +1528,9 @@ struct inode_operations { ...@@ -1528,6 +1528,9 @@ struct inode_operations {
umode_t create_mode, int *opened); umode_t create_mode, int *opened);
int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*tmpfile) (struct inode *, struct dentry *, umode_t);
int (*set_acl)(struct inode *, struct posix_acl *, int); int (*set_acl)(struct inode *, struct posix_acl *, int);
/* WARNING: probably going away soon, do not use! */
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
} ____cacheline_aligned; } ____cacheline_aligned;
ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, ssize_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); ...@@ -2040,6 +2043,7 @@ extern struct file *file_open_name(struct filename *, int, umode_t);
extern struct file *filp_open(const char *, int, umode_t); extern struct file *filp_open(const char *, int, umode_t);
extern struct file *file_open_root(struct dentry *, struct vfsmount *, extern struct file *file_open_root(struct dentry *, struct vfsmount *,
const char *, int); 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 struct file * dentry_open(const struct path *, int, const struct cred *);
extern int filp_close(struct file *, fl_owner_t id); extern int filp_close(struct file *, fl_owner_t id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment