aboutsummaryrefslogtreecommitdiffstats
path: root/mm/filemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 88d719665a28..45a2d18df849 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1105,6 +1105,12 @@ page_not_up_to_date_locked:
1105 } 1105 }
1106 1106
1107readpage: 1107readpage:
1108 /*
1109 * A previous I/O error may have been due to temporary
1110 * failures, eg. multipath errors.
1111 * PG_error will be set again if readpage fails.
1112 */
1113 ClearPageError(page);
1108 /* Start the actual read. The read will unlock the page. */ 1114 /* Start the actual read. The read will unlock the page. */
1109 error = mapping->a_ops->readpage(filp, page); 1115 error = mapping->a_ops->readpage(filp, page);
1110 1116
@@ -1269,7 +1275,7 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1269{ 1275{
1270 struct file *filp = iocb->ki_filp; 1276 struct file *filp = iocb->ki_filp;
1271 ssize_t retval; 1277 ssize_t retval;
1272 unsigned long seg; 1278 unsigned long seg = 0;
1273 size_t count; 1279 size_t count;
1274 loff_t *ppos = &iocb->ki_pos; 1280 loff_t *ppos = &iocb->ki_pos;
1275 1281
@@ -1296,21 +1302,47 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
1296 retval = mapping->a_ops->direct_IO(READ, iocb, 1302 retval = mapping->a_ops->direct_IO(READ, iocb,
1297 iov, pos, nr_segs); 1303 iov, pos, nr_segs);
1298 } 1304 }
1299 if (retval > 0) 1305 if (retval > 0) {
1300 *ppos = pos + retval; 1306 *ppos = pos + retval;
1301 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) {
1302 file_accessed(filp); 1319 file_accessed(filp);
1303 goto out; 1320 goto out;
1304 } 1321 }
1305 } 1322 }
1306 } 1323 }
1307 1324
1325 count = retval;
1308 for (seg = 0; seg < nr_segs; seg++) { 1326 for (seg = 0; seg < nr_segs; seg++) {
1309 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 }
1310 1342
1311 desc.written = 0; 1343 desc.written = 0;
1312 desc.arg.buf = iov[seg].iov_base; 1344 desc.arg.buf = iov[seg].iov_base + offset;
1313 desc.count = iov[seg].iov_len; 1345 desc.count = iov[seg].iov_len - offset;
1314 if (desc.count == 0) 1346 if (desc.count == 0)
1315 continue; 1347 continue;
1316 desc.error = 0; 1348 desc.error = 0;