aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file_table.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-03-14 12:02:47 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-04-01 23:19:12 -0400
commit83f936c75e3689a63253d89c47a4d239c56d7410 (patch)
tree430d89096a9b56ffb8e80bd4febde39e1d05ad4c /fs/file_table.c
parent0ccb286346c4c0644be17f04a9eb23ad99262882 (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.c37
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}
194EXPORT_SYMBOL(alloc_file); 184EXPORT_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 */
204static 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 */
219static void __fput(struct file *file) 188static 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;