aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/fs/open.c b/fs/open.c
index 8111947905d8..e12f17010324 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -730,6 +730,35 @@ out:
730 return error; 730 return error;
731} 731}
732 732
733/*
734 * You have to be very careful that these write
735 * counts get cleaned up in error cases and
736 * upon __fput(). This should probably never
737 * be called outside of __dentry_open().
738 */
739static inline int __get_file_write_access(struct inode *inode,
740 struct vfsmount *mnt)
741{
742 int error;
743 error = get_write_access(inode);
744 if (error)
745 return error;
746 /*
747 * Do not take mount writer counts on
748 * special files since no writes to
749 * the mount itself will occur.
750 */
751 if (!special_file(inode->i_mode)) {
752 /*
753 * Balanced in __fput()
754 */
755 error = mnt_want_write(mnt);
756 if (error)
757 put_write_access(inode);
758 }
759 return error;
760}
761
733static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, 762static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
734 int flags, struct file *f, 763 int flags, struct file *f,
735 int (*open)(struct inode *, struct file *)) 764 int (*open)(struct inode *, struct file *))
@@ -742,7 +771,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
742 FMODE_PREAD | FMODE_PWRITE; 771 FMODE_PREAD | FMODE_PWRITE;
743 inode = dentry->d_inode; 772 inode = dentry->d_inode;
744 if (f->f_mode & FMODE_WRITE) { 773 if (f->f_mode & FMODE_WRITE) {
745 error = get_write_access(inode); 774 error = __get_file_write_access(inode, mnt);
746 if (error) 775 if (error)
747 goto cleanup_file; 776 goto cleanup_file;
748 } 777 }
@@ -784,8 +813,11 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
784 813
785cleanup_all: 814cleanup_all:
786 fops_put(f->f_op); 815 fops_put(f->f_op);
787 if (f->f_mode & FMODE_WRITE) 816 if (f->f_mode & FMODE_WRITE) {
788 put_write_access(inode); 817 put_write_access(inode);
818 if (!special_file(inode->i_mode))
819 mnt_drop_write(mnt);
820 }
789 file_kill(f); 821 file_kill(f);
790 f->f_path.dentry = NULL; 822 f->f_path.dentry = NULL;
791 f->f_path.mnt = NULL; 823 f->f_path.mnt = NULL;