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>
This commit is contained in:
parent
0ad2507d5d
commit
fcf857ee19
1 changed files with 19 additions and 0 deletions
|
@ -130,6 +130,20 @@ static void nfs_direct_truncate_request(struct nfs_direct_req *dreq,
|
||||||
dreq->count = req_start;
|
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
|
* nfs_swap_rw - NFS address space operation for swap I/O
|
||||||
* @iocb: target I/O control block
|
* @iocb: target I/O control block
|
||||||
|
@ -741,6 +755,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
|
||||||
struct nfs_direct_req *dreq = hdr->dreq;
|
struct nfs_direct_req *dreq = hdr->dreq;
|
||||||
struct nfs_commit_info cinfo;
|
struct nfs_commit_info cinfo;
|
||||||
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
|
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
|
||||||
|
struct inode *inode = dreq->inode;
|
||||||
int flags = NFS_ODIRECT_DONE;
|
int flags = NFS_ODIRECT_DONE;
|
||||||
|
|
||||||
trace_nfs_direct_write_completion(dreq);
|
trace_nfs_direct_write_completion(dreq);
|
||||||
|
@ -762,6 +777,10 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
|
||||||
}
|
}
|
||||||
spin_unlock(&dreq->lock);
|
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)) {
|
while (!list_empty(&hdr->pages)) {
|
||||||
|
|
||||||
req = nfs_list_entry(hdr->pages.next);
|
req = nfs_list_entry(hdr->pages.next);
|
||||||
|
|
Loading…
Add table
Reference in a new issue