linux/fs/netfs
David Howells a3de58b12c
netfs: Fix unbuffered write error handling
If all the subrequests in an unbuffered write stream fail, the subrequest
collector doesn't update the stream->transferred value and it retains its
initial LONG_MAX value.  Unfortunately, if all active streams fail, then we
take the smallest value of { LONG_MAX, LONG_MAX, ... } as the value to set
in wreq->transferred - which is then returned from ->write_iter().

LONG_MAX was chosen as the initial value so that all the streams can be
quickly assessed by taking the smallest value of all stream->transferred -
but this only works if we've set any of them.

Fix this by adding a flag to indicate whether the value in
stream->transferred is valid and checking that when we integrate the
values.  stream->transferred can then be initialised to zero.

This was found by running the generic/750 xfstest against cifs with
cache=none.  It splices data to the target file.  Once (if) it has used up
all the available scratch space, the writes start failing with ENOSPC.
This causes ->write_iter() to fail.  However, it was returning
wreq->transferred, i.e. LONG_MAX, rather than an error (because it thought
the amount transferred was non-zero) and iter_file_splice_write() would
then try to clean up that amount of pipe bufferage - leading to an oops
when it overran.  The kernel log showed:

    CIFS: VFS: Send error in write = -28

followed by:

    BUG: kernel NULL pointer dereference, address: 0000000000000008

with:

    RIP: 0010:iter_file_splice_write+0x3a4/0x520
    do_splice+0x197/0x4e0

or:

    RIP: 0010:pipe_buf_release (include/linux/pipe_fs_i.h:282)
    iter_file_splice_write (fs/splice.c:755)

Also put a warning check into splice to announce if ->write_iter() returned
that it had written more than it was asked to.

Fixes: 288ace2f57 ("netfs: New writeback implementation")
Reported-by: Xiaoli Feng <fengxiaoli0714@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220445
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/915443.1755207950@warthog.procyon.org.uk
cc: Paulo Alcantara <pc@manguebit.org>
cc: Steve French <sfrench@samba.org>
cc: Shyam Prasad N <sprasad@microsoft.com>
cc: netfs@lists.linux.dev
cc: linux-cifs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: stable@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
2025-08-15 15:56:49 +02:00
..
Kconfig
Makefile
buffered_read.c
buffered_write.c netfs: Merge i_size update functions 2025-07-01 22:37:14 +02:00
direct_read.c
direct_write.c netfs: Update tracepoints in a number of ways 2025-07-01 22:37:14 +02:00
fscache_cache.c
fscache_cookie.c
fscache_internal.h
fscache_io.c
fscache_main.c
fscache_proc.c
fscache_stats.c
fscache_volume.c
internal.h netfs: Update tracepoints in a number of ways 2025-07-01 22:37:14 +02:00
iterator.c
locking.c
main.c netfs: Renumber the NETFS_RREQ_* flags to make traces easier to read 2025-07-01 22:37:14 +02:00
misc.c netfs: Update tracepoints in a number of ways 2025-07-01 22:37:14 +02:00
objects.c
read_collect.c netfs: Fix unbuffered write error handling 2025-08-15 15:56:49 +02:00
read_pgpriv2.c netfs: Fix race between cache write completion and ALL_QUEUED being set 2025-07-14 11:05:02 +02:00
read_retry.c
read_single.c
rolling_buffer.c
stats.c
write_collect.c netfs: Fix unbuffered write error handling 2025-08-15 15:56:49 +02:00
write_issue.c netfs: Fix unbuffered write error handling 2025-08-15 15:56:49 +02:00
write_retry.c netfs: Update tracepoints in a number of ways 2025-07-01 22:37:14 +02:00