aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-06-05 09:10:17 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-14 08:33:04 -0400
commitd18e9008c377dc6a6d2166a6840bf3a23a5867fd (patch)
tree6bbb29aea7e931b603bd4cea3cc74a0eda7b6379 /fs/open.c
parent54ef487241e863a6046536ac5b1fcd5d7cde86e5 (diff)
vfs: add i_op->atomic_open()
Add a new inode operation which is called on the last component of an open. Using this the filesystem can look up, possibly create and open the file in one atomic operation. If it cannot perform this (e.g. the file type turned out to be wrong) it may signal this by returning NULL instead of an open struct file pointer. i_op->atomic_open() is only called if the last component is negative or needs lookup. Handling cached positive dentries here doesn't add much value: these can be opened using f_op->open(). If the cached file turns out to be invalid, the open can be retried, this time using ->atomic_open() with a fresh dentry. For now leave the old way of using open intents in lookup and revalidate in place. This will be removed once all the users are converted. David Howells noticed that if ->atomic_open() opens the file but does not create it, handle_truncate() will be called on it even if it is not a regular file. Fix this by checking the file type in this case too. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/fs/open.c b/fs/open.c
index 1540632d8387..13bece4f36a4 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -811,6 +811,48 @@ out_err:
811EXPORT_SYMBOL_GPL(lookup_instantiate_filp); 811EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
812 812
813/** 813/**
814 * finish_open - finish opening a file
815 * @od: opaque open data
816 * @dentry: pointer to dentry
817 * @open: open callback
818 *
819 * This can be used to finish opening a file passed to i_op->atomic_open().
820 *
821 * If the open callback is set to NULL, then the standard f_op->open()
822 * filesystem callback is substituted.
823 */
824struct file *finish_open(struct opendata *od, struct dentry *dentry,
825 int (*open)(struct inode *, struct file *))
826{
827 struct file *res;
828
829 mntget(od->mnt);
830 dget(dentry);
831
832 res = do_dentry_open(dentry, od->mnt, *od->filp, open, current_cred());
833 if (!IS_ERR(res))
834 *od->filp = NULL;
835
836 return res;
837}
838EXPORT_SYMBOL(finish_open);
839
840/**
841 * finish_no_open - finish ->atomic_open() without opening the file
842 *
843 * @od: opaque open data
844 * @dentry: dentry or NULL (as returned from ->lookup())
845 *
846 * This can be used to set the result of a successful lookup in ->atomic_open().
847 * The filesystem's atomic_open() method shall return NULL after calling this.
848 */
849void finish_no_open(struct opendata *od, struct dentry *dentry)
850{
851 od->dentry = dentry;
852}
853EXPORT_SYMBOL(finish_no_open);
854
855/**
814 * nameidata_to_filp - convert a nameidata to an open filp. 856 * nameidata_to_filp - convert a nameidata to an open filp.
815 * @nd: pointer to nameidata 857 * @nd: pointer to nameidata
816 * @flags: open flags 858 * @flags: open flags