summaryrefslogtreecommitdiffstats
path: root/fs/ext4/file.c
diff options
context:
space:
mode:
authorGoldwyn Rodrigues <rgoldwyn@suse.com>2017-06-20 08:05:47 -0400
committerJens Axboe <axboe@kernel.dk>2017-06-20 09:12:03 -0400
commit728fbc0e10b7f3ce2ee043b32e3453fd5201c055 (patch)
treeeff612a5bd8832bb002d3adde66a9b6c5a475f6d /fs/ext4/file.c
parent03a07c92a9ed9938d828ca7f1d11b8bc63a7bb89 (diff)
ext4: nowait aio support
Return EAGAIN if any of the following checks fail for direct I/O: + i_rwsem is lockable + Writing beyond end of file (will trigger allocation) + Blocks are not allocated at the write location Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/ext4/file.c')
-rw-r--r--fs/ext4/file.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 02ce7e7bbdf5..58e2eeaa0bc4 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -37,7 +37,11 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
37 struct inode *inode = file_inode(iocb->ki_filp); 37 struct inode *inode = file_inode(iocb->ki_filp);
38 ssize_t ret; 38 ssize_t ret;
39 39
40 inode_lock_shared(inode); 40 if (!inode_trylock_shared(inode)) {
41 if (iocb->ki_flags & IOCB_NOWAIT)
42 return -EAGAIN;
43 inode_lock_shared(inode);
44 }
41 /* 45 /*
42 * Recheck under inode lock - at this point we are sure it cannot 46 * Recheck under inode lock - at this point we are sure it cannot
43 * change anymore 47 * change anymore
@@ -179,7 +183,11 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
179 struct inode *inode = file_inode(iocb->ki_filp); 183 struct inode *inode = file_inode(iocb->ki_filp);
180 ssize_t ret; 184 ssize_t ret;
181 185
182 inode_lock(inode); 186 if (!inode_trylock(inode)) {
187 if (iocb->ki_flags & IOCB_NOWAIT)
188 return -EAGAIN;
189 inode_lock(inode);
190 }
183 ret = ext4_write_checks(iocb, from); 191 ret = ext4_write_checks(iocb, from);
184 if (ret <= 0) 192 if (ret <= 0)
185 goto out; 193 goto out;
@@ -216,7 +224,12 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
216 return ext4_dax_write_iter(iocb, from); 224 return ext4_dax_write_iter(iocb, from);
217#endif 225#endif
218 226
219 inode_lock(inode); 227 if (!inode_trylock(inode)) {
228 if (iocb->ki_flags & IOCB_NOWAIT)
229 return -EAGAIN;
230 inode_lock(inode);
231 }
232
220 ret = ext4_write_checks(iocb, from); 233 ret = ext4_write_checks(iocb, from);
221 if (ret <= 0) 234 if (ret <= 0)
222 goto out; 235 goto out;
@@ -235,9 +248,15 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
235 248
236 iocb->private = &overwrite; 249 iocb->private = &overwrite;
237 /* Check whether we do a DIO overwrite or not */ 250 /* Check whether we do a DIO overwrite or not */
238 if (o_direct && ext4_should_dioread_nolock(inode) && !unaligned_aio && 251 if (o_direct && !unaligned_aio) {
239 ext4_overwrite_io(inode, iocb->ki_pos, iov_iter_count(from))) 252 if (ext4_overwrite_io(inode, iocb->ki_pos, iov_iter_count(from))) {
240 overwrite = 1; 253 if (ext4_should_dioread_nolock(inode))
254 overwrite = 1;
255 } else if (iocb->ki_flags & IOCB_NOWAIT) {
256 ret = -EAGAIN;
257 goto out;
258 }
259 }
241 260
242 ret = __generic_file_write_iter(iocb, from); 261 ret = __generic_file_write_iter(iocb, from);
243 inode_unlock(inode); 262 inode_unlock(inode);
@@ -435,6 +454,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
435 if (ret < 0) 454 if (ret < 0)
436 return ret; 455 return ret;
437 } 456 }
457
458 /* Set the flags to support nowait AIO */
459 filp->f_mode |= FMODE_AIO_NOWAIT;
460
438 return dquot_file_open(inode, filp); 461 return dquot_file_open(inode, filp);
439} 462}
440 463