nfs: only issue commit in DIO codepath if we have uncommitted data

Currently, we try to determine whether to issue a commit based on
nfs_write_need_commit which looks at the current verifier. In the case
where we got a short write and then tried to follow it up with one that
failed, the verifier can't be trusted.

What we really want to know is whether the pgio request had any
successful writes that came back as UNSTABLE. Add a new flag to the pgio
request, and use that to indicate that we've had a successful unstable
write. Only issue a commit if that flag is set.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
Jeff Layton
2022-07-22 14:12:20 -04:00
committed by Trond Myklebust
parent 55051c0ced
commit 69d966510d
3 changed files with 32 additions and 19 deletions

View File

@@ -690,7 +690,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
}
nfs_direct_count_bytes(dreq, hdr);
if (hdr->good_bytes != 0 && nfs_write_need_commit(hdr)) {
if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags)) {
if (!dreq->flags)
dreq->flags = NFS_ODIRECT_DO_COMMIT;
flags = dreq->flags;

View File

@@ -1576,8 +1576,19 @@ static int nfs_writeback_done(struct rpc_task *task,
nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count);
trace_nfs_writeback_done(task, hdr);
if (hdr->res.verf->committed < hdr->args.stable &&
task->tk_status >= 0) {
if (task->tk_status >= 0) {
enum nfs3_stable_how committed = hdr->res.verf->committed;
if (committed == NFS_UNSTABLE) {
/*
* We have some uncommitted data on the server at
* this point, so ensure that we keep track of that
* fact irrespective of what later writes do.
*/
set_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags);
}
if (committed < hdr->args.stable) {
/* We tried a write call, but the server did not
* commit data to stable storage even though we
* requested it.
@@ -1593,10 +1604,11 @@ static int nfs_writeback_done(struct rpc_task *task,
dprintk("NFS: faulty NFS server %s:"
" (committed = %d) != (stable = %d)\n",
NFS_SERVER(inode)->nfs_client->cl_hostname,
hdr->res.verf->committed, hdr->args.stable);
committed, hdr->args.stable);
complain = jiffies + 300 * HZ;
}
}
}
/* Deal with the suid/sgid bit corner case */
if (nfs_should_remove_suid(inode)) {

View File

@@ -1600,6 +1600,7 @@ enum {
NFS_IOHDR_STAT,
NFS_IOHDR_RESEND_PNFS,
NFS_IOHDR_RESEND_MDS,
NFS_IOHDR_UNSTABLE_WRITES,
};
struct nfs_io_completion;