diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 13:30:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 13:30:18 -0400 |
commit | 16b9057804c02e2d351e9c8f606e909b43cbd9e7 (patch) | |
tree | a3ac6e1d9d57a8abf4267e5ead3f2de1309335eb /fs/btrfs/inode.c | |
parent | 5c02c392cd2320e8d612376d6b72b6548a680923 (diff) | |
parent | c2338f2dc7c1e9f6202f370c64ffd7f44f3d4b51 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro:
"This the bunch that sat in -next + lock_parent() fix. This is the
minimal set; there's more pending stuff.
In particular, I really hope to get acct.c fixes merged this cycle -
we need that to deal sanely with delayed-mntput stuff. In the next
pile, hopefully - that series is fairly short and localized
(kernel/acct.c, fs/super.c and fs/namespace.c). In this pile: more
iov_iter work. Most of prereqs for ->splice_write with sane locking
order are there and Kent's dio rewrite would also fit nicely on top of
this pile"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (70 commits)
lock_parent: don't step on stale ->d_parent of all-but-freed one
kill generic_file_splice_write()
ceph: switch to iter_file_splice_write()
shmem: switch to iter_file_splice_write()
nfs: switch to iter_splice_write_file()
fs/splice.c: remove unneeded exports
ocfs2: switch to iter_file_splice_write()
->splice_write() via ->write_iter()
bio_vec-backed iov_iter
optimize copy_page_{to,from}_iter()
bury generic_file_aio_{read,write}
lustre: get rid of messing with iovecs
ceph: switch to ->write_iter()
ceph_sync_direct_write: stop poking into iov_iter guts
ceph_sync_read: stop poking into iov_iter guts
new helper: copy_page_from_iter()
fuse: switch to ->write_iter()
btrfs: switch to ->write_iter()
ocfs2: switch to ->write_iter()
xfs: switch to ->write_iter()
...
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 47 |
1 files changed, 18 insertions, 29 deletions
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) |