diff --git a/daemon/nfs41.h b/daemon/nfs41.h index b09fdb0..2881e66 100644 --- a/daemon/nfs41.h +++ b/daemon/nfs41.h @@ -370,6 +370,10 @@ void nfs41_session_sequence( nfs41_session *session, bool_t cachethis); +int nfs41_session_bad_slot( + IN nfs41_session *session, + IN OUT struct __nfs41_sequence_args *args); + /* nfs41_server.c */ void nfs41_server_list_init(); diff --git a/daemon/nfs41_compound.c b/daemon/nfs41_compound.c index 5d7fcfd..f7e3d65 100644 --- a/daemon/nfs41_compound.c +++ b/daemon/nfs41_compound.c @@ -254,6 +254,12 @@ retry: goto do_retry; goto out; + case NFS4ERR_BADSLOT: + /* free the slot and retry with a new one */ + if (op1 != OP_SEQUENCE || nfs41_session_bad_slot(session, args)) + goto out; + goto retry; + case NFS4ERR_GRACE: case NFS4ERR_DELAY: #define RETRY_INDEFINITELY diff --git a/daemon/nfs41_session.c b/daemon/nfs41_session.c index ba93d3d..e67dacc 100644 --- a/daemon/nfs41_session.c +++ b/daemon/nfs41_session.c @@ -172,6 +172,33 @@ int nfs41_session_recall_slot( return NFS4_OK; } +int nfs41_session_bad_slot( + IN nfs41_session *session, + IN OUT nfs41_sequence_args *args) +{ + nfs41_slot_table *table = &session->table; + int status = NFS4ERR_BADSLOT; + + if (args->sa_slotid == 0) { + eprintf("server bug detected: NFS4ERR_BADSLOT for slotid=0\n"); + goto out; + } + + /* avoid using any slots >= bad_slotid */ + EnterCriticalSection(&table->lock); + if (table->max_slots > args->sa_slotid) + resize_slot_table(table, args->sa_slotid); + LeaveCriticalSection(&table->lock); + + /* get a new slot */ + nfs41_session_free_slot(session, args->sa_slotid); + nfs41_session_get_slot(session, &args->sa_slotid, + &args->sa_sequenceid, &args->sa_highest_slotid); + status = NFS4_OK; +out: + return status; +} + void nfs41_session_sequence( nfs41_sequence_args *args, nfs41_session *session,