From: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Prefaulting the write source buffer incurs an extra userspace access in the common fast path. Make ntfs_compress_write() consistent with generic_perform_write(): only touch userspace an extra time when copy_page_from_iter_atomic() has failed to make progress. Signed-off-by: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Cc: Konstantin Komarov <almaz.alexandrovich@xxxxxxxxxxxxxxxxxxxx> Cc: ntfs3@xxxxxxxxxxxxxxx --- b/fs/ntfs3/file.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff -puN fs/ntfs3/file.c~ntfs-postfault fs/ntfs3/file.c --- a/fs/ntfs3/file.c~ntfs-postfault 2025-01-29 09:03:33.371460504 -0800 +++ b/fs/ntfs3/file.c 2025-01-29 09:03:33.375460837 -0800 @@ -1092,11 +1092,6 @@ static ssize_t ntfs_compress_write(struc frame_vbo = pos & ~(frame_size - 1); index = frame_vbo >> PAGE_SHIFT; - if (unlikely(fault_in_iov_iter_readable(from, bytes))) { - err = -EFAULT; - goto out; - } - /* Load full frame. */ err = ntfs_get_frame_pages(mapping, index, pages, pages_per_frame, &frame_uptodate); @@ -1172,6 +1167,18 @@ static ssize_t ntfs_compress_write(struc */ cond_resched(); + if (unlikely(!copied)) { + /* + * folios are now unlocked and faults on them can be + * handled. Ensure forward progress by trying to + * fault in 'from' in case it maps one of the folios. + */ + if (fault_in_iov_iter_readable(from, bytes)) { + err = -EFAULT; + goto out; + } + } + pos += copied; written += copied; _