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

nfsd4: drc containerization

The nfsd duplicate reply cache should not be shared between network
namespaces.

The most straightforward way to fix this is just to move every global in
the code to per-net-namespace memory, so that's what we do.

Still todo: sort out which members of nfsd_stats should be global and
which per-net-namespace.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>

+154 -125
+3 -2
fs/nfsd/cache.h
··· 10 10 #define NFSCACHE_H 11 11 12 12 #include <linux/sunrpc/svc.h> 13 + #include "netns.h" 13 14 14 15 /* 15 16 * Representation of a reply cache entry. ··· 78 77 /* Checksum this amount of the request */ 79 78 #define RC_CSUMLEN (256U) 80 79 81 - int nfsd_reply_cache_init(void); 82 - void nfsd_reply_cache_shutdown(void); 80 + int nfsd_reply_cache_init(struct nfsd_net *); 81 + void nfsd_reply_cache_shutdown(struct nfsd_net *); 83 82 int nfsd_cache_lookup(struct svc_rqst *); 84 83 void nfsd_cache_update(struct svc_rqst *, int, __be32 *); 85 84 int nfsd_reply_cache_stats_open(struct inode *, struct file *);
+35
fs/nfsd/netns.h
··· 127 127 */ 128 128 bool *nfsd_versions; 129 129 bool *nfsd4_minorversions; 130 + 131 + /* 132 + * Duplicate reply cache 133 + */ 134 + struct nfsd_drc_bucket *drc_hashtbl; 135 + struct kmem_cache *drc_slab; 136 + 137 + /* max number of entries allowed in the cache */ 138 + unsigned int max_drc_entries; 139 + 140 + /* number of significant bits in the hash value */ 141 + unsigned int maskbits; 142 + unsigned int drc_hashsize; 143 + 144 + /* 145 + * Stats and other tracking of on the duplicate reply cache. All of these and 146 + * the "rc" fields in nfsdstats are protected by the cache_lock 147 + */ 148 + 149 + /* total number of entries */ 150 + atomic_t num_drc_entries; 151 + 152 + /* cache misses due only to checksum comparison failures */ 153 + unsigned int payload_misses; 154 + 155 + /* amount of memory (in bytes) currently consumed by the DRC */ 156 + unsigned int drc_mem_usage; 157 + 158 + /* longest hash chain seen */ 159 + unsigned int longest_chain; 160 + 161 + /* size of cache when we saw the longest hash chain */ 162 + unsigned int longest_chain_cachesize; 163 + 164 + struct shrinker nfsd_reply_cache_shrinker; 130 165 }; 131 166 132 167 /* Simple check to find out if a given net was properly initialized */
+108 -117
fs/nfsd/nfscache.c
··· 9 9 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 10 10 */ 11 11 12 + #include <linux/sunrpc/svc_xprt.h> 12 13 #include <linux/slab.h> 13 14 #include <linux/vmalloc.h> 14 15 #include <linux/sunrpc/addr.h> ··· 36 35 spinlock_t cache_lock; 37 36 }; 38 37 39 - static struct nfsd_drc_bucket *drc_hashtbl; 40 - static struct kmem_cache *drc_slab; 41 - 42 - /* max number of entries allowed in the cache */ 43 - static unsigned int max_drc_entries; 44 - 45 - /* number of significant bits in the hash value */ 46 - static unsigned int maskbits; 47 - static unsigned int drc_hashsize; 48 - 49 - /* 50 - * Stats and other tracking of on the duplicate reply cache. All of these and 51 - * the "rc" fields in nfsdstats are protected by the cache_lock 52 - */ 53 - 54 - /* total number of entries */ 55 - static atomic_t num_drc_entries; 56 - 57 - /* cache misses due only to checksum comparison failures */ 58 - static unsigned int payload_misses; 59 - 60 - /* amount of memory (in bytes) currently consumed by the DRC */ 61 - static unsigned int drc_mem_usage; 62 - 63 - /* longest hash chain seen */ 64 - static unsigned int longest_chain; 65 - 66 - /* size of cache when we saw the longest hash chain */ 67 - static unsigned int longest_chain_cachesize; 68 - 69 38 static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec); 70 39 static unsigned long nfsd_reply_cache_count(struct shrinker *shrink, 71 40 struct shrink_control *sc); 72 41 static unsigned long nfsd_reply_cache_scan(struct shrinker *shrink, 73 42 struct shrink_control *sc); 74 - 75 - static struct shrinker nfsd_reply_cache_shrinker = { 76 - .scan_objects = nfsd_reply_cache_scan, 77 - .count_objects = nfsd_reply_cache_count, 78 - .seeks = 1, 79 - }; 80 43 81 44 /* 82 45 * Put a cap on the size of the DRC based on the amount of available ··· 59 94 * ...with a hard cap of 256k entries. In the worst case, each entry will be 60 95 * ~1k, so the above numbers should give a rough max of the amount of memory 61 96 * used in k. 97 + * 98 + * XXX: these limits are per-container, so memory used will increase 99 + * linearly with number of containers. Maybe that's OK. 62 100 */ 63 101 static unsigned int 64 102 nfsd_cache_size_limit(void) ··· 84 116 } 85 117 86 118 static u32 87 - nfsd_cache_hash(__be32 xid) 119 + nfsd_cache_hash(__be32 xid, struct nfsd_net *nn) 88 120 { 89 - return hash_32(be32_to_cpu(xid), maskbits); 121 + return hash_32(be32_to_cpu(xid), nn->maskbits); 90 122 } 91 123 92 124 static struct svc_cacherep * 93 - nfsd_reply_cache_alloc(struct svc_rqst *rqstp, __wsum csum) 125 + nfsd_reply_cache_alloc(struct svc_rqst *rqstp, __wsum csum, 126 + struct nfsd_net *nn) 94 127 { 95 128 struct svc_cacherep *rp; 96 129 97 - rp = kmem_cache_alloc(drc_slab, GFP_KERNEL); 130 + rp = kmem_cache_alloc(nn->drc_slab, GFP_KERNEL); 98 131 if (rp) { 99 132 rp->c_state = RC_UNUSED; 100 133 rp->c_type = RC_NOCACHE; ··· 116 147 } 117 148 118 149 static void 119 - nfsd_reply_cache_free_locked(struct nfsd_drc_bucket *b, struct svc_cacherep *rp) 150 + nfsd_reply_cache_free_locked(struct nfsd_drc_bucket *b, struct svc_cacherep *rp, 151 + struct nfsd_net *nn) 120 152 { 121 153 if (rp->c_type == RC_REPLBUFF && rp->c_replvec.iov_base) { 122 - drc_mem_usage -= rp->c_replvec.iov_len; 154 + nn->drc_mem_usage -= rp->c_replvec.iov_len; 123 155 kfree(rp->c_replvec.iov_base); 124 156 } 125 157 if (rp->c_state != RC_UNUSED) { 126 158 rb_erase(&rp->c_node, &b->rb_head); 127 159 list_del(&rp->c_lru); 128 - atomic_dec(&num_drc_entries); 129 - drc_mem_usage -= sizeof(*rp); 160 + atomic_dec(&nn->num_drc_entries); 161 + nn->drc_mem_usage -= sizeof(*rp); 130 162 } 131 - kmem_cache_free(drc_slab, rp); 163 + kmem_cache_free(nn->drc_slab, rp); 132 164 } 133 165 134 166 static void 135 - nfsd_reply_cache_free(struct nfsd_drc_bucket *b, struct svc_cacherep *rp) 167 + nfsd_reply_cache_free(struct nfsd_drc_bucket *b, struct svc_cacherep *rp, 168 + struct nfsd_net *nn) 136 169 { 137 170 spin_lock(&b->cache_lock); 138 - nfsd_reply_cache_free_locked(b, rp); 171 + nfsd_reply_cache_free_locked(b, rp, nn); 139 172 spin_unlock(&b->cache_lock); 140 173 } 141 174 142 - int nfsd_reply_cache_init(void) 175 + int nfsd_reply_cache_init(struct nfsd_net *nn) 143 176 { 144 177 unsigned int hashsize; 145 178 unsigned int i; 146 179 int status = 0; 147 180 148 - max_drc_entries = nfsd_cache_size_limit(); 149 - atomic_set(&num_drc_entries, 0); 150 - hashsize = nfsd_hashsize(max_drc_entries); 151 - maskbits = ilog2(hashsize); 181 + nn->max_drc_entries = nfsd_cache_size_limit(); 182 + atomic_set(&nn->num_drc_entries, 0); 183 + hashsize = nfsd_hashsize(nn->max_drc_entries); 184 + nn->maskbits = ilog2(hashsize); 152 185 153 - status = register_shrinker(&nfsd_reply_cache_shrinker); 186 + nn->nfsd_reply_cache_shrinker.scan_objects = nfsd_reply_cache_scan; 187 + nn->nfsd_reply_cache_shrinker.count_objects = nfsd_reply_cache_count; 188 + nn->nfsd_reply_cache_shrinker.seeks = 1; 189 + status = register_shrinker(&nn->nfsd_reply_cache_shrinker); 154 190 if (status) 155 191 return status; 156 192 157 - drc_slab = kmem_cache_create("nfsd_drc", sizeof(struct svc_cacherep), 158 - 0, 0, NULL); 159 - if (!drc_slab) 193 + nn->drc_slab = kmem_cache_create("nfsd_drc", 194 + sizeof(struct svc_cacherep), 0, 0, NULL); 195 + if (!nn->drc_slab) 160 196 goto out_nomem; 161 197 162 - drc_hashtbl = kcalloc(hashsize, sizeof(*drc_hashtbl), GFP_KERNEL); 163 - if (!drc_hashtbl) { 164 - drc_hashtbl = vzalloc(array_size(hashsize, 165 - sizeof(*drc_hashtbl))); 166 - if (!drc_hashtbl) 198 + nn->drc_hashtbl = kcalloc(hashsize, 199 + sizeof(*nn->drc_hashtbl), GFP_KERNEL); 200 + if (!nn->drc_hashtbl) { 201 + nn->drc_hashtbl = vzalloc(array_size(hashsize, 202 + sizeof(*nn->drc_hashtbl))); 203 + if (!nn->drc_hashtbl) 167 204 goto out_nomem; 168 205 } 169 206 170 207 for (i = 0; i < hashsize; i++) { 171 - INIT_LIST_HEAD(&drc_hashtbl[i].lru_head); 172 - spin_lock_init(&drc_hashtbl[i].cache_lock); 208 + INIT_LIST_HEAD(&nn->drc_hashtbl[i].lru_head); 209 + spin_lock_init(&nn->drc_hashtbl[i].cache_lock); 173 210 } 174 - drc_hashsize = hashsize; 211 + nn->drc_hashsize = hashsize; 175 212 176 213 return 0; 177 214 out_nomem: ··· 185 210 return -ENOMEM; 186 211 } 187 212 188 - void nfsd_reply_cache_shutdown(void) 213 + void nfsd_reply_cache_shutdown(struct nfsd_net *nn) 189 214 { 190 215 struct svc_cacherep *rp; 191 216 unsigned int i; 192 217 193 - unregister_shrinker(&nfsd_reply_cache_shrinker); 218 + unregister_shrinker(&nn->nfsd_reply_cache_shrinker); 194 219 195 - for (i = 0; i < drc_hashsize; i++) { 196 - struct list_head *head = &drc_hashtbl[i].lru_head; 220 + for (i = 0; i < nn->drc_hashsize; i++) { 221 + struct list_head *head = &nn->drc_hashtbl[i].lru_head; 197 222 while (!list_empty(head)) { 198 223 rp = list_first_entry(head, struct svc_cacherep, c_lru); 199 - nfsd_reply_cache_free_locked(&drc_hashtbl[i], rp); 224 + nfsd_reply_cache_free_locked(&nn->drc_hashtbl[i], 225 + rp, nn); 200 226 } 201 227 } 202 228 203 - kvfree(drc_hashtbl); 204 - drc_hashtbl = NULL; 205 - drc_hashsize = 0; 229 + kvfree(nn->drc_hashtbl); 230 + nn->drc_hashtbl = NULL; 231 + nn->drc_hashsize = 0; 206 232 207 - kmem_cache_destroy(drc_slab); 208 - drc_slab = NULL; 233 + kmem_cache_destroy(nn->drc_slab); 234 + nn->drc_slab = NULL; 209 235 } 210 236 211 237 /* ··· 221 245 } 222 246 223 247 static long 224 - prune_bucket(struct nfsd_drc_bucket *b) 248 + prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn) 225 249 { 226 250 struct svc_cacherep *rp, *tmp; 227 251 long freed = 0; ··· 233 257 */ 234 258 if (rp->c_state == RC_INPROG) 235 259 continue; 236 - if (atomic_read(&num_drc_entries) <= max_drc_entries && 260 + if (atomic_read(&nn->num_drc_entries) <= nn->max_drc_entries && 237 261 time_before(jiffies, rp->c_timestamp + RC_EXPIRE)) 238 262 break; 239 - nfsd_reply_cache_free_locked(b, rp); 263 + nfsd_reply_cache_free_locked(b, rp, nn); 240 264 freed++; 241 265 } 242 266 return freed; ··· 247 271 * Also prune the oldest ones when the total exceeds the max number of entries. 248 272 */ 249 273 static long 250 - prune_cache_entries(void) 274 + prune_cache_entries(struct nfsd_net *nn) 251 275 { 252 276 unsigned int i; 253 277 long freed = 0; 254 278 255 - for (i = 0; i < drc_hashsize; i++) { 256 - struct nfsd_drc_bucket *b = &drc_hashtbl[i]; 279 + for (i = 0; i < nn->drc_hashsize; i++) { 280 + struct nfsd_drc_bucket *b = &nn->drc_hashtbl[i]; 257 281 258 282 if (list_empty(&b->lru_head)) 259 283 continue; 260 284 spin_lock(&b->cache_lock); 261 - freed += prune_bucket(b); 285 + freed += prune_bucket(b, nn); 262 286 spin_unlock(&b->cache_lock); 263 287 } 264 288 return freed; ··· 267 291 static unsigned long 268 292 nfsd_reply_cache_count(struct shrinker *shrink, struct shrink_control *sc) 269 293 { 270 - return atomic_read(&num_drc_entries); 294 + struct nfsd_net *nn = container_of(shrink, 295 + struct nfsd_net, nfsd_reply_cache_shrinker); 296 + 297 + return atomic_read(&nn->num_drc_entries); 271 298 } 272 299 273 300 static unsigned long 274 301 nfsd_reply_cache_scan(struct shrinker *shrink, struct shrink_control *sc) 275 302 { 276 - return prune_cache_entries(); 303 + struct nfsd_net *nn = container_of(shrink, 304 + struct nfsd_net, nfsd_reply_cache_shrinker); 305 + 306 + return prune_cache_entries(nn); 277 307 } 278 308 /* 279 309 * Walk an xdr_buf and get a CRC for at most the first RC_CSUMLEN bytes ··· 315 333 } 316 334 317 335 static int 318 - nfsd_cache_key_cmp(const struct svc_cacherep *key, const struct svc_cacherep *rp) 336 + nfsd_cache_key_cmp(const struct svc_cacherep *key, 337 + const struct svc_cacherep *rp, struct nfsd_net *nn) 319 338 { 320 339 if (key->c_key.k_xid == rp->c_key.k_xid && 321 340 key->c_key.k_csum != rp->c_key.k_csum) 322 - ++payload_misses; 341 + ++nn->payload_misses; 323 342 324 343 return memcmp(&key->c_key, &rp->c_key, sizeof(key->c_key)); 325 344 } ··· 331 348 * inserts an empty key on failure. 332 349 */ 333 350 static struct svc_cacherep * 334 - nfsd_cache_insert(struct nfsd_drc_bucket *b, struct svc_cacherep *key) 351 + nfsd_cache_insert(struct nfsd_drc_bucket *b, struct svc_cacherep *key, 352 + struct nfsd_net *nn) 335 353 { 336 354 struct svc_cacherep *rp, *ret = key; 337 355 struct rb_node **p = &b->rb_head.rb_node, ··· 345 361 parent = *p; 346 362 rp = rb_entry(parent, struct svc_cacherep, c_node); 347 363 348 - cmp = nfsd_cache_key_cmp(key, rp); 364 + cmp = nfsd_cache_key_cmp(key, rp, nn); 349 365 if (cmp < 0) 350 366 p = &parent->rb_left; 351 367 else if (cmp > 0) ··· 359 375 rb_insert_color(&key->c_node, &b->rb_head); 360 376 out: 361 377 /* tally hash chain length stats */ 362 - if (entries > longest_chain) { 363 - longest_chain = entries; 364 - longest_chain_cachesize = atomic_read(&num_drc_entries); 365 - } else if (entries == longest_chain) { 378 + if (entries > nn->longest_chain) { 379 + nn->longest_chain = entries; 380 + nn->longest_chain_cachesize = atomic_read(&nn->num_drc_entries); 381 + } else if (entries == nn->longest_chain) { 366 382 /* prefer to keep the smallest cachesize possible here */ 367 - longest_chain_cachesize = min_t(unsigned int, 368 - longest_chain_cachesize, 369 - atomic_read(&num_drc_entries)); 383 + nn->longest_chain_cachesize = min_t(unsigned int, 384 + nn->longest_chain_cachesize, 385 + atomic_read(&nn->num_drc_entries)); 370 386 } 371 387 372 388 lru_put_end(b, ret); ··· 383 399 int 384 400 nfsd_cache_lookup(struct svc_rqst *rqstp) 385 401 { 402 + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 386 403 struct svc_cacherep *rp, *found; 387 404 __be32 xid = rqstp->rq_xid; 388 405 __wsum csum; 389 - u32 hash = nfsd_cache_hash(xid); 390 - struct nfsd_drc_bucket *b = &drc_hashtbl[hash]; 406 + u32 hash = nfsd_cache_hash(xid, nn); 407 + struct nfsd_drc_bucket *b = &nn->drc_hashtbl[hash]; 391 408 int type = rqstp->rq_cachetype; 392 409 int rtn = RC_DOIT; 393 410 ··· 404 419 * Since the common case is a cache miss followed by an insert, 405 420 * preallocate an entry. 406 421 */ 407 - rp = nfsd_reply_cache_alloc(rqstp, csum); 422 + rp = nfsd_reply_cache_alloc(rqstp, csum, nn); 408 423 if (!rp) { 409 424 dprintk("nfsd: unable to allocate DRC entry!\n"); 410 425 return rtn; 411 426 } 412 427 413 428 spin_lock(&b->cache_lock); 414 - found = nfsd_cache_insert(b, rp); 429 + found = nfsd_cache_insert(b, rp, nn); 415 430 if (found != rp) { 416 - nfsd_reply_cache_free_locked(NULL, rp); 431 + nfsd_reply_cache_free_locked(NULL, rp, nn); 417 432 rp = found; 418 433 goto found_entry; 419 434 } ··· 422 437 rqstp->rq_cacherep = rp; 423 438 rp->c_state = RC_INPROG; 424 439 425 - atomic_inc(&num_drc_entries); 426 - drc_mem_usage += sizeof(*rp); 440 + atomic_inc(&nn->num_drc_entries); 441 + nn->drc_mem_usage += sizeof(*rp); 427 442 428 443 /* go ahead and prune the cache */ 429 - prune_bucket(b); 444 + prune_bucket(b, nn); 430 445 out: 431 446 spin_unlock(&b->cache_lock); 432 447 return rtn; ··· 461 476 break; 462 477 default: 463 478 printk(KERN_WARNING "nfsd: bad repcache type %d\n", rp->c_type); 464 - nfsd_reply_cache_free_locked(b, rp); 479 + nfsd_reply_cache_free_locked(b, rp, nn); 465 480 } 466 481 467 482 goto out; ··· 486 501 void 487 502 nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp) 488 503 { 504 + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 489 505 struct svc_cacherep *rp = rqstp->rq_cacherep; 490 506 struct kvec *resv = &rqstp->rq_res.head[0], *cachv; 491 507 u32 hash; ··· 497 511 if (!rp) 498 512 return; 499 513 500 - hash = nfsd_cache_hash(rp->c_key.k_xid); 501 - b = &drc_hashtbl[hash]; 514 + hash = nfsd_cache_hash(rp->c_key.k_xid, nn); 515 + b = &nn->drc_hashtbl[hash]; 502 516 503 517 len = resv->iov_len - ((char*)statp - (char*)resv->iov_base); 504 518 len >>= 2; 505 519 506 520 /* Don't cache excessive amounts of data and XDR failures */ 507 521 if (!statp || len > (256 >> 2)) { 508 - nfsd_reply_cache_free(b, rp); 522 + nfsd_reply_cache_free(b, rp, nn); 509 523 return; 510 524 } 511 525 ··· 520 534 bufsize = len << 2; 521 535 cachv->iov_base = kmalloc(bufsize, GFP_KERNEL); 522 536 if (!cachv->iov_base) { 523 - nfsd_reply_cache_free(b, rp); 537 + nfsd_reply_cache_free(b, rp, nn); 524 538 return; 525 539 } 526 540 cachv->iov_len = bufsize; 527 541 memcpy(cachv->iov_base, statp, bufsize); 528 542 break; 529 543 case RC_NOCACHE: 530 - nfsd_reply_cache_free(b, rp); 544 + nfsd_reply_cache_free(b, rp, nn); 531 545 return; 532 546 } 533 547 spin_lock(&b->cache_lock); 534 - drc_mem_usage += bufsize; 548 + nn->drc_mem_usage += bufsize; 535 549 lru_put_end(b, rp); 536 550 rp->c_secure = test_bit(RQ_SECURE, &rqstp->rq_flags); 537 551 rp->c_type = cachetype; ··· 567 581 */ 568 582 static int nfsd_reply_cache_stats_show(struct seq_file *m, void *v) 569 583 { 570 - seq_printf(m, "max entries: %u\n", max_drc_entries); 584 + struct nfsd_net *nn = v; 585 + 586 + seq_printf(m, "max entries: %u\n", nn->max_drc_entries); 571 587 seq_printf(m, "num entries: %u\n", 572 - atomic_read(&num_drc_entries)); 573 - seq_printf(m, "hash buckets: %u\n", 1 << maskbits); 574 - seq_printf(m, "mem usage: %u\n", drc_mem_usage); 588 + atomic_read(&nn->num_drc_entries)); 589 + seq_printf(m, "hash buckets: %u\n", 1 << nn->maskbits); 590 + seq_printf(m, "mem usage: %u\n", nn->drc_mem_usage); 575 591 seq_printf(m, "cache hits: %u\n", nfsdstats.rchits); 576 592 seq_printf(m, "cache misses: %u\n", nfsdstats.rcmisses); 577 593 seq_printf(m, "not cached: %u\n", nfsdstats.rcnocache); 578 - seq_printf(m, "payload misses: %u\n", payload_misses); 579 - seq_printf(m, "longest chain len: %u\n", longest_chain); 580 - seq_printf(m, "cachesize at longest: %u\n", longest_chain_cachesize); 594 + seq_printf(m, "payload misses: %u\n", nn->payload_misses); 595 + seq_printf(m, "longest chain len: %u\n", nn->longest_chain); 596 + seq_printf(m, "cachesize at longest: %u\n", nn->longest_chain_cachesize); 581 597 return 0; 582 598 } 583 599 584 600 int nfsd_reply_cache_stats_open(struct inode *inode, struct file *file) 585 601 { 586 - return single_open(file, nfsd_reply_cache_stats_show, NULL); 602 + struct nfsd_net *nn = net_generic(file_inode(file)->i_sb->s_fs_info, 603 + nfsd_net_id); 604 + 605 + return single_open(file, nfsd_reply_cache_stats_show, nn); 587 606 }
+8 -6
fs/nfsd/nfsctl.c
··· 1242 1242 goto out_idmap_error; 1243 1243 nn->nfsd_versions = NULL; 1244 1244 nn->nfsd4_minorversions = NULL; 1245 + retval = nfsd_reply_cache_init(nn); 1246 + if (retval) 1247 + goto out_drc_error; 1245 1248 nn->nfsd4_lease = 90; /* default lease time */ 1246 1249 nn->nfsd4_grace = 90; 1247 1250 nn->somebody_reclaimed = false; ··· 1257 1254 init_waitqueue_head(&nn->ntf_wq); 1258 1255 return 0; 1259 1256 1257 + out_drc_error: 1258 + nfsd_idmap_shutdown(net); 1260 1259 out_idmap_error: 1261 1260 nfsd_export_shutdown(net); 1262 1261 out_export_error: ··· 1267 1262 1268 1263 static __net_exit void nfsd_exit_net(struct net *net) 1269 1264 { 1265 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1266 + 1267 + nfsd_reply_cache_shutdown(nn); 1270 1268 nfsd_idmap_shutdown(net); 1271 1269 nfsd_export_shutdown(net); 1272 1270 nfsd_netns_free_versions(net_generic(net, nfsd_net_id)); ··· 1303 1295 if (retval) 1304 1296 goto out_exit_pnfs; 1305 1297 nfsd_stat_init(); /* Statistics */ 1306 - retval = nfsd_reply_cache_init(); 1307 - if (retval) 1308 - goto out_free_stat; 1309 1298 nfsd_lockd_init(); /* lockd->nfsd callbacks */ 1310 1299 retval = create_proc_exports_entry(); 1311 1300 if (retval) ··· 1316 1311 remove_proc_entry("fs/nfs", NULL); 1317 1312 out_free_lockd: 1318 1313 nfsd_lockd_shutdown(); 1319 - nfsd_reply_cache_shutdown(); 1320 - out_free_stat: 1321 1314 nfsd_stat_shutdown(); 1322 1315 nfsd_fault_inject_cleanup(); 1323 1316 out_exit_pnfs: ··· 1331 1328 1332 1329 static void __exit exit_nfsd(void) 1333 1330 { 1334 - nfsd_reply_cache_shutdown(); 1335 1331 remove_proc_entry("fs/nfs/exports", NULL); 1336 1332 remove_proc_entry("fs/nfs", NULL); 1337 1333 nfsd_stat_shutdown();