[PATCH 2/2] nfs: expose FMODE_NOWAIT for O_DIRECT read files
From: Dylan Yudaken
Date: Sat May 30 2026 - 18:25:43 EST
O_DIRECT reads already (mostly) handle async requests, with the
exception of locking the inode for direct.
Handle async requests properly by using nfs_start_io_direct_nowait,
and then expose FMODE_NOWAIT since it's now properly supported.
Signed-off-by: Dylan Yudaken <dyudaken@xxxxxxxxx>
---
fs/nfs/direct.c | 5 ++++-
fs/nfs/file.c | 13 ++++++++++++-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 48d89716193a..bf0bad971d22 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -473,7 +473,10 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
if (!swap) {
- result = nfs_start_io_direct(inode);
+ if (iocb->ki_flags & IOCB_NOWAIT)
+ result = nfs_start_io_direct_nowait(inode);
+ else
+ result = nfs_start_io_direct(inode);
if (result) {
/* release the reference that would usually be
* consumed by nfs_direct_read_schedule_iovec()
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 25048a3c2364..c5eb22036e71 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -72,8 +72,13 @@ nfs_file_open(struct inode *inode, struct file *filp)
return res;
res = nfs_open(inode, filp);
- if (res == 0)
+ if (res == 0) {
filp->f_mode |= FMODE_CAN_ODIRECT;
+ /* flag NOWAIT on read-only O_DIRECT files only */
+ if ((filp->f_flags & O_DIRECT) &&
+ !(filp->f_mode & FMODE_WRITE))
+ filp->f_mode |= FMODE_NOWAIT;
+ }
return res;
}
@@ -705,6 +710,12 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
trace_nfs_file_write(iocb, from);
+ /*
+ * FMODE_NOWAIT is not set for writable files
+ */
+ if (WARN_ON_ONCE(iocb->ki_flags & IOCB_NOWAIT))
+ return -EAGAIN;
+
result = nfs_key_timeout_notify(file, inode);
if (result)
return result;
--
2.50.1