]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
NFS: Serialise O_DIRECT i/o and truncate()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 5 Sep 2025 16:06:23 +0000 (12:06 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 19 Sep 2025 14:35:44 +0000 (16:35 +0200)
[ Upstream commit 9eb90f435415c7da4800974ed943e39b5578ee7f ]

Ensure that all O_DIRECT reads and writes are complete, and prevent the
initiation of new i/o until the setattr operation that will truncate the
file is complete.

Fixes: a5864c999de6 ("NFS: Do not serialise O_DIRECT reads and writes")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/io.c

index 8827cb00f86d52b0437b7a3f57feb3c27c6f6c54..5bf5fb5ddd34c0327d63f4f4f0ed42996bced814 100644 (file)
@@ -761,8 +761,10 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
        trace_nfs_setattr_enter(inode);
 
        /* Write all dirty data */
-       if (S_ISREG(inode->i_mode))
+       if (S_ISREG(inode->i_mode)) {
+               nfs_file_block_o_direct(NFS_I(inode));
                nfs_sync_inode(inode);
+       }
 
        fattr = nfs_alloc_fattr_with_label(NFS_SERVER(inode));
        if (fattr == NULL) {
index 4860270f1be0499ddf5e11647193bea25e074d56..456b42340281418b3612088e655f584375590b82 100644 (file)
@@ -529,6 +529,16 @@ static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)
        return test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0;
 }
 
+/* Must be called with exclusively locked inode->i_rwsem */
+static inline void nfs_file_block_o_direct(struct nfs_inode *nfsi)
+{
+       if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
+               clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
+               inode_dio_wait(&nfsi->vfs_inode);
+       }
+}
+
+
 /* namespace.c */
 #define NFS_PATH_CANONICAL 1
 extern char *nfs_path(char **p, struct dentry *dentry,
index 3388faf2acb9f59c20feb5bfc3f01023e9c18147..d275b0a250bf3bd79d324af35004125718710f52 100644 (file)
 
 #include "internal.h"
 
-/* Call with exclusively locked inode->i_rwsem */
-static void nfs_block_o_direct(struct nfs_inode *nfsi, struct inode *inode)
-{
-       if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
-               clear_bit(NFS_INO_ODIRECT, &nfsi->flags);
-               inode_dio_wait(inode);
-       }
-}
-
 /**
  * nfs_start_io_read - declare the file is being used for buffered reads
  * @inode: file inode
@@ -57,7 +48,7 @@ nfs_start_io_read(struct inode *inode)
        err = down_write_killable(&inode->i_rwsem);
        if (err)
                return err;
-       nfs_block_o_direct(nfsi, inode);
+       nfs_file_block_o_direct(nfsi);
        downgrade_write(&inode->i_rwsem);
 
        return 0;
@@ -90,7 +81,7 @@ nfs_start_io_write(struct inode *inode)
 
        err = down_write_killable(&inode->i_rwsem);
        if (!err)
-               nfs_block_o_direct(NFS_I(inode), inode);
+               nfs_file_block_o_direct(NFS_I(inode));
        return err;
 }