diff options
author | Paul Winder <paul@winders.demon.co.uk> | 2019-11-21 14:08:31 +0000 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2019-11-25 11:10:02 -0500 |
commit | 247e9a8ed695b16d62e2a0cb581e5c07d949d5ae (patch) | |
tree | 6fc7618006187f5a1a048a8349b2c859488db6c2 /usr/src/uts/common/io/blkdev | |
parent | eb44bcc7bc940d7cc1f4c10afa5a1cb7ec0dd198 (diff) | |
download | illumos-joyent-247e9a8ed695b16d62e2a0cb581e5c07d949d5ae.tar.gz |
12009 Memory leaks in blkdev when blkdev device is detached
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Reviewed by: Igor Kozhukhov <igor@dilos.org>
Reviewed by: Randy Fishel <randyf@sibernet.com>
Reviewed by: Matthias Scheler <matthias.scheler@wdc.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/uts/common/io/blkdev')
-rw-r--r-- | usr/src/uts/common/io/blkdev/blkdev.c | 44 |
1 files 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,20 +495,35 @@ 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) { struct bd_errstats *est = bd->d_kerr; @@ -535,6 +550,22 @@ bd_init_errstats(bd_t *bd, bd_drive_t *drive) } 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) { uint32_t i; @@ -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 { |