Skip to content

Commit 42fcb65

Browse files
committed
NFS: O_DIRECT writes must check and adjust the file length
JIRA: https://issues.redhat.com/browse/RHEL-87767 commit fcf857e Author: Trond Myklebust <trond.myklebust@hammerspace.com> Date: Sat Feb 1 14:59:02 2025 -0500 NFS: O_DIRECT writes must check and adjust the file length 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> Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
1 parent 29b928d commit 42fcb65

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

fs/nfs/direct.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,20 @@ static void nfs_direct_truncate_request(struct nfs_direct_req *dreq,
130130
dreq->count = req_start;
131131
}
132132

133+
static void nfs_direct_file_adjust_size_locked(struct inode *inode,
134+
loff_t offset, size_t count)
135+
{
136+
loff_t newsize = offset + (loff_t)count;
137+
loff_t oldsize = i_size_read(inode);
138+
139+
if (newsize > oldsize) {
140+
i_size_write(inode, newsize);
141+
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_SIZE;
142+
trace_nfs_size_grow(inode, newsize);
143+
nfs_inc_stats(inode, NFSIOS_EXTENDWRITE);
144+
}
145+
}
146+
133147
/**
134148
* nfs_swap_rw - NFS address space operation for swap I/O
135149
* @iocb: target I/O control block
@@ -732,6 +746,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
732746
struct nfs_direct_req *dreq = hdr->dreq;
733747
struct nfs_commit_info cinfo;
734748
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
749+
struct inode *inode = dreq->inode;
735750
int flags = NFS_ODIRECT_DONE;
736751

737752
trace_nfs_direct_write_completion(dreq);
@@ -753,6 +768,10 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
753768
}
754769
spin_unlock(&dreq->lock);
755770

771+
spin_lock(&inode->i_lock);
772+
nfs_direct_file_adjust_size_locked(inode, dreq->io_start, dreq->count);
773+
spin_unlock(&inode->i_lock);
774+
756775
while (!list_empty(&hdr->pages)) {
757776

758777
req = nfs_list_entry(hdr->pages.next);

0 commit comments

Comments
 (0)