diff options
Diffstat (limited to 'fs/direct-io.c')
-rw-r--r-- | fs/direct-io.c | 104 |
1 files changed, 36 insertions, 68 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c index 7600aacf531d..85882f6ba5f7 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -218,7 +218,7 @@ static struct page *dio_get_page(struct dio *dio) | |||
218 | * filesystems can use it to hold additional state between get_block calls and | 218 | * filesystems can use it to hold additional state between get_block calls and |
219 | * dio_complete. | 219 | * dio_complete. |
220 | */ | 220 | */ |
221 | static int dio_complete(struct dio *dio, loff_t offset, int ret) | 221 | static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is_async) |
222 | { | 222 | { |
223 | ssize_t transferred = 0; | 223 | ssize_t transferred = 0; |
224 | 224 | ||
@@ -239,14 +239,6 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret) | |||
239 | transferred = dio->i_size - offset; | 239 | transferred = dio->i_size - offset; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (dio->end_io && dio->result) | ||
243 | dio->end_io(dio->iocb, offset, transferred, | ||
244 | dio->map_bh.b_private); | ||
245 | |||
246 | if (dio->flags & DIO_LOCKING) | ||
247 | /* lockdep: non-owner release */ | ||
248 | up_read_non_owner(&dio->inode->i_alloc_sem); | ||
249 | |||
250 | if (ret == 0) | 242 | if (ret == 0) |
251 | ret = dio->page_errors; | 243 | ret = dio->page_errors; |
252 | if (ret == 0) | 244 | if (ret == 0) |
@@ -254,6 +246,17 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret) | |||
254 | if (ret == 0) | 246 | if (ret == 0) |
255 | ret = transferred; | 247 | ret = transferred; |
256 | 248 | ||
249 | if (dio->end_io && dio->result) { | ||
250 | dio->end_io(dio->iocb, offset, transferred, | ||
251 | dio->map_bh.b_private, ret, is_async); | ||
252 | } else if (is_async) { | ||
253 | aio_complete(dio->iocb, ret, 0); | ||
254 | } | ||
255 | |||
256 | if (dio->flags & DIO_LOCKING) | ||
257 | /* lockdep: non-owner release */ | ||
258 | up_read_non_owner(&dio->inode->i_alloc_sem); | ||
259 | |||
257 | return ret; | 260 | return ret; |
258 | } | 261 | } |
259 | 262 | ||
@@ -277,8 +280,7 @@ static void dio_bio_end_aio(struct bio *bio, int error) | |||
277 | spin_unlock_irqrestore(&dio->bio_lock, flags); | 280 | spin_unlock_irqrestore(&dio->bio_lock, flags); |
278 | 281 | ||
279 | if (remaining == 0) { | 282 | if (remaining == 0) { |
280 | int ret = dio_complete(dio, dio->iocb->ki_pos, 0); | 283 | dio_complete(dio, dio->iocb->ki_pos, 0, true); |
281 | aio_complete(dio->iocb, ret, 0); | ||
282 | kfree(dio); | 284 | kfree(dio); |
283 | } | 285 | } |
284 | } | 286 | } |
@@ -632,7 +634,7 @@ static int dio_send_cur_page(struct dio *dio) | |||
632 | int ret = 0; | 634 | int ret = 0; |
633 | 635 | ||
634 | if (dio->bio) { | 636 | if (dio->bio) { |
635 | loff_t cur_offset = dio->block_in_file << dio->blkbits; | 637 | loff_t cur_offset = dio->cur_page_fs_offset; |
636 | loff_t bio_next_offset = dio->logical_offset_in_bio + | 638 | loff_t bio_next_offset = dio->logical_offset_in_bio + |
637 | dio->bio->bi_size; | 639 | dio->bio->bi_size; |
638 | 640 | ||
@@ -657,7 +659,7 @@ static int dio_send_cur_page(struct dio *dio) | |||
657 | * Submit now if the underlying fs is about to perform a | 659 | * Submit now if the underlying fs is about to perform a |
658 | * metadata read | 660 | * metadata read |
659 | */ | 661 | */ |
660 | if (dio->boundary) | 662 | else if (dio->boundary) |
661 | dio_bio_submit(dio); | 663 | dio_bio_submit(dio); |
662 | } | 664 | } |
663 | 665 | ||
@@ -1126,7 +1128,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
1126 | spin_unlock_irqrestore(&dio->bio_lock, flags); | 1128 | spin_unlock_irqrestore(&dio->bio_lock, flags); |
1127 | 1129 | ||
1128 | if (ret2 == 0) { | 1130 | if (ret2 == 0) { |
1129 | ret = dio_complete(dio, offset, ret); | 1131 | ret = dio_complete(dio, offset, ret, false); |
1130 | kfree(dio); | 1132 | kfree(dio); |
1131 | } else | 1133 | } else |
1132 | BUG_ON(ret != -EIOCBQUEUED); | 1134 | BUG_ON(ret != -EIOCBQUEUED); |
@@ -1134,8 +1136,27 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
1134 | return ret; | 1136 | return ret; |
1135 | } | 1137 | } |
1136 | 1138 | ||
1139 | /* | ||
1140 | * This is a library function for use by filesystem drivers. | ||
1141 | * | ||
1142 | * The locking rules are governed by the flags parameter: | ||
1143 | * - if the flags value contains DIO_LOCKING we use a fancy locking | ||
1144 | * scheme for dumb filesystems. | ||
1145 | * For writes this function is called under i_mutex and returns with | ||
1146 | * i_mutex held, for reads, i_mutex is not held on entry, but it is | ||
1147 | * taken and dropped again before returning. | ||
1148 | * For reads and writes i_alloc_sem is taken in shared mode and released | ||
1149 | * on I/O completion (which may happen asynchronously after returning to | ||
1150 | * the caller). | ||
1151 | * | ||
1152 | * - if the flags value does NOT contain DIO_LOCKING we don't use any | ||
1153 | * internal locking but rather rely on the filesystem to synchronize | ||
1154 | * direct I/O reads/writes versus each other and truncate. | ||
1155 | * For reads and writes both i_mutex and i_alloc_sem are not held on | ||
1156 | * entry and are never taken. | ||
1157 | */ | ||
1137 | ssize_t | 1158 | ssize_t |
1138 | __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode, | 1159 | __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
1139 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | 1160 | struct block_device *bdev, const struct iovec *iov, loff_t offset, |
1140 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | 1161 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, |
1141 | dio_submit_t submit_io, int flags) | 1162 | dio_submit_t submit_io, int flags) |
@@ -1231,57 +1252,4 @@ __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode, | |||
1231 | out: | 1252 | out: |
1232 | return retval; | 1253 | return retval; |
1233 | } | 1254 | } |
1234 | EXPORT_SYMBOL(__blockdev_direct_IO_newtrunc); | ||
1235 | |||
1236 | /* | ||
1237 | * This is a library function for use by filesystem drivers. | ||
1238 | * | ||
1239 | * The locking rules are governed by the flags parameter: | ||
1240 | * - if the flags value contains DIO_LOCKING we use a fancy locking | ||
1241 | * scheme for dumb filesystems. | ||
1242 | * For writes this function is called under i_mutex and returns with | ||
1243 | * i_mutex held, for reads, i_mutex is not held on entry, but it is | ||
1244 | * taken and dropped again before returning. | ||
1245 | * For reads and writes i_alloc_sem is taken in shared mode and released | ||
1246 | * on I/O completion (which may happen asynchronously after returning to | ||
1247 | * the caller). | ||
1248 | * | ||
1249 | * - if the flags value does NOT contain DIO_LOCKING we don't use any | ||
1250 | * internal locking but rather rely on the filesystem to synchronize | ||
1251 | * direct I/O reads/writes versus each other and truncate. | ||
1252 | * For reads and writes both i_mutex and i_alloc_sem are not held on | ||
1253 | * entry and are never taken. | ||
1254 | */ | ||
1255 | ssize_t | ||
1256 | __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | ||
1257 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | ||
1258 | unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, | ||
1259 | dio_submit_t submit_io, int flags) | ||
1260 | { | ||
1261 | ssize_t retval; | ||
1262 | |||
1263 | retval = __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, | ||
1264 | offset, nr_segs, get_block, end_io, submit_io, flags); | ||
1265 | /* | ||
1266 | * In case of error extending write may have instantiated a few | ||
1267 | * blocks outside i_size. Trim these off again for DIO_LOCKING. | ||
1268 | * NOTE: DIO_NO_LOCK/DIO_OWN_LOCK callers have to handle this in | ||
1269 | * their own manner. This is a further example of where the old | ||
1270 | * truncate sequence is inadequate. | ||
1271 | * | ||
1272 | * NOTE: filesystems with their own locking have to handle this | ||
1273 | * on their own. | ||
1274 | */ | ||
1275 | if (flags & DIO_LOCKING) { | ||
1276 | if (unlikely((rw & WRITE) && retval < 0)) { | ||
1277 | loff_t isize = i_size_read(inode); | ||
1278 | loff_t end = offset + iov_length(iov, nr_segs); | ||
1279 | |||
1280 | if (end > isize) | ||
1281 | vmtruncate(inode, isize); | ||
1282 | } | ||
1283 | } | ||
1284 | |||
1285 | return retval; | ||
1286 | } | ||
1287 | EXPORT_SYMBOL(__blockdev_direct_IO); | 1255 | EXPORT_SYMBOL(__blockdev_direct_IO); |