diff --git a/daemon/callback_server.c b/daemon/callback_server.c index a6e758e..f08d486 100644 --- a/daemon/callback_server.c +++ b/daemon/callback_server.c @@ -85,10 +85,12 @@ static enum_t handle_cb_layoutrecall( /* OP_CB_RECALL_SLOT */ static enum_t handle_cb_recall_slot( + IN nfs41_rpc_clnt *rpc_clnt, IN struct cb_recall_slot_args *args, OUT struct cb_recall_slot_res *res) { - res->status = NFS4_OK; + res->status = nfs41_session_recall_slot(rpc_clnt->client->session, + args->target_highest_slotid); dprintf(CBSLVL, " OP_CB_RECALL_SLOT { %u } %s\n", args->target_highest_slotid, nfs_error_string(res->status)); @@ -425,8 +427,8 @@ static void handle_cb_compound(nfs41_rpc_clnt *rpc_clnt, cb_req *req, struct cb_ break; case OP_CB_RECALL_SLOT: dprintf(1, "OP_CB_RECALL_SLOT\n"); - res->status = handle_cb_recall_slot(&argop->args.recall_slot, - &resop->res.recall_slot); + res->status = handle_cb_recall_slot(rpc_clnt, + &argop->args.recall_slot, &resop->res.recall_slot); break; case OP_CB_SEQUENCE: dprintf(1, "OP_CB_SEQUENCE\n"); diff --git a/daemon/nfs41.h b/daemon/nfs41.h index 3e5052b..b09fdb0 100644 --- a/daemon/nfs41.h +++ b/daemon/nfs41.h @@ -347,7 +347,8 @@ void nfs41_session_free( void nfs41_session_bump_seq( IN nfs41_session *session, - IN uint32_t slotid); + IN uint32_t slotid, + IN uint32_t target_highest_slotid); void nfs41_session_free_slot( IN nfs41_session *session, @@ -359,6 +360,10 @@ void nfs41_session_get_slot( OUT uint32_t *seq, OUT uint32_t *highest); +int nfs41_session_recall_slot( + IN nfs41_session *session, + IN OUT uint32_t target_highest_slotid); + struct __nfs41_sequence_args; void nfs41_session_sequence( struct __nfs41_sequence_args *args, diff --git a/daemon/nfs41_compound.c b/daemon/nfs41_compound.c index 20b6a36..5d7fcfd 100644 --- a/daemon/nfs41_compound.c +++ b/daemon/nfs41_compound.c @@ -179,7 +179,8 @@ retry: if (seq->sr_resok4.sr_status_flags) print_sr_status_flags(1, seq->sr_resok4.sr_status_flags); - nfs41_session_bump_seq(session, args->sa_slotid); + nfs41_session_bump_seq(session, args->sa_slotid, + seq->sr_resok4.sr_target_highest_slotid); /* check sequence status flags for state revocation */ if (try_recovery && seq->sr_resok4.sr_status_flags) diff --git a/daemon/nfs41_session.c b/daemon/nfs41_session.c index 7b8126b..ba93d3d 100644 --- a/daemon/nfs41_session.c +++ b/daemon/nfs41_session.c @@ -54,9 +54,27 @@ static void init_slot_table(nfs41_slot_table *table) LeaveCriticalSection(&table->lock); } +static void resize_slot_table( + IN nfs41_slot_table *table, + IN uint32_t target_highest_slotid) +{ + if (target_highest_slotid >= NFS41_MAX_NUM_SLOTS) + target_highest_slotid = NFS41_MAX_NUM_SLOTS - 1; + + if (table->max_slots != target_highest_slotid + 1) { + dprintf(2, "updated max_slots %u to %u\n", + table->max_slots, target_highest_slotid + 1); + table->max_slots = target_highest_slotid + 1; + + if (slot_table_avail(table)) + WakeAllConditionVariable(&table->cond); + } +} + void nfs41_session_bump_seq( IN nfs41_session *session, - IN uint32_t slotid) + IN uint32_t slotid, + IN uint32_t target_highest_slotid) { nfs41_slot_table *table = &session->table; @@ -66,6 +84,8 @@ void nfs41_session_bump_seq( if (slotid < NFS41_MAX_NUM_SLOTS) table->seq_nums[slotid]++; + resize_slot_table(table, target_highest_slotid); + LeaveCriticalSection(&table->lock); ReleaseSRWLockShared(&session->client->session_lock); } @@ -137,6 +157,21 @@ void nfs41_session_get_slot( session, *slot, *seqid, *highest); } +int nfs41_session_recall_slot( + IN nfs41_session *session, + IN OUT uint32_t target_highest_slotid) +{ + nfs41_slot_table *table = &session->table; + + AcquireSRWLockShared(&session->client->session_lock); + EnterCriticalSection(&table->lock); + resize_slot_table(table, target_highest_slotid); + LeaveCriticalSection(&table->lock); + ReleaseSRWLockShared(&session->client->session_lock); + + return NFS4_OK; +} + void nfs41_session_sequence( nfs41_sequence_args *args, nfs41_session *session,