aboutsummaryrefslogtreecommitdiffstats
path: root/fs/direct-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/direct-io.c')
-rw-r--r--fs/direct-io.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 472037732daf..3bf3f20f8ecc 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -224,9 +224,9 @@ static inline struct page *dio_get_page(struct dio *dio,
224 * filesystems can use it to hold additional state between get_block calls and 224 * filesystems can use it to hold additional state between get_block calls and
225 * dio_complete. 225 * dio_complete.
226 */ 226 */
227static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, 227static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
228 bool is_async)
229{ 228{
229 loff_t offset = dio->iocb->ki_pos;
230 ssize_t transferred = 0; 230 ssize_t transferred = 0;
231 231
232 /* 232 /*
@@ -256,6 +256,7 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret,
256 if (dio->end_io) { 256 if (dio->end_io) {
257 int err; 257 int err;
258 258
259 // XXX: ki_pos??
259 err = dio->end_io(dio->iocb, offset, ret, dio->private); 260 err = dio->end_io(dio->iocb, offset, ret, dio->private);
260 if (err) 261 if (err)
261 ret = err; 262 ret = err;
@@ -265,15 +266,15 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret,
265 inode_dio_end(dio->inode); 266 inode_dio_end(dio->inode);
266 267
267 if (is_async) { 268 if (is_async) {
268 if (dio->rw & WRITE) { 269 /*
269 int err; 270 * generic_write_sync expects ki_pos to have been updated
270 271 * already, but the submission path only does this for
271 err = generic_write_sync(dio->iocb->ki_filp, offset, 272 * synchronous I/O.
272 transferred); 273 */
273 if (err < 0 && ret > 0) 274 dio->iocb->ki_pos += transferred;
274 ret = err;
275 }
276 275
276 if (dio->rw & WRITE)
277 ret = generic_write_sync(dio->iocb, transferred);
277 dio->iocb->ki_complete(dio->iocb, ret, 0); 278 dio->iocb->ki_complete(dio->iocb, ret, 0);
278 } 279 }
279 280
@@ -285,7 +286,7 @@ static void dio_aio_complete_work(struct work_struct *work)
285{ 286{
286 struct dio *dio = container_of(work, struct dio, complete_work); 287 struct dio *dio = container_of(work, struct dio, complete_work);
287 288
288 dio_complete(dio, dio->iocb->ki_pos, 0, true); 289 dio_complete(dio, 0, true);
289} 290}
290 291
291static int dio_bio_complete(struct dio *dio, struct bio *bio); 292static int dio_bio_complete(struct dio *dio, struct bio *bio);
@@ -314,7 +315,7 @@ static void dio_bio_end_aio(struct bio *bio)
314 queue_work(dio->inode->i_sb->s_dio_done_wq, 315 queue_work(dio->inode->i_sb->s_dio_done_wq,
315 &dio->complete_work); 316 &dio->complete_work);
316 } else { 317 } else {
317 dio_complete(dio, dio->iocb->ki_pos, 0, true); 318 dio_complete(dio, 0, true);
318 } 319 }
319 } 320 }
320} 321}
@@ -1113,7 +1114,7 @@ static inline int drop_refcount(struct dio *dio)
1113static inline ssize_t 1114static inline ssize_t
1114do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, 1115do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
1115 struct block_device *bdev, struct iov_iter *iter, 1116 struct block_device *bdev, struct iov_iter *iter,
1116 loff_t offset, get_block_t get_block, dio_iodone_t end_io, 1117 get_block_t get_block, dio_iodone_t end_io,
1117 dio_submit_t submit_io, int flags) 1118 dio_submit_t submit_io, int flags)
1118{ 1119{
1119 unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits); 1120 unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits);
@@ -1121,6 +1122,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
1121 unsigned blocksize_mask = (1 << blkbits) - 1; 1122 unsigned blocksize_mask = (1 << blkbits) - 1;
1122 ssize_t retval = -EINVAL; 1123 ssize_t retval = -EINVAL;
1123 size_t count = iov_iter_count(iter); 1124 size_t count = iov_iter_count(iter);
1125 loff_t offset = iocb->ki_pos;
1124 loff_t end = offset + count; 1126 loff_t end = offset + count;
1125 struct dio *dio; 1127 struct dio *dio;
1126 struct dio_submit sdio = { 0, }; 1128 struct dio_submit sdio = { 0, };
@@ -1318,7 +1320,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
1318 dio_await_completion(dio); 1320 dio_await_completion(dio);
1319 1321
1320 if (drop_refcount(dio) == 0) { 1322 if (drop_refcount(dio) == 0) {
1321 retval = dio_complete(dio, offset, retval, false); 1323 retval = dio_complete(dio, retval, false);
1322 } else 1324 } else
1323 BUG_ON(retval != -EIOCBQUEUED); 1325 BUG_ON(retval != -EIOCBQUEUED);
1324 1326
@@ -1328,7 +1330,7 @@ out:
1328 1330
1329ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, 1331ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
1330 struct block_device *bdev, struct iov_iter *iter, 1332 struct block_device *bdev, struct iov_iter *iter,
1331 loff_t offset, get_block_t get_block, 1333 get_block_t get_block,
1332 dio_iodone_t end_io, dio_submit_t submit_io, 1334 dio_iodone_t end_io, dio_submit_t submit_io,
1333 int flags) 1335 int flags)
1334{ 1336{
@@ -1344,7 +1346,7 @@ ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
1344 prefetch(bdev->bd_queue); 1346 prefetch(bdev->bd_queue);
1345 prefetch((char *)bdev->bd_queue + SMP_CACHE_BYTES); 1347 prefetch((char *)bdev->bd_queue + SMP_CACHE_BYTES);
1346 1348
1347 return do_blockdev_direct_IO(iocb, inode, bdev, iter, offset, get_block, 1349 return do_blockdev_direct_IO(iocb, inode, bdev, iter, get_block,
1348 end_io, submit_io, flags); 1350 end_io, submit_io, flags);
1349} 1351}
1350 1352