diff options
-rw-r--r-- | fs/file_table.c | 37 | ||||
-rw-r--r-- | fs/namespace.c | 4 | ||||
-rw-r--r-- | fs/open.c | 9 | ||||
-rw-r--r-- | include/linux/fs.h | 2 |
4 files changed, 11 insertions, 41 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; |
diff --git a/fs/namespace.c b/fs/namespace.c index a66aff5bd3fe..20e8696c31a7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -414,9 +414,7 @@ EXPORT_SYMBOL_GPL(mnt_clone_write); | |||
414 | */ | 414 | */ |
415 | int __mnt_want_write_file(struct file *file) | 415 | int __mnt_want_write_file(struct file *file) |
416 | { | 416 | { |
417 | struct inode *inode = file_inode(file); | 417 | if (!(file->f_mode & FMODE_WRITER)) |
418 | |||
419 | if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode)) | ||
420 | return __mnt_want_write(file->f_path.mnt); | 418 | return __mnt_want_write(file->f_path.mnt); |
421 | else | 419 | else |
422 | return mnt_clone_write(file->f_path.mnt); | 420 | return mnt_clone_write(file->f_path.mnt); |
@@ -670,6 +670,7 @@ static int do_dentry_open(struct file *f, | |||
670 | put_write_access(inode); | 670 | put_write_access(inode); |
671 | goto cleanup_file; | 671 | goto cleanup_file; |
672 | } | 672 | } |
673 | f->f_mode |= FMODE_WRITER; | ||
673 | } | 674 | } |
674 | 675 | ||
675 | f->f_mapping = inode->i_mapping; | 676 | f->f_mapping = inode->i_mapping; |
@@ -715,11 +716,9 @@ static int do_dentry_open(struct file *f, | |||
715 | 716 | ||
716 | cleanup_all: | 717 | cleanup_all: |
717 | fops_put(f->f_op); | 718 | fops_put(f->f_op); |
718 | if (f->f_mode & FMODE_WRITE) { | 719 | if (f->f_mode & FMODE_WRITER) { |
719 | if (!special_file(inode->i_mode)) { | 720 | put_write_access(inode); |
720 | put_write_access(inode); | 721 | __mnt_drop_write(f->f_path.mnt); |
721 | __mnt_drop_write(f->f_path.mnt); | ||
722 | } | ||
723 | } | 722 | } |
724 | cleanup_file: | 723 | cleanup_file: |
725 | path_put(&f->f_path); | 724 | path_put(&f->f_path); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index e80659ed78fc..d9d88a0b456e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -125,6 +125,8 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, | |||
125 | 125 | ||
126 | /* File needs atomic accesses to f_pos */ | 126 | /* File needs atomic accesses to f_pos */ |
127 | #define FMODE_ATOMIC_POS ((__force fmode_t)0x8000) | 127 | #define FMODE_ATOMIC_POS ((__force fmode_t)0x8000) |
128 | /* Write access to underlying fs */ | ||
129 | #define FMODE_WRITER ((__force fmode_t)0x10000) | ||
128 | 130 | ||
129 | /* File was opened by fanotify and shouldn't generate fanotify events */ | 131 | /* File was opened by fanotify and shouldn't generate fanotify events */ |
130 | #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) | 132 | #define FMODE_NONOTIFY ((__force fmode_t)0x1000000) |