recovery: open and lock recovery in separate functions

moved recovery of lock stateids from recover_open() to new function recover_locks()
split nfs41_recover_stateid() into recover_stateid_open() and recover_stateid_lock()

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2011-07-18 13:43:49 -04:00 committed by unknown
parent 6878e71ec0
commit 115ed7c1d3

View file

@ -69,9 +69,7 @@ static int recover_open(
{ {
open_claim4 claim; open_claim4 claim;
open_delegation4 delegation; open_delegation4 delegation;
stateid_arg stateid; stateid4 stateid;
struct list_entry *entry;
nfs41_lock_state *lock;
int status; int status;
/* reclaim the open stateid */ /* reclaim the open stateid */
@ -80,27 +78,42 @@ static int recover_open(
status = nfs41_open(session, &open->parent, &open->file, status = nfs41_open(session, &open->parent, &open->file,
&open->owner, &claim, open->share_access, open->share_deny, &open->owner, &claim, open->share_access, open->share_deny,
OPEN4_NOCREATE, 0, 0, FALSE, &stateid.stateid, &delegation, NULL); OPEN4_NOCREATE, 0, 0, FALSE, &stateid, &delegation, NULL);
if (status == NFS4ERR_NO_GRACE) { if (status == NFS4ERR_NO_GRACE) {
dprintf(1, "not in grace period, retrying a normal open\n"); /* attempt out-of-grace recovery with CLAIM_NULL */
claim.claim = CLAIM_NULL; claim.claim = CLAIM_NULL;
claim.u.null.filename = &open->file.name; claim.u.null.filename = &open->file.name;
status = nfs41_open(session, &open->parent, &open->file, status = nfs41_open(session, &open->parent, &open->file,
&open->owner, &claim, open->share_access, open->share_deny, &open->owner, &claim, open->share_access, open->share_deny,
OPEN4_NOCREATE, 0, 0, FALSE, &stateid.stateid, &delegation, NULL); OPEN4_NOCREATE, 0, 0, FALSE, &stateid, &delegation, NULL);
} }
if (status) if (status)
goto out; goto out;
/* update the open stateid on success */
AcquireSRWLockExclusive(&open->lock);
memcpy(&open->stateid, &stateid, sizeof(stateid4));
open->layout = NULL;
ReleaseSRWLockExclusive(&open->lock);
out:
return status;
}
static int recover_locks(
IN nfs41_session *session,
IN nfs41_open_state *open)
{
stateid_arg stateid;
struct list_entry *entry;
nfs41_lock_state *lock;
int status = NFS4_OK;
AcquireSRWLockExclusive(&open->lock); AcquireSRWLockExclusive(&open->lock);
/* update the open stateid on success */ /* initialize the open stateid for the first lock request */
memcpy(&open->stateid, &stateid.stateid, sizeof(stateid4)); memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4));
open->layout = NULL;
stateid.type = STATEID_OPEN; stateid.type = STATEID_OPEN;
stateid.open = open; stateid.open = open;
@ -110,7 +123,7 @@ static int recover_open(
status = nfs41_lock(session, &open->file, &open->owner, status = nfs41_lock(session, &open->file, &open->owner,
lock->type, lock->offset, lock->length, TRUE, FALSE, &stateid); lock->type, lock->offset, lock->length, TRUE, FALSE, &stateid);
if (status == NFS4ERR_NO_GRACE) { if (status == NFS4ERR_NO_GRACE) {
dprintf(1, "not in grace period, retrying a normal lock\n"); /* attempt out-of-grace recovery with a normal LOCK */
status = nfs41_lock(session, &open->file, &open->owner, status = nfs41_lock(session, &open->file, &open->owner,
lock->type, lock->offset, lock->length, FALSE, FALSE, &stateid); lock->type, lock->offset, lock->length, FALSE, FALSE, &stateid);
} }
@ -127,7 +140,6 @@ static int recover_open(
} }
ReleaseSRWLockExclusive(&open->lock); ReleaseSRWLockExclusive(&open->lock);
out:
return status; return status;
} }
@ -147,6 +159,8 @@ int nfs41_recover_client_state(
list_for_each(entry, &state->opens) { list_for_each(entry, &state->opens) {
open = list_container(entry, nfs41_open_state, client_entry); open = list_container(entry, nfs41_open_state, client_entry);
status = recover_open(session, open); status = recover_open(session, open);
if (status == NFS4_OK)
status = recover_locks(session, open);
if (status == NFS4ERR_BADSESSION) if (status == NFS4ERR_BADSESSION)
break; break;
} }
@ -165,13 +179,60 @@ int nfs41_recover_client_state(
return status; return status;
} }
static bool_t recover_stateid_open(
IN nfs_argop4 *argop,
IN stateid_arg *stateid)
{
bool_t retry = FALSE;
if (stateid->open) {
stateid4 *source = &stateid->open->stateid;
/* if the source stateid is different, update and retry */
AcquireSRWLockShared(&stateid->open->lock);
if (memcmp(&stateid->stateid, source, sizeof(stateid4))) {
memcpy(&stateid->stateid, source, sizeof(stateid4));
retry = TRUE;
}
ReleaseSRWLockShared(&stateid->open->lock);
}
return retry;
}
static bool_t recover_stateid_lock(
IN nfs_argop4 *argop,
IN stateid_arg *stateid)
{
bool_t retry = FALSE;
if (stateid->open) {
stateid4 *source = &stateid->open->locks.stateid;
/* if the source stateid is different, update and retry */
AcquireSRWLockShared(&stateid->open->lock);
if (memcmp(&stateid->stateid, source, sizeof(stateid4))) {
if (argop->op == OP_LOCK && source->seqid == 0) {
/* resend LOCK with an open stateid */
nfs41_lock_args *lock = (nfs41_lock_args*)argop->arg;
lock->locker.new_lock_owner = 1;
lock->locker.u.open_owner.open_stateid = stateid;
lock->locker.u.open_owner.lock_owner = &stateid->open->owner;
source = &stateid->open->stateid;
}
memcpy(&stateid->stateid, source, sizeof(stateid4));
retry = TRUE;
}
ReleaseSRWLockShared(&stateid->open->lock);
}
return retry;
}
bool_t nfs41_recover_stateid( bool_t nfs41_recover_stateid(
IN nfs41_session *session, IN nfs41_session *session,
IN nfs_argop4 *argop) IN nfs_argop4 *argop)
{ {
stateid_arg *stateid = NULL; stateid_arg *stateid = NULL;
stateid4 *source = NULL;
bool_t retry = FALSE;
if (argop->op == OP_CLOSE) { if (argop->op == OP_CLOSE) {
nfs41_op_close_args *close = (nfs41_op_close_args*)argop->arg; nfs41_op_close_args *close = (nfs41_op_close_args*)argop->arg;
@ -198,11 +259,9 @@ bool_t nfs41_recover_stateid(
pnfs_layoutget_args *lget = (pnfs_layoutget_args*)argop->arg; pnfs_layoutget_args *lget = (pnfs_layoutget_args*)argop->arg;
stateid = lget->stateid; stateid = lget->stateid;
} }
if (stateid == NULL)
return FALSE;
if (stateid) {
switch (stateid->type) {
case STATEID_OPEN:
case STATEID_LOCK:
/* if there's recovery in progress, wait for it to finish */ /* if there's recovery in progress, wait for it to finish */
EnterCriticalSection(&session->client->recovery.lock); EnterCriticalSection(&session->client->recovery.lock);
while (session->client->recovery.in_recovery) while (session->client->recovery.in_recovery)
@ -210,34 +269,17 @@ bool_t nfs41_recover_stateid(
&session->client->recovery.lock, INFINITE); &session->client->recovery.lock, INFINITE);
LeaveCriticalSection(&session->client->recovery.lock); LeaveCriticalSection(&session->client->recovery.lock);
if (stateid->type == STATEID_OPEN) switch (stateid->type) {
source = &stateid->open->stateid; case STATEID_OPEN:
else return recover_stateid_open(argop, stateid);
source = &stateid->open->locks.stateid;
/* if the source stateid is different, update and retry */ case STATEID_LOCK:
AcquireSRWLockShared(&stateid->open->lock); return recover_stateid_lock(argop, stateid);
if (memcmp(&stateid->stateid, source, sizeof(stateid4))) {
/* if it was a lock stateid that was cleared, resend it with an open stateid */
if (argop->op == OP_LOCK && stateid->type == STATEID_LOCK && source->seqid == 0) {
nfs41_lock_args *lock = (nfs41_lock_args*)argop->arg;
lock->locker.new_lock_owner = 1;
lock->locker.u.open_owner.open_stateid = stateid;
lock->locker.u.open_owner.lock_owner = &stateid->open->owner;
source = &stateid->open->stateid;
}
memcpy(&stateid->stateid, source, sizeof(stateid4));
retry = TRUE;
}
ReleaseSRWLockShared(&stateid->open->lock);
break;
default: default:
eprintf("%s can't recover stateid type %u\n", eprintf("%s can't recover stateid type %u\n",
nfs_opnum_to_string(argop->op), stateid->type); nfs_opnum_to_string(argop->op), stateid->type);
break; break;
} }
} return FALSE;
return retry;
} }