Skip to content

Commit a629459

Browse files
author
Andreas Gruenbacher
committed
iov_iter: Turn iov_iter_fault_in_readable into fault_in_iov_iter_readable
Turn iov_iter_fault_in_readable into a function that returns the number of bytes not faulted in, similar to copy_to_user, instead of returning a non-zero value when any of the requested pages couldn't be faulted in. This supports the existing users that require all pages to be faulted in as well as new users that are happy if any pages can be faulted in. Rename iov_iter_fault_in_readable to fault_in_iov_iter_readable to make sure this change doesn't silently break things. Signed-off-by: Andreas Gruenbacher <[email protected]>
1 parent bb523b4 commit a629459

File tree

9 files changed

+29
-20
lines changed

9 files changed

+29
-20
lines changed

fs/btrfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1710,7 +1710,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
17101710
* Fault pages before locking them in prepare_pages
17111711
* to avoid recursive lock
17121712
*/
1713-
if (unlikely(iov_iter_fault_in_readable(i, write_bytes))) {
1713+
if (unlikely(fault_in_iov_iter_readable(i, write_bytes))) {
17141714
ret = -EFAULT;
17151715
break;
17161716
}

fs/f2fs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4276,7 +4276,7 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
42764276
size_t target_size = 0;
42774277
int err;
42784278

4279-
if (iov_iter_fault_in_readable(from, iov_iter_count(from)))
4279+
if (fault_in_iov_iter_readable(from, iov_iter_count(from)))
42804280
set_inode_flag(inode, FI_NO_PREALLOC);
42814281

42824282
if ((iocb->ki_flags & IOCB_NOWAIT)) {

fs/fuse/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
11641164

11651165
again:
11661166
err = -EFAULT;
1167-
if (iov_iter_fault_in_readable(ii, bytes))
1167+
if (fault_in_iov_iter_readable(ii, bytes))
11681168
break;
11691169

11701170
err = -ENOMEM;

fs/iomap/buffered-io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
750750
* same page as we're writing to, without it being marked
751751
* up-to-date.
752752
*/
753-
if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
753+
if (unlikely(fault_in_iov_iter_readable(i, bytes))) {
754754
status = -EFAULT;
755755
break;
756756
}

fs/ntfs/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1829,7 +1829,7 @@ static ssize_t ntfs_perform_write(struct file *file, struct iov_iter *i,
18291829
* pages being swapped out between us bringing them into memory
18301830
* and doing the actual copying.
18311831
*/
1832-
if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
1832+
if (unlikely(fault_in_iov_iter_readable(i, bytes))) {
18331833
status = -EFAULT;
18341834
break;
18351835
}

fs/ntfs3/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
987987
frame_vbo = pos & ~(frame_size - 1);
988988
index = frame_vbo >> PAGE_SHIFT;
989989

990-
if (unlikely(iov_iter_fault_in_readable(from, bytes))) {
990+
if (unlikely(fault_in_iov_iter_readable(from, bytes))) {
991991
err = -EFAULT;
992992
goto out;
993993
}

include/linux/uio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ size_t copy_page_from_iter_atomic(struct page *page, unsigned offset,
133133
size_t bytes, struct iov_iter *i);
134134
void iov_iter_advance(struct iov_iter *i, size_t bytes);
135135
void iov_iter_revert(struct iov_iter *i, size_t bytes);
136-
int iov_iter_fault_in_readable(const struct iov_iter *i, size_t bytes);
136+
size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t bytes);
137137
size_t iov_iter_single_seg_count(const struct iov_iter *i);
138138
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
139139
struct iov_iter *i);

lib/iov_iter.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -430,33 +430,42 @@ static size_t copy_page_to_iter_pipe(struct page *page, size_t offset, size_t by
430430
}
431431

432432
/*
433+
* fault_in_iov_iter_readable - fault in iov iterator for reading
434+
* @i: iterator
435+
* @size: maximum length
436+
*
433437
* Fault in one or more iovecs of the given iov_iter, to a maximum length of
434-
* bytes. For each iovec, fault in each page that constitutes the iovec.
438+
* @size. For each iovec, fault in each page that constitutes the iovec.
439+
*
440+
* Returns the number of bytes not faulted in (like copy_to_user() and
441+
* copy_from_user()).
435442
*
436-
* Return 0 on success, or non-zero if the memory could not be accessed (i.e.
437-
* because it is an invalid address).
443+
* Always returns 0 for non-userspace iterators.
438444
*/
439-
int iov_iter_fault_in_readable(const struct iov_iter *i, size_t bytes)
445+
size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t size)
440446
{
441447
if (iter_is_iovec(i)) {
448+
size_t count = min(size, iov_iter_count(i));
442449
const struct iovec *p;
443450
size_t skip;
444451

445-
if (bytes > i->count)
446-
bytes = i->count;
447-
for (p = i->iov, skip = i->iov_offset; bytes; p++, skip = 0) {
448-
size_t len = min(bytes, p->iov_len - skip);
452+
size -= count;
453+
for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) {
454+
size_t len = min(count, p->iov_len - skip);
455+
size_t ret;
449456

450457
if (unlikely(!len))
451458
continue;
452-
if (fault_in_readable(p->iov_base + skip, len))
453-
return -EFAULT;
454-
bytes -= len;
459+
ret = fault_in_readable(p->iov_base + skip, len);
460+
count -= len - ret;
461+
if (ret)
462+
break;
455463
}
464+
return count + size;
456465
}
457466
return 0;
458467
}
459-
EXPORT_SYMBOL(iov_iter_fault_in_readable);
468+
EXPORT_SYMBOL(fault_in_iov_iter_readable);
460469

461470
void iov_iter_init(struct iov_iter *i, unsigned int direction,
462471
const struct iovec *iov, unsigned long nr_segs,

mm/filemap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3757,7 +3757,7 @@ ssize_t generic_perform_write(struct file *file,
37573757
* same page as we're writing to, without it being marked
37583758
* up-to-date.
37593759
*/
3760-
if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
3760+
if (unlikely(fault_in_iov_iter_readable(i, bytes))) {
37613761
status = -EFAULT;
37623762
break;
37633763
}

0 commit comments

Comments
 (0)