From 247e9a8ed695b16d62e2a0cb581e5c07d949d5ae Mon Sep 17 00:00:00 2001 From: Paul Winder Date: Thu, 21 Nov 2019 14:08:31 +0000 Subject: [PATCH] 12009 Memory leaks in blkdev when blkdev device is detached Reviewed by: Robert Mustacchi Reviewed by: Igor Kozhukhov Reviewed by: Randy Fishel Reviewed by: Matthias Scheler Approved by: Dan McDonald --- usr/src/uts/common/io/blkdev/blkdev.c | 44 +++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/usr/src/uts/common/io/blkdev/blkdev.c b/usr/src/uts/common/io/blkdev/blkdev.c index 3405187f60..2b185dff2b 100644 --- a/usr/src/uts/common/io/blkdev/blkdev.c +++ b/usr/src/uts/common/io/blkdev/blkdev.c @@ -495,19 +495,34 @@ static void bd_errstats_setstr(kstat_named_t *k, char *str, size_t len, char *alt) { char *tmp; + size_t km_len; if (KSTAT_NAMED_STR_PTR(k) == NULL) { - if (len > 0) { - tmp = kmem_alloc(len + 1, KM_SLEEP); - (void) strlcpy(tmp, str, len + 1); - } else { - tmp = alt; - } + if (len > 0) + km_len = strnlen(str, len); + else if (alt != NULL) + km_len = strlen(alt); + else + return; + + tmp = kmem_alloc(km_len + 1, KM_SLEEP); + bcopy(len > 0 ? str : alt, tmp, km_len); + tmp[km_len] = '\0'; kstat_named_setstr(k, tmp); } } +static void +bd_errstats_clrstr(kstat_named_t *k) +{ + if (KSTAT_NAMED_STR_PTR(k) == NULL) + return; + + kmem_free(KSTAT_NAMED_STR_PTR(k), KSTAT_NAMED_STR_BUFLEN(k)); + kstat_named_setstr(k, NULL); +} + static void bd_init_errstats(bd_t *bd, bd_drive_t *drive) { @@ -534,6 +549,22 @@ bd_init_errstats(bd_t *bd, bd_drive_t *drive) mutex_exit(&bd->d_errmutex); } +static void +bd_fini_errstats(bd_t *bd) +{ + struct bd_errstats *est = bd->d_kerr; + + mutex_enter(&bd->d_errmutex); + + bd_errstats_clrstr(&est->bd_model); + bd_errstats_clrstr(&est->bd_vid); + bd_errstats_clrstr(&est->bd_pid); + bd_errstats_clrstr(&est->bd_revision); + bd_errstats_clrstr(&est->bd_serial); + + mutex_exit(&bd->d_errmutex); +} + static void bd_queues_free(bd_t *bd) { @@ -773,6 +804,7 @@ bd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) } if (bd->d_errstats != NULL) { + bd_fini_errstats(bd); kstat_delete(bd->d_errstats); bd->d_errstats = NULL; } else { -- 2.45.2