]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
nfs: expose FMODE_NOWAIT for read-only files
authorDylan Yudaken <dyudaken@gmail.com>
Sun, 7 Jun 2026 07:31:55 +0000 (08:31 +0100)
committerAnna Schumaker <anna.schumaker@hammerspace.com>
Mon, 8 Jun 2026 16:07:16 +0000 (12:07 -0400)
NFS 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 supported for direct reads.

Signed-off-by: Dylan Yudaken <dyudaken@gmail.com>
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
fs/nfs/direct.c
fs/nfs/file.c

index 48d89716193a7ed1c0033fb093d4fa9d5a099139..e626c72495e69a074149ca20379a2fa5e6f903df 100644 (file)
@@ -466,14 +466,22 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
                goto out_release;
        }
        dreq->l_ctx = l_ctx;
-       if (!is_sync_kiocb(iocb))
+       if (!is_sync_kiocb(iocb)) {
                dreq->iocb = iocb;
+       } else if (iocb->ki_flags & IOCB_NOWAIT) {
+               result = -EAGAIN;
+               nfs_direct_req_release(dreq);
+               goto out_release;
+       }
 
        if (user_backed_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()
index 25048a3c236436f334c87e2d58614f8af8929560..a0d8f1c1cf103e663ee2858a0958144400e81b47 100644 (file)
@@ -72,8 +72,12 @@ 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 files only */
+               if (!(filp->f_mode & FMODE_WRITE))
+                       filp->f_mode |= FMODE_NOWAIT;
+       }
        return res;
 }
 
@@ -166,6 +170,10 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
        if (iocb->ki_flags & IOCB_DIRECT)
                return nfs_file_direct_read(iocb, to, false);
 
+       /* NOWAIT only supported on direct reads */
+       if (iocb->ki_flags & IOCB_NOWAIT)
+               return -EAGAIN;
+
        dprintk("NFS: read(%pD2, %zu@%lu)\n",
                iocb->ki_filp,
                iov_iter_count(to), (unsigned long) iocb->ki_pos);
@@ -705,6 +713,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;