]>
Commit | Line | Data |
---|---|---|
68184a5a JR |
1 | From b0c34c08a36aafbbb2240d384935343feefb68f3 Mon Sep 17 00:00:00 2001 |
2 | From: Miklos Szeredi <mszeredi@suse.cz> | |
3 | Date: Thu, 30 Aug 2012 16:13:49 +0200 | |
4 | Subject: [PATCH 01/13] vfs: add i_op->dentry_open() | |
5 | Patch-mainline: not yet | |
6 | ||
7 | Add a new inode operation i_op->dentry_open(). This is for stacked filesystems | |
8 | that want to return a struct file from a different filesystem. | |
9 | ||
10 | Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> | |
11 | --- | |
12 | Documentation/filesystems/Locking | 2 ++ | |
13 | Documentation/filesystems/vfs.txt | 7 +++++++ | |
14 | fs/namei.c | 9 ++++++--- | |
15 | fs/open.c | 23 +++++++++++++++++++++-- | |
16 | include/linux/fs.h | 2 ++ | |
17 | 5 files changed, 38 insertions(+), 5 deletions(-) | |
18 | ||
392086de AM |
19 | --- a/Documentation/filesystems/Locking |
20 | +++ b/Documentation/filesystems/Locking | |
21 | @@ -66,6 +66,7 @@ d_manage: no no yes (ref-walk) maybe | |
68184a5a JR |
22 | struct file *, unsigned open_flag, |
23 | umode_t create_mode, int *opened); | |
392086de | 24 | int (*tmpfile) (struct inode *, struct dentry *, umode_t); |
68184a5a JR |
25 | + int (*dentry_open)(struct dentry *, struct file *, const struct cred *); |
26 | ||
27 | locking rules: | |
28 | all may block | |
392086de | 29 | @@ -93,6 +94,7 @@ removexattr: yes |
68184a5a JR |
30 | update_time: no |
31 | atomic_open: yes | |
392086de | 32 | tmpfile: no |
68184a5a JR |
33 | +dentry_open: no |
34 | ||
35 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on | |
36 | victim. | |
392086de AM |
37 | --- a/Documentation/filesystems/vfs.txt |
38 | +++ b/Documentation/filesystems/vfs.txt | |
39 | @@ -362,6 +362,7 @@ struct inode_operations { | |
40 | int (*atomic_open)(struct inode *, struct dentry *, struct file *, | |
41 | unsigned open_flag, umode_t create_mode, int *opened); | |
42 | int (*tmpfile) (struct inode *, struct dentry *, umode_t); | |
68184a5a JR |
43 | + int (*dentry_open)(struct dentry *, struct file *, const struct cred *); |
44 | }; | |
45 | ||
46 | Again, all methods are called without any locks being held, unless | |
392086de | 47 | @@ -681,6 +682,12 @@ struct address_space_operations { |
68184a5a JR |
48 | but instead uses bmap to find out where the blocks in the file |
49 | are and uses those addresses directly. | |
50 | ||
51 | + dentry_open: this is an alternative to f_op->open(), the difference is that | |
52 | + this method may open a file not necessarily originating from the same | |
53 | + filesystem as the one i_op->open() was called on. It may be | |
54 | + useful for stacking filesystems which want to allow native I/O directly | |
55 | + on underlying files. | |
56 | + | |
57 | ||
58 | invalidatepage: If a page has PagePrivate set, then invalidatepage | |
59 | will be called when part or all of the page is to be removed | |
392086de AM |
60 | --- a/fs/namei.c |
61 | +++ b/fs/namei.c | |
62 | @@ -2915,9 +2915,12 @@ static int do_last(struct nameidata *nd, | |
68184a5a JR |
63 | error = may_open(&nd->path, acc_mode, open_flag); |
64 | if (error) | |
65 | goto out; | |
66 | - file->f_path.mnt = nd->path.mnt; | |
67 | - error = finish_open(file, nd->path.dentry, NULL, opened); | |
68 | - if (error) { | |
69 | + | |
70 | + BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */ | |
71 | + error = vfs_open(&nd->path, file, current_cred()); | |
72 | + if (!error) { | |
73 | + *opened |= FILE_OPENED; | |
74 | + } else { | |
75 | if (error == -EOPENSTALE) | |
76 | goto stale_open; | |
77 | goto out; | |
392086de AM |
78 | --- a/fs/open.c |
79 | +++ b/fs/open.c | |
80 | @@ -800,8 +800,7 @@ struct file *dentry_open(const struct pa | |
514e5dae AM |
81 | f = get_empty_filp(); |
82 | if (!IS_ERR(f)) { | |
392086de | 83 | f->f_flags = flags; |
514e5dae AM |
84 | - f->f_path = *path; |
85 | - error = do_dentry_open(f, NULL, cred); | |
86 | + error = vfs_open(path, f, cred); | |
87 | if (!error) { | |
392086de | 88 | /* from now on we need fput() to dispose of f */ |
514e5dae | 89 | error = open_check_o_direct(f); |
392086de | 90 | @@ -818,6 +817,26 @@ struct file *dentry_open(const struct pa |
68184a5a JR |
91 | } |
92 | EXPORT_SYMBOL(dentry_open); | |
93 | ||
94 | +/** | |
95 | + * vfs_open - open the file at the given path | |
96 | + * @path: path to open | |
97 | + * @filp: newly allocated file with f_flag initialized | |
98 | + * @cred: credentials to use | |
99 | + */ | |
100 | +int vfs_open(const struct path *path, struct file *filp, | |
101 | + const struct cred *cred) | |
102 | +{ | |
103 | + struct inode *inode = path->dentry->d_inode; | |
104 | + | |
105 | + if (inode->i_op->dentry_open) | |
106 | + return inode->i_op->dentry_open(path->dentry, filp, cred); | |
107 | + else { | |
108 | + filp->f_path = *path; | |
109 | + return do_dentry_open(filp, NULL, cred); | |
110 | + } | |
111 | +} | |
112 | +EXPORT_SYMBOL(vfs_open); | |
113 | + | |
114 | static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op) | |
115 | { | |
116 | int lookup_flags = 0; | |
392086de AM |
117 | --- a/include/linux/fs.h |
118 | +++ b/include/linux/fs.h | |
119 | @@ -1585,6 +1585,7 @@ struct inode_operations { | |
68184a5a | 120 | umode_t create_mode, int *opened); |
392086de | 121 | int (*tmpfile) (struct inode *, struct dentry *, umode_t); |
f15949f2 | 122 | int (*set_acl)(struct inode *, struct posix_acl *, int); |
68184a5a JR |
123 | + int (*dentry_open)(struct dentry *, struct file *, const struct cred *); |
124 | } ____cacheline_aligned; | |
125 | ||
514e5dae | 126 | ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, |
392086de | 127 | @@ -2019,6 +2020,7 @@ extern struct file *file_open_name(struc |
68184a5a JR |
128 | extern struct file *filp_open(const char *, int, umode_t); |
129 | extern struct file *file_open_root(struct dentry *, struct vfsmount *, | |
130 | const char *, int); | |
131 | +extern int vfs_open(const struct path *, struct file *, const struct cred *); | |
132 | extern struct file * dentry_open(const struct path *, int, const struct cred *); | |
133 | extern int filp_close(struct file *, fl_owner_t id); | |
134 |