summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-06-05 17:10:17 +0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-14 16:33:04 +0400
commitd18e9008c377dc6a6d2166a6840bf3a23a5867fd (patch)
tree6bbb29aea7e931b603bd4cea3cc74a0eda7b6379 /include
parent54ef487241e863a6046536ac5b1fcd5d7cde86e5 (diff)
downloadlinux-d18e9008c377dc6a6d2166a6840bf3a23a5867fd.tar.xz
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 'include')
-rw-r--r--include/linux/fs.h7
1 files changed, 7 insertions, 0 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f06db6bd5a74..0314635cf833 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -427,6 +427,7 @@ struct kstatfs;
struct vm_area_struct;
struct vfsmount;
struct cred;
+struct opendata;
extern void __init inode_init(void);
extern void __init inode_init_early(void);
@@ -1693,6 +1694,9 @@ struct inode_operations {
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len);
int (*update_time)(struct inode *, struct timespec *, int);
+ struct file * (*atomic_open)(struct inode *, struct dentry *,
+ struct opendata *, unsigned open_flag,
+ umode_t create_mode, bool *created);
} ____cacheline_aligned;
struct seq_file;
@@ -2061,6 +2065,9 @@ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
const struct cred *);
extern int filp_close(struct file *, fl_owner_t id);
extern char * getname(const char __user *);
+extern struct file *finish_open(struct opendata *od, struct dentry *dentry,
+ int (*open)(struct inode *, struct file *));
+extern void finish_no_open(struct opendata *od, struct dentry *dentry);
/* fs/ioctl.c */