Commit 69d96651 authored by Jeff Layton's avatar Jeff Layton Committed by Trond Myklebust

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: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 55051c0c
...@@ -690,7 +690,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) ...@@ -690,7 +690,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
} }
nfs_direct_count_bytes(dreq, 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) if (!dreq->flags)
dreq->flags = NFS_ODIRECT_DO_COMMIT; dreq->flags = NFS_ODIRECT_DO_COMMIT;
flags = dreq->flags; flags = dreq->flags;
......
...@@ -1576,25 +1576,37 @@ static int nfs_writeback_done(struct rpc_task *task, ...@@ -1576,25 +1576,37 @@ static int nfs_writeback_done(struct rpc_task *task,
nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count); nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count);
trace_nfs_writeback_done(task, hdr); trace_nfs_writeback_done(task, hdr);
if (hdr->res.verf->committed < hdr->args.stable && if (task->tk_status >= 0) {
task->tk_status >= 0) { enum nfs3_stable_how committed = hdr->res.verf->committed;
/* We tried a write call, but the server did not
* commit data to stable storage even though we if (committed == NFS_UNSTABLE) {
* requested it. /*
* Note: There is a known bug in Tru64 < 5.0 in which * We have some uncommitted data on the server at
* the server reports NFS_DATA_SYNC, but performs * this point, so ensure that we keep track of that
* NFS_FILE_SYNC. We therefore implement this checking * fact irrespective of what later writes do.
* as a dprintk() in order to avoid filling syslog. */
*/ set_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags);
static unsigned long complain; }
/* Note this will print the MDS for a DS write */ if (committed < hdr->args.stable) {
if (time_before(complain, jiffies)) { /* We tried a write call, but the server did not
dprintk("NFS: faulty NFS server %s:" * commit data to stable storage even though we
" (committed = %d) != (stable = %d)\n", * requested it.
NFS_SERVER(inode)->nfs_client->cl_hostname, * Note: There is a known bug in Tru64 < 5.0 in which
hdr->res.verf->committed, hdr->args.stable); * the server reports NFS_DATA_SYNC, but performs
complain = jiffies + 300 * HZ; * NFS_FILE_SYNC. We therefore implement this checking
* as a dprintk() in order to avoid filling syslog.
*/
static unsigned long complain;
/* Note this will print the MDS for a DS write */
if (time_before(complain, jiffies)) {
dprintk("NFS: faulty NFS server %s:"
" (committed = %d) != (stable = %d)\n",
NFS_SERVER(inode)->nfs_client->cl_hostname,
committed, hdr->args.stable);
complain = jiffies + 300 * HZ;
}
} }
} }
......
...@@ -1600,6 +1600,7 @@ enum { ...@@ -1600,6 +1600,7 @@ enum {
NFS_IOHDR_STAT, NFS_IOHDR_STAT,
NFS_IOHDR_RESEND_PNFS, NFS_IOHDR_RESEND_PNFS,
NFS_IOHDR_RESEND_MDS, NFS_IOHDR_RESEND_MDS,
NFS_IOHDR_UNSTABLE_WRITES,
}; };
struct nfs_io_completion; struct nfs_io_completion;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment