[PATCH 01/13] vfs: add i_op->dentry_open()
From: Miklos Szeredi 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 --- 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(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index eba790134253..09a7b57d2f47 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -67,6 +67,7 @@ prototypes: struct file *, unsigned open_flag, umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); + int (*dentry_open)(struct dentry *, struct file *, const struct cred *); locking rules: all may block @@ -96,6 +97,7 @@ fiemap: no update_time: no atomic_open: yes tmpfile: no +dentry_open: no Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on victim. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 617f6d70c077..938aea64b2fa 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -364,6 +364,7 @@ struct inode_operations { int (*atomic_open)(struct inode *, struct dentry *, struct file *, unsigned open_flag, umode_t create_mode, int *opened); 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 @@ -697,6 +698,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 diff --git a/fs/namei.c b/fs/namei.c index 80168273396b..a7cf0fb1f638 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3046,9 +3046,12 @@ finish_open_created: error = may_open(>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(>path, file, current_cred()); + if (!error) { + *opened |= FILE_OPENED; + } else { if (error == -EOPENSTALE) goto stale_open; goto out; diff --git a/fs/open.c b/fs/open.c index 9d64679cec73..3302cd25403f 100644 --- a/fs/open.c +++ b/fs/open.c @@ -818,8 +818,7 @@ struct file *dentry_open(const struct path *path, int flags, f = get_empty_filp(); if (!IS_ERR(f)) { f->f_flags = flags; - f->f_path = *path; - error = do_dentry_open(f, NULL, cred); + error = vfs_open(path, f, cred); if (!error) { /* from now on we need fput() to dispose of f */ error = open_check_o_direct(f); @@ -836,6 +835,26 @@ struct file *dentry_open(const struct path *path, int flags, } 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; diff --git a/include/linux/fs.h b/include/linux/fs.h index 878031227c57..d38875d70db2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1513,6 +1513,7 @@ struct inode_operations { umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*set_acl)(struct
[PATCH 01/13] vfs: add i_op-dentry_open()
From: Miklos Szeredi mszer...@suse.cz 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 mszer...@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(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index eba790134253..09a7b57d2f47 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -67,6 +67,7 @@ prototypes: struct file *, unsigned open_flag, umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); + int (*dentry_open)(struct dentry *, struct file *, const struct cred *); locking rules: all may block @@ -96,6 +97,7 @@ fiemap: no update_time: no atomic_open: yes tmpfile: no +dentry_open: no Additionally, -rmdir(), -unlink() and -rename() have -i_mutex on victim. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 617f6d70c077..938aea64b2fa 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -364,6 +364,7 @@ struct inode_operations { int (*atomic_open)(struct inode *, struct dentry *, struct file *, unsigned open_flag, umode_t create_mode, int *opened); 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 @@ -697,6 +698,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 diff --git a/fs/namei.c b/fs/namei.c index 80168273396b..a7cf0fb1f638 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3046,9 +3046,12 @@ finish_open_created: 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; diff --git a/fs/open.c b/fs/open.c index 9d64679cec73..3302cd25403f 100644 --- a/fs/open.c +++ b/fs/open.c @@ -818,8 +818,7 @@ struct file *dentry_open(const struct path *path, int flags, f = get_empty_filp(); if (!IS_ERR(f)) { f-f_flags = flags; - f-f_path = *path; - error = do_dentry_open(f, NULL, cred); + error = vfs_open(path, f, cred); if (!error) { /* from now on we need fput() to dispose of f */ error = open_check_o_direct(f); @@ -836,6 +835,26 @@ struct file *dentry_open(const struct path *path, int flags, } 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; diff --git a/include/linux/fs.h b/include/linux/fs.h index 878031227c57..d38875d70db2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1513,6 +1513,7 @@ struct inode_operations { umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int
[PATCH 01/13] vfs-add-i_op-dentry_open
From: Miklos Szeredi 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 --- 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(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 0706d32..4331290 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -66,6 +66,7 @@ prototypes: 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 @@ -93,6 +94,7 @@ removexattr: yes fiemap:no update_time: no atomic_open: yes +dentry_open: no Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on victim. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index bc4b06b..f64a4d1 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -362,6 +362,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 @@ -681,6 +682,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 diff --git a/fs/namei.c b/fs/namei.c index 57ae9c8..c1c0c15 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2867,9 +2867,12 @@ finish_open_created: error = may_open(>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(>path, file, current_cred()); + if (!error) { + *opened |= FILE_OPENED; + } else { if (error == -EOPENSTALE) goto stale_open; goto out; diff --git a/fs/open.c b/fs/open.c index 6835446..b9d9f9e 100644 --- a/fs/open.c +++ b/fs/open.c @@ -828,8 +828,7 @@ struct file *dentry_open(const struct path *path, int flags, f = get_empty_filp(); if (!IS_ERR(f)) { f->f_flags = flags; - f->f_path = *path; - error = do_dentry_open(f, NULL, cred); + error = vfs_open(path, f, cred); if (!error) { /* from now on we need fput() to dispose of f */ error = open_check_o_direct(f); @@ -846,6 +845,26 @@ struct file *dentry_open(const struct path *path, int flags, } 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; diff --git a/include/linux/fs.h b/include/linux/fs.h index 2c28271..891c93d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1573,6 +1573,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
[PATCH 01/13] vfs-add-i_op-dentry_open
From: Miklos Szeredi mszer...@suse.cz 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 mszer...@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(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 0706d32..4331290 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -66,6 +66,7 @@ prototypes: 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 @@ -93,6 +94,7 @@ removexattr: yes fiemap:no update_time: no atomic_open: yes +dentry_open: no Additionally, -rmdir(), -unlink() and -rename() have -i_mutex on victim. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index bc4b06b..f64a4d1 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -362,6 +362,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 @@ -681,6 +682,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 diff --git a/fs/namei.c b/fs/namei.c index 57ae9c8..c1c0c15 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2867,9 +2867,12 @@ finish_open_created: 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; diff --git a/fs/open.c b/fs/open.c index 6835446..b9d9f9e 100644 --- a/fs/open.c +++ b/fs/open.c @@ -828,8 +828,7 @@ struct file *dentry_open(const struct path *path, int flags, f = get_empty_filp(); if (!IS_ERR(f)) { f-f_flags = flags; - f-f_path = *path; - error = do_dentry_open(f, NULL, cred); + error = vfs_open(path, f, cred); if (!error) { /* from now on we need fput() to dispose of f */ error = open_check_o_direct(f); @@ -846,6 +845,26 @@ struct file *dentry_open(const struct path *path, int flags, } 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; diff --git a/include/linux/fs.h b/include/linux/fs.h index 2c28271..891c93d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1573,6 +1573,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
[PATCH 01/13] vfs: add i_op->dentry_open()
From: Miklos Szeredi 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 --- 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(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index e540a24..019fc72 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -64,6 +64,7 @@ prototypes: 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. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 2ee133e..ea1379c 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -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 diff --git a/fs/namei.c b/fs/namei.c index dd1ed1b..829404a 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2822,9 +2822,12 @@ finish_open_created: error = may_open(>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(>path, file, current_cred()); + if (!error) { + *opened |= FILE_OPENED; + } else { if (error == -EOPENSTALE) goto stale_open; goto out; diff --git a/fs/open.c b/fs/open.c index e1f2cdb..d0f0ec7 100644 --- a/fs/open.c +++ b/fs/open.c @@ -787,8 +787,7 @@ struct file *dentry_open(const struct path *path, int flags, 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 path *path, int flags, } 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 void __put_unused_fd(struct files_struct *files, unsigned int fd) { struct fdtable *fdt = files_fdtable(files); diff --git a/include/linux/fs.h b/include/linux/fs.h index aa11047..e372113 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1835,6 +1835,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; @@ -2199,6 +2200,7
[PATCH 01/13] vfs: add i_op-dentry_open()
From: Miklos Szeredi mszer...@suse.cz 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 mszer...@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(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index e540a24..019fc72 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -64,6 +64,7 @@ prototypes: 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. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 2ee133e..ea1379c 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -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 diff --git a/fs/namei.c b/fs/namei.c index dd1ed1b..829404a 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2822,9 +2822,12 @@ finish_open_created: 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; diff --git a/fs/open.c b/fs/open.c index e1f2cdb..d0f0ec7 100644 --- a/fs/open.c +++ b/fs/open.c @@ -787,8 +787,7 @@ struct file *dentry_open(const struct path *path, int flags, 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 path *path, int flags, } 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 void __put_unused_fd(struct files_struct *files, unsigned int fd) { struct fdtable *fdt = files_fdtable(files); diff --git a/include/linux/fs.h b/include/linux/fs.h index aa11047..e372113 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1835,6 +1835,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; @@