From 30e8df149e331f8ca1d9d104c079ad678cd63f77 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Thu, 10 May 2012 12:26:32 -0400 Subject: [PATCH] session: handle NFS4ERR_BADSLOT errors NFS4ERR_BADSLOT indicates that the supplied slotid is outside the server's expected range. update table.max_slots to this value to prevent it from being used again, then acquire a new slot and retry the rpc Signed-off-by: Casey Bodley --- daemon/nfs41.h | 4 ++++ daemon/nfs41_compound.c | 6 ++++++ daemon/nfs41_session.c | 27 +++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) 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,