[cifs-protocol] Clarification on expected behavior with SMB2 short reads/writes.
jra at samba.org
Thu May 14 17:32:17 UTC 2020
We recently noticed a problem with the Windows
(and MacOSX) clients when the server returns
The MS-SMB2 description of SMB2_READ has the following
field inside the read request:
MinimumCount (4 bytes): The minimum number of bytes to be read for this operation to be
successful. If fewer than the minimum number of bytes are read by the server, the server
MUST return an error rather than the bytes read.
Windows sets this to zero, implying that
for a read request of X bytes, a server
may optionally return less than X bytes,
so long as the number of bytes returned
is greater than MinimumCount.
This is expected at end-of-file, when
the server has run out of available bytes
However, the Windows client misbehaves
if this is returned for an SMB2_READ at
an offset in the middle of a file.
The Windows client pipelines reads at
(around) 1MB byte boundaries, and issues
as many async simultaneous reads as it
has credits for. So for a 1GB file it
can simultaneously send (note this is
an example only, I have wireshark traces
of real behavior):
1). SMB2_READ offset 0 length 1MB
2). SMB2_READ offset 1MB length 1MB
3). SMB2_READ offset 2MB length 1MB
X). SMB2_READ offset (X-1)MB length 1MB
Consider if the server returns a read
return value of 1MB-2 bytes for the
(1) read (the one at offset 0).
Linux cifsfs and the libsmbclient Samba
library check the short read return value,
and will re-issue a read at offset 1MB-2
length 2 bytes to fill in the missing data.
The Windows client doesn't treat the short
read reply at (1) as EOF, and doesn't re-issue a
read for the missing 2 bytes, ending up with
data corruption in the copied file.
If this is expected behavior, I think either
the protocol doc needs updating to prohibit
short reads (and probably writes too) or
a Windows behavior note adding explaining
that Windows clients cannot cope with short
SMB2_READ / SMB2_WRITE replies (execpt for
EOF/EIO or DISK_FULL/EIO cases).
More information about the cifs-protocol