diff options
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 79 |
1 files changed, 28 insertions, 51 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 70273f8df586..8f1a95406bae 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1402,13 +1402,25 @@ shmem_write_end(struct file *file, struct address_space *mapping, | |||
1402 | return copied; | 1402 | return copied; |
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor) | 1405 | static ssize_t shmem_file_aio_read(struct kiocb *iocb, |
1406 | const struct iovec *iov, unsigned long nr_segs, loff_t pos) | ||
1406 | { | 1407 | { |
1407 | struct inode *inode = file_inode(filp); | 1408 | struct file *file = iocb->ki_filp; |
1409 | struct inode *inode = file_inode(file); | ||
1408 | struct address_space *mapping = inode->i_mapping; | 1410 | struct address_space *mapping = inode->i_mapping; |
1409 | pgoff_t index; | 1411 | pgoff_t index; |
1410 | unsigned long offset; | 1412 | unsigned long offset; |
1411 | enum sgp_type sgp = SGP_READ; | 1413 | enum sgp_type sgp = SGP_READ; |
1414 | int error; | ||
1415 | ssize_t retval; | ||
1416 | size_t count; | ||
1417 | loff_t *ppos = &iocb->ki_pos; | ||
1418 | struct iov_iter iter; | ||
1419 | |||
1420 | retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); | ||
1421 | if (retval) | ||
1422 | return retval; | ||
1423 | iov_iter_init(&iter, iov, nr_segs, count, 0); | ||
1412 | 1424 | ||
1413 | /* | 1425 | /* |
1414 | * Might this read be for a stacking filesystem? Then when reading | 1426 | * Might this read be for a stacking filesystem? Then when reading |
@@ -1436,10 +1448,10 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ | |||
1436 | break; | 1448 | break; |
1437 | } | 1449 | } |
1438 | 1450 | ||
1439 | desc->error = shmem_getpage(inode, index, &page, sgp, NULL); | 1451 | error = shmem_getpage(inode, index, &page, sgp, NULL); |
1440 | if (desc->error) { | 1452 | if (error) { |
1441 | if (desc->error == -EINVAL) | 1453 | if (error == -EINVAL) |
1442 | desc->error = 0; | 1454 | error = 0; |
1443 | break; | 1455 | break; |
1444 | } | 1456 | } |
1445 | if (page) | 1457 | if (page) |
@@ -1483,61 +1495,26 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ | |||
1483 | /* | 1495 | /* |
1484 | * Ok, we have the page, and it's up-to-date, so | 1496 | * Ok, we have the page, and it's up-to-date, so |
1485 | * now we can copy it to user space... | 1497 | * now we can copy it to user space... |
1486 | * | ||
1487 | * The actor routine returns how many bytes were actually used.. | ||
1488 | * NOTE! This may not be the same as how much of a user buffer | ||
1489 | * we filled up (we may be padding etc), so we can only update | ||
1490 | * "pos" here (the actor routine has to update the user buffer | ||
1491 | * pointers and the remaining count). | ||
1492 | */ | 1498 | */ |
1493 | ret = actor(desc, page, offset, nr); | 1499 | ret = copy_page_to_iter(page, offset, nr, &iter); |
1500 | retval += ret; | ||
1494 | offset += ret; | 1501 | offset += ret; |
1495 | index += offset >> PAGE_CACHE_SHIFT; | 1502 | index += offset >> PAGE_CACHE_SHIFT; |
1496 | offset &= ~PAGE_CACHE_MASK; | 1503 | offset &= ~PAGE_CACHE_MASK; |
1497 | 1504 | ||
1498 | page_cache_release(page); | 1505 | page_cache_release(page); |
1499 | if (ret != nr || !desc->count) | 1506 | if (!iov_iter_count(&iter)) |
1500 | break; | 1507 | break; |
1501 | 1508 | if (ret < nr) { | |
1509 | error = -EFAULT; | ||
1510 | break; | ||
1511 | } | ||
1502 | cond_resched(); | 1512 | cond_resched(); |
1503 | } | 1513 | } |
1504 | 1514 | ||
1505 | *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; | 1515 | *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; |
1506 | file_accessed(filp); | 1516 | file_accessed(file); |
1507 | } | 1517 | return retval ? retval : error; |
1508 | |||
1509 | static ssize_t shmem_file_aio_read(struct kiocb *iocb, | ||
1510 | const struct iovec *iov, unsigned long nr_segs, loff_t pos) | ||
1511 | { | ||
1512 | struct file *filp = iocb->ki_filp; | ||
1513 | ssize_t retval; | ||
1514 | unsigned long seg; | ||
1515 | size_t count; | ||
1516 | loff_t *ppos = &iocb->ki_pos; | ||
1517 | |||
1518 | retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); | ||
1519 | if (retval) | ||
1520 | return retval; | ||
1521 | |||
1522 | for (seg = 0; seg < nr_segs; seg++) { | ||
1523 | read_descriptor_t desc; | ||
1524 | |||
1525 | desc.written = 0; | ||
1526 | desc.arg.buf = iov[seg].iov_base; | ||
1527 | desc.count = iov[seg].iov_len; | ||
1528 | if (desc.count == 0) | ||
1529 | continue; | ||
1530 | desc.error = 0; | ||
1531 | do_shmem_file_read(filp, ppos, &desc, file_read_actor); | ||
1532 | retval += desc.written; | ||
1533 | if (desc.error) { | ||
1534 | retval = retval ?: desc.error; | ||
1535 | break; | ||
1536 | } | ||
1537 | if (desc.count > 0) | ||
1538 | break; | ||
1539 | } | ||
1540 | return retval; | ||
1541 | } | 1518 | } |
1542 | 1519 | ||
1543 | static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | 1520 | static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, |
@@ -1576,7 +1553,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | |||
1576 | index = *ppos >> PAGE_CACHE_SHIFT; | 1553 | index = *ppos >> PAGE_CACHE_SHIFT; |
1577 | loff = *ppos & ~PAGE_CACHE_MASK; | 1554 | loff = *ppos & ~PAGE_CACHE_MASK; |
1578 | req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 1555 | req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
1579 | nr_pages = min(req_pages, pipe->buffers); | 1556 | nr_pages = min(req_pages, spd.nr_pages_max); |
1580 | 1557 | ||
1581 | spd.nr_pages = find_get_pages_contig(mapping, index, | 1558 | spd.nr_pages = find_get_pages_contig(mapping, index, |
1582 | nr_pages, spd.pages); | 1559 | nr_pages, spd.pages); |