[BUG netfs] folio changes during io results in CIFS send failures
"Henrique Carvalho" <[email protected]> Thu, 23 Jul 2026 18:28:25 -0300
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <[email protected]> |
Hi David and Steve,
When running the fio write workload
fio --name=smb-fio \
--directory=/mnt \
--rw=write \
--bs=4k \
--size=4k \
--ioengine=io_uring \
--direct=0 \
--numjobs=1 \
--iodepth=1 \
--time_based=1 \
--runtime=500 \
--unlink=0 \
--group_reporting=1 \
--filename_format="$file_fmt" \
--output-format=json \
--output=smb-fio.json
on a mounted CIFS share I saw the messages
CIFS: VFS: sign fail cmd 0x9 message id 0x49127
CIFS: VFS: \\win22.bira.test SMB signature verification returned error = -13
After debugging the signed request, sent request, signature and
recalculated signature on sent request I found out that a folio content
change is happening between signature and sending the data, while the
signature is not changing. Some debug messages for reference:
CIFS: sign-write-req-sig-changed conn=1 mid=0x49127 hdr_mid=0x49127
flags=0x8 cc=64 cr=72 tid=0x5 sid=0x2880074000071 iter_1=4194304 iter_2=4194304
sig_1=92eeb2b661423fc65c86401a4c14888f
sig_2=8e53f3f500d42122183c8c74227520e7
CIFS: sign-write-req-delta conn=3 mid=0xccb4 first_diff=168
last_diff=3754 diff_bytes=24 diff_ranges=8 len_1=4208
len_2=4208 iter_1=4096 iter_2=4096
CIFS: sign-write-req-delta-range conn=3 mid=0xccb4 range=0 off=168
len=3
buf_1=1d5e730f000000000000000000000000b62c7d9d5f374dcc11c33b6c0fd37332
buf_2=9db87c0f000000000000000000000000b62c7d9d5f374dcc11c33b6c0fd37332
^^^^^^
`first_diff` above shows the first changed byte is payload offset 56
(112 byte header) and we can see a 3-byte change there. This same 3-byte
change repeats every 512 bytes in the payload.
After digging into netfs code, I noticed the folios are not kept locked
while a subrequest is being filled, and maybe this allows changes to
this folio even though it has not been marked as ended writeback.
In my case, the subrequest can be much larger than a single folio, so
netfs accumulates several 4k folios before issuing the network write.
So a minimal change that prevented this unwanted change during write is
the following -- *although I'm likely missing something*.
If you think this makes sense I can send a formal patch.
diff --git a/fs/netfs/write_collect.c b/fs/netfs/write_collect.c
index 210eb8f3958d..bce1f2b80a9c 100644
--- a/fs/netfs/write_collect.c
+++ b/fs/netfs/write_collect.c
@@ -63,6 +63,8 @@ int netfs_folio_written_back(struct folio *folio)
struct netfs_group *group = NULL;
int gcount = 0;
+ folio_unlock(folio);
+
if ((finfo = netfs_folio_info(folio))) {
/* Streaming writes cannot be redirtied whilst under writeback,
* so discard the streaming record.
diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c
index f2761c99795a..cf4e39d593ce 100644
--- a/fs/netfs/write_issue.c
+++ b/fs/netfs/write_issue.c
@@ -347,7 +347,6 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
/* mmap beyond eof. */
_debug("beyond eof");
folio_start_writeback(folio);
- folio_unlock(folio);
wreq->nr_group_rel += netfs_folio_written_back(folio);
netfs_put_group_many(wreq->group, wreq->nr_group_rel);
wreq->nr_group_rel = 0;
@@ -415,7 +414,6 @@ static int netfs_write_folio(struct netfs_io_request *wreq,
netfs_issue_write(wreq, cache);
folio_start_writeback(folio);
- folio_unlock(folio);
if (fgroup == NETFS_FOLIO_COPY_TO_CACHE) {
if (!cache->avail) {
--
Henrique