diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-27 14:09:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-27 14:09:37 -0400 |
commit | f56fc7bdaa22e7b2fac18de430db8195d2dfd7bd (patch) | |
tree | 7888be1d5179784a70d670fdf2542cc382bf93b4 /fs | |
parent | 59372bbf3abd5b24a7f6f676a3968685c280f955 (diff) | |
parent | 1741937d475d91ed95abb37f07e8571e23b9a7fe (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro:
- fix orangefs handling of faults on write() - I'd missed that one back
when orangefs was going through review.
- readdir counterpart of "9p: cope with bogus responses from server in
p9_client_{read,write}" - server might be lying or broken, and we'd
better not overrun the kmalloc'ed buffer we are copying the results
into.
- NFS O_DIRECT read/write can leave iov_iter advanced by too much;
that's what had been causing iov_iter_pipe() warnings davej had been
seeing.
- statx_timestamp.tv_nsec type fix (s32 -> u32). That one really should
go in before 4.11.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
uapi: change the type of struct statx_timestamp.tv_nsec to unsigned
fix nfs O_DIRECT advancing iov_iter too much
p9_client_readdir() fix
orangefs_bufmap_copy_from_iovec(): fix EFAULT handling
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/direct.c | 27 | ||||
-rw-r--r-- | fs/orangefs/orangefs-bufmap.c | 4 |
2 files changed, 19 insertions, 12 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index aab32fc3d6a8..c1b5fed7c863 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -537,7 +537,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
537 | 537 | ||
538 | if (put_dreq(dreq)) | 538 | if (put_dreq(dreq)) |
539 | nfs_direct_complete(dreq); | 539 | nfs_direct_complete(dreq); |
540 | return 0; | 540 | return requested_bytes; |
541 | } | 541 | } |
542 | 542 | ||
543 | /** | 543 | /** |
@@ -566,7 +566,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) | |||
566 | struct inode *inode = mapping->host; | 566 | struct inode *inode = mapping->host; |
567 | struct nfs_direct_req *dreq; | 567 | struct nfs_direct_req *dreq; |
568 | struct nfs_lock_context *l_ctx; | 568 | struct nfs_lock_context *l_ctx; |
569 | ssize_t result = -EINVAL; | 569 | ssize_t result = -EINVAL, requested; |
570 | size_t count = iov_iter_count(iter); | 570 | size_t count = iov_iter_count(iter); |
571 | nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); | 571 | nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); |
572 | 572 | ||
@@ -600,14 +600,19 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter) | |||
600 | nfs_start_io_direct(inode); | 600 | nfs_start_io_direct(inode); |
601 | 601 | ||
602 | NFS_I(inode)->read_io += count; | 602 | NFS_I(inode)->read_io += count; |
603 | result = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos); | 603 | requested = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos); |
604 | 604 | ||
605 | nfs_end_io_direct(inode); | 605 | nfs_end_io_direct(inode); |
606 | 606 | ||
607 | if (!result) { | 607 | if (requested > 0) { |
608 | result = nfs_direct_wait(dreq); | 608 | result = nfs_direct_wait(dreq); |
609 | if (result > 0) | 609 | if (result > 0) { |
610 | requested -= result; | ||
610 | iocb->ki_pos += result; | 611 | iocb->ki_pos += result; |
612 | } | ||
613 | iov_iter_revert(iter, requested); | ||
614 | } else { | ||
615 | result = requested; | ||
611 | } | 616 | } |
612 | 617 | ||
613 | out_release: | 618 | out_release: |
@@ -954,7 +959,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
954 | 959 | ||
955 | if (put_dreq(dreq)) | 960 | if (put_dreq(dreq)) |
956 | nfs_direct_write_complete(dreq); | 961 | nfs_direct_write_complete(dreq); |
957 | return 0; | 962 | return requested_bytes; |
958 | } | 963 | } |
959 | 964 | ||
960 | /** | 965 | /** |
@@ -979,7 +984,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
979 | */ | 984 | */ |
980 | ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | 985 | ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) |
981 | { | 986 | { |
982 | ssize_t result = -EINVAL; | 987 | ssize_t result = -EINVAL, requested; |
983 | size_t count; | 988 | size_t count; |
984 | struct file *file = iocb->ki_filp; | 989 | struct file *file = iocb->ki_filp; |
985 | struct address_space *mapping = file->f_mapping; | 990 | struct address_space *mapping = file->f_mapping; |
@@ -1022,7 +1027,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | |||
1022 | 1027 | ||
1023 | nfs_start_io_direct(inode); | 1028 | nfs_start_io_direct(inode); |
1024 | 1029 | ||
1025 | result = nfs_direct_write_schedule_iovec(dreq, iter, pos); | 1030 | requested = nfs_direct_write_schedule_iovec(dreq, iter, pos); |
1026 | 1031 | ||
1027 | if (mapping->nrpages) { | 1032 | if (mapping->nrpages) { |
1028 | invalidate_inode_pages2_range(mapping, | 1033 | invalidate_inode_pages2_range(mapping, |
@@ -1031,13 +1036,17 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter) | |||
1031 | 1036 | ||
1032 | nfs_end_io_direct(inode); | 1037 | nfs_end_io_direct(inode); |
1033 | 1038 | ||
1034 | if (!result) { | 1039 | if (requested > 0) { |
1035 | result = nfs_direct_wait(dreq); | 1040 | result = nfs_direct_wait(dreq); |
1036 | if (result > 0) { | 1041 | if (result > 0) { |
1042 | requested -= result; | ||
1037 | iocb->ki_pos = pos + result; | 1043 | iocb->ki_pos = pos + result; |
1038 | /* XXX: should check the generic_write_sync retval */ | 1044 | /* XXX: should check the generic_write_sync retval */ |
1039 | generic_write_sync(iocb, result); | 1045 | generic_write_sync(iocb, result); |
1040 | } | 1046 | } |
1047 | iov_iter_revert(iter, requested); | ||
1048 | } else { | ||
1049 | result = requested; | ||
1041 | } | 1050 | } |
1042 | out_release: | 1051 | out_release: |
1043 | nfs_direct_req_release(dreq); | 1052 | nfs_direct_req_release(dreq); |
diff --git a/fs/orangefs/orangefs-bufmap.c b/fs/orangefs/orangefs-bufmap.c index 6333cbbdfef7..83b506020718 100644 --- a/fs/orangefs/orangefs-bufmap.c +++ b/fs/orangefs/orangefs-bufmap.c | |||
@@ -521,13 +521,11 @@ int orangefs_bufmap_copy_from_iovec(struct iov_iter *iter, | |||
521 | size_t n = size; | 521 | size_t n = size; |
522 | if (n > PAGE_SIZE) | 522 | if (n > PAGE_SIZE) |
523 | n = PAGE_SIZE; | 523 | n = PAGE_SIZE; |
524 | n = copy_page_from_iter(page, 0, n, iter); | 524 | if (copy_page_from_iter(page, 0, n, iter) != n) |
525 | if (!n) | ||
526 | return -EFAULT; | 525 | return -EFAULT; |
527 | size -= n; | 526 | size -= n; |
528 | } | 527 | } |
529 | return 0; | 528 | return 0; |
530 | |||
531 | } | 529 | } |
532 | 530 | ||
533 | /* | 531 | /* |