1
0
Fork 0

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>
wifi-calibration
Miklos Szeredi 2014-10-24 00:14:35 +02:00
parent f114040e3e
commit 4aa7c6346b
5 changed files with 40 additions and 5 deletions

View File

@ -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
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.

View File

@ -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 {
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

View File

@ -3064,9 +3064,12 @@ finish_open_created:
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;

View File

@ -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,
} }
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;

View File

@ -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);
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);