* [PATCH netfs v1 0/2] preserve prepare_write errno across write reissue
@ 2026-10-28 18:12 Iván Ezequiel Rodriguez
2026-10-28 18:12 ` [PATCH netfs v1 1/2] netfs: preserve prepare_write errno on reissue Iván Ezequiel Rodriguez
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Iván Ezequiel Rodriguez @ 2026-10-28 18:12 UTC (permalink / raw)
To: David Howells, Paulo Alcantara, netfs
Cc: Shyam Prasad N, Steve French, linux-fsdevel, linux-cifs, linux-kernel
cifs (and others) may fail in prepare_write() with
netfs_prepare_write_failed() before write_retry calls
netfs_reissue_write(). Since 82e8885bd763, reissue clears
subreq->error to 0 for a clean I/O retry, so a FAILED subreq is
terminated with 0. The collector then does mapping_set_error(0),
which is a no-op — writeback errno is lost (not an infinite retry).
Patch 1 skips that clear when FAILED is already set.
Patch 2 adds a KUnit stub test: FAIL unpatched, PASS patched.
./tools/testing/kunit/kunit.py run --kunitconfig=fs/netfs/.kunitconfig \
netfs_reissue_write*
No prior lore report found for this interaction; surfaces on top of
Shyam's NEED_RETRY change.
Cc: David Howells <dhowells@redhat.com>
Cc: Paulo Alcantara <pc@manguebit.org>
Cc: Shyam Prasad N <sprasad@microsoft.com>
Cc: Steve French <stfrench@microsoft.com>
Cc: netfs@lists.linux.dev
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-cifs@vger.kernel.org
Iván Ezequiel Rodriguez (2):
netfs: preserve prepare_write errno on reissue
netfs: add KUnit coverage for reissue prepare_write errno
fs/netfs/.kunitconfig | 3 ++
fs/netfs/Kconfig | 9 +++++
fs/netfs/Makefile | 2 +
fs/netfs/write_collect.c | 4 ++
fs/netfs/write_issue.c | 4 +-
fs/netfs/write_reissue_kunit.c | 73 ++++++++++++++++++++++++++++++++++
6 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 fs/netfs/.kunitconfig
create mode 100644 fs/netfs/write_reissue_kunit.c
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH netfs v1 1/2] netfs: preserve prepare_write errno on reissue 2026-10-28 18:12 [PATCH netfs v1 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez @ 2026-10-28 18:12 ` Iván Ezequiel Rodriguez 2026-10-28 18:12 ` [PATCH netfs v1 2/2] netfs: add KUnit coverage for reissue prepare_write errno Iván Ezequiel Rodriguez 2026-11-02 15:06 ` [PATCH netfs v2 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez 2 siblings, 0 replies; 7+ messages in thread From: Iván Ezequiel Rodriguez @ 2026-10-28 18:12 UTC (permalink / raw) To: David Howells, Paulo Alcantara, netfs Cc: Shyam Prasad N, Steve French, linux-fsdevel, linux-cifs, linux-kernel prepare_write() may call netfs_prepare_write_failed() (FAILED + errno) before write_retry calls netfs_reissue_write(). Clearing subreq->error to 0 for a clean I/O reissue (82e8885bd763) then makes netfs_do_issue_write() terminate with 0. The collector copies front->error into stream->error and mapping_set_error(), which ignores 0, so writeback failure is silent. Skip clearing error when NETFS_SREQ_FAILED is already set; do_issue_write() already terminates FAILED subrequests. Fixes: 82e8885bd763 ("netfs: when subreq is marked for retry, do not check if it faced an error") Cc: Shyam Prasad N <sprasad@microsoft.com> Cc: Steve French <stfrench@microsoft.com> Signed-off-by: Iván Ezequiel Rodriguez <ivanrwcm25@gmail.com> --- fs/netfs/write_issue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c index b8237e1314d8..f23364116421 100644 --- a/fs/netfs/write_issue.c +++ b/fs/netfs/write_issue.c @@ -268,7 +268,9 @@ void netfs_reissue_write(struct netfs_io_stream *stream, iov_iter_truncate(&subreq->io_iter, size); subreq->retry_count++; - subreq->error = 0; + /* Keep prepare_write() errno; do_issue_write() terminates FAILED. */ + if (!test_bit(NETFS_SREQ_FAILED, &subreq->flags)) + subreq->error = 0; __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); __set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags); netfs_stat(&netfs_n_wh_retry_write_subreq); -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH netfs v1 2/2] netfs: add KUnit coverage for reissue prepare_write errno 2026-10-28 18:12 [PATCH netfs v1 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez 2026-10-28 18:12 ` [PATCH netfs v1 1/2] netfs: preserve prepare_write errno on reissue Iván Ezequiel Rodriguez @ 2026-10-28 18:12 ` Iván Ezequiel Rodriguez 2026-10-29 10:19 ` kernel test robot 2026-11-02 15:06 ` [PATCH netfs v2 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez 2 siblings, 1 reply; 7+ messages in thread From: Iván Ezequiel Rodriguez @ 2026-10-28 18:12 UTC (permalink / raw) To: David Howells, Paulo Alcantara, netfs Cc: Shyam Prasad N, Steve French, linux-fsdevel, linux-cifs, linux-kernel Stub netfs_write_subrequest_terminated() and call netfs_reissue_write() with FAILED + -EIO. Unpatched trees terminate with 0; patched keep -EIO. ./tools/testing/kunit/kunit.py run --kunitconfig=fs/netfs/.kunitconfig \ netfs_reissue_write* Signed-off-by: Iván Ezequiel Rodriguez <ivanrwcm25@gmail.com> --- fs/netfs/.kunitconfig | 3 ++ fs/netfs/Kconfig | 9 +++++ fs/netfs/Makefile | 2 + fs/netfs/write_collect.c | 4 ++ fs/netfs/write_reissue_kunit.c | 73 ++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 fs/netfs/.kunitconfig create mode 100644 fs/netfs/write_reissue_kunit.c diff --git a/fs/netfs/.kunitconfig b/fs/netfs/.kunitconfig new file mode 100644 index 000000000000..c783d180ab8f --- /dev/null +++ b/fs/netfs/.kunitconfig @@ -0,0 +1,3 @@ +CONFIG_KUNIT=y +CONFIG_NETFS_SUPPORT=y +CONFIG_NETFS_KUNIT_TESTS=y diff --git a/fs/netfs/Kconfig b/fs/netfs/Kconfig index d0e7b0971fa3..d796dbe4bd7c 100644 --- a/fs/netfs/Kconfig +++ b/fs/netfs/Kconfig @@ -33,6 +33,15 @@ config NETFS_DEBUG management module. If this is set, the debugging output may be enabled by setting bits in /sys/module/netfs/parameters/debug. +config NETFS_KUNIT_TESTS + tristate "KUnit tests for netfs" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + select NETFS_SUPPORT + help + This builds netfs KUnit tests (e.g. write reissue errno). + Say N unless developing netfs. + config FSCACHE bool "General filesystem local caching manager" depends on NETFS_SUPPORT diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 54834cde7e56..fa1544b9a199 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -33,4 +33,6 @@ netfs-$(CONFIG_FSCACHE) += fscache_proc.o endif netfs-$(CONFIG_FSCACHE_STATS) += fscache_stats.o +netfs-$(CONFIG_NETFS_KUNIT_TESTS) += write_reissue_kunit.o + obj-$(CONFIG_NETFS_SUPPORT) += netfs.o diff --git a/fs/netfs/write_collect.c b/fs/netfs/write_collect.c index 6e8ea534230d..f3236fe494bf 100644 --- a/fs/netfs/write_collect.c +++ b/fs/netfs/write_collect.c @@ -11,6 +11,7 @@ #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/slab.h> +#include <kunit/static_stub.h> #include "internal.h" /* Notes made in the collector */ @@ -529,6 +530,9 @@ void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error) struct netfs_io_subrequest *subreq = _op; struct netfs_io_request *wreq = subreq->rreq; + KUNIT_STATIC_STUB_REDIRECT(netfs_write_subrequest_terminated, + _op, transferred_or_error); + _enter("%x[%x] %zd", wreq->debug_id, subreq->debug_index, transferred_or_error); switch (subreq->source) { diff --git a/fs/netfs/write_reissue_kunit.c b/fs/netfs/write_reissue_kunit.c new file mode 100644 index 000000000000..fca5f7dd9265 --- /dev/null +++ b/fs/netfs/write_reissue_kunit.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * netfs_reissue_write must not clear prepare_write() errno. + */ +#include <kunit/test.h> +#include <kunit/static_stub.h> +#include <linux/uio.h> +#include "internal.h" + +struct term_capture { + ssize_t transferred_or_error; + bool called; +}; + +static void capture_terminated(void *_op, ssize_t transferred_or_error) +{ + struct netfs_io_subrequest *subreq = _op; + struct term_capture *cap = kunit_get_current_test()->priv; + + cap->called = true; + cap->transferred_or_error = transferred_or_error; + /* Mirror production: leave subreq->error as prepare_write set it. */ + (void)subreq; +} + +/* + * prepare_write_failed() sets FAILED + errno, then write_retry still calls + * reissue_write(). Before the fix, reissue wiped error to 0 so terminated + * reported success and mapping_set_error(0) was a no-op. + */ +static void reissue_preserves_prep_error(struct kunit *test) +{ + struct term_capture cap = {}; + struct netfs_io_request wreq = {}; + struct netfs_io_stream stream = { + .source = NETFS_UPLOAD_TO_SERVER, + }; + struct netfs_io_subrequest subreq = { + .rreq = &wreq, + .len = 1, + .transferred = 0, + .error = -EIO, + .source = NETFS_UPLOAD_TO_SERVER, + }; + char buf[1] = { 0 }; + struct kvec kvec = { .iov_base = buf, .iov_len = 1 }; + struct iov_iter source; + + __set_bit(NETFS_SREQ_FAILED, &subreq.flags); + iov_iter_kvec(&source, ITER_SOURCE, &kvec, 1, 1); + + test->priv = ∩ + kunit_activate_static_stub(test, netfs_write_subrequest_terminated, + capture_terminated); + + netfs_reissue_write(&stream, &subreq, &source); + + KUNIT_EXPECT_TRUE(test, cap.called); + KUNIT_EXPECT_EQ(test, cap.transferred_or_error, -EIO); + KUNIT_EXPECT_EQ(test, subreq.error, -EIO); +} + +static struct kunit_case netfs_reissue_test_cases[] = { + KUNIT_CASE(reissue_preserves_prep_error), + {} +}; + +static struct kunit_suite netfs_reissue_test_suite = { + .name = "netfs_reissue_write", + .test_cases = netfs_reissue_test_cases, +}; + +kunit_test_suite(netfs_reissue_test_suite); -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH netfs v1 2/2] netfs: add KUnit coverage for reissue prepare_write errno 2026-10-28 18:12 ` [PATCH netfs v1 2/2] netfs: add KUnit coverage for reissue prepare_write errno Iván Ezequiel Rodriguez @ 2026-10-29 10:19 ` kernel test robot 0 siblings, 0 replies; 7+ messages in thread From: kernel test robot @ 2026-10-29 10:19 UTC (permalink / raw) To: Iván Ezequiel Rodriguez, David Howells, Paulo Alcantara, netfs Cc: oe-kbuild-all, Shyam Prasad N, Steve French, linux-fsdevel, linux-cifs, linux-kernel Hi Iván, kernel test robot noticed the following build warnings: [auto build test WARNING on brauner-vfs/vfs.all] [also build test WARNING on linus/master v7.3 next-20261028] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Iv-n-Ezequiel-Rodriguez/netfs-preserve-prepare_write-errno-on-reissue/20261028-151228 base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all patch link: https://lore.kernel.org/r/20261028181229.1408342-3-ivanrwcm25%40gmail.com patch subject: [PATCH netfs v1 2/2] netfs: add KUnit coverage for reissue prepare_write errno config: arm-allyesconfig (https://download.01.org/0day-ci/archive/20261029/202610291753.Jr3HECY2-lkp@intel.com/config) compiler: arm-linux-gnueabi-gcc (GCC) 16.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261029/202610291753.Jr3HECY2-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202610291753.Jr3HECY2-lkp@intel.com/ All warnings (new ones prefixed by >>): fs/netfs/write_reissue_kunit.c: In function 'reissue_preserves_prep_error': >> fs/netfs/write_reissue_kunit.c:61:1: warning: the frame size of 1400 bytes is larger than 1280 bytes [-Wframe-larger-than=] 61 | } | ^ vim +61 fs/netfs/write_reissue_kunit.c 25 26 /* 27 * prepare_write_failed() sets FAILED + errno, then write_retry still calls 28 * reissue_write(). Before the fix, reissue wiped error to 0 so terminated 29 * reported success and mapping_set_error(0) was a no-op. 30 */ 31 static void reissue_preserves_prep_error(struct kunit *test) 32 { 33 struct term_capture cap = {}; 34 struct netfs_io_request wreq = {}; 35 struct netfs_io_stream stream = { 36 .source = NETFS_UPLOAD_TO_SERVER, 37 }; 38 struct netfs_io_subrequest subreq = { 39 .rreq = &wreq, 40 .len = 1, 41 .transferred = 0, 42 .error = -EIO, 43 .source = NETFS_UPLOAD_TO_SERVER, 44 }; 45 char buf[1] = { 0 }; 46 struct kvec kvec = { .iov_base = buf, .iov_len = 1 }; 47 struct iov_iter source; 48 49 __set_bit(NETFS_SREQ_FAILED, &subreq.flags); 50 iov_iter_kvec(&source, ITER_SOURCE, &kvec, 1, 1); 51 52 test->priv = ∩ 53 kunit_activate_static_stub(test, netfs_write_subrequest_terminated, 54 capture_terminated); 55 56 netfs_reissue_write(&stream, &subreq, &source); 57 58 KUNIT_EXPECT_TRUE(test, cap.called); 59 KUNIT_EXPECT_EQ(test, cap.transferred_or_error, -EIO); 60 KUNIT_EXPECT_EQ(test, subreq.error, -EIO); > 61 } 62 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH netfs v2 0/2] preserve prepare_write errno across write reissue 2026-10-28 18:12 [PATCH netfs v1 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez 2026-10-28 18:12 ` [PATCH netfs v1 1/2] netfs: preserve prepare_write errno on reissue Iván Ezequiel Rodriguez 2026-10-28 18:12 ` [PATCH netfs v1 2/2] netfs: add KUnit coverage for reissue prepare_write errno Iván Ezequiel Rodriguez @ 2026-11-02 15:06 ` Iván Ezequiel Rodriguez 2026-11-02 15:06 ` [PATCH netfs v2 1/2] netfs: preserve prepare_write errno on reissue Iván Ezequiel Rodriguez 2026-11-02 15:06 ` [PATCH netfs v2 2/2] netfs: add KUnit coverage for reissue prepare_write errno Iván Ezequiel Rodriguez 2 siblings, 2 replies; 7+ messages in thread From: Iván Ezequiel Rodriguez @ 2026-11-02 15:06 UTC (permalink / raw) To: David Howells, Paulo Alcantara, netfs Cc: Shyam Prasad N, Steve French, linux-fsdevel, linux-cifs, linux-kernel cifs (and others) may fail in prepare_write() with netfs_prepare_write_failed() before write_retry calls netfs_reissue_write(). Since 82e8885bd763, reissue clears subreq->error to 0 for a clean I/O retry, so a FAILED subreq is terminated with 0. The collector then does mapping_set_error(0), which is a no-op — writeback errno is lost (not an infinite retry). Patch 1 skips that clear when FAILED is already set. Patch 2 adds a KUnit stub test: FAIL unpatched, PASS patched. ./tools/testing/kunit/kunit.py run --kunitconfig=fs/netfs/.kunitconfig \ netfs_reissue_write* Changes in v2: - KUnit: allocate netfs_io_request / netfs_io_subrequest with kunit_kzalloc() to fix ARM allyesconfig -Wframe-larger-than= (kernel test robot). No prior lore report found for this interaction; surfaces on top of Shyam's NEED_RETRY change. Cc: David Howells <dhowells@redhat.com> Cc: Paulo Alcantara <pc@manguebit.org> Cc: Shyam Prasad N <sprasad@microsoft.com> Cc: Steve French <stfrench@microsoft.com> Cc: netfs@lists.linux.dev Cc: linux-fsdevel@vger.kernel.org Cc: linux-cifs@vger.kernel.org Iván Ezequiel Rodriguez (2): netfs: preserve prepare_write errno on reissue netfs: add KUnit coverage for reissue prepare_write errno fs/netfs/.kunitconfig | 3 ++ fs/netfs/Kconfig | 9 ++++ fs/netfs/Makefile | 2 + fs/netfs/write_collect.c | 4 ++ fs/netfs/write_issue.c | 4 +- fs/netfs/write_reissue_kunit.c | 80 ++++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 fs/netfs/.kunitconfig create mode 100644 fs/netfs/write_reissue_kunit.c -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH netfs v2 1/2] netfs: preserve prepare_write errno on reissue 2026-11-02 15:06 ` [PATCH netfs v2 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez @ 2026-11-02 15:06 ` Iván Ezequiel Rodriguez 2026-11-02 15:06 ` [PATCH netfs v2 2/2] netfs: add KUnit coverage for reissue prepare_write errno Iván Ezequiel Rodriguez 1 sibling, 0 replies; 7+ messages in thread From: Iván Ezequiel Rodriguez @ 2026-11-02 15:06 UTC (permalink / raw) To: David Howells, Paulo Alcantara, netfs Cc: Shyam Prasad N, Steve French, linux-fsdevel, linux-cifs, linux-kernel prepare_write() may call netfs_prepare_write_failed() (FAILED + errno) before write_retry calls netfs_reissue_write(). Clearing subreq->error to 0 for a clean I/O reissue (82e8885bd763) then makes netfs_do_issue_write() terminate with 0. The collector copies front->error into stream->error and mapping_set_error(), which ignores 0, so writeback failure is silent. Skip clearing error when NETFS_SREQ_FAILED is already set; do_issue_write() already terminates FAILED subrequests. Fixes: 82e8885bd763 ("netfs: when subreq is marked for retry, do not check if it faced an error") Cc: Shyam Prasad N <sprasad@microsoft.com> Cc: Steve French <stfrench@microsoft.com> Signed-off-by: Iván Ezequiel Rodriguez <ivanrwcm25@gmail.com> --- fs/netfs/write_issue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c index b8237e1314d8..f23364116421 100644 --- a/fs/netfs/write_issue.c +++ b/fs/netfs/write_issue.c @@ -268,7 +268,9 @@ void netfs_reissue_write(struct netfs_io_stream *stream, iov_iter_truncate(&subreq->io_iter, size); subreq->retry_count++; - subreq->error = 0; + /* Keep prepare_write() errno; do_issue_write() terminates FAILED. */ + if (!test_bit(NETFS_SREQ_FAILED, &subreq->flags)) + subreq->error = 0; __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); __set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags); netfs_stat(&netfs_n_wh_retry_write_subreq); -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH netfs v2 2/2] netfs: add KUnit coverage for reissue prepare_write errno 2026-11-02 15:06 ` [PATCH netfs v2 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez 2026-11-02 15:06 ` [PATCH netfs v2 1/2] netfs: preserve prepare_write errno on reissue Iván Ezequiel Rodriguez @ 2026-11-02 15:06 ` Iván Ezequiel Rodriguez 1 sibling, 0 replies; 7+ messages in thread From: Iván Ezequiel Rodriguez @ 2026-11-02 15:06 UTC (permalink / raw) To: David Howells, Paulo Alcantara, netfs Cc: Shyam Prasad N, Steve French, linux-fsdevel, linux-cifs, linux-kernel Stub netfs_write_subrequest_terminated() and call netfs_reissue_write() with FAILED + -EIO. Unpatched trees terminate with 0; patched keep -EIO. ./tools/testing/kunit/kunit.py run --kunitconfig=fs/netfs/.kunitconfig \ netfs_reissue_write* Signed-off-by: Iván Ezequiel Rodriguez <ivanrwcm25@gmail.com> --- fs/netfs/.kunitconfig | 3 ++ fs/netfs/Kconfig | 9 ++++ fs/netfs/Makefile | 2 + fs/netfs/write_collect.c | 4 ++ fs/netfs/write_reissue_kunit.c | 80 ++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+) create mode 100644 fs/netfs/.kunitconfig create mode 100644 fs/netfs/write_reissue_kunit.c diff --git a/fs/netfs/.kunitconfig b/fs/netfs/.kunitconfig new file mode 100644 index 000000000000..c783d180ab8f --- /dev/null +++ b/fs/netfs/.kunitconfig @@ -0,0 +1,3 @@ +CONFIG_KUNIT=y +CONFIG_NETFS_SUPPORT=y +CONFIG_NETFS_KUNIT_TESTS=y diff --git a/fs/netfs/Kconfig b/fs/netfs/Kconfig index d0e7b0971fa3..d796dbe4bd7c 100644 --- a/fs/netfs/Kconfig +++ b/fs/netfs/Kconfig @@ -33,6 +33,15 @@ config NETFS_DEBUG management module. If this is set, the debugging output may be enabled by setting bits in /sys/module/netfs/parameters/debug. +config NETFS_KUNIT_TESTS + tristate "KUnit tests for netfs" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + select NETFS_SUPPORT + help + This builds netfs KUnit tests (e.g. write reissue errno). + Say N unless developing netfs. + config FSCACHE bool "General filesystem local caching manager" depends on NETFS_SUPPORT diff --git a/fs/netfs/Makefile b/fs/netfs/Makefile index 54834cde7e56..fa1544b9a199 100644 --- a/fs/netfs/Makefile +++ b/fs/netfs/Makefile @@ -33,4 +33,6 @@ netfs-$(CONFIG_FSCACHE) += fscache_proc.o endif netfs-$(CONFIG_FSCACHE_STATS) += fscache_stats.o +netfs-$(CONFIG_NETFS_KUNIT_TESTS) += write_reissue_kunit.o + obj-$(CONFIG_NETFS_SUPPORT) += netfs.o diff --git a/fs/netfs/write_collect.c b/fs/netfs/write_collect.c index 6e8ea534230d..f3236fe494bf 100644 --- a/fs/netfs/write_collect.c +++ b/fs/netfs/write_collect.c @@ -11,6 +11,7 @@ #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/slab.h> +#include <kunit/static_stub.h> #include "internal.h" /* Notes made in the collector */ @@ -529,6 +530,9 @@ void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error) struct netfs_io_subrequest *subreq = _op; struct netfs_io_request *wreq = subreq->rreq; + KUNIT_STATIC_STUB_REDIRECT(netfs_write_subrequest_terminated, + _op, transferred_or_error); + _enter("%x[%x] %zd", wreq->debug_id, subreq->debug_index, transferred_or_error); switch (subreq->source) { diff --git a/fs/netfs/write_reissue_kunit.c b/fs/netfs/write_reissue_kunit.c new file mode 100644 index 000000000000..df3ef10f4985 --- /dev/null +++ b/fs/netfs/write_reissue_kunit.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * netfs_reissue_write must not clear prepare_write() errno. + */ +#include <kunit/test.h> +#include <kunit/static_stub.h> +#include <linux/uio.h> +#include "internal.h" + +struct term_capture { + ssize_t transferred_or_error; + bool called; +}; + +static void capture_terminated(void *_op, ssize_t transferred_or_error) +{ + struct netfs_io_subrequest *subreq = _op; + struct term_capture *cap = kunit_get_current_test()->priv; + + cap->called = true; + cap->transferred_or_error = transferred_or_error; + /* Mirror production: leave subreq->error as prepare_write set it. */ + (void)subreq; +} + +/* + * prepare_write_failed() sets FAILED + errno, then write_retry still calls + * reissue_write(). Before the fix, reissue wiped error to 0 so terminated + * reported success and mapping_set_error(0) was a no-op. + * + * Large netfs structs go on the heap to keep the stack frame under + * -Wframe-larger-than on 32-bit allyesconfig. + */ +static void reissue_preserves_prep_error(struct kunit *test) +{ + struct term_capture cap = {}; + struct netfs_io_request *wreq; + struct netfs_io_stream stream = { + .source = NETFS_UPLOAD_TO_SERVER, + }; + struct netfs_io_subrequest *subreq; + char buf[1] = { 0 }; + struct kvec kvec = { .iov_base = buf, .iov_len = 1 }; + struct iov_iter source; + + wreq = kunit_kzalloc(test, sizeof(*wreq), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, wreq); + + subreq = kunit_kzalloc(test, sizeof(*subreq), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, subreq); + + subreq->rreq = wreq; + subreq->len = 1; + subreq->error = -EIO; + subreq->source = NETFS_UPLOAD_TO_SERVER; + __set_bit(NETFS_SREQ_FAILED, &subreq->flags); + iov_iter_kvec(&source, ITER_SOURCE, &kvec, 1, 1); + + test->priv = ∩ + kunit_activate_static_stub(test, netfs_write_subrequest_terminated, + capture_terminated); + + netfs_reissue_write(&stream, subreq, &source); + + KUNIT_EXPECT_TRUE(test, cap.called); + KUNIT_EXPECT_EQ(test, cap.transferred_or_error, -EIO); + KUNIT_EXPECT_EQ(test, subreq->error, -EIO); +} + +static struct kunit_case netfs_reissue_test_cases[] = { + KUNIT_CASE(reissue_preserves_prep_error), + {} +}; + +static struct kunit_suite netfs_reissue_test_suite = { + .name = "netfs_reissue_write", + .test_cases = netfs_reissue_test_cases, +}; + +kunit_test_suite(netfs_reissue_test_suite); -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-11-02 15:07 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-28 18:12 [PATCH netfs v1 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez 2026-10-28 18:12 ` [PATCH netfs v1 1/2] netfs: preserve prepare_write errno on reissue Iván Ezequiel Rodriguez 2026-10-28 18:12 ` [PATCH netfs v1 2/2] netfs: add KUnit coverage for reissue prepare_write errno Iván Ezequiel Rodriguez 2026-10-29 10:19 ` kernel test robot 2026-11-02 15:06 ` [PATCH netfs v2 0/2] preserve prepare_write errno across write reissue Iván Ezequiel Rodriguez 2026-11-02 15:06 ` [PATCH netfs v2 1/2] netfs: preserve prepare_write errno on reissue Iván Ezequiel Rodriguez 2026-11-02 15:06 ` [PATCH netfs v2 2/2] netfs: add KUnit coverage for reissue prepare_write errno Iván Ezequiel Rodriguez
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®