recovery: support for CLAIM_DELEGATE_PREV, DELEGPURGE
10.2.1. Delegation Recovery (re: client restart/lease expiration) A server MAY support claim types of CLAIM_DELEGATE_PREV and CLAIM_DELEG_PREV_FH, and if it does, it MUST NOT remove delegations upon a CREATE_SESSION that confirm a client ID created by EXCHANGE_ID. Instead, the server MUST, for a period of time no less than that of the value of the lease_time attribute, maintain the client's delegations to allow time for the client to send CLAIM_DELEGATE_PREV and/or CLAIM_DELEG_PREV_FH requests. The server that supports CLAIM_DELEGATE_PREV and/or CLAIM_DELEG_PREV_FH MUST support the DELEGPURGE operation. if there's a delegation to reclaim, recover_open_no_grace() now tries CLAIM_DELEGATE_PREV (supported by emc server, but not linux) before falling back to CLAIM_NULL nfs41_client_delegation_recovery() sends DELEGPURGE to indicate that we're finished reclaiming delegations Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
8e310c5711
commit
b9b3b00e76
5 changed files with 96 additions and 4 deletions
|
|
@ -669,7 +669,15 @@ int nfs41_client_delegation_recovery(
|
|||
}
|
||||
|
||||
if (status == NFS4ERR_BADSESSION)
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* use DELEGPURGE to indicate that we're done reclaiming delegations */
|
||||
status = nfs41_delegpurge(client->session);
|
||||
|
||||
/* support for DELEGPURGE is optional; ignore any errors but BADSESSION */
|
||||
if (status != NFS4ERR_BADSESSION)
|
||||
status = NFS4_OK;
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1527,6 +1527,35 @@ out:
|
|||
return status;
|
||||
}
|
||||
|
||||
int nfs41_delegpurge(
|
||||
IN nfs41_session *session)
|
||||
{
|
||||
int status;
|
||||
nfs41_compound compound;
|
||||
nfs_argop4 argops[2];
|
||||
nfs_resop4 resops[2];
|
||||
nfs41_sequence_args sequence_args;
|
||||
nfs41_sequence_res sequence_res;
|
||||
nfs41_delegpurge_res dp_res;
|
||||
|
||||
compound_init(&compound, argops, resops, "delegpurge");
|
||||
|
||||
compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
|
||||
status = nfs41_session_sequence(&sequence_args, session, 0);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
compound_add_op(&compound, OP_DELEGPURGE, NULL, &dp_res);
|
||||
|
||||
status = compound_encode_send_decode(session, &compound, TRUE);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
compound_error(status = compound.res.status);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
int nfs41_delegreturn(
|
||||
IN nfs41_session *session,
|
||||
IN nfs41_path_fh *file,
|
||||
|
|
|
|||
|
|
@ -373,6 +373,12 @@ typedef struct __nfs41_create_res {
|
|||
} nfs41_create_res;
|
||||
|
||||
|
||||
/* OP_DELEGPURGE */
|
||||
typedef struct __nfs41_delegpurge_res {
|
||||
uint32_t status;
|
||||
} nfs41_delegpurge_res;
|
||||
|
||||
|
||||
/* OP_DELEGRETURN */
|
||||
typedef struct __nfs41_delegreturn_args {
|
||||
stateid_arg *stateid;
|
||||
|
|
@ -1152,6 +1158,9 @@ int nfs41_access(
|
|||
OUT uint32_t *supported OPTIONAL,
|
||||
OUT uint32_t *access OPTIONAL);
|
||||
|
||||
int nfs41_delegpurge(
|
||||
IN nfs41_session *session);
|
||||
|
||||
int nfs41_delegreturn(
|
||||
IN nfs41_session *session,
|
||||
IN nfs41_path_fh *file,
|
||||
|
|
|
|||
|
|
@ -1632,6 +1632,36 @@ static bool_t decode_op_locku(
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* OP_DELEGPURGE
|
||||
*/
|
||||
static bool_t encode_op_delegpurge(
|
||||
XDR *xdr,
|
||||
nfs_argop4 *argop)
|
||||
{
|
||||
uint64_t zero = 0;
|
||||
|
||||
if (unexpected_op(argop->op, OP_DELEGPURGE))
|
||||
return FALSE;
|
||||
|
||||
/* The client SHOULD set the client field to zero,
|
||||
* and the server MUST ignore the clientid field. */
|
||||
return xdr_u_int64_t(xdr, &zero);
|
||||
}
|
||||
|
||||
static bool_t decode_op_delegpurge(
|
||||
XDR *xdr,
|
||||
nfs_resop4 *resop)
|
||||
{
|
||||
nfs41_delegpurge_res *res = (nfs41_delegpurge_res*)resop->res;
|
||||
|
||||
if (unexpected_op(resop->op, OP_DELEGPURGE))
|
||||
return FALSE;
|
||||
|
||||
return xdr_u_int32_t(xdr, &res->status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* OP_DELEGRETURN
|
||||
*/
|
||||
|
|
@ -3347,7 +3377,7 @@ static const op_table_entry g_op_table[] = {
|
|||
{ encode_op_close, decode_op_close }, /* OP_CLOSE = 4 */
|
||||
{ encode_op_commit, decode_op_commit }, /* OP_COMMIT = 5 */
|
||||
{ encode_op_create, decode_op_create }, /* OP_CREATE = 6 */
|
||||
{ NULL, NULL }, /* OP_DELEGPURGE = 7 */
|
||||
{ encode_op_delegpurge, decode_op_delegpurge }, /* OP_DELEGPURGE = 7 */
|
||||
{ encode_op_delegreturn, decode_op_delegreturn }, /* OP_DELEGRETURN = 8 */
|
||||
{ encode_op_getattr, decode_op_getattr }, /* OP_GETATTR = 9 */
|
||||
{ encode_op_getfh, decode_op_getfh }, /* OP_GETFH = 10 */
|
||||
|
|
|
|||
|
|
@ -101,8 +101,22 @@ static int recover_open_no_grace(
|
|||
OUT open_delegation4 *delegation)
|
||||
{
|
||||
open_claim4 claim;
|
||||
int status;
|
||||
|
||||
/* TODO: try CLAIM_DELEGATE_PREV / CLAIM_DELEG_PREV_FH first */
|
||||
if (delegate_type != OPEN_DELEGATE_NONE) {
|
||||
/* attempt out-of-grace recovery with CLAIM_DELEGATE_PREV */
|
||||
claim.claim = CLAIM_DELEGATE_PREV;
|
||||
claim.u.deleg_prev.filename = &file->name;
|
||||
|
||||
status = nfs41_open(session, parent, file, owner,
|
||||
&claim, access, deny, OPEN4_NOCREATE, 0, 0, FALSE,
|
||||
stateid, delegation, NULL);
|
||||
if (status == NFS4_OK || status == NFS4ERR_BADSESSION)
|
||||
goto out;
|
||||
|
||||
/* server support for CLAIM_DELEGATE_PREV is optional;
|
||||
* fall back to CLAIM_NULL on errors */
|
||||
}
|
||||
|
||||
/* attempt out-of-grace recovery with CLAIM_NULL */
|
||||
claim.claim = CLAIM_NULL;
|
||||
|
|
@ -114,9 +128,11 @@ static int recover_open_no_grace(
|
|||
else if (delegate_type == OPEN_DELEGATE_WRITE)
|
||||
access |= OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG;
|
||||
|
||||
return nfs41_open(session, parent, file, owner,
|
||||
status = nfs41_open(session, parent, file, owner,
|
||||
&claim, access, deny, OPEN4_NOCREATE, 0, 0, FALSE,
|
||||
stateid, delegation, NULL);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int recover_open(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue