diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/file.c | 51 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 47 |
2 files changed, 36 insertions, 62 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e472441feb5d..1f2b99cb55ea 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -448,7 +448,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
| 448 | write_bytes -= copied; | 448 | write_bytes -= copied; |
| 449 | total_copied += copied; | 449 | total_copied += copied; |
| 450 | 450 | ||
| 451 | /* Return to btrfs_file_aio_write to fault page */ | 451 | /* Return to btrfs_file_write_iter to fault page */ |
| 452 | if (unlikely(copied == 0)) | 452 | if (unlikely(copied == 0)) |
| 453 | break; | 453 | break; |
| 454 | 454 | ||
| @@ -1675,27 +1675,22 @@ again: | |||
| 1675 | } | 1675 | } |
| 1676 | 1676 | ||
| 1677 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, | 1677 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, |
| 1678 | const struct iovec *iov, | 1678 | struct iov_iter *from, |
| 1679 | unsigned long nr_segs, loff_t pos, | 1679 | loff_t pos) |
| 1680 | size_t count, size_t ocount) | ||
| 1681 | { | 1680 | { |
| 1682 | struct file *file = iocb->ki_filp; | 1681 | struct file *file = iocb->ki_filp; |
| 1683 | struct iov_iter i; | ||
| 1684 | ssize_t written; | 1682 | ssize_t written; |
| 1685 | ssize_t written_buffered; | 1683 | ssize_t written_buffered; |
| 1686 | loff_t endbyte; | 1684 | loff_t endbyte; |
| 1687 | int err; | 1685 | int err; |
| 1688 | 1686 | ||
| 1689 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, | 1687 | written = generic_file_direct_write(iocb, from, pos); |
| 1690 | count, ocount); | ||
| 1691 | 1688 | ||
| 1692 | if (written < 0 || written == count) | 1689 | if (written < 0 || !iov_iter_count(from)) |
| 1693 | return written; | 1690 | return written; |
| 1694 | 1691 | ||
| 1695 | pos += written; | 1692 | pos += written; |
| 1696 | count -= written; | 1693 | written_buffered = __btrfs_buffered_write(file, from, pos); |
| 1697 | iov_iter_init(&i, iov, nr_segs, count, written); | ||
| 1698 | written_buffered = __btrfs_buffered_write(file, &i, pos); | ||
| 1699 | if (written_buffered < 0) { | 1694 | if (written_buffered < 0) { |
| 1700 | err = written_buffered; | 1695 | err = written_buffered; |
| 1701 | goto out; | 1696 | goto out; |
| @@ -1730,9 +1725,8 @@ static void update_time_for_write(struct inode *inode) | |||
| 1730 | inode_inc_iversion(inode); | 1725 | inode_inc_iversion(inode); |
| 1731 | } | 1726 | } |
| 1732 | 1727 | ||
| 1733 | static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | 1728 | static ssize_t btrfs_file_write_iter(struct kiocb *iocb, |
| 1734 | const struct iovec *iov, | 1729 | struct iov_iter *from) |
| 1735 | unsigned long nr_segs, loff_t pos) | ||
| 1736 | { | 1730 | { |
| 1737 | struct file *file = iocb->ki_filp; | 1731 | struct file *file = iocb->ki_filp; |
| 1738 | struct inode *inode = file_inode(file); | 1732 | struct inode *inode = file_inode(file); |
| @@ -1741,18 +1735,12 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1741 | u64 end_pos; | 1735 | u64 end_pos; |
| 1742 | ssize_t num_written = 0; | 1736 | ssize_t num_written = 0; |
| 1743 | ssize_t err = 0; | 1737 | ssize_t err = 0; |
| 1744 | size_t count, ocount; | 1738 | size_t count = iov_iter_count(from); |
| 1745 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); | 1739 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); |
| 1740 | loff_t pos = iocb->ki_pos; | ||
| 1746 | 1741 | ||
| 1747 | mutex_lock(&inode->i_mutex); | 1742 | mutex_lock(&inode->i_mutex); |
| 1748 | 1743 | ||
| 1749 | err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); | ||
| 1750 | if (err) { | ||
| 1751 | mutex_unlock(&inode->i_mutex); | ||
| 1752 | goto out; | ||
| 1753 | } | ||
| 1754 | count = ocount; | ||
| 1755 | |||
| 1756 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | 1744 | current->backing_dev_info = inode->i_mapping->backing_dev_info; |
| 1757 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | 1745 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); |
| 1758 | if (err) { | 1746 | if (err) { |
| @@ -1765,6 +1753,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1765 | goto out; | 1753 | goto out; |
| 1766 | } | 1754 | } |
| 1767 | 1755 | ||
| 1756 | iov_iter_truncate(from, count); | ||
| 1757 | |||
| 1768 | err = file_remove_suid(file); | 1758 | err = file_remove_suid(file); |
| 1769 | if (err) { | 1759 | if (err) { |
| 1770 | mutex_unlock(&inode->i_mutex); | 1760 | mutex_unlock(&inode->i_mutex); |
| @@ -1806,14 +1796,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1806 | atomic_inc(&BTRFS_I(inode)->sync_writers); | 1796 | atomic_inc(&BTRFS_I(inode)->sync_writers); |
| 1807 | 1797 | ||
| 1808 | if (unlikely(file->f_flags & O_DIRECT)) { | 1798 | if (unlikely(file->f_flags & O_DIRECT)) { |
| 1809 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, | 1799 | num_written = __btrfs_direct_write(iocb, from, pos); |
| 1810 | pos, count, ocount); | ||
| 1811 | } else { | 1800 | } else { |
| 1812 | struct iov_iter i; | 1801 | num_written = __btrfs_buffered_write(file, from, pos); |
| 1813 | |||
| 1814 | iov_iter_init(&i, iov, nr_segs, count, num_written); | ||
| 1815 | |||
| 1816 | num_written = __btrfs_buffered_write(file, &i, pos); | ||
| 1817 | if (num_written > 0) | 1802 | if (num_written > 0) |
| 1818 | iocb->ki_pos = pos + num_written; | 1803 | iocb->ki_pos = pos + num_written; |
| 1819 | } | 1804 | } |
| @@ -2740,11 +2725,11 @@ out: | |||
| 2740 | 2725 | ||
| 2741 | const struct file_operations btrfs_file_operations = { | 2726 | const struct file_operations btrfs_file_operations = { |
| 2742 | .llseek = btrfs_file_llseek, | 2727 | .llseek = btrfs_file_llseek, |
| 2743 | .read = do_sync_read, | 2728 | .read = new_sync_read, |
| 2744 | .write = do_sync_write, | 2729 | .write = new_sync_write, |
| 2745 | .aio_read = generic_file_aio_read, | 2730 | .read_iter = generic_file_read_iter, |
| 2746 | .splice_read = generic_file_splice_read, | 2731 | .splice_read = generic_file_splice_read, |
| 2747 | .aio_write = btrfs_file_aio_write, | 2732 | .write_iter = btrfs_file_write_iter, |
| 2748 | .mmap = btrfs_file_mmap, | 2733 | .mmap = btrfs_file_mmap, |
| 2749 | .open = generic_file_open, | 2734 | .open = generic_file_open, |
| 2750 | .release = btrfs_release_file, | 2735 | .release = btrfs_release_file, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7fa5f7fd7bc7..8925f66a1411 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -7445,39 +7445,30 @@ free_ordered: | |||
| 7445 | } | 7445 | } |
| 7446 | 7446 | ||
| 7447 | static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb, | 7447 | static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb, |
| 7448 | const struct iovec *iov, loff_t offset, | 7448 | const struct iov_iter *iter, loff_t offset) |
| 7449 | unsigned long nr_segs) | ||
| 7450 | { | 7449 | { |
| 7451 | int seg; | 7450 | int seg; |
| 7452 | int i; | 7451 | int i; |
| 7453 | size_t size; | ||
| 7454 | unsigned long addr; | ||
| 7455 | unsigned blocksize_mask = root->sectorsize - 1; | 7452 | unsigned blocksize_mask = root->sectorsize - 1; |
| 7456 | ssize_t retval = -EINVAL; | 7453 | ssize_t retval = -EINVAL; |
| 7457 | loff_t end = offset; | ||
| 7458 | 7454 | ||
| 7459 | if (offset & blocksize_mask) | 7455 | if (offset & blocksize_mask) |
| 7460 | goto out; | 7456 | goto out; |
| 7461 | 7457 | ||
| 7462 | /* Check the memory alignment. Blocks cannot straddle pages */ | 7458 | if (iov_iter_alignment(iter) & blocksize_mask) |
| 7463 | for (seg = 0; seg < nr_segs; seg++) { | 7459 | goto out; |
| 7464 | addr = (unsigned long)iov[seg].iov_base; | ||
| 7465 | size = iov[seg].iov_len; | ||
| 7466 | end += size; | ||
| 7467 | if ((addr & blocksize_mask) || (size & blocksize_mask)) | ||
| 7468 | goto out; | ||
| 7469 | |||
| 7470 | /* If this is a write we don't need to check anymore */ | ||
| 7471 | if (rw & WRITE) | ||
| 7472 | continue; | ||
| 7473 | 7460 | ||
| 7474 | /* | 7461 | /* If this is a write we don't need to check anymore */ |
| 7475 | * Check to make sure we don't have duplicate iov_base's in this | 7462 | if (rw & WRITE) |
| 7476 | * iovec, if so return EINVAL, otherwise we'll get csum errors | 7463 | return 0; |
| 7477 | * when reading back. | 7464 | /* |
| 7478 | */ | 7465 | * Check to make sure we don't have duplicate iov_base's in this |
| 7479 | for (i = seg + 1; i < nr_segs; i++) { | 7466 | * iovec, if so return EINVAL, otherwise we'll get csum errors |
| 7480 | if (iov[seg].iov_base == iov[i].iov_base) | 7467 | * when reading back. |
| 7468 | */ | ||
| 7469 | for (seg = 0; seg < iter->nr_segs; seg++) { | ||
| 7470 | for (i = seg + 1; i < iter->nr_segs; i++) { | ||
| 7471 | if (iter->iov[seg].iov_base == iter->iov[i].iov_base) | ||
| 7481 | goto out; | 7472 | goto out; |
| 7482 | } | 7473 | } |
| 7483 | } | 7474 | } |
| @@ -7487,8 +7478,7 @@ out: | |||
| 7487 | } | 7478 | } |
| 7488 | 7479 | ||
| 7489 | static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | 7480 | static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, |
| 7490 | const struct iovec *iov, loff_t offset, | 7481 | struct iov_iter *iter, loff_t offset) |
| 7491 | unsigned long nr_segs) | ||
| 7492 | { | 7482 | { |
| 7493 | struct file *file = iocb->ki_filp; | 7483 | struct file *file = iocb->ki_filp; |
| 7494 | struct inode *inode = file->f_mapping->host; | 7484 | struct inode *inode = file->f_mapping->host; |
| @@ -7498,8 +7488,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
| 7498 | bool relock = false; | 7488 | bool relock = false; |
| 7499 | ssize_t ret; | 7489 | ssize_t ret; |
| 7500 | 7490 | ||
| 7501 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, | 7491 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iter, offset)) |
| 7502 | offset, nr_segs)) | ||
| 7503 | return 0; | 7492 | return 0; |
| 7504 | 7493 | ||
| 7505 | atomic_inc(&inode->i_dio_count); | 7494 | atomic_inc(&inode->i_dio_count); |
| @@ -7511,7 +7500,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
| 7511 | * we need to flush the dirty pages again to make absolutely sure | 7500 | * we need to flush the dirty pages again to make absolutely sure |
| 7512 | * that any outstanding dirty pages are on disk. | 7501 | * that any outstanding dirty pages are on disk. |
| 7513 | */ | 7502 | */ |
| 7514 | count = iov_length(iov, nr_segs); | 7503 | count = iov_iter_count(iter); |
| 7515 | if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, | 7504 | if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, |
| 7516 | &BTRFS_I(inode)->runtime_flags)) | 7505 | &BTRFS_I(inode)->runtime_flags)) |
| 7517 | filemap_fdatawrite_range(inode->i_mapping, offset, count); | 7506 | filemap_fdatawrite_range(inode->i_mapping, offset, count); |
| @@ -7538,7 +7527,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
| 7538 | 7527 | ||
| 7539 | ret = __blockdev_direct_IO(rw, iocb, inode, | 7528 | ret = __blockdev_direct_IO(rw, iocb, inode, |
| 7540 | BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, | 7529 | BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, |
| 7541 | iov, offset, nr_segs, btrfs_get_blocks_direct, NULL, | 7530 | iter, offset, btrfs_get_blocks_direct, NULL, |
| 7542 | btrfs_submit_direct, flags); | 7531 | btrfs_submit_direct, flags); |
| 7543 | if (rw & WRITE) { | 7532 | if (rw & WRITE) { |
| 7544 | if (ret < 0 && ret != -EIOCBQUEUED) | 7533 | if (ret < 0 && ret != -EIOCBQUEUED) |
