]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
NFS: fix eof updates after NFSv4.2 fallocate/zero-range
authorDai Ngo <dai.ngo@oracle.com>
Thu, 23 Apr 2026 17:52:10 +0000 (10:52 -0700)
committerAnna Schumaker <anna.schumaker@hammerspace.com>
Mon, 8 Jun 2026 14:21:55 +0000 (10:21 -0400)
Generic/075 reliably exposes a regression when the client holds an
NFSv4 write delegation: ZERO_RANGE/ALLOCATE extends the file on the
server, but the local inode keeps the old i_size. The test then fails
with 'Size error' because the post-op attribute refresh refuses to
touch i_size while a delegation is outstanding, and the cached EOF
was never marked stale.

Update _nfs42_proc_fallocate() so that on success it:

- bumps i_size when the operation extends the file, and
- marks NFS_INO_INVALID_BLOCKS since the block count can also change

Tested with xfstests generic/075 over NFSv4.2.

Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
fs/nfs/nfs42proc.c

index 7602ede6f75f7c7afbe39076ce3521eef9a5d768..ab86246fc364f631d7664462d2048d9e83ac40d1 100644 (file)
@@ -81,12 +81,17 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
        status = nfs4_call_sync(server->client, server, msg,
                                &args.seq_args, &res.seq_res, 0);
        if (status == 0) {
-               if (nfs_should_remove_suid(inode)) {
-                       spin_lock(&inode->i_lock);
+               loff_t newsize = offset + len;
+
+               spin_lock(&inode->i_lock);
+               if (newsize > i_size_read(inode))
+                       i_size_write(inode, newsize);
+               nfs_set_cache_invalid(inode, NFS_INO_INVALID_BLOCKS);
+               if (nfs_should_remove_suid(inode))
                        nfs_set_cache_invalid(inode,
-                               NFS_INO_REVAL_FORCED | NFS_INO_INVALID_MODE);
-                       spin_unlock(&inode->i_lock);
-               }
+                                             NFS_INO_REVAL_FORCED |
+                                             NFS_INO_INVALID_MODE);
+               spin_unlock(&inode->i_lock);
                status = nfs_post_op_update_inode_force_wcc(inode,
                                                            res.falloc_fattr);
        }