Skip to content

Commit 7f49fd5

Browse files
neilbrownJ. Bruce Fields
authored andcommitted
nfsd: handle drc over-allocation gracefully.
Currently, if there are more clients than allowed for by the space allocation in set_max_drc(), we fail a SESSION_CREATE request with NFS4ERR_DELAY. This means that the client retries indefinitely, which isn't a user-friendly response. The RFC requires NFS4ERR_NOSPC, but that would at best result in a clean failure on the client, which is not much more friendly. The current space allocation is a best-guess and doesn't provide any guarantees, we could still run out of space when trying to allocate drc space. So fail more gracefully - always give out at least one slot. If all clients used all the space in all slots, we might start getting memory pressure, but that is possible anyway. So ensure 'num' is always at least 1, and remove the test for it being zero. Signed-off-by: NeilBrown <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 6ee95d1 commit 7f49fd5

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

fs/nfsd/nfs4state.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,14 +1575,25 @@ static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
15751575
unsigned long avail, total_avail;
15761576

15771577
spin_lock(&nfsd_drc_lock);
1578-
total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used;
1578+
if (nfsd_drc_max_mem > nfsd_drc_mem_used)
1579+
total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used;
1580+
else
1581+
/* We have handed out more space than we chose in
1582+
* set_max_drc() to allow. That isn't really a
1583+
* problem as long as that doesn't make us think we
1584+
* have lots more due to integer overflow.
1585+
*/
1586+
total_avail = 0;
15791587
avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, total_avail);
15801588
/*
15811589
* Never use more than a third of the remaining memory,
1582-
* unless it's the only way to give this client a slot:
1590+
* unless it's the only way to give this client a slot.
1591+
* Give the client one slot even if that would require
1592+
* over-allocation--it is better than failure.
15831593
*/
15841594
avail = clamp_t(unsigned long, avail, slotsize, total_avail/3);
15851595
num = min_t(int, num, avail / slotsize);
1596+
num = max_t(int, num, 1);
15861597
nfsd_drc_mem_used += num * slotsize;
15871598
spin_unlock(&nfsd_drc_lock);
15881599

@@ -3174,10 +3185,10 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs
31743185
* performance. When short on memory we therefore prefer to
31753186
* decrease number of slots instead of their size. Clients that
31763187
* request larger slots than they need will get poor results:
3188+
* Note that we always allow at least one slot, because our
3189+
* accounting is soft and provides no guarantees either way.
31773190
*/
31783191
ca->maxreqs = nfsd4_get_drc_mem(ca);
3179-
if (!ca->maxreqs)
3180-
return nfserr_jukebox;
31813192

31823193
return nfs_ok;
31833194
}

0 commit comments

Comments
 (0)