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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+30 −18
Original line number Diff line number Diff line
@@ -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)) {
+1 −0
Original line number Diff line number Diff line
@@ -1600,6 +1600,7 @@ enum {
	NFS_IOHDR_STAT,
	NFS_IOHDR_RESEND_PNFS,
	NFS_IOHDR_RESEND_MDS,
	NFS_IOHDR_UNSTABLE_WRITES,
};

struct nfs_io_completion;