diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-03-14 12:02:47 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-04-01 23:19:12 -0400 |
commit | 83f936c75e3689a63253d89c47a4d239c56d7410 (patch) | |
tree | 430d89096a9b56ffb8e80bd4febde39e1d05ad4c /fs/file_table.c | |
parent | 0ccb286346c4c0644be17f04a9eb23ad99262882 (diff) |
mark struct file that had write access grabbed by open()
new flag in ->f_mode - FMODE_WRITER. Set by do_dentry_open() in case
when it has grabbed write access, checked by __fput() to decide whether
it wants to drop the sucker. Allows to stop bothering with mnt_clone_write()
in alloc_file(), along with fewer special_file() checks.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/file_table.c')
-rw-r--r-- | fs/file_table.c | 37 |
1 files changed, 4 insertions, 33 deletions
diff --git a/fs/file_table.c b/fs/file_table.c index ee20658a0647..ce1504fec5a1 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -177,43 +177,12 @@ struct file *alloc_file(struct path *path, fmode_t mode, | |||
177 | file->f_mapping = path->dentry->d_inode->i_mapping; | 177 | file->f_mapping = path->dentry->d_inode->i_mapping; |
178 | file->f_mode = mode; | 178 | file->f_mode = mode; |
179 | file->f_op = fop; | 179 | file->f_op = fop; |
180 | |||
181 | /* | ||
182 | * These mounts don't really matter in practice | ||
183 | * for r/o bind mounts. They aren't userspace- | ||
184 | * visible. We do this for consistency, and so | ||
185 | * that we can do debugging checks at __fput() | ||
186 | */ | ||
187 | if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) { | ||
188 | WARN_ON(mnt_clone_write(path->mnt)); | ||
189 | } | ||
190 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 180 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
191 | i_readcount_inc(path->dentry->d_inode); | 181 | i_readcount_inc(path->dentry->d_inode); |
192 | return file; | 182 | return file; |
193 | } | 183 | } |
194 | EXPORT_SYMBOL(alloc_file); | 184 | EXPORT_SYMBOL(alloc_file); |
195 | 185 | ||
196 | /** | ||
197 | * drop_file_write_access - give up ability to write to a file | ||
198 | * @file: the file to which we will stop writing | ||
199 | * | ||
200 | * This is a central place which will give up the ability | ||
201 | * to write to @file, along with access to write through | ||
202 | * its vfsmount. | ||
203 | */ | ||
204 | static void drop_file_write_access(struct file *file) | ||
205 | { | ||
206 | struct vfsmount *mnt = file->f_path.mnt; | ||
207 | struct dentry *dentry = file->f_path.dentry; | ||
208 | struct inode *inode = dentry->d_inode; | ||
209 | |||
210 | if (special_file(inode->i_mode)) | ||
211 | return; | ||
212 | |||
213 | put_write_access(inode); | ||
214 | __mnt_drop_write(mnt); | ||
215 | } | ||
216 | |||
217 | /* the real guts of fput() - releasing the last reference to file | 186 | /* the real guts of fput() - releasing the last reference to file |
218 | */ | 187 | */ |
219 | static void __fput(struct file *file) | 188 | static void __fput(struct file *file) |
@@ -248,8 +217,10 @@ static void __fput(struct file *file) | |||
248 | put_pid(file->f_owner.pid); | 217 | put_pid(file->f_owner.pid); |
249 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 218 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
250 | i_readcount_dec(inode); | 219 | i_readcount_dec(inode); |
251 | if (file->f_mode & FMODE_WRITE) | 220 | if (file->f_mode & FMODE_WRITER) { |
252 | drop_file_write_access(file); | 221 | put_write_access(inode); |
222 | __mnt_drop_write(mnt); | ||
223 | } | ||
253 | file->f_path.dentry = NULL; | 224 | file->f_path.dentry = NULL; |
254 | file->f_path.mnt = NULL; | 225 | file->f_path.mnt = NULL; |
255 | file->f_inode = NULL; | 226 | file->f_inode = NULL; |