/** * nfs4_slot_tbl_drain_complete - wake waiters when drain is complete * @tbl: controlling slot table *
*/ void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl)
{ if (nfs4_slot_tbl_draining(tbl))
complete(&tbl->complete);
}
/* * nfs4_free_slot - free a slot and efficiently update slot table. * * freeing a slot is trivially done by clearing its respective bit * in the bitmap. * If the freed slotid equals highest_used_slotid we want to update it * so that the server would be able to size down the slot table if needed, * otherwise we know that the highest_used_slotid is still in use. * When updating highest_used_slotid there may be "holes" in the bitmap * so we need to scan down from highest_used_slotid to 0 looking for the now * highest slotid in use. * If none found, highest_used_slotid is set to NFS4_NO_SLOT. * * Must be called while holding tbl->slot_tbl_lock
*/ void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
{
u32 slotid = slot->slot_nr;
/* clear used bit in bitmap */
__clear_bit(slotid, tbl->used_slots);
/* update highest_used_slotid when it is freed */ if (slotid == tbl->highest_used_slotid) {
u32 new_max = find_last_bit(tbl->used_slots, slotid); if (new_max < slotid)
tbl->highest_used_slotid = new_max; else {
tbl->highest_used_slotid = NFS4_NO_SLOT;
nfs4_slot_tbl_drain_complete(tbl);
}
}
dprintk("%s: slotid %u highest_used_slotid %u\n", __func__,
slotid, tbl->highest_used_slotid);
}
/* * nfs4_try_to_lock_slot - Given a slot try to allocate it * * Note: must be called with the slot_tbl_lock held.
*/ bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
{ if (nfs4_test_locked_slot(tbl, slot->slot_nr)) returnfalse;
nfs4_lock_slot(tbl, slot); returntrue;
}
/* * nfs4_lookup_slot - Find a slot but don't allocate it * * Note: must be called with the slot_tbl_lock held.
*/ struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid)
{ if (slotid <= tbl->max_slotid) return nfs4_find_or_create_slot(tbl, slotid, 0, GFP_NOWAIT); return ERR_PTR(-E2BIG);
}
slot = nfs4_lookup_slot(tbl, slotid);
ret = PTR_ERR_OR_ZERO(slot); if (!ret)
*seq_nr = slot->seq_nr;
return ret;
}
/* * nfs4_slot_seqid_in_use - test if a slot sequence id is still in use * * Given a slot table, slot id and sequence number, determine if the * RPC call in question is still in flight. This function is mainly * intended for use by the callback channel.
*/ staticbool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl,
u32 slotid, u32 seq_nr)
{
u32 cur_seq = 0; bool ret = false;
/* * nfs4_slot_wait_on_seqid - wait until a slot sequence id is complete * * Given a slot table, slot id and sequence number, wait until the * corresponding RPC call completes. This function is mainly * intended for use by the callback channel.
*/ int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
u32 slotid, u32 seq_nr, unsignedlong timeout)
{ if (wait_event_timeout(tbl->slot_waitq,
!nfs4_slot_seqid_in_use(tbl, slotid, seq_nr),
timeout) == 0) return -ETIMEDOUT; return 0;
}
/* * nfs4_alloc_slot - efficiently look for a free slot * * nfs4_alloc_slot looks for an unset bit in the used_slots bitmap. * If found, we mark the slot as used, update the highest_used_slotid, * and respectively set up the sequence operation args. * * Note: must be called with under the slot_tbl_lock.
*/ struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl)
{ struct nfs4_slot *ret = ERR_PTR(-EBUSY);
u32 slotid;
/** * nfs4_shutdown_slot_table - release resources attached to a slot table * @tbl: slot table to shut down *
*/ void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl)
{
nfs4_release_slot_table(tbl);
rpc_destroy_wait_queue(&tbl->slot_tbl_waitq);
}
/** * nfs4_setup_slot_table - prepare a stand-alone slot table for use * @tbl: slot table to set up * @max_reqs: maximum number of requests allowed * @queue: name to give RPC wait queue * * Returns zero on success, or a negative errno.
*/ int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, unsignedint max_reqs, constchar *queue)
{
nfs4_init_slot_table(tbl, queue); return nfs4_realloc_slot_table(tbl, max_reqs, 0);
}
/* Try to eliminate outliers by checking for sharp changes in the * derivatives and second derivatives
*/ staticbool nfs41_is_outlier_target_slotid(struct nfs4_slot_table *tbl,
u32 new_target)
{
s32 d_target, d2_target; bool ret = true;
d_target = nfs41_derivative_target_slotid(new_target,
tbl->target_highest_slotid);
d2_target = nfs41_derivative_target_slotid(d_target,
tbl->d_target_highest_slotid); /* Is first derivative same sign? */ if (nfs41_same_sign_or_zero_s32(d_target, tbl->d_target_highest_slotid))
ret = false; /* Is second derivative same sign? */ if (nfs41_same_sign_or_zero_s32(d2_target, tbl->d2_target_highest_slotid))
ret = false;
tbl->d_target_highest_slotid = d_target;
tbl->d2_target_highest_slotid = d2_target; return ret;
}
/* * Initialize or reset the forechannel and backchannel tables
*/ int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
{ struct nfs4_slot_table *tbl; int status;
dprintk("--> %s\n", __func__); /* Fore channel */
tbl = &ses->fc_slot_table;
tbl->session = ses;
status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); if (status || !(ses->flags & SESSION4_BACK_CHAN)) /* -ENOMEM */ return status; /* Back channel */
tbl = &ses->bc_slot_table;
tbl->session = ses;
status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); if (status && tbl->slots == NULL) /* Fore and back channel share a connection so get
* both slot tables or neither */
nfs4_release_session_slot_tables(ses); return status;
}
/* * With sessions, the client is not marked ready until after a * successful EXCHANGE_ID and CREATE_SESSION. * * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate * other versions of NFS can be tried.
*/ staticint nfs41_check_session_ready(struct nfs_client *clp)
{ int ret;
if (clp->cl_cons_state == NFS_CS_SESSION_INITING) {
ret = nfs4_client_recover_expired_lease(clp); if (ret) return ret;
} if (clp->cl_cons_state < NFS_CS_READY) return -EPROTONOSUPPORT;
smp_rmb(); return 0;
}
int nfs4_init_session(struct nfs_client *clp)
{ if (!nfs4_has_session(clp)) return 0;
int nfs4_init_ds_session(struct nfs_client *clp, unsignedlong lease_time)
{ struct nfs4_session *session = clp->cl_session; int ret;
spin_lock(&clp->cl_lock); if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { /* * Do not set NFS_CS_CHECK_LEASE_TIME instead set the * DS lease to be equal to the MDS lease.
*/
clp->cl_lease_time = lease_time;
clp->cl_last_renewal = jiffies;
}
spin_unlock(&clp->cl_lock);
ret = nfs41_check_session_ready(clp); if (ret) return ret; /* Test for the DS role */ if (!is_ds_client(clp)) return -ENODEV; return 0;
}
EXPORT_SYMBOL_GPL(nfs4_init_ds_session);
#endif/* defined(CONFIG_NFS_V4_1) */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-04-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.