Skip to content

Commit 24c96a4

Browse files
Daniel Zahkakuba-moo
authored andcommitted
netdevsim: psp: serialize calls to nsim_psp_uninit()
The debugfs write handler, nsim_psp_rereg_write(), can race against nsim_destroy() and against itself, causing nsim_psp_uninit() to run more than once concurrently. Two complementary changes serialize all callers: 1. Delete the psp_rereg debugfs file from nsim_psp_uninit() before doing the actual teardown. debugfs_remove() drains any in-flight writers and prevents new ones from starting. 2. Add a mutex around the body of nsim_psp_rereg_write() so that two concurrent userspace writers cannot both enter the teardown path at once. The teardown work itself is moved into a new __nsim_psp_uninit() that the rereg handler calls under the mutex, while the public nsim_psp_uninit() wraps it with the debugfs_remove()/mutex_destroy() pair so nsim_destroy() doesn't have to know about the psp internals. Fixes: f857478 ("netdevsim: a basic test PSP implementation") Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20260505-psd-rcu-v1-2-a8f69ec1ab96@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 7ce3f1b commit 24c96a4

2 files changed

Lines changed: 16 additions & 3 deletions

File tree

drivers/net/netdevsim/netdevsim.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ struct netdevsim {
121121
u64_stats_t tx_bytes;
122122
struct u64_stats_sync syncp;
123123
struct psp_dev *dev;
124+
struct dentry *rereg;
125+
struct mutex rereg_lock;
124126
u32 spi;
125127
u32 assoc_cnt;
126128
} psp;

drivers/net/netdevsim/psp.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,25 +209,34 @@ static struct psp_dev_caps nsim_psp_caps = {
209209
.assoc_drv_spc = sizeof(void *),
210210
};
211211

212-
void nsim_psp_uninit(struct netdevsim *ns)
212+
static void __nsim_psp_uninit(struct netdevsim *ns)
213213
{
214214
if (!IS_ERR(ns->psp.dev))
215215
psp_dev_unregister(ns->psp.dev);
216216
WARN_ON(ns->psp.assoc_cnt);
217217
}
218218

219+
void nsim_psp_uninit(struct netdevsim *ns)
220+
{
221+
debugfs_remove(ns->psp.rereg);
222+
mutex_destroy(&ns->psp.rereg_lock);
223+
__nsim_psp_uninit(ns);
224+
}
225+
219226
static ssize_t
220227
nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
221228
loff_t *ppos)
222229
{
223230
struct netdevsim *ns = file->private_data;
224231
int err;
225232

226-
nsim_psp_uninit(ns);
233+
mutex_lock(&ns->psp.rereg_lock);
234+
__nsim_psp_uninit(ns);
227235

228236
ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
229237
&nsim_psp_caps, ns);
230238
err = PTR_ERR_OR_ZERO(ns->psp.dev);
239+
mutex_unlock(&ns->psp.rereg_lock);
231240
return err ?: count;
232241
}
233242

@@ -249,6 +258,8 @@ int nsim_psp_init(struct netdevsim *ns)
249258
if (err)
250259
return err;
251260

252-
debugfs_create_file("psp_rereg", 0200, ddir, ns, &nsim_psp_rereg_fops);
261+
mutex_init(&ns->psp.rereg_lock);
262+
ns->psp.rereg = debugfs_create_file("psp_rereg", 0200, ddir, ns,
263+
&nsim_psp_rereg_fops);
253264
return 0;
254265
}

0 commit comments

Comments
 (0)