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 ae6af072b635..17e7393c50f0 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -447,7 +447,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
447 | write_bytes -= copied; | 447 | write_bytes -= copied; |
448 | total_copied += copied; | 448 | total_copied += copied; |
449 | 449 | ||
450 | /* Return to btrfs_file_aio_write to fault page */ | 450 | /* Return to btrfs_file_write_iter to fault page */ |
451 | if (unlikely(copied == 0)) | 451 | if (unlikely(copied == 0)) |
452 | break; | 452 | break; |
453 | 453 | ||
@@ -1658,27 +1658,22 @@ again: | |||
1658 | } | 1658 | } |
1659 | 1659 | ||
1660 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, | 1660 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, |
1661 | const struct iovec *iov, | 1661 | struct iov_iter *from, |
1662 | unsigned long nr_segs, loff_t pos, | 1662 | loff_t pos) |
1663 | size_t count, size_t ocount) | ||
1664 | { | 1663 | { |
1665 | struct file *file = iocb->ki_filp; | 1664 | struct file *file = iocb->ki_filp; |
1666 | struct iov_iter i; | ||
1667 | ssize_t written; | 1665 | ssize_t written; |
1668 | ssize_t written_buffered; | 1666 | ssize_t written_buffered; |
1669 | loff_t endbyte; | 1667 | loff_t endbyte; |
1670 | int err; | 1668 | int err; |
1671 | 1669 | ||
1672 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, | 1670 | written = generic_file_direct_write(iocb, from, pos); |
1673 | count, ocount); | ||
1674 | 1671 | ||
1675 | if (written < 0 || written == count) | 1672 | if (written < 0 || !iov_iter_count(from)) |
1676 | return written; | 1673 | return written; |
1677 | 1674 | ||
1678 | pos += written; | 1675 | pos += written; |
1679 | count -= written; | 1676 | written_buffered = __btrfs_buffered_write(file, from, pos); |
1680 | iov_iter_init(&i, iov, nr_segs, count, written); | ||
1681 | written_buffered = __btrfs_buffered_write(file, &i, pos); | ||
1682 | if (written_buffered < 0) { | 1677 | if (written_buffered < 0) { |
1683 | err = written_buffered; | 1678 | err = written_buffered; |
1684 | goto out; | 1679 | goto out; |
@@ -1713,9 +1708,8 @@ static void update_time_for_write(struct inode *inode) | |||
1713 | inode_inc_iversion(inode); | 1708 | inode_inc_iversion(inode); |
1714 | } | 1709 | } |
1715 | 1710 | ||
1716 | static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | 1711 | static ssize_t btrfs_file_write_iter(struct kiocb *iocb, |
1717 | const struct iovec *iov, | 1712 | struct iov_iter *from) |
1718 | unsigned long nr_segs, loff_t pos) | ||
1719 | { | 1713 | { |
1720 | struct file *file = iocb->ki_filp; | 1714 | struct file *file = iocb->ki_filp; |
1721 | struct inode *inode = file_inode(file); | 1715 | struct inode *inode = file_inode(file); |
@@ -1724,18 +1718,12 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1724 | u64 end_pos; | 1718 | u64 end_pos; |
1725 | ssize_t num_written = 0; | 1719 | ssize_t num_written = 0; |
1726 | ssize_t err = 0; | 1720 | ssize_t err = 0; |
1727 | size_t count, ocount; | 1721 | size_t count = iov_iter_count(from); |
1728 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); | 1722 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); |
1723 | loff_t pos = iocb->ki_pos; | ||
1729 | 1724 | ||
1730 | mutex_lock(&inode->i_mutex); | 1725 | mutex_lock(&inode->i_mutex); |
1731 | 1726 | ||
1732 | err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); | ||
1733 | if (err) { | ||
1734 | mutex_unlock(&inode->i_mutex); | ||
1735 | goto out; | ||
1736 | } | ||
1737 | count = ocount; | ||
1738 | |||
1739 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | 1727 | current->backing_dev_info = inode->i_mapping->backing_dev_info; |
1740 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | 1728 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); |
1741 | if (err) { | 1729 | if (err) { |
@@ -1748,6 +1736,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1748 | goto out; | 1736 | goto out; |
1749 | } | 1737 | } |
1750 | 1738 | ||
1739 | iov_iter_truncate(from, count); | ||
1740 | |||
1751 | err = file_remove_suid(file); | 1741 | err = file_remove_suid(file); |
1752 | if (err) { | 1742 | if (err) { |
1753 | mutex_unlock(&inode->i_mutex); | 1743 | mutex_unlock(&inode->i_mutex); |
@@ -1789,14 +1779,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1789 | atomic_inc(&BTRFS_I(inode)->sync_writers); | 1779 | atomic_inc(&BTRFS_I(inode)->sync_writers); |
1790 | 1780 | ||
1791 | if (unlikely(file->f_flags & O_DIRECT)) { | 1781 | if (unlikely(file->f_flags & O_DIRECT)) { |
1792 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, | 1782 | num_written = __btrfs_direct_write(iocb, from, pos); |
1793 | pos, count, ocount); | ||
1794 | } else { | 1783 | } else { |
1795 | struct iov_iter i; | 1784 | num_written = __btrfs_buffered_write(file, from, pos); |
1796 | |||
1797 | iov_iter_init(&i, iov, nr_segs, count, num_written); | ||
1798 | |||
1799 | num_written = __btrfs_buffered_write(file, &i, pos); | ||
1800 | if (num_written > 0) | 1785 | if (num_written > 0) |
1801 | iocb->ki_pos = pos + num_written; | 1786 | iocb->ki_pos = pos + num_written; |
1802 | } | 1787 | } |
@@ -2633,11 +2618,11 @@ out: | |||
2633 | 2618 | ||
2634 | const struct file_operations btrfs_file_operations = { | 2619 | const struct file_operations btrfs_file_operations = { |
2635 | .llseek = btrfs_file_llseek, | 2620 | .llseek = btrfs_file_llseek, |
2636 | .read = do_sync_read, | 2621 | .read = new_sync_read, |
2637 | .write = do_sync_write, | 2622 | .write = new_sync_write, |
2638 | .aio_read = generic_file_aio_read, | 2623 | .read_iter = generic_file_read_iter, |
2639 | .splice_read = generic_file_splice_read, | 2624 | .splice_read = generic_file_splice_read, |
2640 | .aio_write = btrfs_file_aio_write, | 2625 | .write_iter = btrfs_file_write_iter, |
2641 | .mmap = btrfs_file_mmap, | 2626 | .mmap = btrfs_file_mmap, |
2642 | .open = generic_file_open, | 2627 | .open = generic_file_open, |
2643 | .release = btrfs_release_file, | 2628 | .release = btrfs_release_file, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5f805bc944fa..c8386f1961f0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -7391,39 +7391,30 @@ free_ordered: | |||
7391 | } | 7391 | } |
7392 | 7392 | ||
7393 | static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb, | 7393 | static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb, |
7394 | const struct iovec *iov, loff_t offset, | 7394 | const struct iov_iter *iter, loff_t offset) |
7395 | unsigned long nr_segs) | ||
7396 | { | 7395 | { |
7397 | int seg; | 7396 | int seg; |
7398 | int i; | 7397 | int i; |
7399 | size_t size; | ||
7400 | unsigned long addr; | ||
7401 | unsigned blocksize_mask = root->sectorsize - 1; | 7398 | unsigned blocksize_mask = root->sectorsize - 1; |
7402 | ssize_t retval = -EINVAL; | 7399 | ssize_t retval = -EINVAL; |
7403 | loff_t end = offset; | ||
7404 | 7400 | ||
7405 | if (offset & blocksize_mask) | 7401 | if (offset & blocksize_mask) |
7406 | goto out; | 7402 | goto out; |
7407 | 7403 | ||
7408 | /* Check the memory alignment. Blocks cannot straddle pages */ | 7404 | if (iov_iter_alignment(iter) & blocksize_mask) |
7409 | for (seg = 0; seg < nr_segs; seg++) { | 7405 | goto out; |
7410 | addr = (unsigned long)iov[seg].iov_base; | ||
7411 | size = iov[seg].iov_len; | ||
7412 | end += size; | ||
7413 | if ((addr & blocksize_mask) || (size & blocksize_mask)) | ||
7414 | goto out; | ||
7415 | |||
7416 | /* If this is a write we don't need to check anymore */ | ||
7417 | if (rw & WRITE) | ||
7418 | continue; | ||
7419 | 7406 | ||
7420 | /* | 7407 | /* If this is a write we don't need to check anymore */ |
7421 | * Check to make sure we don't have duplicate iov_base's in this | 7408 | if (rw & WRITE) |
7422 | * iovec, if so return EINVAL, otherwise we'll get csum errors | 7409 | return 0; |
7423 | * when reading back. | 7410 | /* |
7424 | */ | 7411 | * Check to make sure we don't have duplicate iov_base's in this |
7425 | for (i = seg + 1; i < nr_segs; i++) { | 7412 | * iovec, if so return EINVAL, otherwise we'll get csum errors |
7426 | if (iov[seg].iov_base == iov[i].iov_base) | 7413 | * when reading back. |
7414 | */ | ||
7415 | for (seg = 0; seg < iter->nr_segs; seg++) { | ||
7416 | for (i = seg + 1; i < iter->nr_segs; i++) { | ||
7417 | if (iter->iov[seg].iov_base == iter->iov[i].iov_base) | ||
7427 | goto out; | 7418 | goto out; |
7428 | } | 7419 | } |
7429 | } | 7420 | } |
@@ -7433,8 +7424,7 @@ out: | |||
7433 | } | 7424 | } |
7434 | 7425 | ||
7435 | static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | 7426 | static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, |
7436 | const struct iovec *iov, loff_t offset, | 7427 | struct iov_iter *iter, loff_t offset) |
7437 | unsigned long nr_segs) | ||
7438 | { | 7428 | { |
7439 | struct file *file = iocb->ki_filp; | 7429 | struct file *file = iocb->ki_filp; |
7440 | struct inode *inode = file->f_mapping->host; | 7430 | struct inode *inode = file->f_mapping->host; |
@@ -7444,8 +7434,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
7444 | bool relock = false; | 7434 | bool relock = false; |
7445 | ssize_t ret; | 7435 | ssize_t ret; |
7446 | 7436 | ||
7447 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov, | 7437 | if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iter, offset)) |
7448 | offset, nr_segs)) | ||
7449 | return 0; | 7438 | return 0; |
7450 | 7439 | ||
7451 | atomic_inc(&inode->i_dio_count); | 7440 | atomic_inc(&inode->i_dio_count); |
@@ -7457,7 +7446,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
7457 | * we need to flush the dirty pages again to make absolutely sure | 7446 | * we need to flush the dirty pages again to make absolutely sure |
7458 | * that any outstanding dirty pages are on disk. | 7447 | * that any outstanding dirty pages are on disk. |
7459 | */ | 7448 | */ |
7460 | count = iov_length(iov, nr_segs); | 7449 | count = iov_iter_count(iter); |
7461 | if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, | 7450 | if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, |
7462 | &BTRFS_I(inode)->runtime_flags)) | 7451 | &BTRFS_I(inode)->runtime_flags)) |
7463 | filemap_fdatawrite_range(inode->i_mapping, offset, count); | 7452 | filemap_fdatawrite_range(inode->i_mapping, offset, count); |
@@ -7484,7 +7473,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, | |||
7484 | 7473 | ||
7485 | ret = __blockdev_direct_IO(rw, iocb, inode, | 7474 | ret = __blockdev_direct_IO(rw, iocb, inode, |
7486 | BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, | 7475 | BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev, |
7487 | iov, offset, nr_segs, btrfs_get_blocks_direct, NULL, | 7476 | iter, offset, btrfs_get_blocks_direct, NULL, |
7488 | btrfs_submit_direct, flags); | 7477 | btrfs_submit_direct, flags); |
7489 | if (rw & WRITE) { | 7478 | if (rw & WRITE) { |
7490 | if (ret < 0 && ret != -EIOCBQUEUED) | 7479 | if (ret < 0 && ret != -EIOCBQUEUED) |