diff options
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 77 |
1 files changed, 27 insertions, 50 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 9398e6cd48cb..17d3799d04bd 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1462,13 +1462,25 @@ shmem_write_end(struct file *file, struct address_space *mapping, | |||
1462 | return copied; | 1462 | return copied; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc) | 1465 | static ssize_t shmem_file_aio_read(struct kiocb *iocb, |
1466 | const struct iovec *iov, unsigned long nr_segs, loff_t pos) | ||
1466 | { | 1467 | { |
1467 | struct inode *inode = file_inode(filp); | 1468 | struct file *file = iocb->ki_filp; |
1469 | struct inode *inode = file_inode(file); | ||
1468 | struct address_space *mapping = inode->i_mapping; | 1470 | struct address_space *mapping = inode->i_mapping; |
1469 | pgoff_t index; | 1471 | pgoff_t index; |
1470 | unsigned long offset; | 1472 | unsigned long offset; |
1471 | enum sgp_type sgp = SGP_READ; | 1473 | enum sgp_type sgp = SGP_READ; |
1474 | int error; | ||
1475 | ssize_t retval; | ||
1476 | size_t count; | ||
1477 | loff_t *ppos = &iocb->ki_pos; | ||
1478 | struct iov_iter iter; | ||
1479 | |||
1480 | retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); | ||
1481 | if (retval) | ||
1482 | return retval; | ||
1483 | iov_iter_init(&iter, iov, nr_segs, count, 0); | ||
1472 | 1484 | ||
1473 | /* | 1485 | /* |
1474 | * Might this read be for a stacking filesystem? Then when reading | 1486 | * Might this read be for a stacking filesystem? Then when reading |
@@ -1496,10 +1508,10 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ | |||
1496 | break; | 1508 | break; |
1497 | } | 1509 | } |
1498 | 1510 | ||
1499 | desc->error = shmem_getpage(inode, index, &page, sgp, NULL); | 1511 | error = shmem_getpage(inode, index, &page, sgp, NULL); |
1500 | if (desc->error) { | 1512 | if (error) { |
1501 | if (desc->error == -EINVAL) | 1513 | if (error == -EINVAL) |
1502 | desc->error = 0; | 1514 | error = 0; |
1503 | break; | 1515 | break; |
1504 | } | 1516 | } |
1505 | if (page) | 1517 | if (page) |
@@ -1543,61 +1555,26 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ | |||
1543 | /* | 1555 | /* |
1544 | * Ok, we have the page, and it's up-to-date, so | 1556 | * Ok, we have the page, and it's up-to-date, so |
1545 | * now we can copy it to user space... | 1557 | * now we can copy it to user space... |
1546 | * | ||
1547 | * The actor routine returns how many bytes were actually used.. | ||
1548 | * NOTE! This may not be the same as how much of a user buffer | ||
1549 | * we filled up (we may be padding etc), so we can only update | ||
1550 | * "pos" here (the actor routine has to update the user buffer | ||
1551 | * pointers and the remaining count). | ||
1552 | */ | 1558 | */ |
1553 | ret = file_read_actor(desc, page, offset, nr); | 1559 | ret = copy_page_to_iter(page, offset, nr, &iter); |
1560 | retval += ret; | ||
1554 | offset += ret; | 1561 | offset += ret; |
1555 | index += offset >> PAGE_CACHE_SHIFT; | 1562 | index += offset >> PAGE_CACHE_SHIFT; |
1556 | offset &= ~PAGE_CACHE_MASK; | 1563 | offset &= ~PAGE_CACHE_MASK; |
1557 | 1564 | ||
1558 | page_cache_release(page); | 1565 | page_cache_release(page); |
1559 | if (ret != nr || !desc->count) | 1566 | if (!iov_iter_count(&iter)) |
1560 | break; | 1567 | break; |
1561 | 1568 | if (ret < nr) { | |
1569 | error = -EFAULT; | ||
1570 | break; | ||
1571 | } | ||
1562 | cond_resched(); | 1572 | cond_resched(); |
1563 | } | 1573 | } |
1564 | 1574 | ||
1565 | *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; | 1575 | *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; |
1566 | file_accessed(filp); | 1576 | file_accessed(file); |
1567 | } | 1577 | return retval ? retval : error; |
1568 | |||
1569 | static ssize_t shmem_file_aio_read(struct kiocb *iocb, | ||
1570 | const struct iovec *iov, unsigned long nr_segs, loff_t pos) | ||
1571 | { | ||
1572 | struct file *filp = iocb->ki_filp; | ||
1573 | ssize_t retval; | ||
1574 | unsigned long seg; | ||
1575 | size_t count; | ||
1576 | loff_t *ppos = &iocb->ki_pos; | ||
1577 | |||
1578 | retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); | ||
1579 | if (retval) | ||
1580 | return retval; | ||
1581 | |||
1582 | for (seg = 0; seg < nr_segs; seg++) { | ||
1583 | read_descriptor_t desc; | ||
1584 | |||
1585 | desc.written = 0; | ||
1586 | desc.arg.buf = iov[seg].iov_base; | ||
1587 | desc.count = iov[seg].iov_len; | ||
1588 | if (desc.count == 0) | ||
1589 | continue; | ||
1590 | desc.error = 0; | ||
1591 | do_shmem_file_read(filp, ppos, &desc); | ||
1592 | retval += desc.written; | ||
1593 | if (desc.error) { | ||
1594 | retval = retval ?: desc.error; | ||
1595 | break; | ||
1596 | } | ||
1597 | if (desc.count > 0) | ||
1598 | break; | ||
1599 | } | ||
1600 | return retval; | ||
1601 | } | 1578 | } |
1602 | 1579 | ||
1603 | static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | 1580 | static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, |