Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nfsd: use an xarray to store v4.1 session slots

Using an xarray to store session slots will make it easier to change the
number of active slots based on demand, and removes an unnecessary
limit.

To achieve good throughput with a high-latency server it can be helpful
to have hundreds of concurrent writes, which means hundreds of slots.
So increase the limit to 2048 (twice what the Linux client will
currently use). This limit is only a sanity check, not a hard limit.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

NeilBrown and committed by
Chuck Lever
0b6e1424 a4b853f1

+24 -13
+18 -10
fs/nfsd/nfs4state.c
··· 1915 1915 int i; 1916 1916 1917 1917 for (i = 0; i < ses->se_fchannel.maxreqs; i++) { 1918 - free_svc_cred(&ses->se_slots[i]->sl_cred); 1919 - kfree(ses->se_slots[i]); 1918 + struct nfsd4_slot *slot = xa_load(&ses->se_slots, i); 1919 + 1920 + xa_erase(&ses->se_slots, i); 1921 + free_svc_cred(&slot->sl_cred); 1922 + kfree(slot); 1920 1923 } 1921 1924 } 1922 1925 ··· 1999 1996 struct nfsd4_session *new; 2000 1997 int i; 2001 1998 2002 - BUILD_BUG_ON(struct_size(new, se_slots, NFSD_MAX_SLOTS_PER_SESSION) 2003 - > PAGE_SIZE); 2004 - 2005 - new = kzalloc(struct_size(new, se_slots, numslots), GFP_KERNEL); 1999 + new = kzalloc(sizeof(*new), GFP_KERNEL); 2006 2000 if (!new) 2007 2001 return NULL; 2002 + xa_init(&new->se_slots); 2008 2003 /* allocate each struct nfsd4_slot and data cache in one piece */ 2009 2004 for (i = 0; i < numslots; i++) { 2010 - new->se_slots[i] = kzalloc(slotsize, GFP_KERNEL); 2011 - if (!new->se_slots[i]) 2005 + struct nfsd4_slot *slot; 2006 + slot = kzalloc(slotsize, GFP_KERNEL); 2007 + if (!slot) 2012 2008 goto out_free; 2009 + if (xa_is_err(xa_store(&new->se_slots, i, slot, GFP_KERNEL))) { 2010 + kfree(slot); 2011 + goto out_free; 2012 + } 2013 2013 } 2014 2014 2015 2015 memcpy(&new->se_fchannel, fattrs, sizeof(struct nfsd4_channel_attrs)); ··· 2023 2017 return new; 2024 2018 out_free: 2025 2019 while (i--) 2026 - kfree(new->se_slots[i]); 2020 + kfree(xa_load(&new->se_slots, i)); 2021 + xa_destroy(&new->se_slots); 2027 2022 kfree(new); 2028 2023 return NULL; 2029 2024 } ··· 2131 2124 static void __free_session(struct nfsd4_session *ses) 2132 2125 { 2133 2126 free_session_slots(ses); 2127 + xa_destroy(&ses->se_slots); 2134 2128 kfree(ses); 2135 2129 } 2136 2130 ··· 4286 4278 if (seq->slotid >= session->se_fchannel.maxreqs) 4287 4279 goto out_put_session; 4288 4280 4289 - slot = session->se_slots[seq->slotid]; 4281 + slot = xa_load(&session->se_slots, seq->slotid); 4290 4282 dprintk("%s: slotid %d\n", __func__, seq->slotid); 4291 4283 4292 4284 /* We do not negotiate the number of slots yet, so set the
+6 -3
fs/nfsd/state.h
··· 227 227 return container_of(s, struct nfs4_delegation, dl_stid); 228 228 } 229 229 230 - /* Maximum number of slots per session. 160 is useful for long haul TCP */ 231 - #define NFSD_MAX_SLOTS_PER_SESSION 160 230 + /* Maximum number of slots per session. This is for sanity-check only. 231 + * It could be increased if we had a mechanism to shutdown misbehaving clients. 232 + * A large number can be needed to get good throughput on high-latency servers. 233 + */ 234 + #define NFSD_MAX_SLOTS_PER_SESSION 2048 232 235 /* Maximum session per slot cache size */ 233 236 #define NFSD_SLOT_CACHE_SIZE 2048 234 237 /* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */ ··· 330 327 struct nfsd4_cb_sec se_cb_sec; 331 328 struct list_head se_conns; 332 329 u32 se_cb_seq_nr[NFSD_BC_SLOT_TABLE_SIZE]; 333 - struct nfsd4_slot *se_slots[]; /* forward channel slots */ 330 + struct xarray se_slots; /* forward channel slots */ 334 331 }; 335 332 336 333 /* formatted contents of nfs4_sessionid */