mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 13:22:23 +00:00
NFS/pnfs: Fix pnfs_generic_prepare_to_resend_writes()
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: f54bcf2ece
("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>
This commit is contained in:
parent
2197e9b06c
commit
221203ce64
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user