@@ -1909,6 +1909,16 @@ gen_sessionid(struct nfsd4_session *ses)
1909
1909
*/
1910
1910
#define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44)
1911
1911
1912
+ static struct shrinker * nfsd_slot_shrinker ;
1913
+ static DEFINE_SPINLOCK (nfsd_session_list_lock );
1914
+ static LIST_HEAD (nfsd_session_list );
1915
+ /* The sum of "target_slots-1" on every session. The shrinker can push this
1916
+ * down, though it can take a little while for the memory to actually
1917
+ * be freed. The "-1" is because we can never free slot 0 while the
1918
+ * session is active.
1919
+ */
1920
+ static atomic_t nfsd_total_target_slots = ATOMIC_INIT (0 );
1921
+
1912
1922
static void
1913
1923
free_session_slots (struct nfsd4_session * ses , int from )
1914
1924
{
@@ -1930,8 +1940,11 @@ free_session_slots(struct nfsd4_session *ses, int from)
1930
1940
kfree (slot );
1931
1941
}
1932
1942
ses -> se_fchannel .maxreqs = from ;
1933
- if (ses -> se_target_maxslots > from )
1934
- ses -> se_target_maxslots = from ;
1943
+ if (ses -> se_target_maxslots > from ) {
1944
+ int new_target = from ?: 1 ;
1945
+ atomic_sub (ses -> se_target_maxslots - new_target , & nfsd_total_target_slots );
1946
+ ses -> se_target_maxslots = new_target ;
1947
+ }
1935
1948
}
1936
1949
1937
1950
/**
@@ -1949,7 +1962,7 @@ free_session_slots(struct nfsd4_session *ses, int from)
1949
1962
* Return value:
1950
1963
* The number of slots that the target was reduced by.
1951
1964
*/
1952
- static int __maybe_unused
1965
+ static int
1953
1966
reduce_session_slots (struct nfsd4_session * ses , int dec )
1954
1967
{
1955
1968
struct nfsd_net * nn = net_generic (ses -> se_client -> net ,
@@ -1962,6 +1975,7 @@ reduce_session_slots(struct nfsd4_session *ses, int dec)
1962
1975
return ret ;
1963
1976
ret = min (dec , ses -> se_target_maxslots - 1 );
1964
1977
ses -> se_target_maxslots -= ret ;
1978
+ atomic_sub (ret , & nfsd_total_target_slots );
1965
1979
ses -> se_slot_gen += 1 ;
1966
1980
if (ses -> se_slot_gen == 0 ) {
1967
1981
int i ;
@@ -2021,6 +2035,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fattrs,
2021
2035
fattrs -> maxreqs = i ;
2022
2036
memcpy (& new -> se_fchannel , fattrs , sizeof (struct nfsd4_channel_attrs ));
2023
2037
new -> se_target_maxslots = i ;
2038
+ atomic_add (i - 1 , & nfsd_total_target_slots );
2024
2039
new -> se_cb_slot_avail = ~0U ;
2025
2040
new -> se_cb_highest_slot = min (battrs -> maxreqs - 1 ,
2026
2041
NFSD_BC_SLOT_TABLE_SIZE - 1 );
@@ -2145,6 +2160,36 @@ static void free_session(struct nfsd4_session *ses)
2145
2160
__free_session (ses );
2146
2161
}
2147
2162
2163
+ static unsigned long
2164
+ nfsd_slot_count (struct shrinker * s , struct shrink_control * sc )
2165
+ {
2166
+ unsigned long cnt = atomic_read (& nfsd_total_target_slots );
2167
+
2168
+ return cnt ? cnt : SHRINK_EMPTY ;
2169
+ }
2170
+
2171
+ static unsigned long
2172
+ nfsd_slot_scan (struct shrinker * s , struct shrink_control * sc )
2173
+ {
2174
+ struct nfsd4_session * ses ;
2175
+ unsigned long scanned = 0 ;
2176
+ unsigned long freed = 0 ;
2177
+
2178
+ spin_lock (& nfsd_session_list_lock );
2179
+ list_for_each_entry (ses , & nfsd_session_list , se_all_sessions ) {
2180
+ freed += reduce_session_slots (ses , 1 );
2181
+ scanned += 1 ;
2182
+ if (scanned >= sc -> nr_to_scan ) {
2183
+ /* Move starting point for next scan */
2184
+ list_move (& nfsd_session_list , & ses -> se_all_sessions );
2185
+ break ;
2186
+ }
2187
+ }
2188
+ spin_unlock (& nfsd_session_list_lock );
2189
+ sc -> nr_scanned = scanned ;
2190
+ return freed ;
2191
+ }
2192
+
2148
2193
static void init_session (struct svc_rqst * rqstp , struct nfsd4_session * new , struct nfs4_client * clp , struct nfsd4_create_session * cses )
2149
2194
{
2150
2195
int idx ;
@@ -2169,6 +2214,10 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
2169
2214
list_add (& new -> se_perclnt , & clp -> cl_sessions );
2170
2215
spin_unlock (& clp -> cl_lock );
2171
2216
2217
+ spin_lock (& nfsd_session_list_lock );
2218
+ list_add_tail (& new -> se_all_sessions , & nfsd_session_list );
2219
+ spin_unlock (& nfsd_session_list_lock );
2220
+
2172
2221
{
2173
2222
struct sockaddr * sa = svc_addr (rqstp );
2174
2223
/*
@@ -2238,6 +2287,9 @@ unhash_session(struct nfsd4_session *ses)
2238
2287
spin_lock (& ses -> se_client -> cl_lock );
2239
2288
list_del (& ses -> se_perclnt );
2240
2289
spin_unlock (& ses -> se_client -> cl_lock );
2290
+ spin_lock (& nfsd_session_list_lock );
2291
+ list_del (& ses -> se_all_sessions );
2292
+ spin_unlock (& nfsd_session_list_lock );
2241
2293
}
2242
2294
2243
2295
/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
@@ -2373,8 +2425,12 @@ unhash_client_locked(struct nfs4_client *clp)
2373
2425
}
2374
2426
list_del_init (& clp -> cl_lru );
2375
2427
spin_lock (& clp -> cl_lock );
2376
- list_for_each_entry (ses , & clp -> cl_sessions , se_perclnt )
2428
+ spin_lock (& nfsd_session_list_lock );
2429
+ list_for_each_entry (ses , & clp -> cl_sessions , se_perclnt ) {
2377
2430
list_del_init (& ses -> se_hash );
2431
+ list_del_init (& ses -> se_all_sessions );
2432
+ }
2433
+ spin_unlock (& nfsd_session_list_lock );
2378
2434
spin_unlock (& clp -> cl_lock );
2379
2435
}
2380
2436
@@ -4380,6 +4436,8 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4380
4436
GFP_NOWAIT ))) {
4381
4437
s += 1 ;
4382
4438
session -> se_fchannel .maxreqs = s ;
4439
+ atomic_add (s - session -> se_target_maxslots ,
4440
+ & nfsd_total_target_slots );
4383
4441
session -> se_target_maxslots = s ;
4384
4442
} else {
4385
4443
kfree (slot );
@@ -8770,7 +8828,6 @@ nfs4_state_start_net(struct net *net)
8770
8828
}
8771
8829
8772
8830
/* initialization to perform when the nfsd service is started: */
8773
-
8774
8831
int
8775
8832
nfs4_state_start (void )
8776
8833
{
@@ -8780,6 +8837,15 @@ nfs4_state_start(void)
8780
8837
if (ret )
8781
8838
return ret ;
8782
8839
8840
+ nfsd_slot_shrinker = shrinker_alloc (0 , "nfsd-DRC-slot" );
8841
+ if (!nfsd_slot_shrinker ) {
8842
+ rhltable_destroy (& nfs4_file_rhltable );
8843
+ return - ENOMEM ;
8844
+ }
8845
+ nfsd_slot_shrinker -> count_objects = nfsd_slot_count ;
8846
+ nfsd_slot_shrinker -> scan_objects = nfsd_slot_scan ;
8847
+ shrinker_register (nfsd_slot_shrinker );
8848
+
8783
8849
set_max_delegations ();
8784
8850
return 0 ;
8785
8851
}
@@ -8821,6 +8887,7 @@ void
8821
8887
nfs4_state_shutdown (void )
8822
8888
{
8823
8889
rhltable_destroy (& nfs4_file_rhltable );
8890
+ shrinker_free (nfsd_slot_shrinker );
8824
8891
}
8825
8892
8826
8893
static void
0 commit comments