Skip to content

Commit

Permalink
NFS/pnfs: Fix pnfs_generic_prepare_to_resend_writes()
Browse files Browse the repository at this point in the history
Instead of making assumptions about the commit verifier contents, change
the commit code to ensure we always check that the verifier was set
by the XDR code.

Fixes: f54bcf2 ("pnfs: Prepare for flexfiles by pulling out common code")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
  • Loading branch information
trondmy authored and amschuma-ntap committed Jan 15, 2020
1 parent 2197e9b commit 221203c
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 9 deletions.
4 changes: 2 additions & 2 deletions fs/nfs/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,10 @@ static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq,
data->ds_commit_index);

/* verifier not set so always fail */
if (verfp->committed < 0)
if (verfp->committed < 0 || data->res.verf->committed <= NFS_UNSTABLE)
return 1;

return nfs_direct_cmp_verf(verfp, &data->verf);
return nfs_direct_cmp_verf(verfp, data->res.verf);
}

/**
Expand Down
5 changes: 4 additions & 1 deletion fs/nfs/nfs3xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,7 @@ static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
void *data)
{
struct nfs_commitres *result = data;
struct nfs_writeverf *verf = result->verf;
enum nfs_stat status;
int error;

Expand All @@ -2346,7 +2347,9 @@ static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
result->op_status = status;
if (status != NFS3_OK)
goto out_status;
error = decode_writeverf3(xdr, &result->verf->verifier);
error = decode_writeverf3(xdr, &verf->verifier);
if (!error)
verf->committed = NFS_FILE_SYNC;
out:
return error;
out_status:
Expand Down
5 changes: 4 additions & 1 deletion fs/nfs/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -4313,11 +4313,14 @@ static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifi

static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res)
{
struct nfs_writeverf *verf = res->verf;
int status;

status = decode_op_hdr(xdr, OP_COMMIT);
if (!status)
status = decode_write_verifier(xdr, &res->verf->verifier);
status = decode_write_verifier(xdr, &verf->verifier);
if (!status)
verf->committed = NFS_FILE_SYNC;
return status;
}

Expand Down
7 changes: 3 additions & 4 deletions fs/nfs/pnfs_nfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ EXPORT_SYMBOL_GPL(pnfs_generic_rw_release);
/* Fake up some data that will cause nfs_commit_release to retry the writes. */
void pnfs_generic_prepare_to_resend_writes(struct nfs_commit_data *data)
{
struct nfs_page *first = nfs_list_entry(data->pages.next);
struct nfs_writeverf *verf = data->res.verf;

data->task.tk_status = 0;
memcpy(&data->verf.verifier, &first->wb_verf,
sizeof(data->verf.verifier));
data->verf.verifier.data[0]++; /* ensure verifier mismatch */
memset(&verf->verifier, 0, sizeof(verf->verifier));
verf->committed = NFS_UNSTABLE;
}
EXPORT_SYMBOL_GPL(pnfs_generic_prepare_to_resend_writes);

Expand Down
4 changes: 3 additions & 1 deletion fs/nfs/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -1840,6 +1840,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)

static void nfs_commit_release_pages(struct nfs_commit_data *data)
{
const struct nfs_writeverf *verf = data->res.verf;
struct nfs_page *req;
int status = data->task.tk_status;
struct nfs_commit_info cinfo;
Expand Down Expand Up @@ -1868,7 +1869,8 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)

/* Okay, COMMIT succeeded, apparently. Check the verifier
* returned by the server against all stored verfs. */
if (!nfs_write_verifier_cmp(&req->wb_verf, &data->verf.verifier)) {
if (verf->committed > NFS_UNSTABLE &&
!nfs_write_verifier_cmp(&req->wb_verf, &verf->verifier)) {
/* We have a match */
if (req->wb_page)
nfs_inode_remove_request(req);
Expand Down

0 comments on commit 221203c

Please sign in to comment.