mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
smb: client: distinguish real EOF from a stale remote_i_size on read
smb2_readv_callback() sets NETFS_SREQ_HIT_EOF whenever a short read
lines up with netfs_read_remote_i_size(inode), the server's EOF as the
client currently believes it. That belief can be stale: after a lease
downgrade and handle reopen, the tracked remote_i_size can sit below
the client's own i_size while an extending write hasn't reached the
server yet. A read in that gap comes back short for a reason that has
nothing to do with the file's real size, but was still marked HIT_EOF,
and netfs reports a short read for it as-is.
Only treat it as real EOF when the position is also at or past the
client's own i_size; otherwise mark it NETFS_SREQ_CLEAR_TAIL instead,
which tells netfs the shortfall is safe to zero-fill rather than
report as a short read.
This is what fsx (generic/363) sees as "short read: 0x0 bytes instead
of 0x<n>" against a Windows server.
Fixes: 1da29f2c39 ("netfs, cifs: Fix handling of short DIO read")
Reviewed-by: David Howells <dhowells@redhat.com>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Cc: Shyam Prasad N <sprasad@microsoft.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Bharath SM <bharathsm@microsoft.com>
Cc: stable@vger.kernel.org
This commit is contained in:
parent
dd05add7b2
commit
75aa4b4d55
|
|
@ -4796,14 +4796,20 @@ smb2_readv_callback(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||
rdata->got_bytes);
|
||||
|
||||
if (rdata->result == -ENODATA) {
|
||||
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
|
||||
rdata->result = 0;
|
||||
if (rdata->subreq.start + rdata->subreq.transferred >= i_size_read(inode))
|
||||
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
|
||||
else
|
||||
__set_bit(NETFS_SREQ_CLEAR_TAIL, &rdata->subreq.flags);
|
||||
} else {
|
||||
size_t trans = rdata->subreq.transferred + rdata->got_bytes;
|
||||
if (trans < rdata->subreq.len &&
|
||||
rdata->subreq.start + trans >= netfs_read_remote_i_size(inode)) {
|
||||
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
|
||||
rdata->result = 0;
|
||||
if (rdata->subreq.start + trans >= i_size_read(inode))
|
||||
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
|
||||
else
|
||||
__set_bit(NETFS_SREQ_CLEAR_TAIL, &rdata->subreq.flags);
|
||||
}
|
||||
if (rdata->got_bytes)
|
||||
__set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user