aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-03-14 10:56:20 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-04-01 23:19:11 -0400
commitdd20908a8a06b22c171f6c3fcdbdbd65bed07505 (patch)
tree447e2df881b2f056608098d3b24ab6d9734ce992
parent44ba8406d0005400e56c6b6a279a669eb761d1b8 (diff)
don't bother with {get,put}_write_access() on non-regular files
it's pointless and actually leads to wrong behaviour in at least one moderately convoluted case (pipe(), close one end, try to get to another via /proc/*/fd and run into ETXTBUSY). Cc: stable@vger.kernel.org Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/file_table.c4
-rw-r--r--fs/open.c26
2 files changed, 9 insertions, 21 deletions
diff --git a/fs/file_table.c b/fs/file_table.c
index 5b24008ea4f6..79ecae62209a 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -209,10 +209,10 @@ static void drop_file_write_access(struct file *file)
209 struct dentry *dentry = file->f_path.dentry; 209 struct dentry *dentry = file->f_path.dentry;
210 struct inode *inode = dentry->d_inode; 210 struct inode *inode = dentry->d_inode;
211 211
212 put_write_access(inode);
213
214 if (special_file(inode->i_mode)) 212 if (special_file(inode->i_mode))
215 return; 213 return;
214
215 put_write_access(inode);
216 if (file_check_writeable(file) != 0) 216 if (file_check_writeable(file) != 0)
217 return; 217 return;
218 __mnt_drop_write(mnt); 218 __mnt_drop_write(mnt);
diff --git a/fs/open.c b/fs/open.c
index b9ed8b25c108..2ed7325f713e 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -641,23 +641,12 @@ out:
641static inline int __get_file_write_access(struct inode *inode, 641static inline int __get_file_write_access(struct inode *inode,
642 struct vfsmount *mnt) 642 struct vfsmount *mnt)
643{ 643{
644 int error; 644 int error = get_write_access(inode);
645 error = get_write_access(inode);
646 if (error) 645 if (error)
647 return error; 646 return error;
648 /* 647 error = __mnt_want_write(mnt);
649 * Do not take mount writer counts on 648 if (error)
650 * special files since no writes to 649 put_write_access(inode);
651 * the mount itself will occur.
652 */
653 if (!special_file(inode->i_mode)) {
654 /*
655 * Balanced in __fput()
656 */
657 error = __mnt_want_write(mnt);
658 if (error)
659 put_write_access(inode);
660 }
661 return error; 650 return error;
662} 651}
663 652
@@ -690,12 +679,11 @@ static int do_dentry_open(struct file *f,
690 679
691 path_get(&f->f_path); 680 path_get(&f->f_path);
692 inode = f->f_inode = f->f_path.dentry->d_inode; 681 inode = f->f_inode = f->f_path.dentry->d_inode;
693 if (f->f_mode & FMODE_WRITE) { 682 if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
694 error = __get_file_write_access(inode, f->f_path.mnt); 683 error = __get_file_write_access(inode, f->f_path.mnt);
695 if (error) 684 if (error)
696 goto cleanup_file; 685 goto cleanup_file;
697 if (!special_file(inode->i_mode)) 686 file_take_write(f);
698 file_take_write(f);
699 } 687 }
700 688
701 f->f_mapping = inode->i_mapping; 689 f->f_mapping = inode->i_mapping;
@@ -742,7 +730,6 @@ static int do_dentry_open(struct file *f,
742cleanup_all: 730cleanup_all:
743 fops_put(f->f_op); 731 fops_put(f->f_op);
744 if (f->f_mode & FMODE_WRITE) { 732 if (f->f_mode & FMODE_WRITE) {
745 put_write_access(inode);
746 if (!special_file(inode->i_mode)) { 733 if (!special_file(inode->i_mode)) {
747 /* 734 /*
748 * We don't consider this a real 735 * We don't consider this a real
@@ -750,6 +737,7 @@ cleanup_all:
750 * because it all happenend right 737 * because it all happenend right
751 * here, so just reset the state. 738 * here, so just reset the state.
752 */ 739 */
740 put_write_access(inode);
753 file_reset_write(f); 741 file_reset_write(f);
754 __mnt_drop_write(f->f_path.mnt); 742 __mnt_drop_write(f->f_path.mnt);
755 } 743 }