summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@hammerspace.com>2025-02-01 14:59:02 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-03-07 18:26:54 +0100
commit04ad0979b163e2abddde6ee9619551c393d5bad9 (patch)
tree2a1746d1905c07ff3f91d577c2eae2df29cb5d4a /fs
parent60b4b5c1277fc491da9e1e7abab307bfa39c2db7 (diff)
downloadlinux-04ad0979b163e2abddde6ee9619551c393d5bad9.tar.gz
linux-04ad0979b163e2abddde6ee9619551c393d5bad9.tar.bz2
linux-04ad0979b163e2abddde6ee9619551c393d5bad9.zip
NFS: O_DIRECT writes must check and adjust the file length
[ Upstream commit fcf857ee1958e9247298251f7615d0c76f1e9b38 ] While it is uncommon for delegations to be held while O_DIRECT writes are in progress, it is possible. The xfstests generic/647 and generic/729 both end up triggering that state, and end up failing due to the fact that the file size is not adjusted. Reported-by: Chuck Lever <chuck.lever@oracle.com> Link: https://bugzilla.kernel.org/show_bug.cgi?id=219738 Cc: stable@vger.kernel.org Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> Stable-dep-of: 88025c67fe3c ("NFS: Adjust delegated timestamps for O_DIRECT reads and writes") Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/direct.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index b08dbe96bc57..8f2aa2bf4565 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -130,6 +130,20 @@ static void nfs_direct_truncate_request(struct nfs_direct_req *dreq,
dreq->count = req_start;
}
+static void nfs_direct_file_adjust_size_locked(struct inode *inode,
+ loff_t offset, size_t count)
+{
+ loff_t newsize = offset + (loff_t)count;
+ loff_t oldsize = i_size_read(inode);
+
+ if (newsize > oldsize) {
+ i_size_write(inode, newsize);
+ NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_SIZE;
+ trace_nfs_size_grow(inode, newsize);
+ nfs_inc_stats(inode, NFSIOS_EXTENDWRITE);
+ }
+}
+
/**
* nfs_swap_rw - NFS address space operation for swap I/O
* @iocb: target I/O control block
@@ -740,6 +754,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
struct nfs_direct_req *dreq = hdr->dreq;
struct nfs_commit_info cinfo;
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
+ struct inode *inode = dreq->inode;
int flags = NFS_ODIRECT_DONE;
trace_nfs_direct_write_completion(dreq);
@@ -761,6 +776,10 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
}
spin_unlock(&dreq->lock);
+ spin_lock(&inode->i_lock);
+ nfs_direct_file_adjust_size_locked(inode, dreq->io_start, dreq->count);
+ spin_unlock(&inode->i_lock);
+
while (!list_empty(&hdr->pages)) {
req = nfs_list_entry(hdr->pages.next);