Skip to content

Commit 2030ca5

Browse files
neilbrownJ. Bruce Fields
authored andcommitted
nfsd: degraded slot-count more gracefully as allocation nears exhaustion.
This original code in nfsd4_get_drc_mem() would hand out 30 slots (approximately NFSD_MAX_MEM_PER_SESSION bytes at slightly over 2K per slot) to each requesting client until it ran out of space, then it would possibly give one last client a reduced allocation, then fail the allocation. Since commit de766e5 ("nfsd: give out fewer session slots as limit approaches") the last 90 slots to be given to about 12 clients with quickly reducing slot counts (better than just 3 clients). This still seems unnecessarily hasty. A subsequent patch allows over-allocation so every client gets at least one slot, but that might be a bit restrictive. The requested number of nfsd threads is the best guide we have to the expected number of clients, so use that - if it is at least 8. 256 threads on a 256Meg machine - which is a lot for a tiny machine - would result in nfsd_drc_max_mem being 2Meg, so 8K (3 slots) would be available for the first client, and over 200 clients would get more than 1 slot. So I don't think this change will be too debilitating on poorly configured machines, though it does mean that a sensible configuration is a little more important. Signed-off-by: NeilBrown <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 7f49fd5 commit 2030ca5

File tree

1 file changed

+11
-4
lines changed

1 file changed

+11
-4
lines changed

fs/nfsd/nfs4state.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,11 +1568,12 @@ static inline u32 slot_bytes(struct nfsd4_channel_attrs *ca)
15681568
* re-negotiate active sessions and reduce their slot usage to make
15691569
* room for new connections. For now we just fail the create session.
15701570
*/
1571-
static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
1571+
static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca, struct nfsd_net *nn)
15721572
{
15731573
u32 slotsize = slot_bytes(ca);
15741574
u32 num = ca->maxreqs;
15751575
unsigned long avail, total_avail;
1576+
unsigned int scale_factor;
15761577

15771578
spin_lock(&nfsd_drc_lock);
15781579
if (nfsd_drc_max_mem > nfsd_drc_mem_used)
@@ -1586,12 +1587,18 @@ static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
15861587
total_avail = 0;
15871588
avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, total_avail);
15881589
/*
1589-
* Never use more than a third of the remaining memory,
1590+
* Never use more than a fraction of the remaining memory,
15901591
* unless it's the only way to give this client a slot.
1592+
* The chosen fraction is either 1/8 or 1/number of threads,
1593+
* whichever is smaller. This ensures there are adequate
1594+
* slots to support multiple clients per thread.
15911595
* Give the client one slot even if that would require
15921596
* over-allocation--it is better than failure.
15931597
*/
1594-
avail = clamp_t(unsigned long, avail, slotsize, total_avail/3);
1598+
scale_factor = max_t(unsigned int, 8, nn->nfsd_serv->sv_nrthreads);
1599+
1600+
avail = clamp_t(unsigned long, avail, slotsize,
1601+
total_avail/scale_factor);
15951602
num = min_t(int, num, avail / slotsize);
15961603
num = max_t(int, num, 1);
15971604
nfsd_drc_mem_used += num * slotsize;
@@ -3188,7 +3195,7 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs
31883195
* Note that we always allow at least one slot, because our
31893196
* accounting is soft and provides no guarantees either way.
31903197
*/
3191-
ca->maxreqs = nfsd4_get_drc_mem(ca);
3198+
ca->maxreqs = nfsd4_get_drc_mem(ca, nn);
31923199

31933200
return nfs_ok;
31943201
}

0 commit comments

Comments
 (0)