aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-16 23:27:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-16 23:27:56 -0400
commit4fc8adcfec3da639da76e8314c9ccefe5bf9a045 (patch)
treee07a2dea8acf04d8bbbecd4fd3a571653ecdd953 /fs/udf/file.c
parent84588e7a5d8220446d677d7b909a20ee7a4496b9 (diff)
parentaa4d86163e4e91a1ac560954a554bab417e338f4 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull third hunk of vfs changes from Al Viro: "This contains the ->direct_IO() changes from Omar + saner generic_write_checks() + dealing with fcntl()/{read,write}() races (mirroring O_APPEND/O_DIRECT into iocb->ki_flags and instead of repeatedly looking at ->f_flags, which can be changed by fcntl(2), check ->ki_flags - which cannot) + infrastructure bits for dhowells' d_inode annotations + Christophs switch of /dev/loop to vfs_iter_write()" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (30 commits) block: loop: switch to VFS ITER_BVEC configfs: Fix inconsistent use of file_inode() vs file->f_path.dentry->d_inode VFS: Make pathwalk use d_is_reg() rather than S_ISREG() VFS: Fix up debugfs to use d_is_dir() in place of S_ISDIR() VFS: Combine inode checks with d_is_negative() and d_is_positive() in pathwalk NFS: Don't use d_inode as a variable name VFS: Impose ordering on accesses of d_inode and d_flags VFS: Add owner-filesystem positive/negative dentry checks nfs: generic_write_checks() shouldn't be done on swapout... ocfs2: use __generic_file_write_iter() mirror O_APPEND and O_DIRECT into iocb->ki_flags switch generic_write_checks() to iocb and iter ocfs2: move generic_write_checks() before the alignment checks ocfs2_file_write_iter: stop messing with ppos udf_file_write_iter: reorder and simplify fuse: ->direct_IO() doesn't need generic_write_checks() ext4_file_write_iter: move generic_write_checks() up xfs_file_aio_write_checks: switch to iocb/iov_iter generic_write_checks(): drop isblk argument blkdev_write_iter: expand generic_file_checks() call in there ...
Diffstat (limited to 'fs/udf/file.c')
-rw-r--r--fs/udf/file.c25
1 files changed, 11 insertions, 14 deletions
diff --git a/fs/udf/file.c b/fs/udf/file.c
index f77f7681288f..5dadad9960b9 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -99,8 +99,7 @@ static int udf_adinicb_write_begin(struct file *file,
99 return 0; 99 return 0;
100} 100}
101 101
102static ssize_t udf_adinicb_direct_IO(int rw, struct kiocb *iocb, 102static ssize_t udf_adinicb_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
103 struct iov_iter *iter,
104 loff_t offset) 103 loff_t offset)
105{ 104{
106 /* Fallback to buffered I/O. */ 105 /* Fallback to buffered I/O. */
@@ -120,21 +119,21 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
120 ssize_t retval; 119 ssize_t retval;
121 struct file *file = iocb->ki_filp; 120 struct file *file = iocb->ki_filp;
122 struct inode *inode = file_inode(file); 121 struct inode *inode = file_inode(file);
123 int err, pos;
124 size_t count = iov_iter_count(from);
125 struct udf_inode_info *iinfo = UDF_I(inode); 122 struct udf_inode_info *iinfo = UDF_I(inode);
123 int err;
126 124
127 mutex_lock(&inode->i_mutex); 125 mutex_lock(&inode->i_mutex);
126
127 retval = generic_write_checks(iocb, from);
128 if (retval <= 0)
129 goto out;
130
128 down_write(&iinfo->i_data_sem); 131 down_write(&iinfo->i_data_sem);
129 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { 132 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
130 if (file->f_flags & O_APPEND) 133 loff_t end = iocb->ki_pos + iov_iter_count(from);
131 pos = inode->i_size;
132 else
133 pos = iocb->ki_pos;
134 134
135 if (inode->i_sb->s_blocksize < 135 if (inode->i_sb->s_blocksize <
136 (udf_file_entry_alloc_offset(inode) + 136 (udf_file_entry_alloc_offset(inode) + end)) {
137 pos + count)) {
138 err = udf_expand_file_adinicb(inode); 137 err = udf_expand_file_adinicb(inode);
139 if (err) { 138 if (err) {
140 mutex_unlock(&inode->i_mutex); 139 mutex_unlock(&inode->i_mutex);
@@ -142,16 +141,14 @@ static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
142 return err; 141 return err;
143 } 142 }
144 } else { 143 } else {
145 if (pos + count > inode->i_size) 144 iinfo->i_lenAlloc = max(end, inode->i_size);
146 iinfo->i_lenAlloc = pos + count;
147 else
148 iinfo->i_lenAlloc = inode->i_size;
149 up_write(&iinfo->i_data_sem); 145 up_write(&iinfo->i_data_sem);
150 } 146 }
151 } else 147 } else
152 up_write(&iinfo->i_data_sem); 148 up_write(&iinfo->i_data_sem);
153 149
154 retval = __generic_file_write_iter(iocb, from); 150 retval = __generic_file_write_iter(iocb, from);
151out:
155 mutex_unlock(&inode->i_mutex); 152 mutex_unlock(&inode->i_mutex);
156 153
157 if (retval > 0) { 154 if (retval > 0) {