diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/filemap.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 35e12d186566..45a2d18df849 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1275,7 +1275,7 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
1275 | { | 1275 | { |
1276 | struct file *filp = iocb->ki_filp; | 1276 | struct file *filp = iocb->ki_filp; |
1277 | ssize_t retval; | 1277 | ssize_t retval; |
1278 | unsigned long seg; | 1278 | unsigned long seg = 0; |
1279 | size_t count; | 1279 | size_t count; |
1280 | loff_t *ppos = &iocb->ki_pos; | 1280 | loff_t *ppos = &iocb->ki_pos; |
1281 | 1281 | ||
@@ -1302,21 +1302,47 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
1302 | retval = mapping->a_ops->direct_IO(READ, iocb, | 1302 | retval = mapping->a_ops->direct_IO(READ, iocb, |
1303 | iov, pos, nr_segs); | 1303 | iov, pos, nr_segs); |
1304 | } | 1304 | } |
1305 | if (retval > 0) | 1305 | if (retval > 0) { |
1306 | *ppos = pos + retval; | 1306 | *ppos = pos + retval; |
1307 | if (retval) { | 1307 | count -= retval; |
1308 | } | ||
1309 | |||
1310 | /* | ||
1311 | * Btrfs can have a short DIO read if we encounter | ||
1312 | * compressed extents, so if there was an error, or if | ||
1313 | * we've already read everything we wanted to, or if | ||
1314 | * there was a short read because we hit EOF, go ahead | ||
1315 | * and return. Otherwise fallthrough to buffered io for | ||
1316 | * the rest of the read. | ||
1317 | */ | ||
1318 | if (retval < 0 || !count || *ppos >= size) { | ||
1308 | file_accessed(filp); | 1319 | file_accessed(filp); |
1309 | goto out; | 1320 | goto out; |
1310 | } | 1321 | } |
1311 | } | 1322 | } |
1312 | } | 1323 | } |
1313 | 1324 | ||
1325 | count = retval; | ||
1314 | for (seg = 0; seg < nr_segs; seg++) { | 1326 | for (seg = 0; seg < nr_segs; seg++) { |
1315 | read_descriptor_t desc; | 1327 | read_descriptor_t desc; |
1328 | loff_t offset = 0; | ||
1329 | |||
1330 | /* | ||
1331 | * If we did a short DIO read we need to skip the section of the | ||
1332 | * iov that we've already read data into. | ||
1333 | */ | ||
1334 | if (count) { | ||
1335 | if (count > iov[seg].iov_len) { | ||
1336 | count -= iov[seg].iov_len; | ||
1337 | continue; | ||
1338 | } | ||
1339 | offset = count; | ||
1340 | count = 0; | ||
1341 | } | ||
1316 | 1342 | ||
1317 | desc.written = 0; | 1343 | desc.written = 0; |
1318 | desc.arg.buf = iov[seg].iov_base; | 1344 | desc.arg.buf = iov[seg].iov_base + offset; |
1319 | desc.count = iov[seg].iov_len; | 1345 | desc.count = iov[seg].iov_len - offset; |
1320 | if (desc.count == 0) | 1346 | if (desc.count == 0) |
1321 | continue; | 1347 | continue; |
1322 | desc.error = 0; | 1348 | desc.error = 0; |