nfsd: New helper nfsd4_cb_sequence_done() for processing more cb errors
According to Christoph's advice, this patch introduce a new helper nfsd4_cb_sequence_done() for processing more callback errors, following the example of the client's nfs41_sequence_done(). Signed-off-by: Kinglong Mee <kinglongmee@gmail.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
9056fff3d5
commit
7ba6cad6c8
@ -435,12 +435,12 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr,
|
|||||||
*/
|
*/
|
||||||
status = 0;
|
status = 0;
|
||||||
out:
|
out:
|
||||||
if (status)
|
cb->cb_seq_status = status;
|
||||||
nfsd4_mark_cb_fault(cb->cb_clp, status);
|
|
||||||
return status;
|
return status;
|
||||||
out_overflow:
|
out_overflow:
|
||||||
print_overflow_msg(__func__, xdr);
|
print_overflow_msg(__func__, xdr);
|
||||||
return -EIO;
|
status = -EIO;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_cb_sequence4res(struct xdr_stream *xdr,
|
static int decode_cb_sequence4res(struct xdr_stream *xdr,
|
||||||
@ -451,11 +451,10 @@ static int decode_cb_sequence4res(struct xdr_stream *xdr,
|
|||||||
if (cb->cb_minorversion == 0)
|
if (cb->cb_minorversion == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &cb->cb_status);
|
status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &cb->cb_seq_status);
|
||||||
if (unlikely(status || cb->cb_status))
|
if (unlikely(status || cb->cb_seq_status))
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
cb->cb_update_seq_nr = true;
|
|
||||||
return decode_cb_sequence4resok(xdr, cb);
|
return decode_cb_sequence4resok(xdr, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +526,7 @@ static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp,
|
|||||||
|
|
||||||
if (cb != NULL) {
|
if (cb != NULL) {
|
||||||
status = decode_cb_sequence4res(xdr, cb);
|
status = decode_cb_sequence4res(xdr, cb);
|
||||||
if (unlikely(status || cb->cb_status))
|
if (unlikely(status || cb->cb_seq_status))
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,7 +616,7 @@ static int nfs4_xdr_dec_cb_layout(struct rpc_rqst *rqstp,
|
|||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
status = decode_cb_sequence4res(xdr, cb);
|
status = decode_cb_sequence4res(xdr, cb);
|
||||||
if (unlikely(status || cb->cb_status))
|
if (unlikely(status || cb->cb_seq_status))
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
return decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &cb->cb_status);
|
return decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &cb->cb_status);
|
||||||
@ -876,7 +875,11 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
|
|||||||
u32 minorversion = clp->cl_minorversion;
|
u32 minorversion = clp->cl_minorversion;
|
||||||
|
|
||||||
cb->cb_minorversion = minorversion;
|
cb->cb_minorversion = minorversion;
|
||||||
cb->cb_update_seq_nr = false;
|
/*
|
||||||
|
* cb_seq_status is only set in decode_cb_sequence4res,
|
||||||
|
* and so will remain 1 if an rpc level failure occurs.
|
||||||
|
*/
|
||||||
|
cb->cb_seq_status = 1;
|
||||||
cb->cb_status = 0;
|
cb->cb_status = 0;
|
||||||
if (minorversion) {
|
if (minorversion) {
|
||||||
if (!nfsd41_cb_get_slot(clp, task))
|
if (!nfsd41_cb_get_slot(clp, task))
|
||||||
@ -885,6 +888,84 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
|
|||||||
rpc_call_start(task);
|
rpc_call_start(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback *cb)
|
||||||
|
{
|
||||||
|
struct nfs4_client *clp = cb->cb_clp;
|
||||||
|
struct nfsd4_session *session = clp->cl_cb_session;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (!clp->cl_minorversion) {
|
||||||
|
/*
|
||||||
|
* If the backchannel connection was shut down while this
|
||||||
|
* task was queued, we need to resubmit it after setting up
|
||||||
|
* a new backchannel connection.
|
||||||
|
*
|
||||||
|
* Note that if we lost our callback connection permanently
|
||||||
|
* the submission code will error out, so we don't need to
|
||||||
|
* handle that case here.
|
||||||
|
*/
|
||||||
|
if (task->tk_flags & RPC_TASK_KILLED)
|
||||||
|
goto need_restart;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cb->cb_seq_status) {
|
||||||
|
case 0:
|
||||||
|
/*
|
||||||
|
* No need for lock, access serialized in nfsd4_cb_prepare
|
||||||
|
*
|
||||||
|
* RFC5661 20.9.3
|
||||||
|
* If CB_SEQUENCE returns an error, then the state of the slot
|
||||||
|
* (sequence ID, cached reply) MUST NOT change.
|
||||||
|
*/
|
||||||
|
++session->se_cb_seq_nr;
|
||||||
|
break;
|
||||||
|
case -ESERVERFAULT:
|
||||||
|
++session->se_cb_seq_nr;
|
||||||
|
case 1:
|
||||||
|
case -NFS4ERR_BADSESSION:
|
||||||
|
nfsd4_mark_cb_fault(cb->cb_clp, cb->cb_seq_status);
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
case -NFS4ERR_DELAY:
|
||||||
|
if (!rpc_restart_call(task))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rpc_delay(task, 2 * HZ);
|
||||||
|
return false;
|
||||||
|
case -NFS4ERR_BADSLOT:
|
||||||
|
goto retry_nowait;
|
||||||
|
case -NFS4ERR_SEQ_MISORDERED:
|
||||||
|
if (session->se_cb_seq_nr != 1) {
|
||||||
|
session->se_cb_seq_nr = 1;
|
||||||
|
goto retry_nowait;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintk("%s: unprocessed error %d\n", __func__,
|
||||||
|
cb->cb_seq_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_bit(0, &clp->cl_cb_slot_busy);
|
||||||
|
rpc_wake_up_next(&clp->cl_cb_waitq);
|
||||||
|
dprintk("%s: freed slot, new seqid=%d\n", __func__,
|
||||||
|
clp->cl_cb_session->se_cb_seq_nr);
|
||||||
|
|
||||||
|
if (task->tk_flags & RPC_TASK_KILLED)
|
||||||
|
goto need_restart;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
retry_nowait:
|
||||||
|
if (rpc_restart_call_prepare(task))
|
||||||
|
ret = false;
|
||||||
|
goto out;
|
||||||
|
need_restart:
|
||||||
|
task->tk_status = 0;
|
||||||
|
cb->cb_need_restart = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
|
static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
|
||||||
{
|
{
|
||||||
struct nfsd4_callback *cb = calldata;
|
struct nfsd4_callback *cb = calldata;
|
||||||
@ -893,37 +974,8 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
|
|||||||
dprintk("%s: minorversion=%d\n", __func__,
|
dprintk("%s: minorversion=%d\n", __func__,
|
||||||
clp->cl_minorversion);
|
clp->cl_minorversion);
|
||||||
|
|
||||||
if (clp->cl_minorversion) {
|
if (!nfsd4_cb_sequence_done(task, cb))
|
||||||
/*
|
|
||||||
* No need for lock, access serialized in nfsd4_cb_prepare
|
|
||||||
*
|
|
||||||
* RFC5661 20.9.3
|
|
||||||
* If CB_SEQUENCE returns an error, then the state of the slot
|
|
||||||
* (sequence ID, cached reply) MUST NOT change.
|
|
||||||
*/
|
|
||||||
if (cb->cb_update_seq_nr)
|
|
||||||
++clp->cl_cb_session->se_cb_seq_nr;
|
|
||||||
|
|
||||||
clear_bit(0, &clp->cl_cb_slot_busy);
|
|
||||||
rpc_wake_up_next(&clp->cl_cb_waitq);
|
|
||||||
dprintk("%s: freed slot, new seqid=%d\n", __func__,
|
|
||||||
clp->cl_cb_session->se_cb_seq_nr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the backchannel connection was shut down while this
|
|
||||||
* task was queued, we need to resubmit it after setting up
|
|
||||||
* a new backchannel connection.
|
|
||||||
*
|
|
||||||
* Note that if we lost our callback connection permanently
|
|
||||||
* the submission code will error out, so we don't need to
|
|
||||||
* handle that case here.
|
|
||||||
*/
|
|
||||||
if (task->tk_flags & RPC_TASK_KILLED) {
|
|
||||||
task->tk_status = 0;
|
|
||||||
cb->cb_need_restart = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (cb->cb_status) {
|
if (cb->cb_status) {
|
||||||
WARN_ON_ONCE(task->tk_status);
|
WARN_ON_ONCE(task->tk_status);
|
||||||
@ -1099,8 +1151,8 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
|
|||||||
cb->cb_msg.rpc_resp = cb;
|
cb->cb_msg.rpc_resp = cb;
|
||||||
cb->cb_ops = ops;
|
cb->cb_ops = ops;
|
||||||
INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
|
INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
|
||||||
|
cb->cb_seq_status = 1;
|
||||||
cb->cb_status = 0;
|
cb->cb_status = 0;
|
||||||
cb->cb_update_seq_nr = false;
|
|
||||||
cb->cb_need_restart = false;
|
cb->cb_need_restart = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +67,8 @@ struct nfsd4_callback {
|
|||||||
struct rpc_message cb_msg;
|
struct rpc_message cb_msg;
|
||||||
struct nfsd4_callback_ops *cb_ops;
|
struct nfsd4_callback_ops *cb_ops;
|
||||||
struct work_struct cb_work;
|
struct work_struct cb_work;
|
||||||
|
int cb_seq_status;
|
||||||
int cb_status;
|
int cb_status;
|
||||||
bool cb_update_seq_nr;
|
|
||||||
bool cb_need_restart;
|
bool cb_need_restart;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user