Skip to content

Commit 027690c

Browse files
author
J. Bruce Fields
committed
nfsd4: make drc_slab global, not per-net
I made every global per-network-namespace instead. But perhaps doing that to this slab was a step too far. The kmem_cache_create call in our net init method also seems to be responsible for this lockdep warning: [ 45.163710] Unable to find swap-space signature [ 45.375718] trinity-c1 (855): attempted to duplicate a private mapping with mremap. This is not supported. [ 46.055744] futex_wake_op: trinity-c1 tries to shift op by -209; fix this program [ 51.011723] [ 51.013378] ====================================================== [ 51.013875] WARNING: possible circular locking dependency detected [ 51.014378] 5.2.0-rc2 gregkh#1 Not tainted [ 51.014672] ------------------------------------------------------ [ 51.015182] trinity-c2/886 is trying to acquire lock: [ 51.015593] 000000005405f099 (slab_mutex){+.+.}, at: slab_attr_store+0xa2/0x130 [ 51.016190] [ 51.016190] but task is already holding lock: [ 51.016652] 00000000ac662005 (kn->count#43){++++}, at: kernfs_fop_write+0x286/0x500 [ 51.017266] [ 51.017266] which lock already depends on the new lock. [ 51.017266] [ 51.017909] [ 51.017909] the existing dependency chain (in reverse order) is: [ 51.018497] [ 51.018497] -> gregkh#1 (kn->count#43){++++}: [ 51.018956] __lock_acquire+0x7cf/0x1a20 [ 51.019317] lock_acquire+0x17d/0x390 [ 51.019658] __kernfs_remove+0x892/0xae0 [ 51.020020] kernfs_remove_by_name_ns+0x78/0x110 [ 51.020435] sysfs_remove_link+0x55/0xb0 [ 51.020832] sysfs_slab_add+0xc1/0x3e0 [ 51.021332] __kmem_cache_create+0x155/0x200 [ 51.021720] create_cache+0xf5/0x320 [ 51.022054] kmem_cache_create_usercopy+0x179/0x320 [ 51.022486] kmem_cache_create+0x1a/0x30 [ 51.022867] nfsd_reply_cache_init+0x278/0x560 [ 51.023266] nfsd_init_net+0x20f/0x5e0 [ 51.023623] ops_init+0xcb/0x4b0 [ 51.023928] setup_net+0x2fe/0x670 [ 51.024315] copy_net_ns+0x30a/0x3f0 [ 51.024653] create_new_namespaces+0x3c5/0x820 [ 51.025257] unshare_nsproxy_namespaces+0xd1/0x240 [ 51.025881] ksys_unshare+0x506/0x9c0 [ 51.026381] __x64_sys_unshare+0x3a/0x50 [ 51.026937] do_syscall_64+0x110/0x10b0 [ 51.027509] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 51.028175] [ 51.028175] -> #0 (slab_mutex){+.+.}: [ 51.028817] validate_chain+0x1c51/0x2cc0 [ 51.029422] __lock_acquire+0x7cf/0x1a20 [ 51.029947] lock_acquire+0x17d/0x390 [ 51.030438] __mutex_lock+0x100/0xfa0 [ 51.030995] mutex_lock_nested+0x27/0x30 [ 51.031516] slab_attr_store+0xa2/0x130 [ 51.032020] sysfs_kf_write+0x11d/0x180 [ 51.032529] kernfs_fop_write+0x32a/0x500 [ 51.033056] do_loop_readv_writev+0x21d/0x310 [ 51.033627] do_iter_write+0x2e5/0x380 [ 51.034148] vfs_writev+0x170/0x310 [ 51.034616] do_pwritev+0x13e/0x160 [ 51.035100] __x64_sys_pwritev+0xa3/0x110 [ 51.035633] do_syscall_64+0x110/0x10b0 [ 51.036200] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 51.036924] [ 51.036924] other info that might help us debug this: [ 51.036924] [ 51.037876] Possible unsafe locking scenario: [ 51.037876] [ 51.038556] CPU0 CPU1 [ 51.039130] ---- ---- [ 51.039676] lock(kn->count#43); [ 51.040084] lock(slab_mutex); [ 51.040597] lock(kn->count#43); [ 51.041062] lock(slab_mutex); [ 51.041320] [ 51.041320] *** DEADLOCK *** [ 51.041320] [ 51.041793] 3 locks held by trinity-c2/886: [ 51.042128] #0: 000000001f55e152 (sb_writers#5){.+.+}, at: vfs_writev+0x2b9/0x310 [ 51.042739] gregkh#1: 00000000c7d6c034 (&of->mutex){+.+.}, at: kernfs_fop_write+0x25b/0x500 [ 51.043400] gregkh#2: 00000000ac662005 (kn->count#43){++++}, at: kernfs_fop_write+0x286/0x500 Reported-by: kernel test robot <lkp@intel.com> Fixes: 3ba7583 "drc containerization" Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 037e910 commit 027690c

File tree

4 files changed

+25
-13
lines changed

4 files changed

+25
-13
lines changed

fs/nfsd/cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ enum {
7878
/* Checksum this amount of the request */
7979
#define RC_CSUMLEN (256U)
8080

81+
int nfsd_drc_slab_create(void);
82+
void nfsd_drc_slab_free(void);
8183
int nfsd_reply_cache_init(struct nfsd_net *);
8284
void nfsd_reply_cache_shutdown(struct nfsd_net *);
8385
int nfsd_cache_lookup(struct svc_rqst *);

fs/nfsd/netns.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ struct nfsd_net {
139139
* Duplicate reply cache
140140
*/
141141
struct nfsd_drc_bucket *drc_hashtbl;
142-
struct kmem_cache *drc_slab;
143142

144143
/* max number of entries allowed in the cache */
145144
unsigned int max_drc_entries;

fs/nfsd/nfscache.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ struct nfsd_drc_bucket {
3535
spinlock_t cache_lock;
3636
};
3737

38+
static struct kmem_cache *drc_slab;
39+
3840
static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
3941
static unsigned long nfsd_reply_cache_count(struct shrinker *shrink,
4042
struct shrink_control *sc);
@@ -94,7 +96,7 @@ nfsd_reply_cache_alloc(struct svc_rqst *rqstp, __wsum csum,
9496
{
9597
struct svc_cacherep *rp;
9698

97-
rp = kmem_cache_alloc(nn->drc_slab, GFP_KERNEL);
99+
rp = kmem_cache_alloc(drc_slab, GFP_KERNEL);
98100
if (rp) {
99101
rp->c_state = RC_UNUSED;
100102
rp->c_type = RC_NOCACHE;
@@ -128,7 +130,7 @@ nfsd_reply_cache_free_locked(struct nfsd_drc_bucket *b, struct svc_cacherep *rp,
128130
atomic_dec(&nn->num_drc_entries);
129131
nn->drc_mem_usage -= sizeof(*rp);
130132
}
131-
kmem_cache_free(nn->drc_slab, rp);
133+
kmem_cache_free(drc_slab, rp);
132134
}
133135

134136
static void
@@ -140,6 +142,18 @@ nfsd_reply_cache_free(struct nfsd_drc_bucket *b, struct svc_cacherep *rp,
140142
spin_unlock(&b->cache_lock);
141143
}
142144

145+
int nfsd_drc_slab_create(void)
146+
{
147+
drc_slab = kmem_cache_create("nfsd_drc",
148+
sizeof(struct svc_cacherep), 0, 0, NULL);
149+
return drc_slab ? 0: -ENOMEM;
150+
}
151+
152+
void nfsd_drc_slab_free(void)
153+
{
154+
kmem_cache_destroy(drc_slab);
155+
}
156+
143157
int nfsd_reply_cache_init(struct nfsd_net *nn)
144158
{
145159
unsigned int hashsize;
@@ -158,18 +172,13 @@ int nfsd_reply_cache_init(struct nfsd_net *nn)
158172
if (status)
159173
goto out_nomem;
160174

161-
nn->drc_slab = kmem_cache_create("nfsd_drc",
162-
sizeof(struct svc_cacherep), 0, 0, NULL);
163-
if (!nn->drc_slab)
164-
goto out_shrinker;
165-
166175
nn->drc_hashtbl = kcalloc(hashsize,
167176
sizeof(*nn->drc_hashtbl), GFP_KERNEL);
168177
if (!nn->drc_hashtbl) {
169178
nn->drc_hashtbl = vzalloc(array_size(hashsize,
170179
sizeof(*nn->drc_hashtbl)));
171180
if (!nn->drc_hashtbl)
172-
goto out_slab;
181+
goto out_shrinker;
173182
}
174183

175184
for (i = 0; i < hashsize; i++) {
@@ -179,8 +188,6 @@ int nfsd_reply_cache_init(struct nfsd_net *nn)
179188
nn->drc_hashsize = hashsize;
180189

181190
return 0;
182-
out_slab:
183-
kmem_cache_destroy(nn->drc_slab);
184191
out_shrinker:
185192
unregister_shrinker(&nn->nfsd_reply_cache_shrinker);
186193
out_nomem:
@@ -208,8 +215,6 @@ void nfsd_reply_cache_shutdown(struct nfsd_net *nn)
208215
nn->drc_hashtbl = NULL;
209216
nn->drc_hashsize = 0;
210217

211-
kmem_cache_destroy(nn->drc_slab);
212-
nn->drc_slab = NULL;
213218
}
214219

215220
/*

fs/nfsd/nfsctl.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,9 @@ static int __init init_nfsd(void)
15331533
goto out_free_slabs;
15341534
nfsd_fault_inject_init(); /* nfsd fault injection controls */
15351535
nfsd_stat_init(); /* Statistics */
1536+
retval = nfsd_drc_slab_create();
1537+
if (retval)
1538+
goto out_free_stat;
15361539
nfsd_lockd_init(); /* lockd->nfsd callbacks */
15371540
retval = create_proc_exports_entry();
15381541
if (retval)
@@ -1546,6 +1549,8 @@ static int __init init_nfsd(void)
15461549
remove_proc_entry("fs/nfs", NULL);
15471550
out_free_lockd:
15481551
nfsd_lockd_shutdown();
1552+
nfsd_drc_slab_free();
1553+
out_free_stat:
15491554
nfsd_stat_shutdown();
15501555
nfsd_fault_inject_cleanup();
15511556
nfsd4_exit_pnfs();
@@ -1560,6 +1565,7 @@ static int __init init_nfsd(void)
15601565

15611566
static void __exit exit_nfsd(void)
15621567
{
1568+
nfsd_drc_slab_free();
15631569
remove_proc_entry("fs/nfs/exports", NULL);
15641570
remove_proc_entry("fs/nfs", NULL);
15651571
nfsd_stat_shutdown();

0 commit comments

Comments
 (0)