From ace72c3d263294df7111477caaeff37438aa10af Mon Sep 17 00:00:00 2001 From: David Flynn Date: Tue, 8 Sep 2026 12:34:46 -0400 Subject: [PATCH] nfsd: fetch direct I/O alignment for files handed to the filecache nfsd_file_do_acquire() fetches a file's direct I/O alignment attributes (nf_dio_mem_align, nf_dio_offset_align and nf_dio_read_offset_align) only on the branch where NFSD opens the file itself. The other branch, taken when the caller supplies an already-open struct file, stores that file in the nfsd_file and leaves the three alignment fields zero. NFSv4 OPEN with CREATE takes the supplied-file branch: nfsd4_create_file() creates the file with dentry_create() and passes the resulting struct file as open->op_filp, which nfs4_get_vfs_file() hands to nfsd_file_acquire_opened(). The cached nfsd_file therefore keeps zero alignment for its whole life, and nfsd_write_dio_iters_init() refuses direct I/O for every WRITE to a file the client has just created. Observed on an export whose backing device reports a dio_mem_align of 4: all 16 of 16 1 MiB NFSv4.2 writes that followed an OPEN(CREATE) took the buffered path, while 16 of 16 writes to the same file reopened without CREATE went direct. Hoist the nfsd_file_get_dio_attrs() call out of the open branch so that it runs once, for both branches, whenever the acquire has otherwise succeeded. A getattr failure now fails the acquire on the supplied-file branch exactly as it already does on the open branch. Fixes: d11f6cd1bb4a ("NFSD: filecache: add STATX_DIOALIGN and STATX_DIO_READ_ALIGN support") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-fable-5.1 Signed-off-by: David Flynn Signed-off-by: Mike Snitzer Link: https://patch.msgid.link/20260908163448.30841-4-snitzer@kernel.org Signed-off-by: Chuck Lever --- fs/nfsd/filecache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 3539149cc75f..17a94e6fcb15 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -1286,9 +1286,9 @@ open_file: } status = nfserrno(ret); trace_nfsd_file_open(nf, status); - if (status == nfs_ok) - status = nfsd_file_get_dio_attrs(fhp, nf); } + if (status == nfs_ok) + status = nfsd_file_get_dio_attrs(fhp, nf); } else status = nfserr_jukebox; /*