Skip to content

Commit 60aa656

Browse files
neilbrownchucklever
authored andcommitted
nfsd: allocate new session-based DRC slots on demand.
If a client ever uses the highest available slot for a given session, attempt to allocate more slots so there is room for the client to use them if wanted. GFP_NOWAIT is used so if there is not plenty of free memory, failure is expected - which is what we want. It also allows the allocation while holding a spinlock. Each time we increase the number of slots by 20% (rounded up). This allows fairly quick growth while avoiding excessive over-shoot. We would expect to stablise with around 10% more slots available than the client actually uses. Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: NeilBrown <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 601c8cb commit 60aa656

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

fs/nfsd/nfs4state.c

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4235,11 +4235,6 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
42354235
slot = xa_load(&session->se_slots, seq->slotid);
42364236
dprintk("%s: slotid %d\n", __func__, seq->slotid);
42374237

4238-
/* We do not negotiate the number of slots yet, so set the
4239-
* maxslots to the session maxreqs which is used to encode
4240-
* sr_highest_slotid and the sr_target_slot id to maxslots */
4241-
seq->maxslots = session->se_fchannel.maxreqs;
4242-
42434238
trace_nfsd_slot_seqid_sequence(clp, seq, slot);
42444239
status = check_slot_seqid(seq->seqid, slot->sl_seqid,
42454240
slot->sl_flags & NFSD4_SLOT_INUSE);
@@ -4289,6 +4284,38 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
42894284
cstate->session = session;
42904285
cstate->clp = clp;
42914286

4287+
/*
4288+
* If the client ever uses the highest available slot,
4289+
* gently try to allocate another 20%. This allows
4290+
* fairly quick growth without grossly over-shooting what
4291+
* the client might use.
4292+
*/
4293+
if (seq->slotid == session->se_fchannel.maxreqs - 1 &&
4294+
session->se_fchannel.maxreqs < NFSD_MAX_SLOTS_PER_SESSION) {
4295+
int s = session->se_fchannel.maxreqs;
4296+
int cnt = DIV_ROUND_UP(s, 5);
4297+
4298+
do {
4299+
/*
4300+
* GFP_NOWAIT both allows allocation under a
4301+
* spinlock, and only succeeds if there is
4302+
* plenty of memory.
4303+
*/
4304+
slot = kzalloc(slot_bytes(&session->se_fchannel),
4305+
GFP_NOWAIT);
4306+
if (slot &&
4307+
!xa_is_err(xa_store(&session->se_slots, s, slot,
4308+
GFP_NOWAIT))) {
4309+
s += 1;
4310+
session->se_fchannel.maxreqs = s;
4311+
} else {
4312+
kfree(slot);
4313+
slot = NULL;
4314+
}
4315+
} while (slot && --cnt > 0);
4316+
}
4317+
seq->maxslots = session->se_fchannel.maxreqs;
4318+
42924319
out:
42934320
switch (clp->cl_cb_state) {
42944321
case NFSD4_CB_DOWN:

0 commit comments

Comments
 (0)