Skip to content

Commit fcf857e

Browse files
Trond MyklebustAnna Schumaker
authored andcommitted
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 <[email protected]> Link: https://bugzilla.kernel.org/show_bug.cgi?id=219738 Cc: [email protected] Signed-off-by: Trond Myklebust <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 0ad2507 commit fcf857e

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
@@ -741,6 +755,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
741755
struct nfs_direct_req *dreq = hdr->dreq;
742756
struct nfs_commit_info cinfo;
743757
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
758+
struct inode *inode = dreq->inode;
744759
int flags = NFS_ODIRECT_DONE;
745760

746761
trace_nfs_direct_write_completion(dreq);
@@ -762,6 +777,10 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
762777
}
763778
spin_unlock(&dreq->lock);
764779

780+
spin_lock(&inode->i_lock);
781+
nfs_direct_file_adjust_size_locked(inode, dreq->io_start, dreq->count);
782+
spin_unlock(&inode->i_lock);
783+
765784
while (!list_empty(&hdr->pages)) {
766785

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

0 commit comments

Comments
 (0)