Re: [PATCH] smb/client: fix unaligned fallocate emulation with O_DIRECT

Paulo Alcantara <[email protected]> Thu, 16 Jul 2026 12:09:30 -0300
Newsgroups org.kernel.vger.linux-cifs
Message-ID <[email protected]>
Huiwen He <[email protected]> writes:

> From: Huiwen He <[email protected]>
>
> Commit 4a7d2729dc99 ("smb: client: fix atomic open with O_DIRECT & O_SYNC")
> made atomic O_DIRECT opens correctly use CREATE_NO_BUFFER. This exposed
> an issue in the fallocate emulation added by
> commit 966a3cb7c7db ("cifs: improve fallocate emulation"), which may
> reuse the handle for unaligned zero writes.
>
> Windows requires the offset and length of writes on an
> unbuffered handle to be sector aligned, and rejects these writes
> with STATUS_INVALID_PARAMETER, causing xfstests generic/760 to fail.
>
> For SMB3.02 and later, fix this by keeping the handle buffered and using
> READ_UNBUFFERED or WRITE_UNBUFFERED only for actual direct I/O requests.
> Determine this from the netfs request origin rather than the file flags,
> since mmap writeback on an O_DIRECT file is still buffered.
>
> For older dialects, retain CREATE_NO_BUFFER since they do not support
> per-I/O unbuffered flags.
>
> With this change, xfstests generic/760 passes against Windows with SMB3.02
> or later, while Windows SMB3.0 remains affected.
>
> Fixes: 4a7d2729dc99 ("smb: client: fix atomic open with O_DIRECT & O_SYNC")
> Signed-off-by: Huiwen He <[email protected]>
> Reviewed-by: ChenXiaoSong <[email protected]>
> ---
>  fs/smb/client/cifsglob.h | 13 +++++++++++--
>  fs/smb/client/dir.c      |  2 +-
>  fs/smb/client/file.c     |  4 ++--
>  fs/smb/client/smb2pdu.c  |  6 ++++++
>  4 files changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
> index 08e94633a9c1..2e43dbd564de 100644
> --- a/fs/smb/client/cifsglob.h
> +++ b/fs/smb/client/cifsglob.h
> @@ -2374,17 +2374,26 @@ static inline void cifs_reset_oplock(struct cifsInodeInfo *cinode)
>  		WRITE_ONCE(cinode->oplock, 0);
>  }
>  
> +static inline bool
> +cifs_server_supports_per_io_unbuffered(const struct TCP_Server_Info *server)
> +{
> +	return server && server->dialect >= SMB302_PROT_ID;
> +}
> +

Unfortunately this check is unsufficient to tell whether the server will
actually support SMB2_WRITEFLAG_WRITE_UNBUFFERED and
SMB2_READFLAG_READ_UNBUFFERED flags.

Have you tested this against Azure server?  IIRC, the server would
reject the write and read requests with STATUS_INVALID_PARAMETER if any
of those flags was set.

I had a patch to use those flags and improve reuse of open handles but
then gave up as Azure server seems to be the only one broken regarding
those flags.