From e31ed02433e5da20b659396eb39853bfc5828a99 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Wed, 15 May 2024 12:46:22 +1000 Subject: [PATCH] linux/kstat: replace existing kstat if name is reused Previously, if a kstat proc name already existed, the old one would be kept. This makes it so the old one is discarded and the new one kept. Arguably, a collision like this shouldn't ever happen, but during import multiple vdev_t (and so vdev_queue_t, and so vdev_queue stats) can exist at the same time for the same guid. There's no real way to tell which is which without substantial refactoring in the import and vdev init codepaths, whch is probably worthwhile but not for today. Sponsored-by: Klara, Inc. Sponsored-by: Syneto Signed-off-by: Rob Norris --- module/os/linux/spl/spl-kstat.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/module/os/linux/spl/spl-kstat.c b/module/os/linux/spl/spl-kstat.c index 10732d6090..cac2a6d469 100644 --- a/module/os/linux/spl/spl-kstat.c +++ b/module/os/linux/spl/spl-kstat.c @@ -667,12 +667,20 @@ kstat_proc_entry_install(kstat_proc_entry_t *kpep, mode_t mode, } /* - * Only one entry by this name per-module, on failure the module - * shouldn't be deleted because we know it has at least one entry. + * We can only have one entry of this name per module. If one already + * exists, replace it by first removing the proc entry, then removing + * it from the list. The kstat itself lives on; it just can't be + * inspected through the filesystem. */ list_for_each_entry(tmp, &module->ksm_kstat_list, kpe_list) { - if (strncmp(tmp->kpe_name, kpep->kpe_name, KSTAT_STRLEN) == 0) - goto out; + if (tmp->kpe_proc != NULL && + strncmp(tmp->kpe_name, kpep->kpe_name, KSTAT_STRLEN) == 0) { + ASSERT3P(tmp->kpe_owner, ==, module); + remove_proc_entry(tmp->kpe_name, module->ksm_proc); + tmp->kpe_proc = NULL; + list_del_init(&tmp->kpe_list); + break; + } } list_add_tail(&kpep->kpe_list, &module->ksm_kstat_list);